226
229
ssize_t actualread;
231
ssize_t hostnamelen = 0;
228
232
int packetsize = 9 +
229
233
(int)strlen((char*)socksreq + 8); /* size including NUL */
235
/* If SOCKS4a, set special invalid IP address 0.0.0.x */
241
/* If still enough room in buffer, also append hostname */
242
hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
243
if (packetsize + hostnamelen <= SOCKS4REQLEN)
244
strcpy((char*)socksreq + packetsize, hostname);
246
hostnamelen = 0; /* Flag: hostname did not fit in buffer */
231
249
/* Send request */
232
code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
233
if ((code != CURLE_OK) || (written != packetsize)) {
250
code = Curl_write(conn, sock, (char *)socksreq, packetsize + hostnamelen,
252
if((code != CURLE_OK) || (written != packetsize + hostnamelen)) {
234
253
failf(data, "Failed to send SOCKS4 connect request.");
235
254
return CURLE_COULDNT_CONNECT;
256
if (protocol4a && hostnamelen == 0) {
257
/* SOCKS4a with very long hostname - send that name separately */
258
hostnamelen = (ssize_t)strlen(hostname) + 1;
259
code = Curl_write(conn, sock, (char *)hostname, hostnamelen, &written);
260
if((code != CURLE_OK) || (written != hostnamelen)) {
261
failf(data, "Failed to send SOCKS4 connect request.");
262
return CURLE_COULDNT_CONNECT;
238
266
packetsize = 8; /* receive data size */
240
268
/* Receive response */
241
269
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
242
270
&actualread, timeout);
243
if ((result != CURLE_OK) || (actualread != packetsize)) {
271
if((result != CURLE_OK) || (actualread != packetsize)) {
244
272
failf(data, "Failed to receive SOCKS4 connect request ack.");
245
273
return CURLE_COULDNT_CONNECT;
359
390
curl_socket_t sock = conn->sock[sockindex];
360
391
struct SessionHandle *data = conn->data;
393
bool socks5_resolve_local = (bool)(data->set.proxytype == CURLPROXY_SOCKS5);
394
const size_t hostname_len = strlen(hostname);
395
ssize_t packetsize = 0;
397
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
398
if(!socks5_resolve_local && hostname_len > 255)
400
infof(conn->data,"SOCKS5: server resolving disabled for hostnames of "
401
"length > 255 [actual len=%d]\n", hostname_len);
402
socks5_resolve_local = TRUE;
363
405
/* get timeout */
364
406
if(data->set.timeout && data->set.connecttimeout) {
365
if (data->set.timeout < data->set.connecttimeout)
407
if(data->set.timeout < data->set.connecttimeout)
366
408
timeout = data->set.timeout;
368
410
timeout = data->set.connecttimeout;
428
470
Curl_nonblock(sock, FALSE);
430
472
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread, timeout);
431
if ((result != CURLE_OK) || (actualread != 2)) {
473
if((result != CURLE_OK) || (actualread != 2)) {
432
474
failf(data, "Unable to receive initial SOCKS5 response.");
433
475
return CURLE_COULDNT_CONNECT;
436
if (socksreq[0] != 5) {
478
if(socksreq[0] != 5) {
437
479
failf(data, "Received invalid version in initial SOCKS5 response.");
438
480
return CURLE_COULDNT_CONNECT;
440
if (socksreq[1] == 0) {
482
if(socksreq[1] == 0) {
441
483
/* Nothing to do, no authentication needed */
444
else if (socksreq[1] == 2) {
486
else if(socksreq[1] == 2) {
445
487
/* Needs user name and password */
446
488
size_t userlen, pwlen;
473
515
code = Curl_write(conn, sock, (char *)socksreq, len, &written);
474
if ((code != CURLE_OK) || (len != written)) {
516
if((code != CURLE_OK) || (len != written)) {
475
517
failf(data, "Failed to send SOCKS5 sub-negotiation request.");
476
518
return CURLE_COULDNT_CONNECT;
479
521
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
481
if ((result != CURLE_OK) || (actualread != 2)) {
523
if((result != CURLE_OK) || (actualread != 2)) {
482
524
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
483
525
return CURLE_COULDNT_CONNECT;
486
528
/* ignore the first (VER) byte */
487
if (socksreq[1] != 0) { /* status */
529
if(socksreq[1] != 0) { /* status */
488
530
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
489
531
socksreq[0], socksreq[1]);
490
532
return CURLE_COULDNT_CONNECT;
522
564
socksreq[0] = 5; /* version (SOCKS5) */
523
565
socksreq[1] = 1; /* connect */
524
566
socksreq[2] = 0; /* must be zero */
525
socksreq[3] = 1; /* IPv4 = 1 */
568
if(!socks5_resolve_local) {
569
packetsize = (ssize_t)(5 + hostname_len + 2);
571
socksreq[3] = 3; /* ATYP: domain name = 3 */
572
socksreq[4] = (char) hostname_len; /* address length */
573
memcpy(&socksreq[5], hostname, hostname_len); /* address bytes w/o NULL */
575
*((unsigned short*)&socksreq[hostname_len+5]) =
576
htons((unsigned short)remote_port);
528
579
struct Curl_dns_entry *dns;
529
580
Curl_addrinfo *hp=NULL;
530
581
int rc = Curl_resolv(conn, hostname, remote_port, &dns);
585
socksreq[3] = 1; /* IPv4 = 1 */
532
587
if(rc == CURLRESOLV_ERROR)
533
588
return CURLE_COULDNT_RESOLVE_HOST;
565
620
return CURLE_COULDNT_RESOLVE_HOST;
569
*((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port);
572
const int packetsize = 10;
574
code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
575
if ((code != CURLE_OK) || (written != packetsize)) {
576
failf(data, "Failed to send SOCKS5 connect request.");
623
*((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port);
626
code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
627
if((code != CURLE_OK) || (written != packetsize)) {
628
failf(data, "Failed to send SOCKS5 connect request.");
629
return CURLE_COULDNT_CONNECT;
632
packetsize = 10; /* minimum packet size is 10 */
634
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
635
&actualread, timeout);
636
if((result != CURLE_OK) || (actualread != packetsize)) {
637
failf(data, "Failed to receive SOCKS5 connect request ack.");
638
return CURLE_COULDNT_CONNECT;
641
if(socksreq[0] != 5) { /* version */
643
"SOCKS5 reply has wrong version, version should be 5.");
644
return CURLE_COULDNT_CONNECT;
646
if(socksreq[1] != 0) { /* Anything besides 0 is an error */
648
"Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
649
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
650
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
651
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
577
653
return CURLE_COULDNT_CONNECT;
580
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
656
/* Fix: in general, returned BND.ADDR is variable length parameter by RFC
657
1928, so the reply packet should be read until the end to avoid errors at
658
subsequent protocol level.
660
+----+-----+-------+------+----------+----------+
661
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
662
+----+-----+-------+------+----------+----------+
663
| 1 | 1 | X'00' | 1 | Variable | 2 |
664
+----+-----+-------+------+----------+----------+
667
o IP v4 address: X'01', BND.ADDR = 4 byte
668
o domain name: X'03', BND.ADDR = [ 1 byte length, string ]
669
o IP v6 address: X'04', BND.ADDR = 16 byte
672
/* Calculate real packet size */
673
if(socksreq[3] == 3) {
675
int addrlen = (int) socksreq[4];
676
packetsize = 5 + addrlen + 2;
678
else if(socksreq[3] == 4) {
680
packetsize = 4 + 16 + 2;
683
/* At this point we already read first 10 bytes */
684
if(packetsize > 10) {
686
result = blockread_all(conn, sock, (char *)&socksreq[10], packetsize,
581
687
&actualread, timeout);
582
if ((result != CURLE_OK) || (actualread != packetsize)) {
688
if((result != CURLE_OK) || (actualread != packetsize)) {
583
689
failf(data, "Failed to receive SOCKS5 connect request ack.");
584
690
return CURLE_COULDNT_CONNECT;
587
if (socksreq[0] != 5) { /* version */
589
"SOCKS5 reply has wrong version, version should be 5.");
590
return CURLE_COULDNT_CONNECT;
592
if (socksreq[1] != 0) { /* Anything besides 0 is an error */
594
"Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
595
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
596
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
597
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
599
return CURLE_COULDNT_CONNECT;
603
694
Curl_nonblock(sock, TRUE);