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

Added support for specifying the preferred authentication type and SASL
mechanism in the URL as per RFC-2384.
This commit is contained in:
Steve Holme 2013-04-13 16:09:28 +01:00
Родитель 00045a3009
Коммит b3a01be2f3
2 изменённых файлов: 97 добавлений и 8 удалений

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

@ -101,6 +101,7 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks); int numsocks);
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done); static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode pop3_setup_connection(struct connectdata *conn); static CURLcode pop3_setup_connection(struct connectdata *conn);
static CURLcode pop3_parse_url_options(struct connectdata *conn);
static CURLcode pop3_parse_url_path(struct connectdata *conn); static CURLcode pop3_parse_url_path(struct connectdata *conn);
static CURLcode pop3_parse_custom_request(struct connectdata *conn); static CURLcode pop3_parse_custom_request(struct connectdata *conn);
@ -514,12 +515,14 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
security */ security */
if(pop3c->authtypes & POP3_TYPE_SASL) { if(pop3c->authtypes & POP3_TYPE_SASL) {
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authmechs & SASL_MECH_DIGEST_MD5) { if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5"; mech = "DIGEST-MD5";
authstate = POP3_AUTH_DIGESTMD5; authstate = POP3_AUTH_DIGESTMD5;
pop3c->authused = SASL_MECH_DIGEST_MD5; pop3c->authused = SASL_MECH_DIGEST_MD5;
} }
else if(pop3c->authmechs & SASL_MECH_CRAM_MD5) { else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
(pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5"; mech = "CRAM-MD5";
authstate = POP3_AUTH_CRAMMD5; authstate = POP3_AUTH_CRAMMD5;
pop3c->authused = SASL_MECH_CRAM_MD5; pop3c->authused = SASL_MECH_CRAM_MD5;
@ -527,26 +530,29 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
else else
#endif #endif
#ifdef USE_NTLM #ifdef USE_NTLM
if(pop3c->authmechs & SASL_MECH_NTLM) { if((pop3c->authmechs & SASL_MECH_NTLM) &&
(pop3c->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM"; mech = "NTLM";
authstate = POP3_AUTH_NTLM; authstate = POP3_AUTH_NTLM;
pop3c->authused = SASL_MECH_NTLM; pop3c->authused = SASL_MECH_NTLM;
} }
else else
#endif #endif
if(pop3c->authmechs & SASL_MECH_LOGIN) { if((pop3c->authmechs & SASL_MECH_LOGIN) &&
(pop3c->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN"; mech = "LOGIN";
authstate = POP3_AUTH_LOGIN; authstate = POP3_AUTH_LOGIN;
pop3c->authused = SASL_MECH_LOGIN; pop3c->authused = SASL_MECH_LOGIN;
} }
else if(pop3c->authmechs & SASL_MECH_PLAIN) { else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
(pop3c->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN"; mech = "PLAIN";
authstate = POP3_AUTH_PLAIN; authstate = POP3_AUTH_PLAIN;
pop3c->authused = SASL_MECH_PLAIN; pop3c->authused = SASL_MECH_PLAIN;
} }
} }
if(mech) { if(mech && (pop3c->preftype & POP3_TYPE_SASL)) {
/* Perform SASL based authentication */ /* Perform SASL based authentication */
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
@ -554,11 +560,13 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
state(conn, authstate); state(conn, authstate);
} }
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
else if(pop3c->authtypes & POP3_TYPE_APOP) else if((pop3c->authtypes & POP3_TYPE_APOP) &&
(pop3c->preftype & POP3_TYPE_APOP))
/* Perform APOP authentication */ /* Perform APOP authentication */
result = pop3_state_apop(conn); result = pop3_state_apop(conn);
#endif #endif
else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT) else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
(pop3c->preftype & POP3_TYPE_CLEARTEXT))
/* Perform clear text authentication */ /* Perform clear text authentication */
result = pop3_state_user(conn); result = pop3_state_user(conn);
else { else {
@ -1332,9 +1340,18 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
pp->endofresp = pop3_endofresp; pp->endofresp = pop3_endofresp;
pp->conn = conn; pp->conn = conn;
/* Set the default preferred authentication type and mechanism */
pop3c->preftype = POP3_TYPE_ANY;
pop3c->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 = pop3_parse_url_options(conn);
if(result)
return result;
/* Start off waiting for the server greeting response */ /* Start off waiting for the server greeting response */
state(conn, POP3_SERVERGREET); state(conn, POP3_SERVERGREET);
@ -1608,6 +1625,72 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/***********************************************************************
*
* pop3_parse_url_options()
*
* Parse the URL login options.
*/
static CURLcode pop3_parse_url_options(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
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, "*")) {
pop3c->preftype = POP3_TYPE_ANY;
pop3c->prefmech = SASL_AUTH_ANY;
}
else if(strequal(value, "+APOP")) {
pop3c->preftype = POP3_TYPE_APOP;
pop3c->prefmech = SASL_AUTH_NONE;
}
else if(strequal(value, "LOGIN")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_LOGIN;
}
else if(strequal(value, "PLAIN")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_PLAIN;
}
else if(strequal(value, "CRAM-MD5")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_CRAM_MD5;
}
else if(strequal(value, "DIGEST-MD5")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_DIGEST_MD5;
}
else if(strequal(value, "GSSAPI")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_GSSAPI;
}
else if(strequal(value, "NTLM")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_NTLM;
}
else {
pop3c->preftype = POP3_TYPE_NONE;
pop3c->prefmech = SASL_AUTH_NONE;
}
}
else
result = CURLE_URL_MALFORMAT;
}
return result;
}
/*********************************************************************** /***********************************************************************
* *
* pop3_parse_url_path() * pop3_parse_url_path()

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

@ -74,6 +74,8 @@ struct pop3_conn {
non-body */ non-body */
unsigned int authtypes; /* Supported authentication types */ unsigned int authtypes; /* Supported authentication types */
unsigned int authmechs; /* Accepted SASL authentication mechanisms */ unsigned int authmechs; /* Accepted SASL authentication mechanisms */
unsigned int preftype; /* Preferred authentication type */
unsigned int prefmech; /* Preferred SASL authentication mechanism */
unsigned int authused; /* SASL auth mechanism used for the connection */ unsigned int authused; /* SASL auth mechanism used for the connection */
char *apoptimestamp; /* APOP timestamp from the server greeting */ char *apoptimestamp; /* APOP timestamp from the server greeting */
bool tls_supported; /* StartTLS capability supported by server */ bool tls_supported; /* StartTLS capability supported by server */
@ -87,6 +89,10 @@ extern const struct Curl_handler Curl_handler_pop3s;
#define POP3_TYPE_APOP 0x0002 #define POP3_TYPE_APOP 0x0002
#define POP3_TYPE_SASL 0x0004 #define POP3_TYPE_SASL 0x0004
/* Authentication type values */
#define POP3_TYPE_NONE 0
#define POP3_TYPE_ANY ~0
/* This is the 5-bytes End-Of-Body marker for POP3 */ /* This is the 5-bytes End-Of-Body marker for POP3 */
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" #define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
#define POP3_EOB_LEN 5 #define POP3_EOB_LEN 5