gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnurl] 10/411: CURLE_PROXY: new error code


From: gnunet
Subject: [gnurl] 10/411: CURLE_PROXY: new error code
Date: Wed, 13 Jan 2021 01:17:05 +0100

This is an automated email from the git hooks/post-receive script.

nikita pushed a commit to branch master
in repository gnurl.

commit 88b1ca7cba5c94b11c3a6510146ba410e8858771
Author: Daniel Stenberg <daniel@haxx.se>
AuthorDate: Mon Aug 24 08:39:29 2020 +0200

    CURLE_PROXY: new error code
    
    Failures clearly returned from a (SOCKS) proxy now causes this return
    code. Previously the situation was not very clear as what would be
    returned and when.
    
    In addition: when this error code is returned, an application can use
    CURLINFO_PROXY_ERROR to query libcurl for the detailed error, which then
    returns a value from the new 'CURLproxycode' enum.
    
    Closes #5770
---
 docs/libcurl/curl_easy_getinfo.3         |   3 +
 docs/libcurl/opts/CURLINFO_PROXY_ERROR.3 | 104 +++++++++++++++++++
 docs/libcurl/opts/Makefile.inc           |   3 +-
 docs/libcurl/symbols-in-versions         |  36 +++++++
 include/curl/curl.h                      |  46 ++++++++-
 lib/connect.c                            |  14 ++-
 lib/getinfo.c                            |   3 +
 lib/socks.c                              | 165 ++++++++++++++++++-------------
 lib/socks.h                              |  26 ++---
 lib/strerror.c                           |   3 +
 lib/urldata.h                            |   1 +
 tests/data/test1538                      |   3 +-
 tests/data/test702                       |   2 +-
 tests/data/test703                       |   2 +-
 tests/data/test716                       |   2 +-
 15 files changed, 318 insertions(+), 95 deletions(-)

diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3
index 27c277965..68c77e5ca 100644
--- a/docs/libcurl/curl_easy_getinfo.3
+++ b/docs/libcurl/curl_easy_getinfo.3
@@ -141,6 +141,9 @@ See \fICURLINFO_REQUEST_SIZE(3)\fP
 .IP CURLINFO_SSL_VERIFYRESULT
 Certificate verification result.
 See \fICURLINFO_SSL_VERIFYRESULT(3)\fP
+.IP CURLINFO_PROXY_ERROR
+Detailed proxy error.
+See \fICURLINFO_PROXY_ERROR(3)\fP
 .IP CURLINFO_PROXY_SSL_VERIFYRESULT
 Proxy certificate verification result.
 See \fICURLINFO_PROXY_SSL_VERIFYRESULT(3)\fP
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3 
b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
new file mode 100644
index 000000000..c6420b9b3
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
@@ -0,0 +1,104 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, 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 CURLINFO_PROXY_ERROR 3 "3 Aug 2020" "libcurl 7.73.0" "curl_easy_getinfo 
options"
+.SH NAME
+CURLINFO_PROXY_ERROR \- get the detailed (SOCKS) proxy error
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+typedef enum {
+  CURLPX_OK,
+  CURLPX_BAD_ADDRESS_TYPE,
+  CURLPX_BAD_VERSION,
+  CURLPX_CLOSED,
+  CURLPX_GSSAPI,
+  CURLPX_GSSAPI_PERMSG,
+  CURLPX_GSSAPI_PROTECTION,
+  CURLPX_IDENTD,
+  CURLPX_IDENTD_DIFFER,
+  CURLPX_LONG_HOSTNAME,
+  CURLPX_LONG_PASSWD,
+  CURLPX_LONG_USER,
+  CURLPX_NO_AUTH,
+  CURLPX_RECV_ADDRESS,
+  CURLPX_RECV_AUTH,
+  CURLPX_RECV_CONNECT,
+  CURLPX_RECV_REQACK,
+  CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+  CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+  CURLPX_REPLY_CONNECTION_REFUSED,
+  CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+  CURLPX_REPLY_HOST_UNREACHABLE,
+  CURLPX_REPLY_NETWORK_UNREACHABLE,
+  CURLPX_REPLY_NOT_ALLOWED,
+  CURLPX_REPLY_TTL_EXPIRED,
+  CURLPX_REPLY_UNASSIGNED,
+  CURLPX_REQUEST_FAILED,
+  CURLPX_RESOLVE_HOST,
+  CURLPX_SEND_AUTH,
+  CURLPX_SEND_CONNECT,
+  CURLPX_SEND_REQUEST,
+  CURLPX_UNKNOWN_FAIL,
+  CURLPX_UNKNOWN_MODE,
+  CURLPX_USER_REJECTED,
+  CURLPX_LAST /* never use */
+} CURLproxycode;
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_ERROR, long *detail);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a long to receive a detailed error code when the most recent
+transfer returned a CURLE_PROXY error.
+
+The return value will match the CURLproxycode set.
+
+The returned value will be zero (equal to CURLPX_OK) if no such response code
+was available.
+.SH PROTOCOLS
+All that can be done over SOCKS
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+  CURLcode res;
+  curl_easy_setopt(curl, CURLOPT_URL, "https://example.com";);
+
+  curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://127.0.0.1");
+  res = curl_easy_perform(curl);
+  if(res == CURLE_PROXY) {
+    long proxycode;
+    res = curl_easy_getinfo(curl, CURLINFO_PROXY_ERROR, &proxycode);
+    if(!res && proxycode)
+      printf("The detailed proxy error: %ld\\n", proxycode);
+  }
+  curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.73.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLINFO_RESPONSE_CODE "(3), " libcurl-errors "(3), "
+.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 8708f32ed..ebf234002 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -57,8 +57,9 @@ man_MANS =                                      \
   CURLINFO_PRIMARY_PORT.3                       \
   CURLINFO_PRIVATE.3                            \
   CURLINFO_PROTOCOL.3                           \
