1
0
mirror of https://github.com/moparisthebest/curl synced 2025-02-28 17:31:46 -05:00

vauth/oauth2: Fix OAUTHBEARER token generation

OAUTHBEARER tokens were incorrectly generated in a format similar to
XOAUTH2 tokens. These changes make OAUTHBEARER tokens conform to the
RFC7628.

Fixes: #2487
Reported-by: Paolo Mossino

Closes https://github.com/curl/curl/pull/3377
This commit is contained in:
Mert Yazıcıoğlu 2018-12-16 15:45:40 +03:00 committed by Jay Satiro
parent d110d96b98
commit 6227e2bd07
15 changed files with 75 additions and 34 deletions

View File

@ -357,10 +357,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
sasl->authused = SASL_MECH_XOAUTH2; sasl->authused = SASL_MECH_XOAUTH2;
if(force_ir || data->set.sasl_ir) if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_oauth_bearer_message(data, conn->user, result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
NULL, 0, conn->oauth_bearer,
conn->oauth_bearer, &resp, &len);
&resp, &len);
} }
else if(enabledmechs & SASL_MECH_PLAIN) { else if(enabledmechs & SASL_MECH_PLAIN) {
mech = SASL_MECH_STRING_PLAIN; mech = SASL_MECH_STRING_PLAIN;
@ -562,10 +561,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
newstate = SASL_OAUTH2_RESP; newstate = SASL_OAUTH2_RESP;
} }
else else
result = Curl_auth_create_oauth_bearer_message(data, conn->user, result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
NULL, 0, conn->oauth_bearer,
conn->oauth_bearer, &resp, &len);
&resp, &len);
break; break;
case SASL_OAUTH2_RESP: case SASL_OAUTH2_RESP:

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -46,8 +46,8 @@
* *
* data[in] - The session handle. * data[in] - The session handle.
* user[in] - The user name. * user[in] - The user name.
* host[in] - The host name(for OAUTHBEARER). * host[in] - The host name.
* port[in] - The port(for OAUTHBEARER when not Port 80). * port[in] - The port(when not Port 80).
* bearer[in] - The bearer token. * bearer[in] - The bearer token.
* outptr[in / out] - The address where a pointer to newly allocated memory * outptr[in / out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion. * holding the result will be stored upon completion.
@ -66,13 +66,11 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
char *oauth = NULL; char *oauth = NULL;
/* Generate the message */ /* Generate the message */
if(host == NULL && (port == 0 || port == 80)) if(port == 0 || port == 80)
oauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); oauth = aprintf("n,a=%s,\1host=%s\1auth=Bearer %s\1\1", user, host,
else if(port == 0 || port == 80)
oauth = aprintf("user=%s\1host=%s\1auth=Bearer %s\1\1", user, host,
bearer); bearer);
else else
oauth = aprintf("user=%s\1host=%s\1port=%ld\1auth=Bearer %s\1\1", user, oauth = aprintf("n,a=%s,\1host=%s\1port=%ld\1auth=Bearer %s\1\1", user,
host, port, bearer); host, port, bearer);
if(!oauth) if(!oauth)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -84,3 +82,40 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
return result; return result;
} }
/*
* Curl_auth_create_xoauth_bearer_message()
*
* This is used to generate an already encoded XOAuth 2.0 message ready for
* sending to the recipient.
*
* Parameters:
*
* data[in] - The session handle.
* user[in] - The user name.
* bearer[in] - The bearer token.
* outptr[in / out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen[out] - The length of the output message.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data,
const char *user,
const char *bearer,
char **outptr, size_t *outlen)
{
CURLcode result = CURLE_OK;
/* Generate the message */
char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
if(!xoauth)
return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */
result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
free(xoauth);
return result;
}

View File

@ -151,6 +151,13 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
const long port, const long port,
const char *bearer, const char *bearer,
char **outptr, size_t *outlen); char **outptr, size_t *outlen);
/* This is used to generate a base64 encoded XOAuth 2.0 message */
CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data,
const char *user,
const char *bearer,
char **outptr, size_t *outlen);
#if defined(USE_KERBEROS5) #if defined(USE_KERBEROS5)
/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ /* This is used to evaluate if GSSAPI (Kerberos V5) is supported */
bool Curl_auth_is_gssapi_supported(void); bool Curl_auth_is_gssapi_supported(void);

View File

@ -15,7 +15,7 @@ RFC7628
<servercmd> <servercmd>
AUTH OAUTHBEARER AUTH OAUTHBEARER
REPLY AUTHENTICATE + REPLY AUTHENTICATE +
REPLY dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== A002 OK AUTHENTICATE completed REPLY bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== A002 OK AUTHENTICATE completed
</servercmd> </servercmd>
<data> <data>
From: me@somewhere From: me@somewhere
@ -53,7 +53,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<protocol> <protocol>
A001 CAPABILITY A001 CAPABILITY
A002 AUTHENTICATE OAUTHBEARER A002 AUTHENTICATE OAUTHBEARER
dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
A003 SELECT 842 A003 SELECT 842
A004 FETCH 1 BODY[] A004 FETCH 1 BODY[]
A005 LOGOUT A005 LOGOUT

View File

@ -53,7 +53,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<verify> <verify>
<protocol> <protocol>
A001 CAPABILITY A001 CAPABILITY
A002 AUTHENTICATE OAUTHBEARER dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== A002 AUTHENTICATE OAUTHBEARER bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
A003 SELECT 843 A003 SELECT 843
A004 FETCH 1 BODY[] A004 FETCH 1 BODY[]
A005 LOGOUT A005 LOGOUT

View File

