gateway.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  1. /*********************************************************************
  2. *
  3. * File : $Source: /cvsroot/ijbswa/current/gateway.c,v $
  4. *
  5. * Purpose : Contains functions to connect to a server, possibly
  6. * using a "forwarder" (i.e. HTTP proxy and/or a SOCKS4
  7. * or SOCKS5 proxy).
  8. *
  9. * Copyright : Written by and Copyright (C) 2001-2020 the
  10. * Privoxy team. https://www.privoxy.org/
  11. *
  12. * Based on the Internet Junkbuster originally written
  13. * by and Copyright (C) 1997 Anonymous Coders and
  14. * Junkbusters Corporation. http://www.junkbusters.com
  15. *
  16. * This program is free software; you can redistribute it
  17. * and/or modify it under the terms of the GNU General
  18. * Public License as published by the Free Software
  19. * Foundation; either version 2 of the License, or (at
  20. * your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will
  23. * be useful, but WITHOUT ANY WARRANTY; without even the
  24. * implied warranty of MERCHANTABILITY or FITNESS FOR A
  25. * PARTICULAR PURPOSE. See the GNU General Public
  26. * License for more details.
  27. *
  28. * The GNU General Public License should be included with
  29. * this file. If not, you can view it at
  30. * http://www.gnu.org/copyleft/gpl.html
  31. * or write to the Free Software Foundation, Inc., 59
  32. * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  33. *
  34. *********************************************************************/
  35. #include "config.h"
  36. #include <stdio.h>
  37. #include <sys/types.h>
  38. #ifndef _WIN32
  39. #include <netinet/in.h>
  40. #endif
  41. #include <errno.h>
  42. #include <string.h>
  43. #include "assert.h"
  44. #ifdef _WIN32
  45. #include <winsock2.h>
  46. #endif /* def _WIN32 */
  47. #ifdef __BEOS__
  48. #include <netdb.h>
  49. #endif /* def __BEOS__ */
  50. #include "project.h"
  51. #include "jcc.h"
  52. #include "errlog.h"
  53. #include "jbsockets.h"
  54. #include "gateway.h"
  55. #include "miscutil.h"
  56. #include "list.h"
  57. #include "parsers.h"
  58. #ifdef FEATURE_CONNECTION_KEEP_ALIVE
  59. #ifdef HAVE_POLL
  60. #ifdef __GLIBC__
  61. #include <sys/poll.h>
  62. #else
  63. #include <poll.h>
  64. #endif /* def __GLIBC__ */
  65. #endif /* HAVE_POLL */
  66. #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
  67. static jb_socket socks4_connect(const struct forward_spec *fwd,
  68. const char *target_host,
  69. int target_port,
  70. struct client_state *csp);
  71. static jb_socket socks5_connect(const struct forward_spec *fwd,
  72. const char *target_host,
  73. int target_port,
  74. struct client_state *csp);
  75. enum {
  76. SOCKS4_REQUEST_GRANTED = 90,
  77. SOCKS4_REQUEST_REJECT = 91,
  78. SOCKS4_REQUEST_IDENT_FAILED = 92,
  79. SOCKS4_REQUEST_IDENT_CONFLICT = 93
  80. };
  81. enum {
  82. SOCKS5_REQUEST_GRANTED = 0,
  83. SOCKS5_REQUEST_FAILED = 1,
  84. SOCKS5_REQUEST_DENIED = 2,
  85. SOCKS5_REQUEST_NETWORK_UNREACHABLE = 3,
  86. SOCKS5_REQUEST_HOST_UNREACHABLE = 4,
  87. SOCKS5_REQUEST_CONNECTION_REFUSED = 5,
  88. SOCKS5_REQUEST_TTL_EXPIRED = 6,
  89. SOCKS5_REQUEST_PROTOCOL_ERROR = 7,
  90. SOCKS5_REQUEST_BAD_ADDRESS_TYPE = 8
  91. };
  92. /* structure of a socks client operation */
  93. struct socks_op {
  94. unsigned char vn; /* socks version number */
  95. unsigned char cd; /* command code */
  96. unsigned char dstport[2]; /* destination port */
  97. unsigned char dstip[4]; /* destination address */
  98. char userid; /* first byte of userid */
  99. char padding[3]; /* make sure sizeof(struct socks_op) is endian-independent. */
  100. /* more bytes of the userid follow, terminated by a NULL */
  101. };
  102. /* structure of a socks server reply */
  103. struct socks_reply {
  104. unsigned char vn; /* socks version number */
  105. unsigned char cd; /* command code */
  106. unsigned char dstport[2]; /* destination port */
  107. unsigned char dstip[4]; /* destination address */
  108. };
  109. static const char socks_userid[] = "anonymous";
  110. #ifdef FEATURE_CONNECTION_SHARING
  111. #ifndef FEATURE_CONNECTION_KEEP_ALIVE
  112. #error Using FEATURE_CONNECTION_SHARING without FEATURE_CONNECTION_KEEP_ALIVE is impossible
  113. #endif
  114. #define MAX_REUSABLE_CONNECTIONS 100
  115. static struct reusable_connection reusable_connection[MAX_REUSABLE_CONNECTIONS];
  116. static int mark_connection_unused(const struct reusable_connection *connection);
  117. /*********************************************************************
  118. *
  119. * Function : initialize_reusable_connections
  120. *
  121. * Description : Initializes the reusable_connection structures.
  122. * Must be called with connection_reuse_mutex locked.
  123. *
  124. * Parameters : N/A
  125. *
  126. * Returns : void
  127. *
  128. *********************************************************************/
  129. extern void initialize_reusable_connections(void)
  130. {
  131. unsigned int slot = 0;
  132. #if !defined(HAVE_POLL) && !defined(_WIN32)
  133. log_error(LOG_LEVEL_INFO,
  134. "Detecting already dead connections might not work "
  135. "correctly on your platform. In case of problems, "
  136. "unset the keep-alive-timeout option.");
  137. #endif
  138. for (slot = 0; slot < SZ(reusable_connection); slot++)
  139. {
  140. mark_connection_closed(&reusable_connection[slot]);
  141. }
  142. log_error(LOG_LEVEL_CONNECT, "Initialized %d socket slots.", slot);
  143. }
  144. /*********************************************************************
  145. *
  146. * Function : remember_connection
  147. *
  148. * Description : Remembers a server connection for reuse later on.
  149. *
  150. * Parameters :
  151. * 1 : connection = The server connection to remember.
  152. *
  153. * Returns : void
  154. *
  155. *********************************************************************/
  156. void remember_connection(const struct reusable_connection *connection)
  157. {
  158. unsigned int slot = 0;
  159. int free_slot_found = FALSE;
  160. assert(NULL != connection);
  161. assert(connection->sfd != JB_INVALID_SOCKET);
  162. if (mark_connection_unused(connection))
  163. {
  164. return;
  165. }
  166. privoxy_mutex_lock(&connection_reuse_mutex);
  167. /* Find free socket slot. */
  168. for (slot = 0; slot < SZ(reusable_connection); slot++)
  169. {
  170. if (reusable_connection[slot].sfd == JB_INVALID_SOCKET)
  171. {
  172. assert(reusable_connection[slot].in_use == 0);
  173. log_error(LOG_LEVEL_CONNECT,
  174. "Remembering socket %d for %s:%d in slot %d.",
  175. connection->sfd, connection->host, connection->port, slot);
  176. free_slot_found = TRUE;
  177. break;
  178. }
  179. }
  180. if (!free_slot_found)
  181. {
  182. log_error(LOG_LEVEL_CONNECT,
  183. "No free slots found to remember socket for %s:%d. Last slot %d.",
  184. connection->host, connection->port, slot);
  185. privoxy_mutex_unlock(&connection_reuse_mutex);
  186. close_socket(connection->sfd);
  187. return;
  188. }
  189. assert(slot < SZ(reusable_connection));
  190. assert(NULL != connection->host);
  191. reusable_connection[slot].host = strdup_or_die(connection->host);
  192. reusable_connection[slot].sfd = connection->sfd;
  193. reusable_connection[slot].port = connection->port;
  194. reusable_connection[slot].in_use = 0;
  195. reusable_connection[slot].timestamp = connection->timestamp;
  196. reusable_connection[slot].request_sent = connection->request_sent;
  197. reusable_connection[slot].response_received = connection->response_received;
  198. reusable_connection[slot].keep_alive_timeout = connection->keep_alive_timeout;
  199. reusable_connection[slot].requests_sent_total = connection->requests_sent_total;
  200. assert(reusable_connection[slot].gateway_host == NULL);
  201. assert(reusable_connection[slot].gateway_port == 0);
  202. assert(reusable_connection[slot].auth_username == NULL);
  203. assert(reusable_connection[slot].auth_password == NULL);
  204. assert(reusable_connection[slot].forwarder_type == SOCKS_NONE);
  205. assert(reusable_connection[slot].forward_host == NULL);
  206. assert(reusable_connection[slot].forward_port == 0);
  207. reusable_connection[slot].forwarder_type = connection->forwarder_type;
  208. if (NULL != connection->gateway_host)
  209. {
  210. reusable_connection[slot].gateway_host = strdup_or_die(connection->gateway_host);
  211. }
  212. else
  213. {
  214. reusable_connection[slot].gateway_host = NULL;
  215. }
  216. reusable_connection[slot].gateway_port = connection->gateway_port;
  217. if (NULL != connection->auth_username)
  218. {
  219. reusable_connection[slot].auth_username = strdup_or_die(connection->auth_username);
  220. }
  221. else
  222. {
  223. reusable_connection[slot].auth_username = NULL;
  224. }
  225. if (NULL != connection->auth_password)
  226. {
  227. reusable_connection[slot].auth_password = strdup_or_die(connection->auth_password);
  228. }
  229. else
  230. {
  231. reusable_connection[slot].auth_password = NULL;
  232. }
  233. if (NULL != connection->forward_host)
  234. {
  235. reusable_connection[slot].forward_host = strdup_or_die(connection->forward_host);
  236. }
  237. else
  238. {
  239. reusable_connection[slot].forward_host = NULL;
  240. }
  241. reusable_connection[slot].forward_port = connection->forward_port;
  242. privoxy_mutex_unlock(&connection_reuse_mutex);
  243. }
  244. #endif /* def FEATURE_CONNECTION_SHARING */
  245. /*********************************************************************
  246. *
  247. * Function : mark_connection_closed
  248. *
  249. * Description : Marks a reused connection closed.
  250. *
  251. * Parameters :
  252. * 1 : closed_connection = The connection to mark as closed.
  253. *
  254. * Returns : void
  255. *
  256. *********************************************************************/
  257. void mark_connection_closed(struct reusable_connection *closed_connection)
  258. {
  259. closed_connection->in_use = FALSE;
  260. closed_connection->sfd = JB_INVALID_SOCKET;
  261. freez(closed_connection->host);
  262. closed_connection->port = 0;
  263. closed_connection->timestamp = 0;
  264. closed_connection->request_sent = 0;
  265. closed_connection->response_received = 0;
  266. closed_connection->keep_alive_timeout = 0;
  267. closed_connection->requests_sent_total = 0;
  268. closed_connection->forwarder_type = SOCKS_NONE;
  269. freez(closed_connection->gateway_host);
  270. closed_connection->gateway_port = 0;
  271. freez(closed_connection->auth_username);
  272. freez(closed_connection->auth_password);
  273. freez(closed_connection->forward_host);
  274. closed_connection->forward_port = 0;
  275. }
  276. #ifdef FEATURE_CONNECTION_SHARING
  277. /*********************************************************************
  278. *
  279. * Function : forget_connection
  280. *
  281. * Description : Removes a previously remembered connection from
  282. * the list of reusable connections.
  283. *
  284. * Parameters :
  285. * 1 : sfd = The socket belonging to the connection in question.
  286. *
  287. * Returns : void
  288. *
  289. *********************************************************************/
  290. void forget_connection(jb_socket sfd)
  291. {
  292. unsigned int slot = 0;
  293. assert(sfd != JB_INVALID_SOCKET);
  294. privoxy_mutex_lock(&connection_reuse_mutex);
  295. for (slot = 0; slot < SZ(reusable_connection); slot++)
  296. {
  297. if (reusable_connection[slot].sfd == sfd)
  298. {
  299. assert(reusable_connection[slot].in_use);
  300. log_error(LOG_LEVEL_CONNECT,
  301. "Forgetting socket %d for %s:%d in slot %d.",
  302. sfd, reusable_connection[slot].host,
  303. reusable_connection[slot].port, slot);
  304. mark_connection_closed(&reusable_connection[slot]);
  305. break;
  306. }
  307. }
  308. privoxy_mutex_unlock(&connection_reuse_mutex);
  309. }
  310. #endif /* def FEATURE_CONNECTION_SHARING */
  311. #ifdef FEATURE_CONNECTION_KEEP_ALIVE
  312. /*********************************************************************
  313. *
  314. * Function : string_or_none
  315. *
  316. * Description : Returns a given string or "none" if a NULL pointer
  317. * is given.
  318. * Helper function for connection_destination_matches().
  319. *
  320. * Parameters :
  321. * 1 : string = The string to check.
  322. *
  323. * Returns : The string if non-NULL, "none" otherwise.
  324. *
  325. *********************************************************************/
  326. static const char *string_or_none(const char *string)
  327. {
  328. return(string != NULL ? string : "none");
  329. }
  330. /*********************************************************************
  331. *
  332. * Function : connection_detail_matches
  333. *
  334. * Description : Helper function for connection_destination_matches().
  335. * Compares strings which can be NULL.
  336. *
  337. * Parameters :
  338. * 1 : connection_detail = The connection detail to compare.
  339. * 2 : fowarder_detail = The forwarder detail to compare.
  340. *
  341. * Returns : TRUE for yes, FALSE otherwise.
  342. *
  343. *********************************************************************/
  344. static int connection_detail_matches(const char *connection_detail,
  345. const char *forwarder_detail)
  346. {
  347. if (connection_detail == NULL && forwarder_detail == NULL)
  348. {
  349. /* Both details are unset. */
  350. return TRUE;
  351. }
  352. if ((connection_detail == NULL && forwarder_detail != NULL)
  353. || (connection_detail != NULL && forwarder_detail == NULL))
  354. {
  355. /* Only one detail isn't set. */
  356. return FALSE;
  357. }
  358. /* Both details are set, but do they match? */
  359. return(!strcmpic(connection_detail, forwarder_detail));
  360. }
  361. /*********************************************************************
  362. *
  363. * Function : connection_destination_matches
  364. *
  365. * Description : Determines whether a remembered connection can
  366. * be reused. That is, whether the destination and
  367. * the forwarding settings match.
  368. *
  369. * Parameters :
  370. * 1 : connection = The connection to check.
  371. * 2 : http = The destination for the connection.
  372. * 3 : fwd = The forwarder settings.
  373. *
  374. * Returns : TRUE for yes, FALSE otherwise.
  375. *
  376. *********************************************************************/
  377. int connection_destination_matches(const struct reusable_connection *connection,
  378. const struct http_request *http,
  379. const struct forward_spec *fwd)
  380. {
  381. if ((connection->forwarder_type != fwd->type)
  382. || (connection->gateway_port != fwd->gateway_port)
  383. || (connection->forward_port != fwd->forward_port)
  384. || (connection->port != http->port))
  385. {
  386. return FALSE;
  387. }
  388. if (!connection_detail_matches(connection->gateway_host, fwd->gateway_host))
  389. {
  390. log_error(LOG_LEVEL_CONNECT,
  391. "Gateway mismatch. Previous gateway: %s. Current gateway: %s",
  392. string_or_none(connection->gateway_host),
  393. string_or_none(fwd->gateway_host));
  394. return FALSE;
  395. }
  396. if (!connection_detail_matches(connection->auth_username, fwd->auth_username))
  397. {
  398. log_error(LOG_LEVEL_CONNECT, "Socks user name mismatch. "
  399. "Previous user name: %s. Current user name: %s",
  400. string_or_none(connection->auth_username),
  401. string_or_none(fwd->auth_username));
  402. return FALSE;
  403. }
  404. if (!connection_detail_matches(connection->auth_password, fwd->auth_password))
  405. {
  406. log_error(LOG_LEVEL_CONNECT, "Socks user name mismatch. "
  407. "Previous password: %s. Current password: %s",
  408. string_or_none(connection->auth_password),
  409. string_or_none(fwd->auth_password));
  410. return FALSE;
  411. }
  412. if (!connection_detail_matches(connection->forward_host, fwd->forward_host))
  413. {
  414. log_error(LOG_LEVEL_CONNECT,
  415. "Forwarding proxy mismatch. Previous proxy: %s. Current proxy: %s",
  416. string_or_none(connection->forward_host),
  417. string_or_none(fwd->forward_host));
  418. return FALSE;
  419. }
  420. return (!strcmpic(connection->host, http->host));
  421. }
  422. #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
  423. #ifdef FEATURE_CONNECTION_SHARING
  424. /*********************************************************************
  425. *
  426. * Function : close_unusable_connections
  427. *
  428. * Description : Closes remembered connections that have timed
  429. * out or have been closed on the other side.
  430. *
  431. * Parameters : none
  432. *
  433. * Returns : Number of connections that are still alive.
  434. *
  435. *********************************************************************/
  436. int close_unusable_connections(void)
  437. {
  438. unsigned int slot = 0;
  439. int connections_alive = 0;
  440. privoxy_mutex_lock(&connection_reuse_mutex);
  441. for (slot = 0; slot < SZ(reusable_connection); slot++)
  442. {
  443. if (!reusable_connection[slot].in_use
  444. && (JB_INVALID_SOCKET != reusable_connection[slot].sfd))
  445. {
  446. time_t time_open = time(NULL) - reusable_connection[slot].timestamp;
  447. time_t latency = (reusable_connection[slot].response_received -
  448. reusable_connection[slot].request_sent) / 2;
  449. if (reusable_connection[slot].keep_alive_timeout < time_open + latency)
  450. {
  451. log_error(LOG_LEVEL_CONNECT,
  452. "The connection to %s:%d in slot %d timed out. "
  453. "Closing socket %d. Timeout is: %d. Assumed latency: %ld.",
  454. reusable_connection[slot].host,
  455. reusable_connection[slot].port, slot,
  456. reusable_connection[slot].sfd,
  457. reusable_connection[slot].keep_alive_timeout,
  458. latency);
  459. close_socket(reusable_connection[slot].sfd);
  460. mark_connection_closed(&reusable_connection[slot]);
  461. }
  462. else if (!socket_is_still_alive(reusable_connection[slot].sfd))
  463. {
  464. log_error(LOG_LEVEL_CONNECT,
  465. "The connection to %s:%d in slot %d is no longer usable. "
  466. "Closing socket %d.", reusable_connection[slot].host,
  467. reusable_connection[slot].port, slot,
  468. reusable_connection[slot].sfd);
  469. close_socket(reusable_connection[slot].sfd);
  470. mark_connection_closed(&reusable_connection[slot]);
  471. }
  472. else
  473. {
  474. connections_alive++;
  475. }
  476. }
  477. }
  478. privoxy_mutex_unlock(&connection_reuse_mutex);
  479. return connections_alive;
  480. }
  481. /*********************************************************************
  482. *
  483. * Function : get_reusable_connection
  484. *
  485. * Description : Returns an open socket to a previously remembered
  486. * open connection (if there is one).
  487. *
  488. * Parameters :
  489. * 1 : http = The destination for the connection.
  490. * 2 : fwd = The forwarder settings.
  491. *
  492. * Returns : JB_INVALID_SOCKET => No reusable connection found,
  493. * otherwise a usable socket.
  494. *
  495. *********************************************************************/
  496. static jb_socket get_reusable_connection(const struct http_request *http,
  497. const struct forward_spec *fwd)
  498. {
  499. jb_socket sfd = JB_INVALID_SOCKET;
  500. unsigned int slot = 0;
  501. close_unusable_connections();
  502. privoxy_mutex_lock(&connection_reuse_mutex);
  503. for (slot = 0; slot < SZ(reusable_connection); slot++)
  504. {
  505. if (!reusable_connection[slot].in_use
  506. && (JB_INVALID_SOCKET != reusable_connection[slot].sfd))
  507. {
  508. if (connection_destination_matches(&reusable_connection[slot], http, fwd))
  509. {
  510. reusable_connection[slot].in_use = TRUE;
  511. sfd = reusable_connection[slot].sfd;
  512. log_error(LOG_LEVEL_CONNECT,
  513. "Found reusable socket %d for %s:%d in slot %d. Timestamp made %ld "
  514. "seconds ago. Timeout: %d. Latency: %d. Requests served: %d",
  515. sfd, reusable_connection[slot].host, reusable_connection[slot].port,
  516. slot, time(NULL) - reusable_connection[slot].timestamp,
  517. reusable_connection[slot].keep_alive_timeout,
  518. (int)(reusable_connection[slot].response_received -
  519. reusable_connection[slot].request_sent),
  520. reusable_connection[slot].requests_sent_total);
  521. break;
  522. }
  523. }
  524. }
  525. privoxy_mutex_unlock(&connection_reuse_mutex);
  526. return sfd;
  527. }
  528. /*********************************************************************
  529. *
  530. * Function : mark_connection_unused
  531. *
  532. * Description : Gives a remembered connection free for reuse.
  533. *
  534. * Parameters :
  535. * 1 : connection = The connection in question.
  536. *
  537. * Returns : TRUE => Socket found and marked as unused.
  538. * FALSE => Socket not found.
  539. *
  540. *********************************************************************/
  541. static int mark_connection_unused(const struct reusable_connection *connection)
  542. {
  543. unsigned int slot = 0;
  544. int socket_found = FALSE;
  545. assert(connection->sfd != JB_INVALID_SOCKET);
  546. privoxy_mutex_lock(&connection_reuse_mutex);
  547. for (slot = 0; slot < SZ(reusable_connection); slot++)
  548. {
  549. if (reusable_connection[slot].sfd == connection->sfd)
  550. {
  551. assert(reusable_connection[slot].in_use);
  552. socket_found = TRUE;
  553. log_error(LOG_LEVEL_CONNECT,
  554. "Marking open socket %d for %s:%d in slot %d as unused.",
  555. connection->sfd, reusable_connection[slot].host,
  556. reusable_connection[slot].port, slot);
  557. reusable_connection[slot].in_use = 0;
  558. reusable_connection[slot].timestamp = connection->timestamp;
  559. break;
  560. }
  561. }
  562. privoxy_mutex_unlock(&connection_reuse_mutex);
  563. return socket_found;
  564. }
  565. #endif /* def FEATURE_CONNECTION_SHARING */
  566. /*********************************************************************
  567. *
  568. * Function : forwarded_connect
  569. *
  570. * Description : Connect to a specified web server, possibly via
  571. * a HTTP proxy and/or a SOCKS proxy.
  572. *
  573. * Parameters :
  574. * 1 : fwd = the proxies to use when connecting.
  575. * 2 : http = the http request and apropos headers
  576. * 3 : csp = Current client state (buffers, headers, etc...)
  577. *
  578. * Returns : JB_INVALID_SOCKET => failure, else it is the socket file descriptor.
  579. *
  580. *********************************************************************/
  581. jb_socket forwarded_connect(const struct forward_spec *fwd,
  582. struct http_request *http,
  583. struct client_state *csp)
  584. {
  585. const char *dest_host;
  586. int dest_port;
  587. jb_socket sfd = JB_INVALID_SOCKET;
  588. #ifdef FEATURE_CONNECTION_SHARING
  589. if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
  590. && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
  591. {
  592. sfd = get_reusable_connection(http, fwd);
  593. if (JB_INVALID_SOCKET != sfd)
  594. {
  595. return sfd;
  596. }
  597. }
  598. #endif /* def FEATURE_CONNECTION_SHARING */
  599. /* Figure out if we need to connect to the web server or a HTTP proxy. */
  600. if (fwd->forward_host)
  601. {
  602. /* HTTP proxy */
  603. dest_host = fwd->forward_host;
  604. dest_port = fwd->forward_port;
  605. }
  606. else
  607. {
  608. /* Web server */
  609. dest_host = http->host;
  610. dest_port = http->port;
  611. }
  612. /* Connect, maybe using a SOCKS proxy */
  613. switch (fwd->type)
  614. {
  615. case SOCKS_NONE:
  616. case FORWARD_WEBSERVER:
  617. sfd = connect_to(dest_host, dest_port, csp);
  618. break;
  619. case SOCKS_4:
  620. case SOCKS_4A:
  621. sfd = socks4_connect(fwd, dest_host, dest_port, csp);
  622. break;
  623. case SOCKS_5:
  624. case SOCKS_5T:
  625. sfd = socks5_connect(fwd, dest_host, dest_port, csp);
  626. break;
  627. default:
  628. /* Should never get here */
  629. log_error(LOG_LEVEL_FATAL,
  630. "Internal error in forwarded_connect(). Bad proxy type: %d", fwd->type);
  631. }
  632. if (JB_INVALID_SOCKET != sfd)
  633. {
  634. log_error(LOG_LEVEL_CONNECT,
  635. "Created new connection to %s:%d on socket %d.",
  636. http->host, http->port, sfd);
  637. }
  638. return sfd;
  639. }
  640. #ifdef FUZZ
  641. /*********************************************************************
  642. *
  643. * Function : socks_fuzz
  644. *
  645. * Description : Wrapper around socks[45]_connect() used for fuzzing.
  646. *
  647. * Parameters :
  648. * 1 : csp = Current client state (buffers, headers, etc...)
  649. *
  650. * Returns : JB_ERR_OK or JB_ERR_PARSE
  651. *
  652. *********************************************************************/
  653. extern jb_err socks_fuzz(struct client_state *csp)
  654. {
  655. jb_socket socket;
  656. static struct forward_spec fwd;
  657. char target_host[] = "fuzz.example.org";
  658. int target_port = 12345;
  659. fwd.gateway_host = strdup_or_die("fuzz.example.org");
  660. fwd.gateway_port = 12345;
  661. fwd.type = SOCKS_4A;
  662. socket = socks4_connect(&fwd, target_host, target_port, csp);
  663. if (JB_INVALID_SOCKET != socket)
  664. {
  665. fwd.type = SOCKS_5;
  666. socket = socks5_connect(&fwd, target_host, target_port, csp);
  667. }
  668. if (JB_INVALID_SOCKET == socket)
  669. {
  670. log_error(LOG_LEVEL_ERROR, "%s", csp->error_message);
  671. return JB_ERR_PARSE;
  672. }
  673. log_error(LOG_LEVEL_INFO, "Input looks like an acceptable socks response");
  674. return JB_ERR_OK;
  675. }
  676. #endif
  677. /*********************************************************************
  678. *
  679. * Function : socks4_connect
  680. *
  681. * Description : Connect to the SOCKS server, and connect through
  682. * it to the specified server. This handles
  683. * all the SOCKS negotiation, and returns a file
  684. * descriptor for a socket which can be treated as a
  685. * normal (non-SOCKS) socket.
  686. *
  687. * Logged error messages are saved to csp->error_message
  688. * and later reused by error_response() for the CGI
  689. * message. strdup allocation failures are handled there.
  690. *
  691. * Parameters :
  692. * 1 : fwd = Specifies the SOCKS proxy to use.
  693. * 2 : target_host = The final server to connect to.
  694. * 3 : target_port = The final port to connect to.
  695. * 4 : csp = Current client state (buffers, headers, etc...)
  696. *
  697. * Returns : JB_INVALID_SOCKET => failure, else a socket file descriptor.
  698. *
  699. *********************************************************************/
  700. static jb_socket socks4_connect(const struct forward_spec *fwd,
  701. const char *target_host,
  702. int target_port,
  703. struct client_state *csp)
  704. {
  705. unsigned long web_server_addr;
  706. char buf[BUFFER_SIZE];
  707. struct socks_op *c = (struct socks_op *)buf;
  708. struct socks_reply *s = (struct socks_reply *)buf;
  709. size_t n;
  710. size_t csiz;
  711. jb_socket sfd;
  712. int err = 0;
  713. char *errstr = NULL;
  714. if ((fwd->gateway_host == NULL) || (*fwd->gateway_host == '\0'))
  715. {
  716. /* XXX: Shouldn't the config file parser prevent this? */
  717. errstr = "NULL gateway host specified.";
  718. err = 1;
  719. }
  720. if (fwd->gateway_port <= 0)
  721. {
  722. errstr = "invalid gateway port specified.";
  723. err = 1;
  724. }
  725. if (err)
  726. {
  727. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
  728. csp->error_message = strdup(errstr);
  729. errno = EINVAL;
  730. return(JB_INVALID_SOCKET);
  731. }
  732. /* build a socks request for connection to the web server */
  733. strlcpy(&(c->userid), socks_userid, sizeof(buf) - sizeof(struct socks_op));
  734. csiz = sizeof(*c) + sizeof(socks_userid) - sizeof(c->userid) - sizeof(c->padding);
  735. switch (fwd->type)
  736. {
  737. case SOCKS_4:
  738. web_server_addr = resolve_hostname_to_ip(target_host);
  739. if (web_server_addr == INADDR_NONE)
  740. {
  741. errstr = "could not resolve target host";
  742. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s %s", errstr, target_host);
  743. err = 1;
  744. }
  745. else
  746. {
  747. web_server_addr = htonl(web_server_addr);
  748. }
  749. break;
  750. case SOCKS_4A:
  751. web_server_addr = 0x00000001;
  752. n = csiz + strlen(target_host) + 1;
  753. if (n > sizeof(buf))
  754. {
  755. errno = EINVAL;
  756. errstr = "buffer cbuf too small.";
  757. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
  758. err = 1;
  759. }
  760. else
  761. {
  762. strlcpy(buf + csiz, target_host, sizeof(buf) - sizeof(struct socks_op) - csiz);
  763. /*
  764. * What we forward to the socks4a server should have the
  765. * size of socks_op, plus the length of the userid plus
  766. * its \0 byte (which we don't have to add because the
  767. * first byte of the userid is counted twice as it's also
  768. * part of sock_op) minus the padding bytes (which are part
  769. * of the userid as well), plus the length of the target_host
  770. * (which is stored csiz bytes after the beginning of the buffer),
  771. * plus another \0 byte.
  772. */
  773. assert(n == sizeof(struct socks_op) + strlen(&(c->userid)) - sizeof(c->padding) + strlen(buf + csiz) + 1);
  774. csiz = n;
  775. }
  776. break;
  777. default:
  778. /* Should never get here */
  779. log_error(LOG_LEVEL_FATAL,
  780. "socks4_connect: SOCKS4 impossible internal error - bad SOCKS type.");
  781. /* Not reached */
  782. return(JB_INVALID_SOCKET);
  783. }
  784. if (err)
  785. {
  786. csp->error_message = strdup(errstr);
  787. return(JB_INVALID_SOCKET);
  788. }
  789. c->vn = 4;
  790. c->cd = 1;
  791. c->dstport[0] = (unsigned char)((target_port >> 8 ) & 0xff);
  792. c->dstport[1] = (unsigned char)((target_port ) & 0xff);
  793. c->dstip[0] = (unsigned char)((web_server_addr >> 24) & 0xff);
  794. c->dstip[1] = (unsigned char)((web_server_addr >> 16) & 0xff);
  795. c->dstip[2] = (unsigned char)((web_server_addr >> 8) & 0xff);
  796. c->dstip[3] = (unsigned char)((web_server_addr ) & 0xff);
  797. #ifdef FUZZ
  798. sfd = 0;
  799. #else
  800. /* pass the request to the socks server */
  801. sfd = connect_to(fwd->gateway_host, fwd->gateway_port, csp);
  802. if (sfd == JB_INVALID_SOCKET)
  803. {
  804. /* The error an its reason have already been logged by connect_to() */
  805. return(JB_INVALID_SOCKET);
  806. }
  807. else if (write_socket(sfd, (char *)c, csiz))
  808. {
  809. errstr = "SOCKS4 negotiation write failed.";
  810. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
  811. err = 1;
  812. close_socket(sfd);
  813. }
  814. else if (!data_is_available(sfd, csp->config->socket_timeout))
  815. {
  816. if (socket_is_still_alive(sfd))
  817. {
  818. errstr = "SOCKS4 negotiation timed out";
  819. }
  820. else
  821. {
  822. errstr = "SOCKS4 negotiation got aborted by the server";
  823. }
  824. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
  825. err = 1;
  826. close_socket(sfd);
  827. }
  828. else
  829. #endif
  830. if (read_socket(sfd, buf, sizeof(buf)) != sizeof(*s))
  831. {
  832. errstr = "SOCKS4 negotiation read failed.";
  833. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
  834. err = 1;
  835. close_socket(sfd);
  836. }
  837. if (err)
  838. {
  839. csp->error_message = strdup(errstr);
  840. return(JB_INVALID_SOCKET);
  841. }
  842. switch (s->cd)
  843. {
  844. case SOCKS4_REQUEST_GRANTED:
  845. return(sfd);
  846. case SOCKS4_REQUEST_REJECT:
  847. errstr = "SOCKS request rejected or failed.";
  848. errno = EINVAL;
  849. break;
  850. case SOCKS4_REQUEST_IDENT_FAILED:
  851. errstr = "SOCKS request rejected because "
  852. "SOCKS server cannot connect to identd on the client.";
  853. errno = EACCES;
  854. break;
  855. case SOCKS4_REQUEST_IDENT_CONFLICT:
  856. errstr = "SOCKS request rejected because "
  857. "the client program and identd report "
  858. "different user-ids.";
  859. errno = EACCES;
  860. break;
  861. default:
  862. errno = ENOENT;
  863. snprintf(buf, sizeof(buf),
  864. "SOCKS request rejected for reason code %d.", s->cd);
  865. errstr = buf;
  866. }
  867. log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
  868. csp->error_message = strdup(errstr);
  869. close_socket(sfd);
  870. return(JB_INVALID_SOCKET);
  871. }
  872. /*********************************************************************
  873. *
  874. * Function : translate_socks5_error
  875. *
  876. * Description : Translates a SOCKS errors to a string.
  877. *
  878. * Parameters :
  879. * 1 : socks_error = The error code to translate.
  880. *
  881. * Returns : The string translation.
  882. *
  883. *********************************************************************/
  884. static const char *translate_socks5_error(int socks_error)
  885. {
  886. switch (socks_error)
  887. {
  888. /* XXX: these should be more descriptive */
  889. case SOCKS5_REQUEST_FAILED:
  890. return "SOCKS5 request failed";
  891. case SOCKS5_REQUEST_DENIED:
  892. return "SOCKS5 request denied";
  893. case SOCKS5_REQUEST_NETWORK_UNREACHABLE:
  894. return "SOCKS5 network unreachable";
  895. case SOCKS5_REQUEST_HOST_UNREACHABLE:
  896. return "SOCKS5 destination host unreachable";
  897. case SOCKS5_REQUEST_CONNECTION_REFUSED:
  898. return "SOCKS5 connection refused";
  899. case SOCKS5_REQUEST_TTL_EXPIRED:
  900. return "SOCKS5 TTL expired";
  901. case SOCKS5_REQUEST_PROTOCOL_ERROR:
  902. return "SOCKS5 client protocol error";
  903. case SOCKS5_REQUEST_BAD_ADDRESS_TYPE:
  904. return "SOCKS5 domain names unsupported";
  905. case SOCKS5_REQUEST_GRANTED:
  906. return "everything's peachy";
  907. default:
  908. return "SOCKS5 negotiation protocol error";
  909. }
  910. }
  911. /*********************************************************************
  912. *
  913. * Function : socks5_connect
  914. *
  915. * Description : Connect to the SOCKS server, and connect through
  916. * it to the specified server. This handles
  917. * all the SOCKS negotiation, and returns a file
  918. * descriptor for a socket which can be treated as a
  919. * normal (non-SOCKS) socket.
  920. *
  921. * Parameters :
  922. * 1 : fwd = Specifies the SOCKS proxy to use.
  923. * 2 : target_host = The final server to connect to.
  924. * 3 : target_port = The final port to connect to.
  925. * 4 : csp = Current client state (buffers, headers, etc...)
  926. *
  927. * Returns : JB_INVALID_SOCKET => failure, else a socket file descriptor.
  928. *
  929. *********************************************************************/
  930. static jb_socket socks5_connect(const struct forward_spec *fwd,
  931. const char *target_host,
  932. int target_port,
  933. struct client_state *csp)
  934. {
  935. #define SIZE_SOCKS5_REPLY_IPV4 10
  936. #define SIZE_SOCKS5_REPLY_IPV6 22
  937. #define SOCKS5_REPLY_DIFFERENCE (SIZE_SOCKS5_REPLY_IPV6 - SIZE_SOCKS5_REPLY_IPV4)
  938. int err = 0;
  939. char cbuf[300];
  940. char sbuf[SIZE_SOCKS5_REPLY_IPV6];
  941. size_t client_pos = 0;
  942. int server_size = 0;
  943. size_t hostlen = 0;
  944. jb_socket sfd;
  945. const char *errstr = NULL;
  946. assert(fwd->gateway_host);
  947. if ((fwd->gateway_host == NULL) || (*fwd->gateway_host == '\0'))
  948. {
  949. errstr = "NULL gateway host specified";
  950. err = 1;
  951. }
  952. if (fwd->gateway_port <= 0)
  953. {
  954. /*
  955. * XXX: currently this can't happen because in
  956. * case of invalid gateway ports we use the defaults.
  957. * Of course we really shouldn't do that.
  958. */
  959. errstr = "invalid gateway port specified";
  960. err = 1;
  961. }
  962. hostlen = strlen(target_host);
  963. if (hostlen > (size_t)255)
  964. {
  965. errstr = "target host name is longer than 255 characters";
  966. err = 1;
  967. }
  968. if ((fwd->type != SOCKS_5) && (fwd->type != SOCKS_5T))
  969. {
  970. /* Should never get here */
  971. log_error(LOG_LEVEL_FATAL,
  972. "SOCKS5 impossible internal error - bad SOCKS type");
  973. err = 1;
  974. }
  975. if (err)
  976. {
  977. errno = EINVAL;
  978. assert(errstr != NULL);
  979. log_error(LOG_LEVEL_CONNECT, "socks5_connect: %s", errstr);
  980. csp->error_message = strdup(errstr);
  981. return(JB_INVALID_SOCKET);
  982. }
  983. #ifdef FUZZ
  984. sfd = 0;
  985. if (!err && read_socket(sfd, sbuf, 2) != 2)
  986. #else
  987. /* pass the request to the socks server */
  988. sfd = connect_to(fwd->gateway_host, fwd->gateway_port, csp);
  989. if (sfd == JB_INVALID_SOCKET)
  990. {
  991. errstr = "socks5 server unreachable";
  992. log_error(LOG_LEVEL_CONNECT, "socks5_connect: %s", errstr);
  993. /* Free the generic error message provided by connect_to() */
  994. freez(csp->error_message);
  995. csp->error_message = strdup(errstr);
  996. return(JB_INVALID_SOCKET);
  997. }
  998. client_pos = 0;
  999. cbuf[client_pos++] = '\x05'; /* Version */
  1000. if (fwd->auth_username && fwd->auth_password)
  1001. {
  1002. cbuf[client_pos++] = '\x02'; /* Two authentication methods supported */
  1003. cbuf[client_pos++] = '\x02'; /* Username/password */
  1004. }
  1005. else
  1006. {
  1007. cbuf[client_pos++] = '\x01'; /* One authentication method supported */
  1008. }
  1009. cbuf[client_pos++] = '\x00'; /* The no authentication authentication method */
  1010. if (write_socket(sfd, cbuf, client_pos))
  1011. {
  1012. errstr = "SOCKS5 negotiation write failed";
  1013. csp->error_message = strdup(errstr);
  1014. log_error(LOG_LEVEL_CONNECT, "%s", errstr);
  1015. close_socket(sfd);
  1016. return(JB_INVALID_SOCKET);
  1017. }
  1018. if (!data_is_available(sfd, csp->config->socket_timeout))
  1019. {
  1020. if (socket_is_still_alive(sfd))
  1021. {
  1022. errstr = "SOCKS5 negotiation timed out";
  1023. }
  1024. else
  1025. {
  1026. errstr = "SOCKS5 negotiation got aborted by the server";
  1027. }
  1028. err = 1;
  1029. }
  1030. if (!err && read_socket(sfd, sbuf, sizeof(sbuf)) != 2)
  1031. #endif
  1032. {
  1033. errstr = "SOCKS5 negotiation read failed";
  1034. err = 1;
  1035. }
  1036. if (!err && (sbuf[0] != '\x05'))
  1037. {
  1038. errstr = "SOCKS5 negotiation protocol version error";
  1039. err = 1;
  1040. }
  1041. if (!err && (sbuf[1] == '\xff'))
  1042. {
  1043. errstr = "SOCKS5 authentication required";
  1044. err = 1;
  1045. }
  1046. if (!err && (sbuf[1] == '\x02'))
  1047. {
  1048. /* check cbuf overflow */
  1049. size_t auth_len = strlen(fwd->auth_username) + strlen(fwd->auth_password) + 3;
  1050. if (auth_len > sizeof(cbuf))
  1051. {
  1052. errstr = "SOCKS5 username and/or password too long";
  1053. err = 1;
  1054. }
  1055. if (!err)
  1056. {
  1057. client_pos = 0;
  1058. cbuf[client_pos++] = '\x01'; /* Version */
  1059. cbuf[client_pos++] = (char)strlen(fwd->auth_username);
  1060. memcpy(cbuf + client_pos, fwd->auth_username, strlen(fwd->auth_username));
  1061. client_pos += strlen(fwd->auth_username);
  1062. cbuf[client_pos++] = (char)strlen(fwd->auth_password);
  1063. memcpy(cbuf + client_pos, fwd->auth_password, strlen(fwd->auth_password));
  1064. client_pos += strlen(fwd->auth_password);
  1065. if (write_socket(sfd, cbuf, client_pos))
  1066. {
  1067. errstr = "SOCKS5 negotiation auth write failed";
  1068. csp->error_message = strdup(errstr);
  1069. log_error(LOG_LEVEL_CONNECT, "%s", errstr);
  1070. close_socket(sfd);
  1071. return(JB_INVALID_SOCKET);
  1072. }
  1073. if (read_socket(sfd, sbuf, sizeof(sbuf)) != 2)
  1074. {
  1075. errstr = "SOCKS5 negotiation auth read failed";
  1076. err = 1;
  1077. }
  1078. }
  1079. if (!err && (sbuf[1] != '\x00'))
  1080. {
  1081. errstr = "SOCKS5 authentication failed";
  1082. err = 1;
  1083. }
  1084. }
  1085. else if (!err && (sbuf[1] != '\x00'))
  1086. {
  1087. errstr = "SOCKS5 negotiation protocol error";
  1088. err = 1;
  1089. }
  1090. if (err)
  1091. {
  1092. assert(errstr != NULL);
  1093. log_error(LOG_LEVEL_CONNECT, "socks5_connect: %s", errstr);
  1094. csp->error_message = strdup(errstr);
  1095. close_socket(sfd);
  1096. errno = EINVAL;
  1097. return(JB_INVALID_SOCKET);
  1098. }
  1099. client_pos = 0;
  1100. cbuf[client_pos++] = '\x05'; /* Version */
  1101. cbuf[client_pos++] = '\x01'; /* TCP connect */
  1102. cbuf[client_pos++] = '\x00'; /* Reserved, must be 0x00 */
  1103. cbuf[client_pos++] = '\x03'; /* Address is domain name */
  1104. cbuf[client_pos++] = (char)(hostlen & 0xffu);
  1105. assert(sizeof(cbuf) - client_pos > (size_t)255);
  1106. /* Using strncpy because we really want the nul byte padding. */
  1107. strncpy(cbuf + client_pos, target_host, sizeof(cbuf) - client_pos);
  1108. client_pos += (hostlen & 0xffu);
  1109. cbuf[client_pos++] = (char)((target_port >> 8) & 0xff);
  1110. cbuf[client_pos++] = (char)((target_port ) & 0xff);
  1111. #ifndef FUZZ
  1112. if (write_socket(sfd, cbuf, client_pos))
  1113. {
  1114. errstr = "SOCKS5 negotiation write failed";
  1115. csp->error_message = strdup(errstr);
  1116. log_error(LOG_LEVEL_CONNECT, "%s", errstr);
  1117. close_socket(sfd);
  1118. errno = EINVAL;
  1119. return(JB_INVALID_SOCKET);
  1120. }
  1121. /*
  1122. * Optimistically send the HTTP request with the initial
  1123. * SOCKS request if the user enabled the use of Tor extensions,
  1124. * the CONNECT method isn't being used (in which case the client
  1125. * doesn't send data until it gets our 200 response) and the
  1126. * client request has actually been completely read already.
  1127. */
  1128. if ((fwd->type == SOCKS_5T) && (csp->http->ssl == 0)
  1129. && (csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ))
  1130. {
  1131. char *client_headers = list_to_text(csp->headers);
  1132. size_t header_length;
  1133. if (client_headers == NULL)
  1134. {
  1135. log_error(LOG_LEVEL_FATAL, "Out of memory rebuilding client headers");
  1136. }
  1137. list_remove_all(csp->headers);
  1138. header_length= strlen(client_headers);
  1139. log_error(LOG_LEVEL_CONNECT,
  1140. "Optimistically sending %lu bytes of client headers intended for %s",
  1141. header_length, csp->http->hostport);
  1142. if (write_socket(sfd, client_headers, header_length))
  1143. {
  1144. log_error(LOG_LEVEL_CONNECT,
  1145. "optimistically writing header to: %s failed: %E", csp->http->hostport);
  1146. freez(client_headers);
  1147. return(JB_INVALID_SOCKET);
  1148. }
  1149. freez(client_headers);
  1150. if (csp->expected_client_content_length != 0)
  1151. {
  1152. unsigned long long buffered_request_bytes =
  1153. (unsigned long long)(csp->client_iob->eod - csp->client_iob->cur);
  1154. log_error(LOG_LEVEL_CONNECT,
  1155. "Optimistically sending %llu bytes of client body. Expected %llu",
  1156. csp->expected_client_content_length, buffered_request_bytes);
  1157. assert(csp->expected_client_content_length == buffered_request_bytes);
  1158. if (write_socket(sfd, csp->client_iob->cur, buffered_request_bytes))
  1159. {
  1160. log_error(LOG_LEVEL_CONNECT,
  1161. "optimistically writing %llu bytes of client body to: %s failed: %E",
  1162. buffered_request_bytes, csp->http->hostport);
  1163. return(JB_INVALID_SOCKET);
  1164. }
  1165. clear_iob(csp->client_iob);
  1166. }
  1167. }
  1168. #endif
  1169. server_size = read_socket(sfd, sbuf, SIZE_SOCKS5_REPLY_IPV4);
  1170. if (server_size != SIZE_SOCKS5_REPLY_IPV4)
  1171. {
  1172. errstr = "SOCKS5 negotiation read failed";
  1173. }
  1174. else
  1175. {
  1176. if (sbuf[0] != '\x05')
  1177. {
  1178. errstr = "SOCKS5 negotiation protocol version error";
  1179. }
  1180. else if (sbuf[2] != '\x00')
  1181. {
  1182. errstr = "SOCKS5 negotiation protocol error";
  1183. }
  1184. else if (sbuf[1] != SOCKS5_REQUEST_GRANTED)
  1185. {
  1186. errstr = translate_socks5_error(sbuf[1]);
  1187. }
  1188. else
  1189. {
  1190. if (sbuf[3] == '\x04')
  1191. {
  1192. /*
  1193. * The address field contains an IPv6 address
  1194. * which means we didn't get the whole reply
  1195. * yet. Read and discard the rest of it to make
  1196. * sure it isn't treated as HTTP data later on.
  1197. */
  1198. server_size = read_socket(sfd, sbuf, SOCKS5_REPLY_DIFFERENCE);
  1199. if (server_size != SOCKS5_REPLY_DIFFERENCE)
  1200. {
  1201. errstr = "SOCKS5 negotiation read failed (IPv6 address)";
  1202. }
  1203. }
  1204. else if (sbuf[3] != '\x01')
  1205. {
  1206. errstr = "SOCKS5 reply contains unsupported address type";
  1207. }
  1208. if (errstr == NULL)
  1209. {
  1210. return(sfd);
  1211. }
  1212. }
  1213. }
  1214. assert(errstr != NULL);
  1215. csp->error_message = strdup(errstr);
  1216. log_error(LOG_LEVEL_CONNECT, "socks5_connect: %s", errstr);
  1217. close_socket(sfd);
  1218. errno = EINVAL;
  1219. return(JB_INVALID_SOCKET);
  1220. }
  1221. /*
  1222. Local Variables:
  1223. tab-width: 3
  1224. end:
  1225. */