-  CURLINFO_PROXYAUTH_AVAIL.3                    \
+  CURLINFO_PROXY_ERROR.3                        \
   CURLINFO_PROXY_SSL_VERIFYRESULT.3             \
+  CURLINFO_PROXYAUTH_AVAIL.3                    \
   CURLINFO_REDIRECT_COUNT.3                     \
   CURLINFO_REDIRECT_TIME.3                      \
   CURLINFO_REDIRECT_TIME_T.3                    \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index c0cdbdc04..797e8ab33 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -105,6 +105,7 @@ CURLE_OPERATION_TIMEOUTED       7.1           7.17.0
 CURLE_OUT_OF_MEMORY             7.1
 CURLE_PARTIAL_FILE              7.1
 CURLE_PEER_FAILED_VERIFICATION  7.17.1
+CURLE_PROXY                     7.73.0
 CURLE_QUIC_CONNECT_ERROR        7.69.0
 CURLE_QUOTE_ERROR               7.17.0
 CURLE_RANGE_ERROR               7.17.0
@@ -261,6 +262,7 @@ CURLINFO_PRIMARY_PORT           7.21.0
 CURLINFO_PRIVATE                7.10.3
 CURLINFO_PROTOCOL               7.52.0
 CURLINFO_PROXYAUTH_AVAIL        7.10.8
+CURLINFO_PROXY_ERROR            7.73.0
 CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0
 CURLINFO_PTR                    7.54.1
 CURLINFO_REDIRECT_COUNT         7.9.7
@@ -710,6 +712,40 @@ CURLPROXY_SOCKS4                7.10
 CURLPROXY_SOCKS4A               7.18.0
 CURLPROXY_SOCKS5                7.10
 CURLPROXY_SOCKS5_HOSTNAME       7.18.0
