25 #if !defined(CURL_DISABLE_PROXY) 27 #ifdef HAVE_NETINET_IN_H 28 #include <netinet/in.h> 30 #ifdef HAVE_ARPA_INET_H 31 #include <arpa/inet.h> 79 if(buffersize == nread) {
114 const bool protocol4a =
116 #define SOCKS4REQLEN 262 126 failf(data,
"Connection time-out");
131 infof(conn->
data,
"SOCKS4%s: connecting to HTTP proxy %s port %d\n",
132 protocol4a ?
"a" :
"", hostname, remote_port);
136 infof(data,
"SOCKS4 communication to %s:%d\n", hostname, remote_port);
151 socksreq[2] = (
unsigned char)((remote_port >> 8) & 0xff);
152 socksreq[3] = (
unsigned char)(remote_port & 0xff);
160 rc =
Curl_resolv(conn, hostname, remote_port, &dns);
180 struct sockaddr_in *saddr_in;
182 saddr_in = (
struct sockaddr_in *)(
void *)hp->
ai_addr;
183 socksreq[4] = ((
unsigned char *)&saddr_in->sin_addr.s_addr)[0];
184 socksreq[5] = ((
unsigned char *)&saddr_in->sin_addr.s_addr)[1];
185 socksreq[6] = ((
unsigned char *)&saddr_in->sin_addr.s_addr)[2];
186 socksreq[7] = ((
unsigned char *)&saddr_in->sin_addr.s_addr)[3];
188 infof(data,
"SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
193 failf(data,
"SOCKS4 connection to %s not supported\n", buf);
199 failf(data,
"Failed to resolve \"%s\" for SOCKS4 connect.",
210 size_t plen = strlen(proxy_user);
211 if(plen >=
sizeof(socksreq) - 8) {
212 failf(data,
"Too long SOCKS proxy name, can't use!\n");
216 memcpy(socksreq + 8, proxy_user, plen + 1);
227 (int)strlen((
char *)socksreq + 8);
236 hostnamelen = (
ssize_t)strlen(hostname) + 1;
238 strcpy((
char *)socksreq + packetsize, hostname);
245 packetsize + hostnamelen,
247 if(code || (written != packetsize + hostnamelen)) {
248 failf(data,
"Failed to send SOCKS4 connect request.");
251 if(protocol4a && hostnamelen == 0) {
253 hostnamelen = (
ssize_t)strlen(hostname) + 1;
256 if(code || (written != hostnamelen)) {
257 failf(data,
"Failed to send SOCKS4 connect request.");
267 if(result || (actualread != packetsize)) {
268 failf(data,
"Failed to receive SOCKS4 connect request ack.");
292 if(socksreq[0] != 0) {
294 "SOCKS4 reply has wrong version, version should be 4.");
299 switch(socksreq[1]) {
301 infof(data,
"SOCKS4%s request granted.\n", protocol4a?
"a":
"");
305 "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" 306 ", request rejected or failed.",
307 (
unsigned char)socksreq[4], (
unsigned char)socksreq[5],
308 (
unsigned char)socksreq[6], (
unsigned char)socksreq[7],
309 (((
unsigned char)socksreq[2] << 8) | (
unsigned char)socksreq[3]),
310 (
unsigned char)socksreq[1]);
314 "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" 315 ", request rejected because SOCKS server cannot connect to " 316 "identd on the client.",
317 (
unsigned char)socksreq[4], (
unsigned char)socksreq[5],
318 (
unsigned char)socksreq[6], (
unsigned char)socksreq[7],
319 (((
unsigned char)socksreq[2] << 8) | (
unsigned char)socksreq[3]),
320 (
unsigned char)socksreq[1]);
324 "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" 325 ", request rejected because the client program and identd " 326 "report different user-ids.",
327 (
unsigned char)socksreq[4], (
unsigned char)socksreq[5],
328 (
unsigned char)socksreq[6], (
unsigned char)socksreq[7],
329 (((
unsigned char)socksreq[2] << 8) | (
unsigned char)socksreq[3]),
330 (
unsigned char)socksreq[1]);
334 "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" 336 (
unsigned char)socksreq[4], (
unsigned char)socksreq[5],
337 (
unsigned char)socksreq[6], (
unsigned char)socksreq[7],
338 (((
unsigned char)socksreq[2] << 8) | (
unsigned char)socksreq[3]),
339 (
unsigned char)socksreq[1]);
354 const char *proxy_password,
377 unsigned char socksreq[600];
386 bool socks5_resolve_local =
388 const size_t hostname_len = strlen(hostname);
391 bool allow_gssapi =
FALSE;
394 infof(conn->
data,
"SOCKS5: connecting to HTTP proxy %s port %d\n",
395 hostname, remote_port);
398 if(!socks5_resolve_local && hostname_len > 255) {
399 infof(conn->
data,
"SOCKS5: server resolving disabled for hostnames of " 400 "length > 255 [actual len=%zu]\n", hostname_len);
401 socks5_resolve_local =
TRUE;
409 failf(data,
"Connection time-out");
419 failf(conn->
data,
"SOCKS5: no connection here");
423 failf(conn->
data,
"SOCKS5: connection timeout");
428 failf(conn->
data,
"SOCKS5: error occurred during connection");
434 "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
439 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 453 socksreq[1] = (
unsigned char) (idx - 2);
457 infof(data,
"SOCKS5 communication to %s:%d\n", hostname, remote_port);
459 code =
Curl_write_plain(conn, sock, (
char *)socksreq, (2 + (
int)socksreq[1]),
461 if(code || (written != (2 + (
int)socksreq[1]))) {
462 failf(data,
"Unable to send initial SOCKS5 request.");
471 failf(conn->
data,
"SOCKS5 nothing to read");
475 failf(conn->
data,
"SOCKS5 read timeout");
479 if(result & CURL_CSELECT_ERR) {
480 failf(conn->
data,
"SOCKS5 read error occurred");
487 if(result || (actualread != 2)) {
488 failf(data,
"Unable to receive initial SOCKS5 response.");
492 if(socksreq[0] != 5) {
493 failf(data,
"Received invalid version in initial SOCKS5 response.");
496 if(socksreq[1] == 0) {
500 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 501 else if(allow_gssapi && (socksreq[1] == 1)) {
502 code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
504 failf(data,
"Unable to negotiate SOCKS5 GSS-API context.");
509 else if(socksreq[1] == 2) {
511 size_t proxy_user_len, proxy_password_len;
512 if(proxy_user && proxy_password) {
513 proxy_user_len = strlen(proxy_user);
514 proxy_password_len = strlen(proxy_password);
518 proxy_password_len = 0;
530 socksreq[len++] = (
unsigned char) proxy_user_len;
531 if(proxy_user && proxy_user_len)
532 memcpy(socksreq + len, proxy_user, proxy_user_len);
533 len += proxy_user_len;
534 socksreq[len++] = (
unsigned char) proxy_password_len;
535 if(proxy_password && proxy_password_len)
536 memcpy(socksreq + len, proxy_password, proxy_password_len);
537 len += proxy_password_len;
540 if(code || (len != written)) {
541 failf(data,
"Failed to send SOCKS5 sub-negotiation request.");
546 if(result || (actualread != 2)) {
547 failf(data,
"Unable to receive SOCKS5 sub-negotiation response.");
552 if(socksreq[1] != 0) {
553 failf(data,
"User was rejected by the SOCKS5 server (%d %d).",
554 socksreq[0], socksreq[1]);
562 if(!allow_gssapi && (socksreq[1] == 1)) {
564 "SOCKS5 GSSAPI per-message authentication is not supported.");
567 if(socksreq[1] == 255) {
568 if(!proxy_user || !*proxy_user) {
570 "No authentication method was acceptable. (It is quite likely" 571 " that the SOCKS5 server wanted a username/password, since none" 572 " was supplied to the server on this connection.)");
575 failf(data,
"No authentication method was acceptable.");
581 "Undocumented SOCKS5 mode attempted to be used by server.");
592 if(!socks5_resolve_local) {
594 socksreq[len++] = (char) hostname_len;
595 memcpy(&socksreq[len], hostname, hostname_len);
625 struct sockaddr_in *saddr_in;
628 saddr_in = (
struct sockaddr_in *)(
void *)hp->
ai_addr;
629 for(i = 0; i < 4; i++) {
630 socksreq[len++] = ((
unsigned char *)&saddr_in->sin_addr.s_addr)[
i];
633 infof(data,
"SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
637 struct sockaddr_in6 *saddr_in6;
640 saddr_in6 = (
struct sockaddr_in6 *)(
void *)hp->
ai_addr;
641 for(i = 0; i < 16; i++) {
643 ((
unsigned char *)&saddr_in6->sin6_addr.s6_addr)[
i];
646 infof(data,
"SOCKS5 connect to IPv6 %s (locally resolved)\n", buf);
652 failf(data,
"SOCKS5 connection to %s not supported\n", buf);
658 failf(data,
"Failed to resolve \"%s\" for SOCKS5 connect.",
664 socksreq[len++] = (
unsigned char)((remote_port >> 8) & 0xff);
665 socksreq[len++] = (
unsigned char)(remote_port & 0xff);
667 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 668 if(conn->socks5_gssapi_enctype) {
669 failf(data,
"SOCKS5 GSS-API protection not yet implemented.");
675 if(code || (len != written)) {
676 failf(data,
"Failed to send SOCKS5 connect request.");
682 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 683 if(conn->socks5_gssapi_enctype) {
684 failf(data,
"SOCKS5 GSS-API protection not yet implemented.");
691 if(result || (len != actualread)) {
692 failf(data,
"Failed to receive SOCKS5 connect request ack.");
696 if(socksreq[0] != 5) {
698 "SOCKS5 reply has wrong version, version should be 5.");
719 if(socksreq[3] == 3) {
721 int addrlen = (int) socksreq[4];
722 len = 5 + addrlen + 2;
724 else if(socksreq[3] == 4) {
730 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 731 if(!conn->socks5_gssapi_enctype) {
736 len - 10, &actualread);
737 if(result || ((len - 10) != actualread)) {
738 failf(data,
"Failed to receive SOCKS5 connect request ack.");
742 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 746 if(socksreq[1] != 0) {
747 if(socksreq[3] == 1) {
749 "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
750 (
unsigned char)socksreq[4], (
unsigned char)socksreq[5],
751 (
unsigned char)socksreq[6], (
unsigned char)socksreq[7],
752 (((
unsigned char)socksreq[8] << 8) |
753 (
unsigned char)socksreq[9]),
754 (
unsigned char)socksreq[1]);
756 else if(socksreq[3] == 3) {
757 unsigned char port_upper = (
unsigned char)socksreq[len - 2];
758 socksreq[len - 2] = 0;
760 "Can't complete SOCKS5 connection to %s:%d. (%d)",
761 (
char *)&socksreq[5],
763 (
unsigned char)socksreq[len - 1]),
764 (
unsigned char)socksreq[1]);
765 socksreq[len - 2] = port_upper;
767 else if(socksreq[3] == 4) {
769 "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:" 770 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
771 (
unsigned char)socksreq[4], (
unsigned char)socksreq[5],
772 (
unsigned char)socksreq[6], (
unsigned char)socksreq[7],
773 (
unsigned char)socksreq[8], (
unsigned char)socksreq[9],
774 (
unsigned char)socksreq[10], (
unsigned char)socksreq[11],
775 (
unsigned char)socksreq[12], (
unsigned char)socksreq[13],
776 (
unsigned char)socksreq[14], (
unsigned char)socksreq[15],
777 (
unsigned char)socksreq[16], (
unsigned char)socksreq[17],
778 (
unsigned char)socksreq[18], (
unsigned char)socksreq[19],
779 (((
unsigned char)socksreq[20] << 8) |
780 (
unsigned char)socksreq[21]),
781 (
unsigned char)socksreq[1]);
785 infof(data,
"SOCKS5 request granted.\n");
CURLcode Curl_SOCKS5(const char *proxy_user, const char *proxy_password, const char *hostname, int remote_port, int sockindex, struct connectdata *conn)
CURLcode Curl_write_plain(struct connectdata *conn, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written)
#define CURLRESOLV_PENDING
UNITTEST_START int result
CURLcode Curl_SOCKS4(const char *proxy_user, const char *hostname, int remote_port, int sockindex, struct connectdata *conn)
int curlx_nonblock(curl_socket_t sockfd, int nonblock)
struct sockaddr * ai_addr
CURLcode Curl_read_plain(curl_socket_t sockfd, char *buf, size_t bytesfromsocket, ssize_t *n)
memcpy(filename, filename1, strlen(filename1))
time_t Curl_timeleft(struct Curl_easy *data, struct curltime *nowp, bool duringconnect)
#define SOCKET_READABLE(x, z)
const char * Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
#define SOCKET_WRITABLE(x, z)
int Curl_resolv(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry)
void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns)
struct proxy_info socks_proxy
static struct curl_hash hp
int Curl_blockread_all(struct connectdata *conn, curl_socket_t sockfd, char *buf, ssize_t buffersize, ssize_t *n)
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct Curl_dns_entry **dnsentry)