aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Holme <steve_holme@hotmail.com>2015-09-05 18:35:47 +0100
committerSteve Holme <steve_holme@hotmail.com>2015-11-15 20:11:53 +0000
commitee04bee82b7186b7b1f84a741c33aed6bc9da31d (patch)
tree8b7184b393b001c7cc5d361974369b0e9adf90f5
parent6cfd646f58de245375b3ed706f0749cc52067002 (diff)
oauth2: Support OAUTHBEARER failures sent as continuation responses
According to RFC7628 a failure message may be sent by the server in a base64 encoded JSON string as a continuation response. Currently only implemented for OAUTHBEARER and not XAUTH2.
-rw-r--r--lib/curl_sasl.c32
-rw-r--r--lib/curl_sasl.h1
2 files changed, 31 insertions, 2 deletions
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 956801b71..05b201a14 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -1346,6 +1346,7 @@ static void state(struct SASL *sasl, struct connectdata *conn,
"GSSAPI_TOKEN",
"GSSAPI_NO_DATA",
"OAUTH2",
+ "OAUTH2_RESP",
"CANCEL",
"FINAL",
/* LAST */
@@ -1459,6 +1460,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) {
mech = SASL_MECH_STRING_OAUTHBEARER;
state1 = SASL_OAUTH2;
+ state2 = SASL_OAUTH2_RESP;
sasl->authused = SASL_MECH_OAUTHBEARER;
if(force_ir || data->set.sasl_ir)
@@ -1549,7 +1551,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
return result;
}
- if(sasl->state != SASL_CANCEL && code != sasl->params->contcode) {
+ if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
+ code != sasl->params->contcode) {
*progress = SASL_DONE;
state(sasl, conn, SASL_STOP);
return CURLE_LOGIN_DENIED;
@@ -1654,18 +1657,43 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
case SASL_OAUTH2:
/* Create the authorisation message */
- if(sasl->authused == SASL_MECH_OAUTHBEARER)
+ if(sasl->authused == SASL_MECH_OAUTHBEARER) {
result = sasl_create_oauth_bearer_message(data, conn->user,
conn->host.name,
conn->port,
conn->oauth_bearer,
&resp, &len);
+
+ /* Failures maybe sent by the server as continuations for OAUTHBEARER */
+ newstate = SASL_OAUTH2_RESP;
+ }
else
result = sasl_create_oauth_bearer_message(data, conn->user,
NULL, 0,
conn->oauth_bearer,
&resp, &len);
break;
+
+ case SASL_OAUTH2_RESP:
+ /* The continuation is optional so check the response code */
+ if (code == sasl->params->finalcode) {
+ /* Final response was received so we are done */
+ *progress = SASL_DONE;
+ state(sasl, conn, SASL_STOP);
+ return result;
+ }
+ else if (code == sasl->params->contcode) {
+ /* Acknowledge the continuation by sending a 0x01 response base64 encoded */
+ if (!(resp = strdup("AQ==")))
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ else {
+ *progress = SASL_DONE;
+ state(sasl, conn, SASL_STOP);
+ return CURLE_LOGIN_DENIED;
+ }
+
case SASL_CANCEL:
/* Remove the offending mechanism from the supported list */
sasl->authmechs ^= sasl->authused;
diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h
index fb44ac265..2a8cc35c7 100644
--- a/lib/curl_sasl.h
+++ b/lib/curl_sasl.h
@@ -92,6 +92,7 @@ typedef enum {
SASL_GSSAPI_TOKEN,
SASL_GSSAPI_NO_DATA,
SASL_OAUTH2,
+ SASL_OAUTH2_RESP,
SASL_CANCEL,
SASL_FINAL
} saslstate;