+CURLPX_BAD_ADDRESS_TYPE         7.73.0
+CURLPX_BAD_VERSION              7.73.0
+CURLPX_CLOSED                   7.73.0
+CURLPX_GSSAPI                   7.73.0
+CURLPX_GSSAPI_PERMSG            7.73.0
+CURLPX_GSSAPI_PROTECTION        7.73.0
+CURLPX_IDENTD                   7.73.0
+CURLPX_IDENTD_DIFFER            7.73.0
+CURLPX_LONG_HOSTNAME            7.73.0
+CURLPX_LONG_PASSWD              7.73.0
+CURLPX_LONG_USER                7.73.0
+CURLPX_NO_AUTH                  7.73.0
+CURLPX_OK                       7.73.0
+CURLPX_RECV_ADDRESS             7.73.0
+CURLPX_RECV_AUTH                7.73.0
+CURLPX_RECV_CONNECT             7.73.0
+CURLPX_RECV_REQACK              7.73.0
+CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED 7.73.0
+CURLPX_REPLY_COMMAND_NOT_SUPPORTED 7.73.0
+CURLPX_REPLY_CONNECTION_REFUSED 7.73.0
+CURLPX_REPLY_GENERAL_SERVER_FAILURE 7.73.0
+CURLPX_REPLY_HOST_UNREACHABLE   7.73.0
+CURLPX_REPLY_NETWORK_UNREACHABLE 7.73.0
+CURLPX_REPLY_NOT_ALLOWED        7.73.0
+CURLPX_REPLY_TTL_EXPIRED        7.73.0
+CURLPX_REPLY_UNASSIGNED         7.73.0
+CURLPX_REQUEST_FAILED           7.73.0
+CURLPX_RESOLVE_HOST             7.73.0
+CURLPX_SEND_AUTH                7.73.0
+CURLPX_SEND_CONNECT             7.73.0
+CURLPX_SEND_REQUEST             7.73.0
+CURLPX_UNKNOWN_FAIL             7.73.0
+CURLPX_UNKNOWN_MODE             7.73.0
+CURLPX_USER_REJECTED            7.73.0
 CURLSHE_BAD_OPTION              7.10.3
 CURLSHE_INVALID                 7.10.3
 CURLSHE_IN_USE                  7.10.3
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 5aeaca91d..f4d5bf645 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -610,6 +610,7 @@ typedef enum {
                                     error */
   CURLE_HTTP3,                   /* 95 - An HTTP/3 layer problem */
   CURLE_QUIC_CONNECT_ERROR,      /* 96 - QUIC connection error */
+  CURLE_PROXY,                   /* 97 - proxy handshake error */
   CURL_LAST /* never use! */
 } CURLcode;
 
