From 1e39b95682781fd9117eef094f6fd8c58b443610 Mon Sep 17 00:00:00 2001 From: Steve Holme Date: Sun, 27 Oct 2013 12:34:56 +0000 Subject: [PATCH] email: Added support for canceling CRAM-MD5 authentication --- lib/curl_sasl.c | 58 +++++++++++++++++++++++++++++++++---------------- lib/curl_sasl.h | 6 ++++- lib/imap.c | 26 +++++++++++++++------- lib/pop3.c | 26 +++++++++++++++------- lib/smtp.c | 26 +++++++++++++++------- 5 files changed, 98 insertions(+), 44 deletions(-) diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index 044060ff8..15a197cab 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -168,7 +168,37 @@ 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() * * This is used to generate an already encoded CRAM-MD5 response message ready @@ -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; } diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h index 2b6a5a26a..63888ffac 100644 --- a/lib/curl_sasl.h +++ b/lib/curl_sasl.h @@ -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, diff --git a/lib/imap.c b/lib/imap.c index b17b7e533..a4e61622f 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -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,22 +1121,31 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn, /* Get the challenge message */ imap_get_message(data->state.buffer, &chlg64); - /* Create the response message */ - result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user, - conn->passwd, &rplyb64, &len); + /* 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", "*"); - /* Send the response */ - if(!result) { - if(rplyb64) { + if(!result) + state(conn, IMAP_AUTHENTICATE_CANCEL); + } + else { + /* Create the response message */ + result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user, + conn->passwd, &rplyb64, &len); + if(!result && rplyb64) { + /* Send the response */ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); if(!result) state(conn, IMAP_AUTHENTICATE_FINAL); } - - Curl_safefree(rplyb64); } + Curl_safefree(chlg); + Curl_safefree(rplyb64); + return result; } diff --git a/lib/pop3.c b/lib/pop3.c index f4dc5d1b3..d4075f4b3 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -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,22 +979,31 @@ static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn, /* Get the challenge message */ pop3_get_message(data->state.buffer, &chlg64); - /* Create the response message */ - result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user, - conn->passwd, &rplyb64, &len); + /* 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", "*"); - /* Send the response */ - if(!result) { - if(rplyb64) { + 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 */ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64); if(!result) state(conn, POP3_AUTH_FINAL); } - - Curl_safefree(rplyb64); } + Curl_safefree(chlg); + Curl_safefree(rplyb64); + return result; } diff --git a/lib/smtp.c b/lib/smtp.c index 7e07ba6d9..68537e74d 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -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,22 +959,31 @@ static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn, /* Get the challenge message */ smtp_get_message(data->state.buffer, &chlg64); - /* Create the response message */ - result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user, - conn->passwd, &rplyb64, &len); + /* 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", "*"); - /* Send the response */ - if(!result) { - if(rplyb64) { + 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 */ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); if(!result) state(conn, SMTP_AUTH_FINAL); } - - Curl_safefree(rplyb64); } + Curl_safefree(chlg); + Curl_safefree(rplyb64); + return result; }