mirror of
https://github.com/curl/curl.git
synced 2024-11-21 01:16:58 +08:00
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
This commit is contained in:
parent
d71ac6711a
commit
88b1ca7cba
@ -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
|
||||
|
104
docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
Normal file
104
docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
Normal file
@ -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), "
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
165
lib/socks.c
165
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 */
|
||||
|
26
lib/socks.h
26
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)
|
||||
/*
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user