@@ -689,6 +690,48 @@ typedef enum {
 
 #endif /*!CURL_NO_OLDIES*/
 
+/*
+ * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was
+ * return for the transfers.
+ */
+typedef enum {
+  CURLPX_OK,
+  CURLPX_BAD_ADDRESS_TYPE,
+  CURLPX_BAD_VERSION,
+  CURLPX_CLOSED,
+  CURLPX_GSSAPI,
+  CURLPX_GSSAPI_PERMSG,
+  CURLPX_GSSAPI_PROTECTION,
+  CURLPX_IDENTD,
+  CURLPX_IDENTD_DIFFER,
+  CURLPX_LONG_HOSTNAME,
+  CURLPX_LONG_PASSWD,
+  CURLPX_LONG_USER,
+  CURLPX_NO_AUTH,
+  CURLPX_RECV_ADDRESS,
+  CURLPX_RECV_AUTH,
+  CURLPX_RECV_CONNECT,
+  CURLPX_RECV_REQACK,
+  CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+  CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+  CURLPX_REPLY_CONNECTION_REFUSED,
+  CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+  CURLPX_REPLY_HOST_UNREACHABLE,
+  CURLPX_REPLY_NETWORK_UNREACHABLE,
+  CURLPX_REPLY_NOT_ALLOWED,
+  CURLPX_REPLY_TTL_EXPIRED,
+  CURLPX_REPLY_UNASSIGNED,
+  CURLPX_REQUEST_FAILED,
+  CURLPX_RESOLVE_HOST,
+  CURLPX_SEND_AUTH,
+  CURLPX_SEND_CONNECT,
+  CURLPX_SEND_REQUEST,
+  CURLPX_UNKNOWN_FAIL,
+  CURLPX_UNKNOWN_MODE,
+  CURLPX_USER_REJECTED,
+  CURLPX_LAST /* never use */
+} CURLproxycode;
+
 /* This prototype applies to all conversion callbacks */
 typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
 
@@ -2643,8 +2686,9 @@ typedef enum {
   CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
   CURLINFO_RETRY_AFTER      = CURLINFO_OFF_T + 57,
   CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
+  CURLINFO_PROXY_ERROR      = CURLINFO_LONG + 59,
 
-  CURLINFO_LASTONE          = 58
+  CURLINFO_LASTONE          = 59
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
diff --git a/lib/connect.c b/lib/connect.c
index b000b1b2c..f53266054 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -746,8 +746,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int 
sockindex,
                               bool *done)
 {
   CURLcode result = CURLE_OK;
-
 #ifndef CURL_DISABLE_PROXY
+  CURLproxycode pxresult = CURLPX_OK;
   if(conn->bits.socksproxy) {
     /* for the secondary socket (FTP), use the "connect to host"
      * but ignore the "connect to port" (use the secondary port)
@@ -767,20 +767,24 @@ static CURLcode connect_SOCKS(struct connectdata *conn, 
int sockindex,
     switch(conn->socks_proxy.proxytype) {
     case CURLPROXY_SOCKS5:
     case CURLPROXY_SOCKS5_HOSTNAME:
-      result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
-                           host, port, sockindex, conn, done);
+      pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+                             host, port, sockindex, conn, done);
       break;
 
     case CURLPROXY_SOCKS4:
     case CURLPROXY_SOCKS4A:
-      result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
-                           conn, done);
+      pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+                             conn, done);
       break;
 
     default:
       failf(conn->data, "unknown proxytype option given");
       result = CURLE_COULDNT_CONNECT;
     } /* switch proxytype */
+    if(pxresult) {
+      result = CURLE_PROXY;
+      conn->data->info.pxcode = pxresult;
+    }
   }
   else
 #else
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 82691dcc7..49e79e476 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -269,6 +269,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, 
CURLINFO info,
     /* Return the local port of the most recent (primary) connection */
     *param_longp = data->info.conn_local_port;
     break;
+  case CURLINFO_PROXY_ERROR:
+    *param_longp = (long)data->info.pxcode;
+    break;
   case CURLINFO_CONDITION_UNMET:
     if(data->info.httpcode == 304)
       *param_longp = 1L;
diff --git a/lib/socks.c b/lib/socks.c
index 44783d015..a41b67d5a 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -184,12 +184,12 @@ int Curl_SOCKS_getsock(struct connectdata *conn, 
curl_socket_t *sock,
 *   Set protocol4a=true for  "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
 *   Nonsupport "Identification Protocol (RFC1413)"
 */
-CURLcode Curl_SOCKS4(const char *proxy_user,
-                     const char *hostname,
-                     int remote_port,
-                     int sockindex,
-                     struct connectdata *conn,
-                     bool *done)
+CURLproxycode Curl_SOCKS4(const char *proxy_user,
+                          const char *hostname,
+                          int remote_port,
+                          int sockindex,
+                          struct connectdata *conn,
+                          bool *done)
 {
   const bool protocol4a =
     (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
@@ -237,11 +237,11 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
         Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
 
       if(rc == CURLRESOLV_ERROR)
-        return CURLE_COULDNT_RESOLVE_PROXY;
+        return CURLPX_RESOLVE_HOST;
       else if(rc == CURLRESOLV_PENDING) {
         sxstate(conn, CONNECT_RESOLVING);
         infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
-        return CURLE_OK;
+        return CURLPX_OK;
       }
       sxstate(conn, CONNECT_RESOLVED);
       goto CONNECT_RESOLVED;
@@ -265,8 +265,11 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     }
     else {
       result = Curl_resolv_check(data->conn, &dns);
-      if(!dns)
-        return result;
+      if(!dns) {
+        if(result)
+          return CURLPX_RESOLVE_HOST;
+        return CURLPX_OK;
+      }
     }
     /* FALLTHROUGH */
   CONNECT_RESOLVED:
@@ -303,7 +306,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     if(!hp) {
       failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
             hostname);
-      return CURLE_COULDNT_RESOLVE_HOST;
+      return CURLPX_RESOLVE_HOST;
     }
   }
     /* FALLTHROUGH */
@@ -316,8 +319,8 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     if(proxy_user) {
       size_t plen = strlen(proxy_user);
       if(plen >= sizeof(sx->socksreq) - 8) {
-        failf(data, "Too long SOCKS proxy name, can't use!\n");
-        return CURLE_COULDNT_CONNECT;
+        failf(data, "Too long SOCKS proxy user name, can't use!\n");
+        return CURLPX_LONG_USER;
       }
       /* copy the proxy name WITH trailing zero */
       memcpy(socksreq + 8, proxy_user, plen + 1);
@@ -343,7 +346,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
           strcpy((char *)socksreq + packetsize, hostname);
         else {
           failf(data, "SOCKS4: too long host name");
-          return CURLE_COULDNT_CONNECT;
+          return CURLPX_LONG_HOSTNAME;
         }
         packetsize += hostnamelen;
       }
@@ -358,13 +361,13 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
                               sx->outstanding, &written);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to send SOCKS4 connect request.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_SEND_CONNECT;
     }
     if(written != sx->outstanding) {
       /* not done, remain in state */
       sx->outstanding -= written;
       sx->outp += written;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
 
     /* done sending! */
@@ -380,18 +383,18 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "SOCKS4: Failed receiving connect request ack: %s",
             curl_easy_strerror(result));
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_RECV_CONNECT;
     }
     else if(!result && !actualread) {
       /* connection closed */
       failf(data, "connection to proxy closed");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_CLOSED;
     }
     else if(actualread != sx->outstanding) {
       /* remain in reading state */
       sx->outstanding -= actualread;
       sx->outp += actualread;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     sxstate(conn, CONNECT_DONE);
     break;
@@ -422,7 +425,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
   if(socksreq[0] != 0) {
     failf(data,
           "SOCKS4 reply has wrong version, version should be 0.");
-    return CURLE_COULDNT_CONNECT;
+    return CURLPX_BAD_VERSION;
   }
 
   /* Result */
@@ -438,7 +441,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
           (unsigned char)socksreq[6], (unsigned char)socksreq[7],
           (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
           (unsigned char)socksreq[1]);
-    return CURLE_COULDNT_CONNECT;
+    return CURLPX_REQUEST_FAILED;
   case 92:
     failf(data,
           "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
@@ -448,7 +451,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
           (unsigned char)socksreq[6], (unsigned char)socksreq[7],
           (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
           (unsigned char)socksreq[1]);
-    return CURLE_COULDNT_CONNECT;
+    return CURLPX_IDENTD;
   case 93:
     failf(data,
           "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
@@ -458,7 +461,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
           (unsigned char)socksreq[6], (unsigned char)socksreq[7],
           (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
           (unsigned char)socksreq[1]);
-    return CURLE_COULDNT_CONNECT;
+    return CURLPX_IDENTD_DIFFER;
   default:
     failf(data,
           "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
@@ -467,24 +470,24 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
           (unsigned char)socksreq[6], (unsigned char)socksreq[7],
           (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
           (unsigned char)socksreq[1]);
-    return CURLE_COULDNT_CONNECT;
+    return CURLPX_UNKNOWN_FAIL;
   }
 
   *done = TRUE;
-  return CURLE_OK; /* Proxy was successful! */
+  return CURLPX_OK; /* Proxy was successful! */
 }
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the final
  * destination server.
  */
-CURLcode Curl_SOCKS5(const char *proxy_user,
-                     const char *proxy_password,
-                     const char *hostname,
-                     int remote_port,
-                     int sockindex,
-                     struct connectdata *conn,
-                     bool *done)
+CURLproxycode Curl_SOCKS5(const char *proxy_user,
+                          const char *proxy_password,
+                          const char *hostname,
+                          int remote_port,
+                          int sockindex,
+                          struct connectdata *conn,
+                          bool *done)
 {
   /*
     According to the RFC1928, section "6.  Replies". This is what a SOCK5
@@ -561,13 +564,13 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Unable to send initial SOCKS5 request.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_SEND_CONNECT;
     }
     if(written != idx) {
       sxstate(conn, CONNECT_SOCKS_SEND);
       sx->outstanding = idx - written;
       sx->outp = &socksreq[written];
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     sxstate(conn, CONNECT_SOCKS_READ);
     goto CONNECT_SOCKS_READ_INIT;
@@ -576,13 +579,13 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                               sx->outstanding, &written);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Unable to send initial SOCKS5 request.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_SEND_CONNECT;
     }
     if(written != sx->outstanding) {
       /* not done, remain in state */
       sx->outstanding -= written;
       sx->outp += written;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     /* FALLTHROUGH */
   CONNECT_SOCKS_READ_INIT:
@@ -595,22 +598,22 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                              sx->outstanding, &actualread);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Unable to receive initial SOCKS5 response.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_RECV_CONNECT;
     }
     else if(!result && !actualread) {
       /* connection closed */
       failf(data, "Connection to proxy closed");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_CLOSED;
     }
     else if(actualread != sx->outstanding) {
       /* remain in reading state */
       sx->outstanding -= actualread;
       sx->outp += actualread;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     else if(socksreq[0] != 5) {
       failf(data, "Received invalid version in initial SOCKS5 response.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_BAD_VERSION;
     }
     else if(socksreq[1] == 0) {
       /* DONE! No authentication needed. Send request. */
@@ -628,7 +631,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
       if(result) {
         failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
-        return CURLE_COULDNT_CONNECT;
+        return CURLPX_GSSAPI;
       }
     }
 #endif
@@ -637,16 +640,16 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       if(!allow_gssapi && (socksreq[1] == 1)) {
         failf(data,
               "SOCKS5 GSSAPI per-message authentication is not supported.");
-        return CURLE_COULDNT_CONNECT;
+        return CURLPX_GSSAPI_PERMSG;
       }
       else if(socksreq[1] == 255) {
         failf(data, "No authentication method was acceptable.");
-        return CURLE_COULDNT_CONNECT;
+        return CURLPX_NO_AUTH;
       }
     }
     failf(data,
           "Undocumented SOCKS5 mode attempted to be used by server.");
-    return CURLE_COULDNT_CONNECT;
+    return CURLPX_UNKNOWN_MODE;
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
   case CONNECT_GSSAPI_INIT:
     /* GSSAPI stuff done non-blocking */
@@ -683,7 +686,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       /* the length must fit in a single byte */
       if(proxy_user_len >= 255) {
         failf(data, "Excessive user name length for proxy auth");
-        return CURLE_BAD_FUNCTION_ARGUMENT;
+        return CURLPX_LONG_USER;
       }
       memcpy(socksreq + len, proxy_user, proxy_user_len);
     }
@@ -693,7 +696,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       /* the length must fit in a single byte */
       if(proxy_password_len > 255) {
         failf(data, "Excessive password length for proxy auth");
-        return CURLE_BAD_FUNCTION_ARGUMENT;
+        return CURLPX_LONG_PASSWD;
       }
       memcpy(socksreq + len, proxy_password, proxy_password_len);
     }
