Commit 8924f58c authored by Kamil Dudka's avatar Kamil Dudka
Browse files

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
parent cd1c9f08
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+63 −0
Original line number Diff line number Diff line
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  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)"
+2 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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;

+18 −9
Original line number Diff line number Diff line
@@ -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)
  if(allow_gssapi)
    socksreq[idx++] = 1; /* GSS-API */
#endif
  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"
Loading