socks.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. #include "curl_setup.h"
  23. #if !defined(CURL_DISABLE_PROXY)
  24. #ifdef HAVE_NETINET_IN_H
  25. #include <netinet/in.h>
  26. #endif
  27. #ifdef HAVE_ARPA_INET_H
  28. #include <arpa/inet.h>
  29. #endif
  30. #include "urldata.h"
  31. #include "sendf.h"
  32. #include "select.h"
  33. #include "connect.h"
  34. #include "timeval.h"
  35. #include "socks.h"
  36. #include "multiif.h" /* for getsock macros */
  37. /* The last 3 #include files should be in this order */
  38. #include "curl_printf.h"
  39. #include "curl_memory.h"
  40. #include "memdebug.h"
  41. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  42. /*
  43. * Helper read-from-socket functions. Does the same as Curl_read() but it
  44. * blocks until all bytes amount of buffersize will be read. No more, no less.
  45. *
  46. * This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions.
  47. */
  48. int Curl_blockread_all(struct connectdata *conn, /* connection data */
  49. curl_socket_t sockfd, /* read from this socket */
  50. char *buf, /* store read data here */
  51. ssize_t buffersize, /* max amount to read */
  52. ssize_t *n) /* amount bytes read */
  53. {
  54. ssize_t nread = 0;
  55. ssize_t allread = 0;
  56. int result;
  57. *n = 0;
  58. for(;;) {
  59. timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, TRUE);
  60. if(timeout_ms < 0) {
  61. /* we already got the timeout */
  62. result = CURLE_OPERATION_TIMEDOUT;
  63. break;
  64. }
  65. if(!timeout_ms)
  66. timeout_ms = TIMEDIFF_T_MAX;
  67. if(SOCKET_READABLE(sockfd, timeout_ms) <= 0) {
  68. result = ~CURLE_OK;
  69. break;
  70. }
  71. result = Curl_read_plain(sockfd, buf, buffersize, &nread);
  72. if(CURLE_AGAIN == result)
  73. continue;
  74. if(result)
  75. break;
  76. if(buffersize == nread) {
  77. allread += nread;
  78. *n = allread;
  79. result = CURLE_OK;
  80. break;
  81. }
  82. if(!nread) {
  83. result = ~CURLE_OK;
  84. break;
  85. }
  86. buffersize -= nread;
  87. buf += nread;
  88. allread += nread;
  89. }
  90. return result;
  91. }
  92. #endif
  93. #ifndef DEBUGBUILD
  94. #define sxstate(x,y) socksstate(x,y)
  95. #else
  96. #define sxstate(x,y) socksstate(x,y, __LINE__)
  97. #endif
  98. /* always use this function to change state, to make debugging easier */
  99. static void socksstate(struct connectdata *conn,
  100. enum connect_t state
  101. #ifdef DEBUGBUILD
  102. , int lineno
  103. #endif
  104. )
  105. {
  106. enum connect_t oldstate = conn->cnnct.state;
  107. #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  108. /* synced with the state list in urldata.h */
  109. static const char * const statename[] = {
  110. "INIT",
  111. "SOCKS_INIT",
  112. "SOCKS_SEND",
  113. "SOCKS_READ_INIT",
  114. "SOCKS_READ",
  115. "GSSAPI_INIT",
  116. "AUTH_INIT",
  117. "AUTH_SEND",
  118. "AUTH_READ",
  119. "REQ_INIT",
  120. "RESOLVING",
  121. "RESOLVED",
  122. "RESOLVE_REMOTE",
  123. "REQ_SEND",
  124. "REQ_SENDING",
  125. "REQ_READ",
  126. "REQ_READ_MORE",
  127. "DONE"
  128. };
  129. #endif
  130. if(oldstate == state)
  131. /* don't bother when the new state is the same as the old state */
  132. return;
  133. conn->cnnct.state = state;
  134. #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  135. infof(conn->data,
  136. "SXSTATE: %s => %s conn %p; line %d\n",
  137. statename[oldstate], statename[conn->cnnct.state], conn,
  138. lineno);
  139. #endif
  140. }
  141. int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
  142. int sockindex)
  143. {
  144. int rc = 0;
  145. sock[0] = conn->sock[sockindex];
  146. switch(conn->cnnct.state) {
  147. case CONNECT_RESOLVING:
  148. case CONNECT_SOCKS_READ:
  149. case CONNECT_AUTH_READ:
  150. case CONNECT_REQ_READ:
  151. case CONNECT_REQ_READ_MORE:
  152. rc = GETSOCK_READSOCK(0);
  153. break;
  154. default:
  155. rc = GETSOCK_WRITESOCK(0);
  156. break;
  157. }
  158. return rc;
  159. }
  160. /*
  161. * This function logs in to a SOCKS4 proxy and sends the specifics to the final
  162. * destination server.
  163. *
  164. * Reference :
  165. * https://www.openssh.com/txt/socks4.protocol
  166. *
  167. * Note :
  168. * Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
  169. * Nonsupport "Identification Protocol (RFC1413)"
  170. */
  171. CURLcode Curl_SOCKS4(const char *proxy_user,
  172. const char *hostname,
  173. int remote_port,
  174. int sockindex,
  175. struct connectdata *conn,
  176. bool *done)
  177. {
  178. const bool protocol4a =
  179. (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
  180. unsigned char *socksreq = &conn->cnnct.socksreq[0];
  181. CURLcode result;
  182. curl_socket_t sockfd = conn->sock[sockindex];
  183. struct Curl_easy *data = conn->data;
  184. struct connstate *sx = &conn->cnnct;
  185. struct Curl_dns_entry *dns = NULL;
  186. ssize_t actualread;
  187. ssize_t written;
  188. if(!SOCKS_STATE(sx->state) && !*done)
  189. sxstate(conn, CONNECT_SOCKS_INIT);
  190. switch(sx->state) {
  191. case CONNECT_SOCKS_INIT:
  192. /* SOCKS4 can only do IPv4, insist! */
  193. conn->ip_version = CURL_IPRESOLVE_V4;
  194. if(conn->bits.httpproxy)
  195. infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
  196. protocol4a ? "a" : "", hostname, remote_port);
  197. infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
  198. /*
  199. * Compose socks4 request
  200. *
  201. * Request format
  202. *
  203. * +----+----+----+----+----+----+----+----+----+----+....+----+
  204. * | VN | CD | DSTPORT | DSTIP | USERID |NULL|
  205. * +----+----+----+----+----+----+----+----+----+----+....+----+
  206. * # of bytes: 1 1 2 4 variable 1
  207. */
  208. socksreq[0] = 4; /* version (SOCKS4) */
  209. socksreq[1] = 1; /* connect */
  210. socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
  211. socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
  212. /* DNS resolve only for SOCKS4, not SOCKS4a */
  213. if(!protocol4a) {
  214. enum resolve_t rc =
  215. Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
  216. if(rc == CURLRESOLV_ERROR)
  217. return CURLE_COULDNT_RESOLVE_PROXY;
  218. else if(rc == CURLRESOLV_PENDING) {
  219. sxstate(conn, CONNECT_RESOLVING);
  220. infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
  221. return CURLE_OK;
  222. }
  223. sxstate(conn, CONNECT_RESOLVED);
  224. goto CONNECT_RESOLVED;
  225. }
  226. /* socks4a doesn't resolve anything locally */
  227. sxstate(conn, CONNECT_REQ_INIT);
  228. goto CONNECT_REQ_INIT;
  229. case CONNECT_RESOLVING:
  230. /* check if we have the name resolved by now */
  231. dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
  232. if(dns) {
  233. #ifdef CURLRES_ASYNCH
  234. conn->async.dns = dns;
  235. conn->async.done = TRUE;
  236. #endif
  237. infof(data, "Hostname '%s' was found\n", hostname);
  238. sxstate(conn, CONNECT_RESOLVED);
  239. }
  240. else {
  241. result = Curl_resolv_check(data->conn, &dns);
  242. if(!dns)
  243. return result;
  244. }
  245. /* FALLTHROUGH */
  246. CONNECT_RESOLVED:
  247. case CONNECT_RESOLVED: {
  248. struct Curl_addrinfo *hp = NULL;
  249. char buf[64];
  250. /*
  251. * We cannot use 'hostent' as a struct that Curl_resolv() returns. It
  252. * returns a Curl_addrinfo pointer that may not always look the same.
  253. */
  254. if(dns)
  255. hp = dns->addr;
  256. if(hp) {
  257. Curl_printable_address(hp, buf, sizeof(buf));
  258. if(hp->ai_family == AF_INET) {
  259. struct sockaddr_in *saddr_in;
  260. saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
  261. socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0];
  262. socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1];
  263. socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
  264. socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];
  265. infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
  266. }
  267. else {
  268. hp = NULL; /* fail! */
  269. failf(data, "SOCKS4 connection to %s not supported\n", buf);
  270. }
  271. Curl_resolv_unlock(data, dns); /* not used anymore from now on */
  272. }
  273. if(!hp) {
  274. failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
  275. hostname);
  276. return CURLE_COULDNT_RESOLVE_HOST;
  277. }
  278. }
  279. /* FALLTHROUGH */
  280. CONNECT_REQ_INIT:
  281. case CONNECT_REQ_INIT:
  282. /*
  283. * This is currently not supporting "Identification Protocol (RFC1413)".
  284. */
  285. socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
  286. if(proxy_user) {
  287. size_t plen = strlen(proxy_user);
  288. if(plen >= sizeof(sx->socksreq) - 8) {
  289. failf(data, "Too long SOCKS proxy name, can't use!\n");
  290. return CURLE_COULDNT_CONNECT;
  291. }
  292. /* copy the proxy name WITH trailing zero */
  293. memcpy(socksreq + 8, proxy_user, plen + 1);
  294. }
  295. /*
  296. * Make connection
  297. */
  298. {
  299. size_t packetsize = 9 +
  300. strlen((char *)socksreq + 8); /* size including NUL */
  301. /* If SOCKS4a, set special invalid IP address 0.0.0.x */
  302. if(protocol4a) {
  303. size_t hostnamelen = 0;
  304. socksreq[4] = 0;
  305. socksreq[5] = 0;
  306. socksreq[6] = 0;
  307. socksreq[7] = 1;
  308. /* append hostname */
  309. hostnamelen = strlen(hostname) + 1; /* length including NUL */
  310. if(hostnamelen <= 255)
  311. strcpy((char *)socksreq + packetsize, hostname);
  312. else {
  313. failf(data, "SOCKS4: too long host name");
  314. return CURLE_COULDNT_CONNECT;
  315. }
  316. packetsize += hostnamelen;
  317. }
  318. sx->outp = socksreq;
  319. sx->outstanding = packetsize;
  320. sxstate(conn, CONNECT_REQ_SENDING);
  321. }
  322. /* FALLTHROUGH */
  323. case CONNECT_REQ_SENDING:
  324. /* Send request */
  325. result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
  326. sx->outstanding, &written);
  327. if(result && (CURLE_AGAIN != result)) {
  328. failf(data, "Failed to send SOCKS4 connect request.");
  329. return CURLE_COULDNT_CONNECT;
  330. }
  331. if(written != sx->outstanding) {
  332. /* not done, remain in state */
  333. sx->outstanding -= written;
  334. sx->outp += written;
  335. return CURLE_OK;
  336. }
  337. /* done sending! */
  338. sx->outstanding = 8; /* receive data size */
  339. sx->outp = socksreq;
  340. sxstate(conn, CONNECT_SOCKS_READ);
  341. /* FALLTHROUGH */
  342. case CONNECT_SOCKS_READ:
  343. /* Receive response */
  344. result = Curl_read_plain(sockfd, (char *)sx->outp,
  345. sx->outstanding, &actualread);
  346. if(result && (CURLE_AGAIN != result)) {
  347. failf(data, "SOCKS4: Failed receiving connect request ack: %s",
  348. curl_easy_strerror(result));
  349. return CURLE_COULDNT_CONNECT;
  350. }
  351. else if(!result && !actualread) {
  352. /* connection closed */
  353. failf(data, "connection to proxy closed");
  354. return CURLE_COULDNT_CONNECT;
  355. }
  356. else if(actualread != sx->outstanding) {
  357. /* remain in reading state */
  358. sx->outstanding -= actualread;
  359. sx->outp += actualread;
  360. return CURLE_OK;
  361. }
  362. sxstate(conn, CONNECT_DONE);
  363. break;
  364. default: /* lots of unused states in SOCKS4 */
  365. break;
  366. }
  367. /*
  368. * Response format
  369. *
  370. * +----+----+----+----+----+----+----+----+
  371. * | VN | CD | DSTPORT | DSTIP |
  372. * +----+----+----+----+----+----+----+----+
  373. * # of bytes: 1 1 2 4
  374. *
  375. * VN is the version of the reply code and should be 0. CD is the result
  376. * code with one of the following values:
  377. *
  378. * 90: request granted
  379. * 91: request rejected or failed
  380. * 92: request rejected because SOCKS server cannot connect to
  381. * identd on the client
  382. * 93: request rejected because the client program and identd
  383. * report different user-ids
  384. */
  385. /* wrong version ? */
  386. if(socksreq[0] != 0) {
  387. failf(data,
  388. "SOCKS4 reply has wrong version, version should be 0.");
  389. return CURLE_COULDNT_CONNECT;
  390. }
  391. /* Result */
  392. switch(socksreq[1]) {
  393. case 90:
  394. infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
  395. break;
  396. case 91:
  397. failf(data,
  398. "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
  399. ", request rejected or failed.",
  400. (unsigned char)socksreq[4], (unsigned char)socksreq[5],
  401. (unsigned char)socksreq[6], (unsigned char)socksreq[7],
  402. (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
  403. (unsigned char)socksreq[1]);
  404. return CURLE_COULDNT_CONNECT;
  405. case 92:
  406. failf(data,
  407. "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
  408. ", request rejected because SOCKS server cannot connect to "
  409. "identd on the client.",
  410. (unsigned char)socksreq[4], (unsigned char)socksreq[5],
  411. (unsigned char)socksreq[6], (unsigned char)socksreq[7],
  412. (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
  413. (unsigned char)socksreq[1]);
  414. return CURLE_COULDNT_CONNECT;
  415. case 93:
  416. failf(data,
  417. "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
  418. ", request rejected because the client program and identd "
  419. "report different user-ids.",
  420. (unsigned char)socksreq[4], (unsigned char)socksreq[5],
  421. (unsigned char)socksreq[6], (unsigned char)socksreq[7],
  422. (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
  423. (unsigned char)socksreq[1]);
  424. return CURLE_COULDNT_CONNECT;
  425. default:
  426. failf(data,
  427. "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
  428. ", Unknown.",
  429. (unsigned char)socksreq[4], (unsigned char)socksreq[5],
  430. (unsigned char)socksreq[6], (unsigned char)socksreq[7],
  431. (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
  432. (unsigned char)socksreq[1]);
  433. return CURLE_COULDNT_CONNECT;
  434. }
  435. *done = TRUE;
  436. return CURLE_OK; /* Proxy was successful! */
  437. }
  438. /*
  439. * This function logs in to a SOCKS5 proxy and sends the specifics to the final
  440. * destination server.
  441. */
  442. CURLcode Curl_SOCKS5(const char *proxy_user,
  443. const char *proxy_password,
  444. const char *hostname,
  445. int remote_port,
  446. int sockindex,
  447. struct connectdata *conn,
  448. bool *done)
  449. {
  450. /*
  451. According to the RFC1928, section "6. Replies". This is what a SOCK5
  452. replies:
  453. +----+-----+-------+------+----------+----------+
  454. |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
  455. +----+-----+-------+------+----------+----------+
  456. | 1 | 1 | X'00' | 1 | Variable | 2 |
  457. +----+-----+-------+------+----------+----------+
  458. Where:
  459. o VER protocol version: X'05'
  460. o REP Reply field:
  461. o X'00' succeeded
  462. */
  463. unsigned char *socksreq = &conn->cnnct.socksreq[0];
  464. char dest[256] = "unknown"; /* printable hostname:port */
  465. int idx;
  466. ssize_t actualread;
  467. ssize_t written;
  468. CURLcode result;
  469. curl_socket_t sockfd = conn->sock[sockindex];
  470. struct Curl_easy *data = conn->data;
  471. bool socks5_resolve_local =
  472. (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
  473. const size_t hostname_len = strlen(hostname);
  474. ssize_t len = 0;
  475. const unsigned long auth = data->set.socks5auth;
  476. bool allow_gssapi = FALSE;
  477. struct connstate *sx = &conn->cnnct;
  478. struct Curl_dns_entry *dns = NULL;
  479. if(!SOCKS_STATE(sx->state) && !*done)
  480. sxstate(conn, CONNECT_SOCKS_INIT);
  481. switch(sx->state) {
  482. case CONNECT_SOCKS_INIT:
  483. if(conn->bits.httpproxy)
  484. infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
  485. hostname, remote_port);
  486. /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
  487. if(!socks5_resolve_local && hostname_len > 255) {
  488. infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
  489. "length > 255 [actual len=%zu]\n", hostname_len);
  490. socks5_resolve_local = TRUE;
  491. }
  492. if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
  493. infof(conn->data,
  494. "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
  495. auth);
  496. if(!(auth & CURLAUTH_BASIC))
  497. /* disable username/password auth */
  498. proxy_user = NULL;
  499. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  500. if(auth & CURLAUTH_GSSAPI)
  501. allow_gssapi = TRUE;
  502. #endif
  503. idx = 0;
  504. socksreq[idx++] = 5; /* version */
  505. idx++; /* number of authentication methods */
  506. socksreq[idx++] = 0; /* no authentication */
  507. if(allow_gssapi)
  508. socksreq[idx++] = 1; /* GSS-API */
  509. if(proxy_user)
  510. socksreq[idx++] = 2; /* username/password */
  511. /* write the number of authentication methods */
  512. socksreq[1] = (unsigned char) (idx - 2);
  513. result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written);
  514. if(result && (CURLE_AGAIN != result)) {
  515. failf(data, "Unable to send initial SOCKS5 request.");
  516. return CURLE_COULDNT_CONNECT;
  517. }
  518. if(written != idx) {
  519. sxstate(conn, CONNECT_SOCKS_SEND);
  520. sx->outstanding = idx - written;
  521. sx->outp = &socksreq[written];
  522. return CURLE_OK;
  523. }
  524. sxstate(conn, CONNECT_SOCKS_READ);
  525. goto CONNECT_SOCKS_READ_INIT;
  526. case CONNECT_SOCKS_SEND:
  527. result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
  528. sx->outstanding, &written);
  529. if(result && (CURLE_AGAIN != result)) {
  530. failf(data, "Unable to send initial SOCKS5 request.");
  531. return CURLE_COULDNT_CONNECT;
  532. }
  533. if(written != sx->outstanding) {
  534. /* not done, remain in state */
  535. sx->outstanding -= written;
  536. sx->outp += written;
  537. return CURLE_OK;
  538. }
  539. /* FALLTHROUGH */
  540. CONNECT_SOCKS_READ_INIT:
  541. case CONNECT_SOCKS_READ_INIT:
  542. sx->outstanding = 2; /* expect two bytes */
  543. sx->outp = socksreq; /* store it here */
  544. /* FALLTHROUGH */
  545. case CONNECT_SOCKS_READ:
  546. result = Curl_read_plain(sockfd, (char *)sx->outp,
  547. sx->outstanding, &actualread);
  548. if(result && (CURLE_AGAIN != result)) {
  549. failf(data, "Unable to receive initial SOCKS5 response.");
  550. return CURLE_COULDNT_CONNECT;
  551. }
  552. else if(!result && !actualread) {
  553. /* connection closed */
  554. failf(data, "Connection to proxy closed");
  555. return CURLE_COULDNT_CONNECT;
  556. }
  557. else if(actualread != sx->outstanding) {
  558. /* remain in reading state */
  559. sx->outstanding -= actualread;
  560. sx->outp += actualread;
  561. return CURLE_OK;
  562. }
  563. else if(socksreq[0] != 5) {
  564. failf(data, "Received invalid version in initial SOCKS5 response.");
  565. return CURLE_COULDNT_CONNECT;
  566. }
  567. else if(socksreq[1] == 0) {
  568. /* DONE! No authentication needed. Send request. */
  569. sxstate(conn, CONNECT_REQ_INIT);
  570. goto CONNECT_REQ_INIT;
  571. }
  572. else if(socksreq[1] == 2) {
  573. /* regular name + password authentication */
  574. sxstate(conn, CONNECT_AUTH_INIT);
  575. goto CONNECT_AUTH_INIT;
  576. }
  577. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  578. else if(allow_gssapi && (socksreq[1] == 1)) {
  579. sxstate(conn, CONNECT_GSSAPI_INIT);
  580. result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
  581. if(result) {
  582. failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
  583. return CURLE_COULDNT_CONNECT;
  584. }
  585. }
  586. #endif
  587. else {
  588. /* error */
  589. if(!allow_gssapi && (socksreq[1] == 1)) {
  590. failf(data,
  591. "SOCKS5 GSSAPI per-message authentication is not supported.");
  592. return CURLE_COULDNT_CONNECT;
  593. }
  594. else if(socksreq[1] == 255) {
  595. failf(data, "No authentication method was acceptable.");
  596. return CURLE_COULDNT_CONNECT;
  597. }
  598. }
  599. failf(data,
  600. "Undocumented SOCKS5 mode attempted to be used by server.");
  601. return CURLE_COULDNT_CONNECT;
  602. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  603. case CONNECT_GSSAPI_INIT:
  604. /* GSSAPI stuff done non-blocking */
  605. break;
  606. #endif
  607. default: /* do nothing! */
  608. break;
  609. CONNECT_AUTH_INIT:
  610. case CONNECT_AUTH_INIT: {
  611. /* Needs user name and password */
  612. size_t proxy_user_len, proxy_password_len;
  613. if(proxy_user && proxy_password) {
  614. proxy_user_len = strlen(proxy_user);
  615. proxy_password_len = strlen(proxy_password);
  616. }
  617. else {
  618. proxy_user_len = 0;
  619. proxy_password_len = 0;
  620. }
  621. /* username/password request looks like
  622. * +----+------+----------+------+----------+
  623. * |VER | ULEN | UNAME | PLEN | PASSWD |
  624. * +----+------+----------+------+----------+
  625. * | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
  626. * +----+------+----------+------+----------+
  627. */
  628. len = 0;
  629. socksreq[len++] = 1; /* username/pw subnegotiation version */
  630. socksreq[len++] = (unsigned char) proxy_user_len;
  631. if(proxy_user && proxy_user_len) {
  632. /* the length must fit in a single byte */
  633. if(proxy_user_len >= 255) {
  634. failf(data, "Excessive user name length for proxy auth");
  635. return CURLE_BAD_FUNCTION_ARGUMENT;
  636. }
  637. memcpy(socksreq + len, proxy_user, proxy_user_len);
  638. }
  639. len += proxy_user_len;
  640. socksreq[len++] = (unsigned char) proxy_password_len;
  641. if(proxy_password && proxy_password_len) {
  642. /* the length must fit in a single byte */
  643. if(proxy_password_len > 255) {
  644. failf(data, "Excessive password length for proxy auth");
  645. return CURLE_BAD_FUNCTION_ARGUMENT;
  646. }
  647. memcpy(socksreq + len, proxy_password, proxy_password_len);
  648. }
  649. len += proxy_password_len;
  650. sxstate(conn, CONNECT_AUTH_SEND);
  651. sx->outstanding = len;
  652. sx->outp = socksreq;
  653. }
  654. /* FALLTHROUGH */
  655. case CONNECT_AUTH_SEND:
  656. result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
  657. sx->outstanding, &written);
  658. if(result && (CURLE_AGAIN != result)) {
  659. failf(data, "Failed to send SOCKS5 sub-negotiation request.");
  660. return CURLE_COULDNT_CONNECT;
  661. }
  662. if(sx->outstanding != written) {
  663. /* remain in state */
  664. sx->outstanding -= written;
  665. sx->outp += written;
  666. return CURLE_OK;
  667. }
  668. sx->outp = socksreq;
  669. sx->outstanding = 2;
  670. sxstate(conn, CONNECT_AUTH_READ);
  671. /* FALLTHROUGH */
  672. case CONNECT_AUTH_READ:
  673. result = Curl_read_plain(sockfd, (char *)sx->outp,
  674. sx->outstanding, &actualread);
  675. if(result && (CURLE_AGAIN != result)) {
  676. failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
  677. return CURLE_COULDNT_CONNECT;
  678. }
  679. else if(!result && !actualread) {
  680. /* connection closed */
  681. failf(data, "connection to proxy closed");
  682. return CURLE_COULDNT_CONNECT;
  683. }
  684. else if(actualread != sx->outstanding) {
  685. /* remain in state */
  686. sx->outstanding -= actualread;
  687. sx->outp += actualread;
  688. return CURLE_OK;
  689. }
  690. /* ignore the first (VER) byte */
  691. else if(socksreq[1] != 0) { /* status */
  692. failf(data, "User was rejected by the SOCKS5 server (%d %d).",
  693. socksreq[0], socksreq[1]);
  694. return CURLE_COULDNT_CONNECT;
  695. }
  696. /* Everything is good so far, user was authenticated! */
  697. sxstate(conn, CONNECT_REQ_INIT);
  698. /* FALLTHROUGH */
  699. CONNECT_REQ_INIT:
  700. case CONNECT_REQ_INIT:
  701. if(socks5_resolve_local) {
  702. enum resolve_t rc = Curl_resolv(conn, hostname, remote_port,
  703. FALSE, &dns);
  704. if(rc == CURLRESOLV_ERROR)
  705. return CURLE_COULDNT_RESOLVE_HOST;
  706. if(rc == CURLRESOLV_PENDING) {
  707. sxstate(conn, CONNECT_RESOLVING);
  708. return CURLE_OK;
  709. }
  710. sxstate(conn, CONNECT_RESOLVED);
  711. goto CONNECT_RESOLVED;
  712. }
  713. goto CONNECT_RESOLVE_REMOTE;
  714. case CONNECT_RESOLVING:
  715. /* check if we have the name resolved by now */
  716. dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
  717. if(dns) {
  718. #ifdef CURLRES_ASYNCH
  719. conn->async.dns = dns;
  720. conn->async.done = TRUE;
  721. #endif
  722. infof(data, "SOCKS5: hostname '%s' found\n", hostname);
  723. }
  724. if(!dns) {
  725. result = Curl_resolv_check(data->conn, &dns);
  726. if(!dns)
  727. return result;
  728. }
  729. /* FALLTHROUGH */
  730. CONNECT_RESOLVED:
  731. case CONNECT_RESOLVED: {
  732. struct Curl_addrinfo *hp = NULL;
  733. size_t destlen;
  734. if(dns)
  735. hp = dns->addr;
  736. if(!hp) {
  737. failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
  738. hostname);
  739. return CURLE_COULDNT_RESOLVE_HOST;
  740. }
  741. Curl_printable_address(hp, dest, sizeof(dest));
  742. destlen = strlen(dest);
  743. msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
  744. len = 0;
  745. socksreq[len++] = 5; /* version (SOCKS5) */
  746. socksreq[len++] = 1; /* connect */
  747. socksreq[len++] = 0; /* must be zero */
  748. if(hp->ai_family == AF_INET) {
  749. int i;
  750. struct sockaddr_in *saddr_in;
  751. socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
  752. saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
  753. for(i = 0; i < 4; i++) {
  754. socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
  755. }
  756. infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest);
  757. }
  758. #ifdef ENABLE_IPV6
  759. else if(hp->ai_family == AF_INET6) {
  760. int i;
  761. struct sockaddr_in6 *saddr_in6;
  762. socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
  763. saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
  764. for(i = 0; i < 16; i++) {
  765. socksreq[len++] =
  766. ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
  767. }
  768. infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest);
  769. }
  770. #endif
  771. else {
  772. hp = NULL; /* fail! */
  773. failf(data, "SOCKS5 connection to %s not supported\n", dest);
  774. }
  775. Curl_resolv_unlock(data, dns); /* not used anymore from now on */
  776. goto CONNECT_REQ_SEND;
  777. }
  778. CONNECT_RESOLVE_REMOTE:
  779. case CONNECT_RESOLVE_REMOTE:
  780. /* Authentication is complete, now specify destination to the proxy */
  781. len = 0;
  782. socksreq[len++] = 5; /* version (SOCKS5) */
  783. socksreq[len++] = 1; /* connect */
  784. socksreq[len++] = 0; /* must be zero */
  785. if(!socks5_resolve_local) {
  786. socksreq[len++] = 3; /* ATYP: domain name = 3 */
  787. socksreq[len++] = (char) hostname_len; /* one byte address length */
  788. memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
  789. len += hostname_len;
  790. infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n",
  791. hostname, remote_port);
  792. }
  793. /* FALLTHROUGH */
  794. CONNECT_REQ_SEND:
  795. case CONNECT_REQ_SEND:
  796. /* PORT MSB */
  797. socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff);
  798. /* PORT LSB */
  799. socksreq[len++] = (unsigned char)(remote_port & 0xff);
  800. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  801. if(conn->socks5_gssapi_enctype) {
  802. failf(data, "SOCKS5 GSS-API protection not yet implemented.");
  803. return CURLE_COULDNT_CONNECT;
  804. }
  805. #endif
  806. sx->outp = socksreq;
  807. sx->outstanding = len;
  808. sxstate(conn, CONNECT_REQ_SENDING);
  809. /* FALLTHROUGH */
  810. case CONNECT_REQ_SENDING:
  811. result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
  812. sx->outstanding, &written);
  813. if(result && (CURLE_AGAIN != result)) {
  814. failf(data, "Failed to send SOCKS5 connect request.");
  815. return CURLE_COULDNT_CONNECT;
  816. }
  817. if(sx->outstanding != written) {
  818. /* remain in state */
  819. sx->outstanding -= written;
  820. sx->outp += written;
  821. return CURLE_OK;
  822. }
  823. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  824. if(conn->socks5_gssapi_enctype) {
  825. failf(data, "SOCKS5 GSS-API protection not yet implemented.");
  826. return CURLE_COULDNT_CONNECT;
  827. }
  828. #endif
  829. sx->outstanding = 10; /* minimum packet size is 10 */
  830. sx->outp = socksreq;
  831. sxstate(conn, CONNECT_REQ_READ);
  832. /* FALLTHROUGH */
  833. case CONNECT_REQ_READ:
  834. result = Curl_read_plain(sockfd, (char *)sx->outp,
  835. sx->outstanding, &actualread);
  836. if(result && (CURLE_AGAIN != result)) {
  837. failf(data, "Failed to receive SOCKS5 connect request ack.");
  838. return CURLE_COULDNT_CONNECT;
  839. }
  840. else if(!result && !actualread) {
  841. /* connection closed */
  842. failf(data, "connection to proxy closed");
  843. return CURLE_COULDNT_CONNECT;
  844. }
  845. else if(actualread != sx->outstanding) {
  846. /* remain in state */
  847. sx->outstanding -= actualread;
  848. sx->outp += actualread;
  849. return CURLE_OK;
  850. }
  851. if(socksreq[0] != 5) { /* version */
  852. failf(data,
  853. "SOCKS5 reply has wrong version, version should be 5.");
  854. return CURLE_COULDNT_CONNECT;
  855. }
  856. else if(socksreq[1] != 0) { /* Anything besides 0 is an error */
  857. failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
  858. hostname, (unsigned char)socksreq[1]);
  859. return CURLE_COULDNT_CONNECT;
  860. }
  861. /* Fix: in general, returned BND.ADDR is variable length parameter by RFC
  862. 1928, so the reply packet should be read until the end to avoid errors
  863. at subsequent protocol level.
  864. +----+-----+-------+------+----------+----------+
  865. |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
  866. +----+-----+-------+------+----------+----------+
  867. | 1 | 1 | X'00' | 1 | Variable | 2 |
  868. +----+-----+-------+------+----------+----------+
  869. ATYP:
  870. o IP v4 address: X'01', BND.ADDR = 4 byte
  871. o domain name: X'03', BND.ADDR = [ 1 byte length, string ]
  872. o IP v6 address: X'04', BND.ADDR = 16 byte
  873. */
  874. /* Calculate real packet size */
  875. if(socksreq[3] == 3) {
  876. /* domain name */
  877. int addrlen = (int) socksreq[4];
  878. len = 5 + addrlen + 2;
  879. }
  880. else if(socksreq[3] == 4) {
  881. /* IPv6 */
  882. len = 4 + 16 + 2;
  883. }
  884. else if(socksreq[3] == 1) {
  885. len = 4 + 4 + 2;
  886. }
  887. else {
  888. failf(data, "SOCKS5 reply has wrong address type.");
  889. return CURLE_COULDNT_CONNECT;
  890. }
  891. /* At this point we already read first 10 bytes */
  892. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  893. if(!conn->socks5_gssapi_enctype) {
  894. /* decrypt_gssapi_blockread already read the whole packet */
  895. #endif
  896. if(len > 10) {
  897. sx->outstanding = len - 10; /* get the rest */
  898. sx->outp = &socksreq[10];
  899. sxstate(conn, CONNECT_REQ_READ_MORE);
  900. }
  901. else {
  902. sxstate(conn, CONNECT_DONE);
  903. break;
  904. }
  905. #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  906. }
  907. #endif
  908. /* FALLTHROUGH */
  909. case CONNECT_REQ_READ_MORE:
  910. result = Curl_read_plain(sockfd, (char *)sx->outp,
  911. sx->outstanding, &actualread);
  912. if(result && (CURLE_AGAIN != result)) {
  913. failf(data, "Failed to receive SOCKS5 connect request ack.");
  914. return CURLE_COULDNT_CONNECT;
  915. }
  916. else if(!result && !actualread) {
  917. /* connection closed */
  918. failf(data, "connection to proxy closed");
  919. return CURLE_COULDNT_CONNECT;
  920. }
  921. else if(actualread != sx->outstanding) {
  922. /* remain in state */
  923. sx->outstanding -= actualread;
  924. sx->outp += actualread;
  925. return CURLE_OK;
  926. }
  927. sxstate(conn, CONNECT_DONE);
  928. }
  929. infof(data, "SOCKS5 request granted.\n");
  930. *done = TRUE;
  931. return CURLE_OK; /* Proxy was successful! */
  932. }
  933. #endif /* CURL_DISABLE_PROXY */