@@ -708,13 +711,13 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                               sx->outstanding, &written);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to send SOCKS5 sub-negotiation request.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_SEND_AUTH;
     }
     if(sx->outstanding != written) {
       /* remain in state */
       sx->outstanding -= written;
       sx->outp += written;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     sx->outp = socksreq;
     sx->outstanding = 2;
@@ -725,24 +728,24 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                              sx->outstanding, &actualread);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_RECV_AUTH;
     }
     else if(!result && !actualread) {
       /* connection closed */
       failf(data, "connection to proxy closed");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_CLOSED;
     }
     else if(actualread != sx->outstanding) {
       /* remain in state */
       sx->outstanding -= actualread;
       sx->outp += actualread;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     /* ignore the first (VER) byte */
     else if(socksreq[1] != 0) { /* status */
       failf(data, "User was rejected by the SOCKS5 server (%d %d).",
             socksreq[0], socksreq[1]);
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_USER_REJECTED;
     }
 
     /* Everything is good so far, user was authenticated! */
@@ -755,11 +758,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                                       FALSE, &dns);
 
       if(rc == CURLRESOLV_ERROR)
-        return CURLE_COULDNT_RESOLVE_HOST;
+        return CURLPX_RESOLVE_HOST;
 
       if(rc == CURLRESOLV_PENDING) {
         sxstate(conn, CONNECT_RESOLVING);
-        return CURLE_OK;
+        return CURLPX_OK;
       }
       sxstate(conn, CONNECT_RESOLVED);
       goto CONNECT_RESOLVED;
