From 59eaaed3168f49e8a7a3821730277aff68a86d16 Mon Sep 17 00:00:00 2001 From: drons Date: Fri, 10 Nov 2023 22:18:42 +0300 Subject: [PATCH] /vsicurl: add ANYSAFE & BEARER to auth methods (#8683) --- autotest/gcore/vsicurl.py | 19 ++++++++++++++++++ doc/source/user/configoptions.rst | 17 ++++++++++++++-- port/cpl_http.cpp | 32 ++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/autotest/gcore/vsicurl.py b/autotest/gcore/vsicurl.py index 64f494885182..4c3ff47229d9 100755 --- a/autotest/gcore/vsicurl.py +++ b/autotest/gcore/vsicurl.py @@ -1088,3 +1088,22 @@ def test_vsicurl_NETRC_FILE(): pytest.skip("got exception %s" % str(e)) assert "/i_do/not_exist" in err + + +############################################################################### +# Check auth with bearer token + + +def test_vsicurl_bearer(): + if gdaltest.is_travis_branch("ubuntu_1804") or gdaltest.is_travis_branch( + "ubuntu_1804_32bit" + ): + pytest.skip("Too old libcurl version, requires at least 7.61.0") + token = "myuniqtok" + with gdal.config_options({"GDAL_HTTP_AUTH": "BEARER", "GDAL_HTTP_BEARER": token}): + f = gdal.VSIFOpenL("/vsicurl/http://httpbin.org/bearer", "rb") + gdal.VSIFSeekL(f, 0, 2) + vsilen = gdal.VSIFTellL(f) + gdal.VSIFSeekL(f, 0, 0) + data = gdal.VSIFReadL(1, vsilen, f).decode("ascii") + assert token in data diff --git a/doc/source/user/configoptions.rst b/doc/source/user/configoptions.rst index 296f2b7cdfc7..f3c7f0703b5b 100644 --- a/doc/source/user/configoptions.rst +++ b/doc/source/user/configoptions.rst @@ -812,7 +812,7 @@ Networking options into a single request. - .. config:: GDAL_HTTP_AUTH - :choices: BASIC, NTLM, GSSNEGOTIATE, ANY + :choices: BASIC, NTLM, NEGOTIATE, ANY, ANYSAFE, BEARER Set value to tell libcurl which authentication method(s) you want it to use. See http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTHTTPAUTH @@ -829,6 +829,19 @@ Networking options this: "domain/user:password" or "domain\user:password". Some HTTP servers (on Windows) support this style even for Basic authentication. +- .. config:: GDAL_GSSAPI_DELEGATION + :since: 3.3 + :choices: NONE, POLICY, ALWAYS + + Set allowed GSS-API delegation. Relevant only with + :config:`GDAL_HTTP_AUTH=NEGOTIATE`. + +- .. config:: GDAL_HTTP_BEARER + :since: 3.9 + + Set HTTP OAuth 2.0 Bearer Access Token to use for the connection. Must be used + with :config:`GDAL_HTTP_AUTH=BEARER`. + - .. config:: GDAL_HTTP_PROXY Set HTTP proxy to use. The parameter should be the host name or dotted IP @@ -852,7 +865,7 @@ Networking options in the form of [user name]:[password]. - .. config:: GDAL_PROXY_AUTH - :choices: BASIC, NTLM, DIGEST, ANY + :choices: BASIC, NTLM, NEGOTIATE, DIGEST, ANY, ANYSAFE Set value to to tell libcurl which authentication method(s) you want it to use for your proxy authentication. See diff --git a/port/cpl_http.cpp b/port/cpl_http.cpp index a0498c8ef7bd..42175f644ec8 100644 --- a/port/cpl_http.cpp +++ b/port/cpl_http.cpp @@ -551,6 +551,7 @@ constexpr TupleEnvVarOptionName asAssocEnvVarOptionName[] = { {"GDAL_HTTP_HEADER_FILE", "HEADER_FILE"}, {"GDAL_HTTP_AUTH", "HTTPAUTH"}, {"GDAL_GSSAPI_DELEGATION", "GSSAPI_DELEGATION"}, + {"GDAL_HTTP_BEARER", "HTTP_BEARER"}, {"GDAL_HTTP_COOKIE", "COOKIE"}, {"GDAL_HTTP_COOKIEFILE", "COOKIEFILE"}, {"GDAL_HTTP_COOKIEJAR", "COOKIEJAR"}, @@ -966,12 +967,14 @@ int CPLHTTPPopFetchCallback(void) * For example "Accept: application/x-ogcwkt" *
  • HEADER_FILE=filename: filename of a text file with "key: value" headers. * (GDAL >= 2.2)
  • - *
  • HTTPAUTH=[BASIC/NTLM/NEGOTIATE/ANY] to specify an authentication scheme - * to use.
  • + *
  • HTTPAUTH=[BASIC/NTLM/NEGOTIATE/ANY/ANYSAFE/BEARER] to specify an + * authentication scheme to use.
  • *
  • USERPWD=userid:password to specify a user and password for * authentication
  • *
  • GSSAPI_DELEGATION=[NONE/POLICY/ALWAYS] set allowed * GSS-API delegation. Relevant only with HTTPAUTH=NEGOTIATE (GDAL >= 3.3).
  • + *
  • HTTP_BEARER=val set OAuth 2.0 Bearer Access Token. + * Relevant only with HTTPAUTH=BEARER (GDAL >= 3.8).
  • *
  • POSTFIELDS=val, where val is a nul-terminated string to be passed to the * server with a POST request.
  • *
  • PROXY=val, to make requests go through a @@ -982,7 +985,7 @@ int CPLHTTPPopFetchCallback(void) * only for HTTPS URLs.
  • *
  • PROXYUSERPWD=val, where val is of the form * username:password
  • - *
  • PROXYAUTH=[BASIC/NTLM/DIGEST/NEGOTIATE/ANY] to + *
  • PROXYAUTH=[BASIC/NTLM/DIGEST/NEGOTIATE/ANY/ANYSAFE] to * specify an proxy authentication scheme to use.
  • *
  • NETRC=[YES/NO] to * enable or disable use of $HOME/.netrc (or NETRC_FILE), default YES.
  • @@ -1054,7 +1057,7 @@ int CPLHTTPPopFetchCallback(void) * CONNECTTIMEOUT, TIMEOUT, * LOW_SPEED_TIME, LOW_SPEED_LIMIT, USERPWD, PROXY, HTTPS_PROXY, PROXYUSERPWD, * PROXYAUTH, NETRC, NETRC_FILE, MAX_RETRY and RETRY_DELAY, HEADER_FILE, HTTP_VERSION, - * SSL_VERIFYSTATUS, USE_CAPI_STORE, GSSAPI_DELEGATION, TCP_KEEPALIVE, + * SSL_VERIFYSTATUS, USE_CAPI_STORE, GSSAPI_DELEGATION, HTTP_BEARER, TCP_KEEPALIVE, * TCP_KEEPIDLE, TCP_KEEPINTVL, USERAGENT, SSLCERT, SSLCERTTYPE, SSLKEY, * KEYPASSWD values are searched in the configuration options * respectively named GDAL_HTTP_CONNECTTIMEOUT, GDAL_HTTP_TIMEOUT, @@ -1062,7 +1065,7 @@ int CPLHTTPPopFetchCallback(void) * GDAL_HTTP_PROXY, GDAL_HTTPS_PROXY, GDAL_HTTP_PROXYUSERPWD, GDAL_PROXY_AUTH, * GDAL_HTTP_NETRC, GDAL_HTTP_NETC_FILE, GDAL_HTTP_MAX_RETRY, GDAL_HTTP_RETRY_DELAY, * GDAL_HTTP_HEADER_FILE, GDAL_HTTP_VERSION, GDAL_HTTP_SSL_VERIFYSTATUS, - * GDAL_HTTP_USE_CAPI_STORE, GDAL_GSSAPI_DELEGATION, + * GDAL_HTTP_USE_CAPI_STORE, GDAL_GSSAPI_DELEGATION, GDAL_HTTP_BEARER, * GDAL_HTTP_TCP_KEEPALIVE, GDAL_HTTP_TCP_KEEPIDLE, GDAL_HTTP_TCP_KEEPINTVL, * GDAL_HTTP_USERAGENT, GDAL_HTTP_SSLCERT, GDAL_HTTP_SSLCERTTYPE, * GDAL_HTTP_SSLKEY and GDAL_HTTP_KEYPASSWD. @@ -2146,6 +2149,22 @@ void *CPLHTTPSetOptions(void *pcurl, const char *pszURL, CURLAUTH_NTLM); else if (EQUAL(pszHttpAuth, "ANY")) unchecked_curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + else if (EQUAL(pszHttpAuth, "ANYSAFE")) + unchecked_curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, + CURLAUTH_ANYSAFE); +#ifdef CURLAUTH_BEARER + else if (EQUAL(pszHttpAuth, "BEARER")) + { + const char *pszBearer = CSLFetchNameValue(papszOptions, "HTTP_BEARER"); + if (pszBearer == nullptr) + pszBearer = CPLGetConfigOption("GDAL_HTTP_BEARER", nullptr); + if (pszBearer != nullptr) + unchecked_curl_easy_setopt(http_handle, CURLOPT_XOAUTH2_BEARER, + pszBearer); + unchecked_curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, + CURLAUTH_BEARER); + } +#endif // CURLAUTH_BEARER #ifdef CURLAUTH_NEGOTIATE else if (EQUAL(pszHttpAuth, "NEGOTIATE")) unchecked_curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, @@ -2253,6 +2272,9 @@ void *CPLHTTPSetOptions(void *pcurl, const char *pszURL, else if (EQUAL(pszProxyAuth, "ANY")) unchecked_curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + else if (EQUAL(pszProxyAuth, "ANYSAFE")) + unchecked_curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, + CURLAUTH_ANYSAFE); #ifdef CURLAUTH_NEGOTIATE else if (EQUAL(pszProxyAuth, "NEGOTIATE")) unchecked_curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH,