From 8723cade21fbfc811777b893d03192294c2ed85f Mon Sep 17 00:00:00 2001 From: Steve Holme Date: Sat, 13 Apr 2013 16:21:58 +0100 Subject: [PATCH] smtp: Added support for ;auth= in the URL Added support for specifying the preferred authentication mechanism in the URL as per Internet-Draft 'draft-earhart-url-smtp-00'. --- lib/smtp.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++---- lib/smtp.h | 1 + 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/lib/smtp.c b/lib/smtp.c index 4c293a426..49da078ef 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -26,6 +26,7 @@ * RFC4616 PLAIN authentication * RFC4954 SMTP Authentication * RFC5321 SMTP protocol + * Draft SMTP URL Interface * ***************************************************************************/ @@ -99,6 +100,7 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks); static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); static CURLcode smtp_setup_connection(struct connectdata *conn); +static CURLcode smtp_parse_url_options(struct connectdata *conn); static CURLcode smtp_parse_url_path(struct connectdata *conn); /* @@ -422,12 +424,14 @@ static CURLcode smtp_authenticate(struct connectdata *conn) /* Calculate the supported authentication mechanism, by decreasing order of security, as well as the initial response where appropriate */ #ifndef CURL_DISABLE_CRYPTO_AUTH - if(smtpc->authmechs & SASL_MECH_DIGEST_MD5) { + if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) && + (smtpc->prefmech & SASL_MECH_DIGEST_MD5)) { mech = "DIGEST-MD5"; state1 = SMTP_AUTH_DIGESTMD5; smtpc->authused = SASL_MECH_DIGEST_MD5; } - else if(smtpc->authmechs & SASL_MECH_CRAM_MD5) { + else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) && + (smtpc->prefmech & SASL_MECH_CRAM_MD5)) { mech = "CRAM-MD5"; state1 = SMTP_AUTH_CRAMMD5; smtpc->authused = SASL_MECH_CRAM_MD5; @@ -435,7 +439,8 @@ static CURLcode smtp_authenticate(struct connectdata *conn) else #endif #ifdef USE_NTLM - if(smtpc->authmechs & SASL_MECH_NTLM) { + if((smtpc->authmechs & SASL_MECH_NTLM) && + (smtpc->prefmech & SASL_MECH_NTLM)) { mech = "NTLM"; state1 = SMTP_AUTH_NTLM; state2 = SMTP_AUTH_NTLM_TYPE2MSG; @@ -446,7 +451,8 @@ static CURLcode smtp_authenticate(struct connectdata *conn) } else #endif - if(smtpc->authmechs & SASL_MECH_LOGIN) { + if((smtpc->authmechs & SASL_MECH_LOGIN) && + (smtpc->prefmech & SASL_MECH_LOGIN)) { mech = "LOGIN"; state1 = SMTP_AUTH_LOGIN; state2 = SMTP_AUTH_LOGIN_PASSWD; @@ -454,7 +460,8 @@ static CURLcode smtp_authenticate(struct connectdata *conn) result = Curl_sasl_create_login_message(conn->data, conn->user, &initresp, &len); } - else if(smtpc->authmechs & SASL_MECH_PLAIN) { + else if((smtpc->authmechs & SASL_MECH_PLAIN) && + (smtpc->prefmech & SASL_MECH_PLAIN)) { mech = "PLAIN"; state1 = SMTP_AUTH_PLAIN; state2 = SMTP_AUTH_FINAL; @@ -1322,9 +1329,17 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) pp->endofresp = smtp_endofresp; pp->conn = conn; + /* Set the default preferred authentication mechanism */ + smtpc->prefmech = SASL_AUTH_ANY; + /* Initialise the pingpong layer */ Curl_pp_init(pp); + /* Parse the URL options */ + result = smtp_parse_url_options(conn); + if(result) + return result; + /* Parse the URL path */ result = smtp_parse_url_path(conn); if(result) @@ -1631,6 +1646,52 @@ static CURLcode smtp_setup_connection(struct connectdata *conn) return CURLE_OK; } +/*********************************************************************** + * + * smtp_parse_url_options() + * + * Parse the URL login options. + */ +static CURLcode smtp_parse_url_options(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct smtp_conn *smtpc = &conn->proto.smtpc; + const char *options = conn->options; + const char *ptr = options; + + if(options) { + const char *key = ptr; + + while(*ptr && *ptr != '=') + ptr++; + + if(strnequal(key, "AUTH", 4)) { + const char *value = ptr + 1; + + if(strequal(value, "*")) + smtpc->prefmech = SASL_AUTH_ANY; + else if(strequal(value, "LOGIN")) + smtpc->prefmech = SASL_MECH_LOGIN; + else if(strequal(value, "PLAIN")) + smtpc->prefmech = SASL_MECH_PLAIN; + else if(strequal(value, "CRAM-MD5")) + smtpc->prefmech = SASL_MECH_CRAM_MD5; + else if(strequal(value, "DIGEST-MD5")) + smtpc->prefmech = SASL_MECH_DIGEST_MD5; + else if(strequal(value, "GSSAPI")) + smtpc->prefmech = SASL_MECH_GSSAPI; + else if(strequal(value, "NTLM")) + smtpc->prefmech = SASL_MECH_NTLM; + else + smtpc->prefmech = SASL_AUTH_NONE; + } + else + result = CURLE_URL_MALFORMAT; + } + + return result; +} + /*********************************************************************** * * smtp_parse_url_path() diff --git a/lib/smtp.h b/lib/smtp.h index a4749b3cf..ed704abd6 100644 --- a/lib/smtp.h +++ b/lib/smtp.h @@ -72,6 +72,7 @@ struct smtp_conn { size_t eob; /* Number of bytes of the EOB (End Of Body) that have been received so far */ unsigned int authmechs; /* Accepted authentication mechanisms */ + unsigned int prefmech; /* Preferred authentication mechanism */ unsigned int authused; /* Auth mechanism used for the connection */ bool tls_supported; /* StartTLS capability supported by server */ bool size_supported; /* If server supports SIZE extension according to