@@ -780,8 +783,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
 
     if(!dns) {
       result = Curl_resolv_check(data->conn, &dns);
-      if(!dns)
-        return result;
+      if(!dns) {
+        if(result)
+          return CURLPX_RESOLVE_HOST;
+        return CURLPX_OK;
+      }
     }
     /* FALLTHROUGH */
   CONNECT_RESOLVED:
@@ -793,7 +799,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     if(!hp) {
       failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
             hostname);
-      return CURLE_COULDNT_RESOLVE_HOST;
+      return CURLPX_RESOLVE_HOST;
     }
 
     Curl_printable_address(hp, dest, sizeof(dest));
@@ -867,7 +873,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
     if(conn->socks5_gssapi_enctype) {
       failf(data, "SOCKS5 GSS-API protection not yet implemented.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_GSSAPI_PROTECTION;
     }
 #endif
     sx->outp = socksreq;
@@ -879,18 +885,18 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                               sx->outstanding, &written);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to send SOCKS5 connect request.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_SEND_REQUEST;
     }
     if(sx->outstanding != written) {
       /* remain in state */
       sx->outstanding -= written;
       sx->outp += written;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
     if(conn->socks5_gssapi_enctype) {
       failf(data, "SOCKS5 GSS-API protection not yet implemented.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_GSSAPI_PROTECTION;
     }
 #endif
     sx->outstanding = 10; /* minimum packet size is 10 */
@@ -902,29 +908,46 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                              sx->outstanding, &actualread);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to receive SOCKS5 connect request ack.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_RECV_REQACK;
     }
     else if(!result && !actualread) {
       /* connection closed */
       failf(data, "connection to proxy closed");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_CLOSED;
     }
     else if(actualread != sx->outstanding) {
       /* remain in state */
       sx->outstanding -= actualread;
       sx->outp += actualread;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
 
     if(socksreq[0] != 5) { /* version */
       failf(data,
             "SOCKS5 reply has wrong version, version should be 5.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_BAD_VERSION;
     }
     else if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+      CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
+      int code = socksreq[1];
       failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
             hostname, (unsigned char)socksreq[1]);
-      return CURLE_COULDNT_CONNECT;
+      if(code < 9) {
+        /* RFC 1928 section 6 lists: */
+        static const CURLproxycode lookup[] = {
+          CURLPX_OK,
+          CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+          CURLPX_REPLY_NOT_ALLOWED,
+          CURLPX_REPLY_NETWORK_UNREACHABLE,
+          CURLPX_REPLY_HOST_UNREACHABLE,
+          CURLPX_REPLY_CONNECTION_REFUSED,
+          CURLPX_REPLY_TTL_EXPIRED,
+          CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+          CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+        };
+        rc = lookup[code];
+      }
+      return rc;
     }
 
     /* Fix: in general, returned BND.ADDR is variable length parameter by RFC
@@ -958,7 +981,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     }
     else {
       failf(data, "SOCKS5 reply has wrong address type.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_BAD_ADDRESS_TYPE;
     }
 
     /* At this point we already read first 10 bytes */
