smtp: Added support for ;auth=<mech> in the URL

Added support for specifying the preferred authentication mechanism in
the URL as per Internet-Draft 'draft-earhart-url-smtp-00'.
This commit is contained in:
Steve Holme 2013-04-13 16:21:58 +01:00
Родитель d956d9db47
Коммит 8723cade21
2 изменённых файлов: 67 добавлений и 5 удалений

Просмотреть файл

@ -26,6 +26,7 @@
* RFC4616 PLAIN authentication * RFC4616 PLAIN authentication
* RFC4954 SMTP Authentication * RFC4954 SMTP Authentication
* RFC5321 SMTP protocol * RFC5321 SMTP protocol
* Draft SMTP URL Interface
* *
***************************************************************************/ ***************************************************************************/
@ -99,6 +100,7 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks); int numsocks);
static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode smtp_setup_connection(struct connectdata *conn); 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); 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 /* Calculate the supported authentication mechanism, by decreasing order of
security, as well as the initial response where appropriate */ security, as well as the initial response where appropriate */
#ifndef CURL_DISABLE_CRYPTO_AUTH #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"; mech = "DIGEST-MD5";
state1 = SMTP_AUTH_DIGESTMD5; state1 = SMTP_AUTH_DIGESTMD5;
smtpc->authused = SASL_MECH_DIGEST_MD5; 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"; mech = "CRAM-MD5";
state1 = SMTP_AUTH_CRAMMD5; state1 = SMTP_AUTH_CRAMMD5;
smtpc->authused = SASL_MECH_CRAM_MD5; smtpc->authused = SASL_MECH_CRAM_MD5;
@ -435,7 +439,8 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
else else
#endif #endif
#ifdef USE_NTLM #ifdef USE_NTLM
if(smtpc->authmechs & SASL_MECH_NTLM) { if((smtpc->authmechs & SASL_MECH_NTLM) &&
(smtpc->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM"; mech = "NTLM";
state1 = SMTP_AUTH_NTLM; state1 = SMTP_AUTH_NTLM;
state2 = SMTP_AUTH_NTLM_TYPE2MSG; state2 = SMTP_AUTH_NTLM_TYPE2MSG;
@ -446,7 +451,8 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
} }
else else
#endif #endif
if(smtpc->authmechs & SASL_MECH_LOGIN) { if((smtpc->authmechs & SASL_MECH_LOGIN) &&
(smtpc->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN"; mech = "LOGIN";
state1 = SMTP_AUTH_LOGIN; state1 = SMTP_AUTH_LOGIN;
state2 = SMTP_AUTH_LOGIN_PASSWD; 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, result = Curl_sasl_create_login_message(conn->data, conn->user,
&initresp, &len); &initresp, &len);
} }
else if(smtpc->authmechs & SASL_MECH_PLAIN) { else if((smtpc->authmechs & SASL_MECH_PLAIN) &&
(smtpc->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN"; mech = "PLAIN";
state1 = SMTP_AUTH_PLAIN; state1 = SMTP_AUTH_PLAIN;
state2 = SMTP_AUTH_FINAL; state2 = SMTP_AUTH_FINAL;
@ -1322,9 +1329,17 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
pp->endofresp = smtp_endofresp; pp->endofresp = smtp_endofresp;
pp->conn = conn; pp->conn = conn;
/* Set the default preferred authentication mechanism */
smtpc->prefmech = SASL_AUTH_ANY;
/* Initialise the pingpong layer */ /* Initialise the pingpong layer */
Curl_pp_init(pp); Curl_pp_init(pp);
/* Parse the URL options */
result = smtp_parse_url_options(conn);
if(result)
return result;
/* Parse the URL path */ /* Parse the URL path */
result = smtp_parse_url_path(conn); result = smtp_parse_url_path(conn);
if(result) if(result)
@ -1631,6 +1646,52 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
return CURLE_OK; 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() * smtp_parse_url_path()

Просмотреть файл

@ -72,6 +72,7 @@ struct smtp_conn {
size_t eob; /* Number of bytes of the EOB (End Of Body) that size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */ have been received so far */
unsigned int authmechs; /* Accepted authentication mechanisms */ unsigned int authmechs; /* Accepted authentication mechanisms */
unsigned int prefmech; /* Preferred authentication mechanism */
unsigned int authused; /* Auth mechanism used for the connection */ unsigned int authused; /* Auth mechanism used for the connection */
bool tls_supported; /* StartTLS capability supported by server */ bool tls_supported; /* StartTLS capability supported by server */
bool size_supported; /* If server supports SIZE extension according to bool size_supported; /* If server supports SIZE extension according to