@ -15,7 +15,8 @@ RFC7628
<servercmd> <servercmd>
AUTH OAUTHBEARER AUTH OAUTHBEARER
REPLY AUTHENTICATE + REPLY AUTHENTICATE +
REPLY dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== + eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxlX3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uIn0= REPLY bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== +
eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxlX3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uIn0=
REPLY AQ== A002 NO Authentication failed REPLY AQ== A002 NO Authentication failed
</servercmd> </servercmd>
</reply> </reply>
@ -52,7 +53,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<protocol> <protocol>
A001 CAPABILITY A001 CAPABILITY
A002 AUTHENTICATE OAUTHBEARER A002 AUTHENTICATE OAUTHBEARER
dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
AQ== AQ==
</protocol> </protocol>
</verify> </verify>

View File

@ -52,7 +52,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
# transfer and such a connection will not get a "LOGOUT" # transfer and such a connection will not get a "LOGOUT"
<protocol> <protocol>
A001 CAPABILITY A001 CAPABILITY
A002 AUTHENTICATE OAUTHBEARER dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== A002 AUTHENTICATE OAUTHBEARER bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMwFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
AQ== AQ==
</protocol> </protocol>
</verify> </verify>

View File

@ -17,7 +17,7 @@ RFC7628
<servercmd> <servercmd>
AUTH OAUTHBEARER AUTH OAUTHBEARER
REPLY AUTH + REPLY AUTH +
REPLY dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== +OK Login successful REPLY bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== +OK Login successful
</servercmd> </servercmd>
<data> <data>
From: me@somewhere From: me@somewhere
@ -55,7 +55,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<protocol> <protocol>
CAPA CAPA
AUTH OAUTHBEARER AUTH OAUTHBEARER
dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
RETR 887 RETR 887
QUIT QUIT
</protocol> </protocol>

View File

@ -54,7 +54,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<verify> <verify>
<protocol> <protocol>
CAPA CAPA
AUTH OAUTHBEARER dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== AUTH OAUTHBEARER bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
RETR 888 RETR 888
QUIT QUIT
</protocol> </protocol>

View File

@ -17,7 +17,7 @@ RFC7628
<servercmd> <servercmd>
AUTH OAUTHBEARER AUTH OAUTHBEARER
REPLY AUTH + REPLY AUTH +
REPLY dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== + eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxlX3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uIn0 REPLY bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== + eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxlX3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uIn0
REPLY AQ== -ERR Authentication failed REPLY AQ== -ERR Authentication failed
</servercmd> </servercmd>
</reply> </reply>
@ -54,7 +54,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<protocol> <protocol>
CAPA CAPA
AUTH OAUTHBEARER AUTH OAUTHBEARER
dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
AQ== AQ==
</protocol> </protocol>
</verify> </verify>

View File

@ -53,7 +53,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
# transfer and such a connection will not get a "QUIT" # transfer and such a connection will not get a "QUIT"
<protocol> <protocol>
CAPA CAPA
AUTH OAUTHBEARER dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== AUTH OAUTHBEARER bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwMQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
AQ== AQ==
</protocol> </protocol>
</verify> </verify>

View File

@ -16,7 +16,7 @@ RFC7628
<servercmd> <servercmd>
AUTH OAUTHBEARER AUTH OAUTHBEARER
REPLY AUTH 334 OAUTHBEARER supported REPLY AUTH 334 OAUTHBEARER supported
REPLY dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== 235 Authenticated REPLY bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== 235 Authenticated
</servercmd> </servercmd>
</reply> </reply>
@ -48,7 +48,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<protocol> <protocol>
EHLO 946 EHLO 946
AUTH OAUTHBEARER AUTH OAUTHBEARER
dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
MAIL FROM:<sender@example.com> MAIL FROM:<sender@example.com>
RCPT TO:<recipient@example.com> RCPT TO:<recipient@example.com>
DATA DATA

View File

@ -47,7 +47,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<verify> <verify>
<protocol> <protocol>
EHLO 947 EHLO 947
AUTH OAUTHBEARER dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== AUTH OAUTHBEARER bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
MAIL FROM:<sender@example.com> MAIL FROM:<sender@example.com>
RCPT TO:<recipient@example.com> RCPT TO:<recipient@example.com>
DATA DATA

View File

@ -16,7 +16,7 @@ RFC7628
<servercmd> <servercmd>
AUTH OAUTHBEARER AUTH OAUTHBEARER
REPLY AUTH 334 OAUTHBEARER supported REPLY AUTH 334 OAUTHBEARER supported
REPLY dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== 334 eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxlX3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uIn0 REPLY bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== 334 eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxlX3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uIn0
REPLY AQ== 535 Username and Password not accepted. Learn more at\r\n535 http://support.example.com/mail/oauth REPLY AQ== 535 Username and Password not accepted. Learn more at\r\n535 http://support.example.com/mail/oauth
</servercmd> </servercmd>
</reply> </reply>
@ -56,7 +56,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
<protocol> <protocol>
EHLO 948 EHLO 948
AUTH OAUTHBEARER AUTH OAUTHBEARER
dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
AQ== AQ==
</protocol> </protocol>
</verify> </verify>

View File

@ -55,7 +55,7 @@ perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP'
# transfer and such a connection will not get a "QUIT" # transfer and such a connection will not get a "QUIT"
<protocol> <protocol>
EHLO 949 EHLO 949
AUTH OAUTHBEARER dXNlcj11c2VyAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ== AUTH OAUTHBEARER bixhPXVzZXIsAWhvc3Q9MTI3LjAuMC4xAXBvcnQ9OTAwNQFhdXRoPUJlYXJlciBtRl85LkI1Zi00LjFKcU0BAQ==
AQ== AQ==
</protocol> </protocol>
</verify> </verify>