aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Holme <steve_holme@hotmail.com>2013-09-20 21:56:34 +0100
committerSteve Holme <steve_holme@hotmail.com>2013-09-20 21:56:30 +0100
commit18db7438512de1d6f63c616af5755ea2859597b8 (patch)
tree72c5678f29d94dd175dc78c9a46b04e8a2f83da4
parent0e188e2dc339c6667eb954682a2bf768c6419aa9 (diff)
pop3: Added basic SASL XOAUTH2 support
Added the ability to use an XOAUTH2 bearer token [RFC6750] with POP3 for authentication using RFC6749 "OAuth 2.0 Authorization Framework". The bearer token is expected to be valid for the user specified in conn->user. If CURLOPT_XOAUTH2_BEARER is defined and the connection has an advertised auth mechanism of "XOAUTH2", the user and access token are formatted as a base64 encoded string and sent to the server as "AUTH XOAUTH2 <bearer token>".
-rw-r--r--RELEASE-NOTES2
-rw-r--r--docs/curl.16
-rw-r--r--docs/libcurl/curl_easy_setopt.34
-rw-r--r--lib/pop3.c64
-rw-r--r--lib/pop3.h1
-rw-r--r--src/tool_help.c2
6 files changed, 71 insertions, 8 deletions
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 203b7fb25..50e3a91c7 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -13,7 +13,7 @@ This release includes the following changes:
o CURLM_ADDED_ALREADY: new error code
o test TFTP server: support "writedelay" within <servercmd>
o krb4 support has been removed
- o imap and smtp: added basic SASL XOAUTH2 support [9]
+ o imap/pop3/smtp: added basic SASL XOAUTH2 support [9]
o darwinssl: add support for PKCS#12 files for client authentication
o Pass password to OpenSSL engine by user interface [15]
diff --git a/docs/curl.1 b/docs/curl.1
index 3ce2bfab0..6061f93ac 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -174,9 +174,9 @@ since it may require data to be sent twice and then the client must be able to
rewind. If the need should arise when uploading from stdin, the upload
operation will fail.
.IP "--bearer"
-(IMAP/SMTP) Specify the Bearer Token for OAUTH 2.0 server authentication. The
-Bearer Token is used in conjuction with the user name which can be specified
-as part of the \fI--url\fP option or the \fI-u, --user\fP option.
+(IMAP/POP3/SMTP) Specify the Bearer Token for OAUTH 2.0 server authentication.
+The Bearer Token is used in conjuction with the user name which can be
+specified as part of the \fI--url\fP or \fI-u, --user\fP options.
The Bearer Token and user name are formatted according to RFC 6750.
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index a2b40e0c3..a8d764f07 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -1304,8 +1304,8 @@ as libcurl can determine the feature itself when the server supports the
SASL-IR CAPABILITY.
.IP CURLOPT_BEARER
Pass a char * as parameter, which should point to the zero terminated OAUTH
-2.0 Bearer Access Token for use with IMAP and SMTP servers that support the
-OAUTH 2.0 Authorization Framework. (Added in 7.33.0)
+2.0 Bearer Access Token for use with IMAP. POP3 and SMTP servers that support
+the OAUTH 2.0 Authorization Framework. (Added in 7.33.0)
Note: The user name used to generate the Bearer Token should be supplied via
the \fICURLOPT_USERNAME\fP option.
diff --git a/lib/pop3.c b/lib/pop3.c
index f33b189d1..bb3ed31cc 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -28,6 +28,7 @@
* RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication
* RFC5034 POP3 SASL Authentication Mechanism
+ * RFC6749 OAuth 2.0 Authorization Framework
*
***************************************************************************/
@@ -326,6 +327,8 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
pop3c->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
pop3c->authmechs |= SASL_MECH_NTLM;
+ else if(wordlen == 7 && !memcmp(line, "XOAUTH2", 7))
+ pop3c->authmechs |= SASL_MECH_XOAUTH2;
line += wordlen;
len -= wordlen;
@@ -371,6 +374,7 @@ static void state(struct connectdata *conn, pop3state newstate)
"AUTH_DIGESTMD5_RESP",
"AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG",
+ "AUTH_XOAUTH2",
"AUTH_FINAL",
"APOP",
"USER",
@@ -599,7 +603,20 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
}
else
#endif
- if((pop3c->authmechs & SASL_MECH_LOGIN) &&
+ if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
+ (pop3c->prefmech & SASL_MECH_XOAUTH2) &&
+ (pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
+ mech = "XOAUTH2";
+ state1 = POP3_AUTH_XOAUTH2;
+ state2 = POP3_AUTH_FINAL;
+ pop3c->authused = SASL_MECH_XOAUTH2;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
+ conn->xoauth2_bearer,
+ &initresp, &len);
+ }
+ else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
(pop3c->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
state1 = POP3_AUTH_LOGIN;
@@ -1110,6 +1127,43 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
}
#endif
+/* For AUTH XOAUTH2 (without initial response) responses */
+static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
+ int pop3code, pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *xoauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
+ conn->xoauth2_bearer,
+ &xoauth, &len);
+
+ /* Send the message */
+ if(!result) {
+ if(xoauth) {
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+
+ Curl_safefree(xoauth);
+ }
+ }
+
+ return result;
+}
+
/* For final responses to the AUTH sequence */
static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
int pop3code,
@@ -1328,6 +1382,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
break;
#endif
+ case POP3_AUTH_XOAUTH2:
+ result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
+ break;
+
case POP3_AUTH_FINAL:
result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
break;
@@ -1754,6 +1812,10 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_NTLM;
}
+ else if(strequal(value, "XOAUTH2")) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech = SASL_MECH_XOAUTH2;
+ }
else {
pop3c->preftype = POP3_TYPE_NONE;
pop3c->prefmech = SASL_AUTH_NONE;
diff --git a/lib/pop3.h b/lib/pop3.h
index 0186e0435..7bc774495 100644
--- a/lib/pop3.h
+++ b/lib/pop3.h
@@ -43,6 +43,7 @@ typedef enum {
POP3_AUTH_DIGESTMD5_RESP,
POP3_AUTH_NTLM,
POP3_AUTH_NTLM_TYPE2MSG,
+ POP3_AUTH_XOAUTH2,
POP3_AUTH_FINAL,
POP3_APOP,
POP3_USER,
diff --git a/src/tool_help.c b/src/tool_help.c
index bd3cbb8a9..81f3bcdd7 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -47,7 +47,7 @@ static const char *const helptext[] = {
" --anyauth Pick \"any\" authentication method (H)",
" -a, --append Append to target file when uploading (F/SFTP)",
" --basic Use HTTP Basic Authentication (H)",
- " --bearer BEARER XOAUTH2 Bearer Token (IMAP and SMTP)",
+ " --bearer BEARER XOAUTH2 Bearer Token (IMAP, POP3, SMTP)",
" --cacert FILE CA certificate to verify peer against (SSL)",
" --capath DIR CA directory to verify peer against (SSL)",
" -E, --cert CERT[:PASSWD] Client certificate file and password (SSL)",