diff options
| author | Linus Lewandowski <linus@lew21.net> | 2018-05-22 12:28:41 +0200 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2018-05-24 20:39:49 +0200 | 
| commit | 239a7061f83231f2bac362c6b817a5ae10bd6696 (patch) | |
| tree | 835fe4e25177200a55e0585eff00f6f97bafc1cc | |
| parent | 49fe65ccd81a2f27aae0e77e2714dc234de483c6 (diff) | |
httpauth: add support for Bearer tokens
Closes #2102
| -rw-r--r-- | docs/libcurl/opts/CURLOPT_HTTPAUTH.3 | 4 | ||||
| -rw-r--r-- | docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 | 8 | ||||
| -rw-r--r-- | docs/libcurl/symbols-in-versions | 1 | ||||
| -rw-r--r-- | include/curl/curl.h | 2 | ||||
| -rw-r--r-- | lib/http.c | 55 | ||||
| -rw-r--r-- | src/tool_getparam.c | 1 | ||||
| -rw-r--r-- | tests/data/Makefile.inc | 1 | ||||
| -rw-r--r-- | tests/data/test2074 | 57 | 
8 files changed, 124 insertions, 5 deletions
diff --git a/docs/libcurl/opts/CURLOPT_HTTPAUTH.3 b/docs/libcurl/opts/CURLOPT_HTTPAUTH.3 index 09a9f996a..7bb45506e 100644 --- a/docs/libcurl/opts/CURLOPT_HTTPAUTH.3 +++ b/docs/libcurl/opts/CURLOPT_HTTPAUTH.3 @@ -56,6 +56,10 @@ defined in RFC2617 and is a more secure way to do authentication over public  networks than the regular old-fashioned Basic method. The IE flavor is simply  that libcurl will use a special "quirk" that IE is known to have used before  version 7 and that some servers require the client to use. +.IP CURLAUTH_BEARER +HTTP Bearer token authentication, used primarily in OAuth 2.0 protocol. + +You can set the Bearer token to use with \fICURLOPT_XOAUTH2_BEARER(3)\fP.  .IP CURLAUTH_NEGOTIATE  HTTP Negotiate (SPNEGO) authentication. Negotiate authentication is defined  in RFC 4559 and is the most secure way to perform authentication over HTTP. diff --git a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 index 262c63764..8f86ae9ee 100644 --- a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 +++ b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 @@ -29,11 +29,11 @@ CURLOPT_XOAUTH2_BEARER \- specify OAuth 2.0 access token  CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);  .SH DESCRIPTION  Pass a char * as parameter, which should point to the zero terminated OAuth -2.0 Bearer Access Token for use with IMAP, POP3 and SMTP servers that support -the OAuth 2.0 Authorization Framework. +2.0 Bearer Access Token for use with HTTP, IMAP, POP3 and SMTP servers +that support the OAuth 2.0 Authorization Framework. -Note: The user name used to generate the Bearer Token should be supplied via -the \fICURLOPT_USERNAME(3)\fP option. +Note: For IMAP, POP3 and SMTP, the user name used to generate the Bearer Token +should be supplied via the \fICURLOPT_USERNAME(3)\fP option.  The application does not have to keep the string around after setting this  option. diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 7df2d700c..f98609e1d 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -15,6 +15,7 @@  CURLAUTH_ANY                    7.10.6  CURLAUTH_ANYSAFE                7.10.6  CURLAUTH_BASIC                  7.10.6 +CURLAUTH_BEARER                 7.61.0  CURLAUTH_DIGEST                 7.10.6  CURLAUTH_DIGEST_IE              7.19.3  CURLAUTH_GSSAPI                 7.55.0 diff --git a/include/curl/curl.h b/include/curl/curl.h index 42dfc78bc..3ebaa019a 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -691,6 +691,7 @@ typedef enum {   * CURLAUTH_NTLM         - HTTP NTLM authentication   * CURLAUTH_DIGEST_IE    - HTTP Digest authentication with IE flavour   * CURLAUTH_NTLM_WB      - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER       - HTTP Bearer token authentication   * CURLAUTH_ONLY         - Use together with a single other type to force no   *                         authentication or just that single type   * CURLAUTH_ANY          - All fine types set @@ -708,6 +709,7 @@ typedef enum {  #define CURLAUTH_NTLM         (((unsigned long)1)<<3)  #define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)  #define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5) +#define CURLAUTH_BEARER       (((unsigned long)1)<<6)  #define CURLAUTH_ONLY         (((unsigned long)1)<<31)  #define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)  #define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) diff --git a/lib/http.c b/lib/http.c index dac2b1417..0bcdf194d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -310,6 +310,31 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)    return result;  } +/* + * http_output_bearer() sets up an Authorization: header + * for HTTP Bearer authentication. + * + * Returns CURLcode. + */ +static CURLcode http_output_bearer(struct connectdata *conn) +{ +  char **userp; +  CURLcode result = CURLE_OK; + +  userp = &conn->allocptr.userpwd; +  free(*userp); +  *userp = aprintf("Authorization: Bearer %s\r\n", +                   conn->oauth_bearer); + +  if(!*userp) { +    result = CURLE_OUT_OF_MEMORY; +    goto fail; +  } + +  fail: +  return result; +} +  /* pickoneauth() selects the most favourable authentication method from the   * ones available and the ones we want.   * @@ -326,6 +351,8 @@ static bool pickoneauth(struct auth *pick)       of preference in case of the existence of multiple accepted types. */    if(avail & CURLAUTH_NEGOTIATE)      pick->picked = CURLAUTH_NEGOTIATE; +  else if(avail & CURLAUTH_BEARER) +    pick->picked = CURLAUTH_BEARER;    else if(avail & CURLAUTH_DIGEST)      pick->picked = CURLAUTH_DIGEST;    else if(avail & CURLAUTH_NTLM) @@ -628,6 +655,20 @@ output_auth_headers(struct connectdata *conn,         functions work that way */      authstatus->done = TRUE;    } +  if(authstatus->picked == CURLAUTH_BEARER) { +    /* Bearer */ +    if((!proxy && conn->oauth_bearer && +        !Curl_checkheaders(conn, "Authorization:"))) { +      auth = "Bearer"; +      result = http_output_bearer(conn); +      if(result) +        return result; +    } + +    /* NOTE: this function should set 'done' TRUE, as the other auth +       functions work that way */ +    authstatus->done = TRUE; +  }    if(auth) {      infof(data, "%s auth using %s with user '%s'\n", @@ -674,7 +715,7 @@ Curl_http_output_auth(struct connectdata *conn,    authproxy = &data->state.authproxy;    if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || -     conn->bits.user_passwd) +     conn->bits.user_passwd || conn->oauth_bearer)      /* continue please */;    else {      authhost->done = TRUE; @@ -883,6 +924,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,                data->state.authproblem = TRUE;              }            } +          else +            if(checkprefix("Bearer", auth)) { +              *availp |= CURLAUTH_BEARER; +              authp->avail |= CURLAUTH_BEARER; +              if(authp->picked == CURLAUTH_BEARER) { +                /* We asked for Bearer authentication but got a 40X back +                  anyway, which basically means our token isn't valid. */ +                authp->avail = CURLAUTH_NONE; +                infof(data, "Authentication problem. Ignoring this.\n"); +                data->state.authproblem = TRUE; +              } +            }      /* there may be multiple methods on one line, so keep reading */      while(*auth && *auth != ',') /* read up to the next comma */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 4b9ae0653..e83373c37 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -601,6 +601,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */          break;        case 'B': /* OAuth 2.0 bearer token */          GetStr(&config->oauth_bearer, nextarg); +        config->authtype |= CURLAUTH_BEARER;          break;        case 'c': /* connect-timeout */          err = str2udouble(&config->connecttimeout, nextarg, diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 2d811694d..bce8c9798 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -196,5 +196,6 @@ test2056 test2057 test2058 test2059 test2060 test2061 test2062 test2063 \  test2064 test2065 test2066 test2067 test2068 test2069 \  \  test2070 test2071 test2072 test2073 \ +test2074 \  \  test3000 test3001 diff --git a/tests/data/test2074 b/tests/data/test2074 new file mode 100644 index 000000000..ecff8fe7e --- /dev/null +++ b/tests/data/test2074 @@ -0,0 +1,57 @@ +<testcase> +<info> +<keywords> +HTTP +HTTP GET +AUTH OAUTHBEARER +</keywords> +</info> + +# +# Server-side +<reply> +<data> +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- +</data> +</reply> + +# +# Client-side +<client> +<server> +http +</server> + <name> +HTTP GET + </name> + <command> +http://%HOSTIP:%HTTPPORT/2074 --oauth2-bearer mF_9.B5f-4.1JqM +</command> +</client> + +# +# Verify data after the test has been "shot" +<verify> +<strip> +^User-Agent:.* +</strip> +<protocol> +GET /2074 HTTP/1.1
 +Host: %HOSTIP:%HTTPPORT
 +Authorization: Bearer mF_9.B5f-4.1JqM
 +Accept: */*
 +
 +</protocol> +</verify> +</testcase>  | 
