diff options
author | Steve Holme <steve_holme@hotmail.com> | 2015-09-05 18:35:47 +0100 |
---|---|---|
committer | Steve Holme <steve_holme@hotmail.com> | 2015-11-15 20:11:53 +0000 |
commit | ee04bee82b7186b7b1f84a741c33aed6bc9da31d (patch) | |
tree | 8b7184b393b001c7cc5d361974369b0e9adf90f5 /lib | |
parent | 6cfd646f58de245375b3ed706f0749cc52067002 (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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/curl_sasl.c | 32 | ||||
-rw-r--r-- | lib/curl_sasl.h | 1 |
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; |