@@ -984,25 +1007,25 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                              sx->outstanding, &actualread);
     if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to receive SOCKS5 connect request ack.");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_RECV_ADDRESS;
     }
     else if(!result && !actualread) {
       /* connection closed */
       failf(data, "connection to proxy closed");
-      return CURLE_COULDNT_CONNECT;
+      return CURLPX_CLOSED;
     }
     else if(actualread != sx->outstanding) {
       /* remain in state */
       sx->outstanding -= actualread;
       sx->outp += actualread;
-      return CURLE_OK;
+      return CURLPX_OK;
     }
     sxstate(conn, CONNECT_DONE);
   }
   infof(data, "SOCKS5 request granted.\n");
 
   *done = TRUE;
-  return CURLE_OK; /* Proxy was successful! */
+  return CURLPX_OK; /* Proxy was successful! */
 }
 
 #endif /* CURL_DISABLE_PROXY */
diff --git a/lib/socks.h b/lib/socks.h
index 64a756337..17e6f4610 100644
--- a/lib/socks.h
+++ b/lib/socks.h
@@ -48,24 +48,24 @@ int Curl_SOCKS_getsock(struct connectdata *conn,
  * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
  * final destination server.
  */
-CURLcode Curl_SOCKS4(const char *proxy_name,
-                     const char *hostname,
-                     int remote_port,
-                     int sockindex,
-                     struct connectdata *conn,
-                     bool *done);
+CURLproxycode Curl_SOCKS4(const char *proxy_name,
+                          const char *hostname,
+                          int remote_port,
+                          int sockindex,
+                          struct connectdata *conn,
+                          bool *done);
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the
  * final destination server.
  */
-CURLcode Curl_SOCKS5(const char *proxy_name,
-                     const char *proxy_password,
-                     const char *hostname,
-                     int remote_port,
-                     int sockindex,
-                     struct connectdata *conn,
-                     bool *done);
+CURLproxycode Curl_SOCKS5(const char *proxy_name,
+                          const char *proxy_password,
+                          const char *hostname,
+                          int remote_port,
+                          int sockindex,
+                          struct connectdata *conn,
+                          bool *done);
 
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 /*
diff --git a/lib/strerror.c b/lib/strerror.c
index 015e588cf..5893f49a9 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -320,6 +320,9 @@ curl_easy_strerror(CURLcode error)
   case CURLE_QUIC_CONNECT_ERROR:
     return "QUIC connection error";
 
+ case CURLE_PROXY:
+    return "proxy handshake error";
+
     /* error codes not used by current libcurl */
   case CURLE_OBSOLETE20:
   case CURLE_OBSOLETE24:
diff --git a/lib/urldata.h b/lib/urldata.h
index 0ae926927..86f8af42c 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1134,6 +1134,7 @@ struct PureInfo {
                                  OpenSSL, GnuTLS, Schannel, NSS and GSKit
                                  builds. Asked for with CURLOPT_CERTINFO
                                  / CURLINFO_CERTINFO */
+  CURLproxycode pxcode;
   BIT(timecond);  /* set to TRUE if the time condition didn't match, which
                      thus made the document NOT get fetched */
 };
diff --git a/tests/data/test1538 b/tests/data/test1538
index ea8eddbb8..03481d56e 100644
--- a/tests/data/test1538
+++ b/tests/data/test1538
@@ -129,7 +129,8 @@ e93: API function called from within callback
 e94: An authentication function returned an error
 e95: HTTP/3 error
 e96: QUIC connection error
-e97: Unknown error
+e97: proxy handshake error
+e98: Unknown error
 m-1: Please call curl_multi_perform() soon
 m0: No error
 m1: Invalid multi handle
diff --git a/tests/data/test702 b/tests/data/test702
index 1c18d0976..dd84ffe26 100644
--- a/tests/data/test702
+++ b/tests/data/test702
@@ -38,7 +38,7 @@ Attempt connect to non-listening HTTP server via SOCKS4 proxy
 # Verify data after the test has been "shot"
 <verify>
 <errorcode>
-7
+97
 </errorcode>
 </verify>
 </testcase>
diff --git a/tests/data/test703 b/tests/data/test703
index d7be71393..3c3487aee 100644
--- a/tests/data/test703
+++ b/tests/data/test703
@@ -38,7 +38,7 @@ Attempt connect to non-listening HTTP server via SOCKS5 proxy
 # Verify data after the test has been "shot"
 <verify>
 <errorcode>
-7
+97
 </errorcode>
 </verify>
 </testcase>
diff --git a/tests/data/test716 b/tests/data/test716
index 96167de5c..531e272fa 100644
--- a/tests/data/test716
+++ b/tests/data/test716
@@ -39,7 +39,7 @@ http://hohoho.example.com:99/716 -x 
socks5://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 # Verify data after the test has been "shot"
 <verify>
 <errorcode>
-43
+97
 </errorcode>
 </verify>
 </testcase>

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]