diff options
| author | Kamil Dudka <kdudka@redhat.com> | 2017-04-27 15:18:49 +0200 | 
|---|---|---|
| committer | Kamil Dudka <kdudka@redhat.com> | 2017-06-28 08:02:58 +0200 | 
| commit | 8924f58c370afa756fc4fd13916dfdea91d21b21 (patch) | |
| tree | 3a4787e4a02182513e80e356b3a6ce79cb876496 | |
| parent | cd1c9f08078d4a8566ed10f6df9ae9a729f3290b (diff) | |
CURLOPT_SOCKS5_AUTH: allowed methods for SOCKS5 proxy auth
If libcurl was built with GSS-API support, it unconditionally advertised
GSS-API authentication while connecting to a SOCKS5 proxy.  This caused
problems in environments with improperly configured Kerberos: a stock
libcurl failed to connect, despite libcurl built without GSS-API
connected fine using username and password.
This commit introduces the CURLOPT_SOCKS5_AUTH option to control the
allowed methods for SOCKS5 authentication at run time.
Note that a new option was preferred over reusing CURLOPT_PROXYAUTH
for compatibility reasons because the set of authentication methods
allowed by default was different for HTTP and SOCKS5 proxies.
Bug: https://curl.haxx.se/mail/lib-2017-01/0005.html
Closes https://github.com/curl/curl/pull/1454
| -rw-r--r-- | docs/libcurl/curl_easy_setopt.3 | 2 | ||||
| -rw-r--r-- | docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3 | 63 | ||||
| -rw-r--r-- | docs/libcurl/symbols-in-versions | 2 | ||||
| -rw-r--r-- | include/curl/curl.h | 5 | ||||
| -rw-r--r-- | lib/socks.c | 27 | ||||
| -rw-r--r-- | lib/url.c | 8 | ||||
| -rw-r--r-- | lib/urldata.h | 1 | 
7 files changed, 99 insertions, 9 deletions
| diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index bf3a0f268..26f73ee14 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -173,6 +173,8 @@ Filter out hosts from proxy use. \fICURLOPT_NOPROXY(3)\fP  Tunnel through the HTTP proxy. \fICURLOPT_HTTPPROXYTUNNEL(3)\fP  .IP CURLOPT_CONNECT_TO  Connect to a specific host and port. See \fICURLOPT_CONNECT_TO(3)\fP +.IP CURLOPT_SOCKS5_AUTH +Socks5 authentication methods. See \fICURLOPT_SOCKS5_AUTH(3)\fP  .IP CURLOPT_SOCKS5_GSSAPI_SERVICE  Socks5 GSSAPI service name. \fICURLOPT_SOCKS5_GSSAPI_SERVICE(3)\fP  .IP CURLOPT_SOCKS5_GSSAPI_NEC diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3 new file mode 100644 index 000000000..7b5e5822b --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3 @@ -0,0 +1,63 @@ +.\" ************************************************************************** +.\" *                                  _   _ ____  _ +.\" *  Project                     ___| | | |  _ \| | +.\" *                             / __| | | | |_) | | +.\" *                            | (__| |_| |  _ <| |___ +.\" *                             \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. +.\" * +.\" * This software is licensed as described in the file COPYING, which +.\" * you should have received as part of this distribution. The terms +.\" * are also available at https://curl.haxx.se/docs/copyright.html. +.\" * +.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell +.\" * copies of the Software, and permit persons to whom the Software is +.\" * furnished to do so, under the terms of the COPYING file. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" ************************************************************************** +.\" +.TH CURLOPT_SOCKS5_AUTH 3 "27 April 2017" "libcurl 7.55.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_SOCKS5_AUTH \- set allowed methods for SOCKS5 proxy authentication +.SH SYNOPSIS +#include <curl/curl.h> + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask); +.SH DESCRIPTION +Pass a long as parameter, which is set to a bitmask, to tell libcurl which +authentication method(s) are allowed for SOCKS5 proxy authentication.  The only +supported flags are \fICURLAUTH_BASIC\fP, which allows username/password +authentication, \fICURLAUTH_GSSAPI\fP, which allows GSS-API authentication, and +\fICURLAUTH_NONE\fP, which allows no authentication.  Set the actual user name +and password with the \fICURLOPT_PROXYUSERPWD(3)\fP option. +.SH DEFAULT +CURLAUTH_BASIC|CURLAUTH_GSSAPI +.SH PROTOCOLS +All +.SH EXAMPLE +.nf +CURL *curl = curl_easy_init(); +if(curl) { +  curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); + +  /* request to use a SOCKS5 proxy */ +  curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://user:pass@myproxy.com"); + +  /* enable username/password authentication only */ +  curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, CURLAUTH_BASIC); + +  /* Perform the request */ +  curl_easy_perform(curl); +} +.fi +.SH AVAILABILITY +Added in 7.55.0 +.SH RETURN VALUE +Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or +CURLE_NOT_BUILT_IN if the bitmask contains unsupported flags. +.SH "SEE ALSO" +.BR CURLOPT_PROXY "(3), " CURLOPT_PROXYTYPE "(3)" diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index b1a671cd1..e141b6a57 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -17,6 +17,7 @@ CURLAUTH_ANYSAFE                7.10.6  CURLAUTH_BASIC                  7.10.6  CURLAUTH_DIGEST                 7.10.6  CURLAUTH_DIGEST_IE              7.19.3 +CURLAUTH_GSSAPI                 7.55.0  CURLAUTH_GSSNEGOTIATE           7.10.6       7.38.0  CURLAUTH_NEGOTIATE              7.38.0  CURLAUTH_NONE                   7.10.6 @@ -527,6 +528,7 @@ CURLOPT_SERVICE_NAME            7.43.0  CURLOPT_SHARE                   7.10  CURLOPT_SOCKOPTDATA             7.16.0  CURLOPT_SOCKOPTFUNCTION         7.16.0 +CURLOPT_SOCKS5_AUTH             7.55.0  CURLOPT_SOCKS5_GSSAPI_NEC       7.19.4  CURLOPT_SOCKS5_GSSAPI_SERVICE   7.19.4        7.49.0  CURLOPT_SOURCE_HOST             7.12.1        -           7.15.5 diff --git a/include/curl/curl.h b/include/curl/curl.h index 0b741e82d..82fb8aeb8 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -677,6 +677,8 @@ typedef enum {  #define CURLAUTH_NEGOTIATE    (((unsigned long)1)<<2)  /* Deprecated since the advent of CURLAUTH_NEGOTIATE */  #define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE  #define CURLAUTH_NTLM         (((unsigned long)1)<<3)  #define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)  #define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5) @@ -1783,6 +1785,9 @@ typedef enum {    /* The request target, instead of extracted from the URL */    CINIT(REQUEST_TARGET, STRINGPOINT, 266), +  /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ +  CINIT(SOCKS5_AUTH, LONG, 267), +    CURLOPT_LASTENTRY /* the last unused */  } CURLoption; diff --git a/lib/socks.c b/lib/socks.c index 968b720b7..000cd9c2d 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -387,6 +387,8 @@ CURLcode Curl_SOCKS5(const char *proxy_user,      (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;    const size_t hostname_len = strlen(hostname);    ssize_t len = 0; +  const unsigned long auth = data->set.socks5auth; +  bool allow_gssapi = FALSE;    if(conn->bits.httpproxy)      infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", @@ -427,13 +429,24 @@ CURLcode Curl_SOCKS5(const char *proxy_user,      return CURLE_COULDNT_CONNECT;    } +  if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) +    infof(conn->data, +        "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", +        auth); +  if(!(auth & CURLAUTH_BASIC)) +    /* disable username/password auth */ +    proxy_user = NULL; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) +  if(auth & CURLAUTH_GSSAPI) +    allow_gssapi = TRUE; +#endif +    idx = 0;    socksreq[idx++] = 5;   /* version */    idx++;                 /* reserve for the number of authentication methods */    socksreq[idx++] = 0;   /* no authentication */ -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) -  socksreq[idx++] = 1;   /* GSS-API */ -#endif +  if(allow_gssapi) +    socksreq[idx++] = 1; /* GSS-API */    if(proxy_user)      socksreq[idx++] = 2; /* username/password */    /* write the number of authentication methods */ @@ -485,7 +498,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,      ;    }  #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) -  else if(socksreq[1] == 1) { +  else if(allow_gssapi && (socksreq[1] == 1)) {      code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);      if(code) {        failf(data, "Unable to negotiate SOCKS5 GSS-API context."); @@ -546,16 +559,12 @@ CURLcode Curl_SOCKS5(const char *proxy_user,    }    else {      /* error */ -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) -    if(socksreq[1] == 255) { -#else -    if(socksreq[1] == 1) { +    if(!allow_gssapi && (socksreq[1] == 1)) {        failf(data,              "SOCKS5 GSSAPI per-message authentication is not supported.");        return CURLE_COULDNT_CONNECT;      }      if(socksreq[1] == 255) { -#endif        if(!proxy_user || !*proxy_user) {          failf(data,                "No authentication method was acceptable. (It is quite likely" @@ -545,6 +545,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)    set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */    set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ +  /* SOCKS5 proxy auth defaults to username/password + GSS-API */ +  set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI; +    /* make libcurl quiet by default: */    set->hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */ @@ -1541,6 +1544,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,      break;  #endif   /* CURL_DISABLE_PROXY */ +  case CURLOPT_SOCKS5_AUTH: +    data->set.socks5auth = va_arg(param, unsigned long); +    if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) +      result = CURLE_NOT_BUILT_IN; +    break;  #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)    case CURLOPT_SOCKS5_GSSAPI_NEC:      /* diff --git a/lib/urldata.h b/lib/urldata.h index 8c4a029fe..e89d1d706 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1615,6 +1615,7 @@ struct UserDefined {    long use_port;     /* which port to use (when not using default) */    unsigned long httpauth;  /* kind of HTTP authentication to use (bitmask) */    unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */ +  unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */    long followlocation; /* as in HTTP Location: */    long maxredirs;    /* maximum no. of http(s) redirects to follow, set to -1                          for infinity */ | 
