Commit 1e39b956 authored by Steve Holme's avatar Steve Holme
Browse files

email: Added support for canceling CRAM-MD5 authentication

parent 8230af0b
Loading
Loading
Loading
Loading
+39 −19
Original line number Diff line number Diff line
@@ -168,6 +168,36 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
}

#ifndef CURL_DISABLE_CRYPTO_AUTH
 /*
 * Curl_sasl_decode_cram_md5_message()
 *
 * This is used to decode an already encoded CRAM-MD5 challenge message.
 *
 * Parameters:
 *
 * chlg64  [in]     - Pointer to the base64 encoded challenge message.
 * outptr  [in/out] - The address where a pointer to newly allocated memory
 *                    holding the result will be stored upon completion.
 * outlen  [out]    - The length of the output message.
 *
 * Returns CURLE_OK on success.
 */
CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
                                           size_t *outlen)
{
  CURLcode result = CURLE_OK;
  size_t chlg64len = strlen(chlg64);

  *outptr = NULL;
  *outlen = 0;

  /* Decode the challenge if necessary */
  if(chlg64len && *chlg64 != '=')
    result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);

    return result;
 }

 /*
 * Curl_sasl_create_cram_md5_message()
 *
@@ -177,7 +207,7 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
 * Parameters:
 *
 * data    [in]     - The session handle.
 * chlg64  [in]     - Pointer to the base64 encoded challenge buffer.
 * chlg    [in]     - The challenge.
 * userp   [in]     - The user name.
 * passdwp [in]     - The user's password.
 * outptr  [in/out] - The address where a pointer to newly allocated memory
@@ -187,42 +217,31 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
 * Returns CURLE_OK on success.
 */
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
                                           const char *chlg64,
                                           const char *chlg,
                                           const char *userp,
                                           const char *passwdp,
                                           char **outptr, size_t *outlen)
{
  CURLcode result = CURLE_OK;
  size_t chlg64len = strlen(chlg64);
  unsigned char *chlg = (unsigned char *) NULL;
  size_t chlglen = 0;
  HMAC_context *ctxt;
  unsigned char digest[MD5_DIGEST_LEN];
  char *response;

  /* Decode the challenge if necessary */
  if(chlg64len && *chlg64 != '=') {
    result = Curl_base64_decode(chlg64, &chlg, &chlglen);

    if(result)
      return result;
  }
  if(chlg)
    chlglen = strlen(chlg);

  /* Compute the digest using the password as the key */
  ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
                        (const unsigned char *) passwdp,
                        curlx_uztoui(strlen(passwdp)));

  if(!ctxt) {
    Curl_safefree(chlg);
  if(!ctxt)
    return CURLE_OUT_OF_MEMORY;
  }

  /* Update the digest with the given challenge */
  if(chlglen > 0)
    Curl_HMAC_update(ctxt, chlg, curlx_uztoui(chlglen));

  Curl_safefree(chlg);
    Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
                     curlx_uztoui(chlglen));

  /* Finalise the digest */
  Curl_HMAC_final(ctxt, digest);
@@ -240,6 +259,7 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
  result = Curl_base64_encode(data, response, 0, outptr, outlen);

  Curl_safefree(response);

  return result;
}

+5 −1
Original line number Diff line number Diff line
@@ -66,6 +66,10 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
                                        size_t *outlen);

#ifndef CURL_DISABLE_CRYPTO_AUTH
/* This is used to decode a base64 encoded CRAM-MD5 challange message */
CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
                                           size_t *outlen);

/* This is used to generate a base64 encoded CRAM-MD5 response message */
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
                                           const char *chlg64,
@@ -75,7 +79,7 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,

/* This is used to generate a base64 encoded DIGEST-MD5 response message */
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
                                             const char *chlg64,
                                             const char *chlg,
                                             const char *user,
                                             const char *passwdp,
                                             const char *service,
+18 −8
Original line number Diff line number Diff line
@@ -1106,6 +1106,7 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
{
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;
  char *chlg = NULL;
  char *chlg64 = NULL;
  char *rplyb64 = NULL;
  size_t len = 0;
@@ -1120,21 +1121,30 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
  /* Get the challenge message */
  imap_get_message(data->state.buffer, &chlg64);

  /* Decode the challenge message */
  result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
  if(result) {
    /* Send the cancellation */
    result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");

    if(!result)
      state(conn, IMAP_AUTHENTICATE_CANCEL);
  }
  else {
    /* Create the response message */
  result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user,
    result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user,
                                               conn->passwd, &rplyb64, &len);

    if(!result && rplyb64) {
      /* Send the response */
  if(!result) {
    if(rplyb64) {
      result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);

      if(!result)
        state(conn, IMAP_AUTHENTICATE_FINAL);
    }
  }

  Curl_safefree(chlg);
  Curl_safefree(rplyb64);
  }

  return result;
}
+18 −8
Original line number Diff line number Diff line
@@ -964,6 +964,7 @@ static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
{
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;
  char *chlg = NULL;
  char *chlg64 = NULL;
  char *rplyb64 = NULL;
  size_t len = 0;
@@ -978,21 +979,30 @@ static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
  /* Get the challenge message */
  pop3_get_message(data->state.buffer, &chlg64);

  /* Decode the challenge message */
  result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
  if(result) {
    /* Send the cancellation */
    result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");

    if(!result)
      state(conn, POP3_AUTH_CANCEL);
  }
  else {
    /* Create the response message */
    result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user,
                                               conn->passwd, &rplyb64, &len);

    if(!result && rplyb64) {
      /* Send the response */
  if(!result) {
    if(rplyb64) {
      result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);

      if(!result)
        state(conn, POP3_AUTH_FINAL);
    }
  }

  Curl_safefree(chlg);
  Curl_safefree(rplyb64);
  }

  return result;
}
+18 −8
Original line number Diff line number Diff line
@@ -944,6 +944,7 @@ static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn,
{
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;
  char *chlg = NULL;
  char *chlg64 = NULL;
  char *rplyb64 = NULL;
  size_t len = 0;
@@ -958,21 +959,30 @@ static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn,
  /* Get the challenge message */
  smtp_get_message(data->state.buffer, &chlg64);

  /* Decode the challenge message */
  result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
  if(result) {
    /* Send the cancellation */
    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");

    if(!result)
      state(conn, SMTP_AUTH_CANCEL);
  }
  else {
    /* Create the response message */
    result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user,
                                               conn->passwd, &rplyb64, &len);

    if(!result && rplyb64) {
      /* Send the response */
  if(!result) {
    if(rplyb64) {
      result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);

      if(!result)
        state(conn, SMTP_AUTH_FINAL);
    }
  }

  Curl_safefree(chlg);
  Curl_safefree(rplyb64);
  }

  return result;
}