socks.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009-2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file util/socks.c
  18. * @brief SOCKS5 connection support
  19. * @author Jeffrey Burdges
  20. *
  21. * These routines should be called only on newly active connections.
  22. */
  23. #include "platform.h"
  24. #include "gnunet_util_lib.h"
  25. #define LOG(kind, ...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__)
  26. #define LOG_STRERROR(kind, syscall) \
  27. GNUNET_log_from_strerror (kind, "util-socks", syscall)
  28. /* SOCKS5 authentication methods */
  29. #define SOCKS5_AUTH_REJECT 0xFF /* No acceptable auth method */
  30. #define SOCKS5_AUTH_NOAUTH 0x00 /* without authentication */
  31. #define SOCKS5_AUTH_GSSAPI 0x01 /* GSSAPI */
  32. #define SOCKS5_AUTH_USERPASS 0x02 /* User/Password */
  33. #define SOCKS5_AUTH_CHAP 0x03 /* Challenge-Handshake Auth Proto. */
  34. #define SOCKS5_AUTH_EAP 0x05 /* Extensible Authentication Proto. */
  35. #define SOCKS5_AUTH_MAF 0x08 /* Multi-Authentication Framework */
  36. /* SOCKS5 connection responses */
  37. #define SOCKS5_REP_SUCCEEDED 0x00 /* succeeded */
  38. #define SOCKS5_REP_FAIL 0x01 /* general SOCKS serer failure */
  39. #define SOCKS5_REP_NALLOWED 0x02 /* connection not allowed by ruleset */
  40. #define SOCKS5_REP_NUNREACH 0x03 /* Network unreachable */
  41. #define SOCKS5_REP_HUNREACH 0x04 /* Host unreachable */
  42. #define SOCKS5_REP_REFUSED 0x05 /* connection refused */
  43. #define SOCKS5_REP_EXPIRED 0x06 /* TTL expired */
  44. #define SOCKS5_REP_CNOTSUP 0x07 /* Command not supported */
  45. #define SOCKS5_REP_ANOTSUP 0x08 /* Address not supported */
  46. #define SOCKS5_REP_INVADDR 0x09 /* Invalid address */
  47. const char *
  48. SOCKS5_REP_names (int rep)
  49. {
  50. switch (rep)
  51. {
  52. case SOCKS5_REP_SUCCEEDED:
  53. return "succeeded";
  54. case SOCKS5_REP_FAIL:
  55. return "general SOCKS server failure";
  56. case SOCKS5_REP_NALLOWED:
  57. return "connection not allowed by ruleset";
  58. case SOCKS5_REP_NUNREACH:
  59. return "Network unreachable";
  60. case SOCKS5_REP_HUNREACH:
  61. return "Host unreachable";
  62. case SOCKS5_REP_REFUSED:
  63. return "connection refused";
  64. case SOCKS5_REP_EXPIRED:
  65. return "TTL expired";
  66. case SOCKS5_REP_CNOTSUP:
  67. return "Command not supported";
  68. case SOCKS5_REP_ANOTSUP:
  69. return "Address not supported";
  70. case SOCKS5_REP_INVADDR:
  71. return "Invalid address";
  72. default:
  73. return NULL;
  74. }
  75. };
  76. /**
  77. * Encode a string for the SOCKS5 protocol by prefixing it a byte stating its
  78. * length and stripping the trailing zero byte. Truncates any string longer
  79. * than 255 bytes.
  80. *
  81. * @param b buffer to contain the encoded string
  82. * @param s string to encode
  83. * @return pointer to the end of the encoded string in the buffer
  84. */
  85. unsigned char *
  86. SOCK5_proto_string (unsigned char *b, const char *s)
  87. {
  88. size_t l = strlen (s);
  89. if (l > 255)
  90. {
  91. LOG (GNUNET_ERROR_TYPE_WARNING,
  92. "SOCKS5 cannot handle hostnames, usernames, or passwords over 255 bytes, truncating.\n");
  93. l = 255;
  94. }
  95. *(b++) = (unsigned char) l;
  96. memcpy (b, s, l);
  97. return b + l;
  98. }
  99. #define SOCKS5_step_greet 0
  100. #define SOCKS5_step_auth 1
  101. #define SOCKS5_step_cmd 2
  102. #define SOCKS5_step_done 3
  103. /**
  104. * State of the SOCKS5 handshake.
  105. */
  106. struct GNUNET_SOCKS_Handshake
  107. {
  108. /**
  109. * Connection handle used for SOCKS5
  110. */
  111. struct GNUNET_CONNECTION_Handle *socks5_connection;
  112. /**
  113. * Connection handle initially returned to client
  114. */
  115. struct GNUNET_CONNECTION_Handle *target_connection;
  116. /**
  117. * Transmission handle on socks5_connection.
  118. */
  119. struct GNUNET_CONNECTION_TransmitHandle *th;
  120. /**
  121. * Our stage in the SOCKS5 handshake
  122. */
  123. int step;
  124. /**
  125. * Precomputed SOCKS5 handshake output buffer
  126. */
  127. unsigned char outbuf[1024];
  128. /**
  129. * Pointers delineating protoocol steps in the output buffer
  130. */
  131. unsigned char *(outstep[4]);
  132. /**
  133. * SOCKS5 handshake input buffer
  134. */
  135. unsigned char inbuf[1024];
  136. /**
  137. * Pointers delimiting the current step in the input buffer
  138. */
  139. unsigned char *instart;
  140. unsigned char *inend;
  141. };
  142. /* Registering prototypes */
  143. void
  144. register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want);
  145. /* In fact, the client sends first rule in GNUnet suggests one could take
  146. * large mac read sizes without fear of screwing up the proxied protocol,
  147. * but we make a proper SOCKS5 client. */
  148. #define register_reciever_wants(ih) ((SOCKS5_step_cmd == ih->step) ? 10 : 2)
  149. struct GNUNET_CONNECTION_TransmitHandle *
  150. register_sender (struct GNUNET_SOCKS_Handshake *ih);
  151. /**
  152. * Conclude the SOCKS5 handshake successfully.
  153. *
  154. * @param ih SOCKS5 handshake, consumed here.
  155. * @param c open unused connection, consumed here.
  156. * @return Connection handle that becomes usable when the handshake completes.
  157. */
  158. void
  159. SOCKS5_handshake_done (struct GNUNET_SOCKS_Handshake *ih)
  160. {
  161. GNUNET_CONNECTION_acivate_proxied (ih->target_connection);
  162. }
  163. /**
  164. * Read one step in the SOCKS5 handshake.
  165. *
  166. * @param ih SOCKS5 Handshake
  167. */
  168. void
  169. SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
  170. {
  171. unsigned char *b = ih->instart;
  172. size_t available = ih->inend - b;
  173. int want = register_reciever_wants (ih);
  174. if (available < want)
  175. {
  176. register_reciever (ih, want - available);
  177. return;
  178. }
  179. GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
  180. switch (ih->step)
  181. {
  182. case SOCKS5_step_greet: /* SOCKS5 server's greeting */
  183. if (b[0] != 5)
  184. {
  185. LOG (GNUNET_ERROR_TYPE_ERROR, "Not a SOCKS5 server\n");
  186. GNUNET_assert (0);
  187. }
  188. switch (b[1])
  189. {
  190. case SOCKS5_AUTH_NOAUTH:
  191. ih->step = SOCKS5_step_cmd; /* no authentication to do */
  192. break;
  193. case SOCKS5_AUTH_USERPASS:
  194. ih->step = SOCKS5_step_auth;
  195. break;
  196. case SOCKS5_AUTH_REJECT:
  197. LOG (GNUNET_ERROR_TYPE_ERROR, "No authentication method accepted\n");
  198. return;
  199. default:
  200. LOG (GNUNET_ERROR_TYPE_ERROR,
  201. "Not a SOCKS5 server / Nonsensical authentication\n");
  202. return;
  203. }
  204. b += 2;
  205. break;
  206. case SOCKS5_step_auth: /* SOCKS5 server's response to authentication */
  207. if (b[1] != 0)
  208. {
  209. LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 authentication failed\n");
  210. GNUNET_assert (0);
  211. }
  212. ih->step = SOCKS5_step_cmd;
  213. b += 2;
  214. break;
  215. case SOCKS5_step_cmd: /* SOCKS5 server's response to command */
  216. if (b[0] != 5)
  217. {
  218. LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 protocol error\n");
  219. GNUNET_assert (0);
  220. }
  221. if (0 != b[1])
  222. {
  223. LOG (GNUNET_ERROR_TYPE_ERROR,
  224. "SOCKS5 connection error : %s\n",
  225. SOCKS5_REP_names (b[1]));
  226. return;
  227. }
  228. b += 3;
  229. /* There is no reason to verify host and port afaik. */
  230. switch (*(b++))
  231. {
  232. case 1: /* IPv4 */
  233. b += sizeof(struct in_addr); /* 4 */
  234. break;
  235. case 4: /* IPv6 */
  236. b += sizeof(struct in6_addr); /* 16 */
  237. break;
  238. case 3: /* hostname */
  239. b += *b;
  240. break;
  241. }
  242. b += 2; /* port */
  243. if (b > ih->inend)
  244. {
  245. register_reciever (ih, b - ih->inend);
  246. return;
  247. }
  248. ih->step = SOCKS5_step_done;
  249. LOG (GNUNET_ERROR_TYPE_DEBUG,
  250. "SOCKS5 server : %s\n",
  251. SOCKS5_REP_names (b[1]));
  252. ih->instart = b;
  253. SOCKS5_handshake_done (ih);
  254. return;
  255. case SOCKS5_step_done:
  256. GNUNET_assert (0);
  257. }
  258. ih->instart = b;
  259. /* Do not reschedule the sender unless we're done reading.
  260. * I imagine this lets us avoid ever cancelling the transmit handle. */
  261. register_sender (ih);
  262. }
  263. /**
  264. * Callback to read from the SOCKS5 proxy.
  265. *
  266. * @param client the service
  267. * @param handler function to call with the message
  268. * @param handler_cls closure for @a handler
  269. */
  270. void
  271. receiver (void *cls,
  272. const void *buf,
  273. size_t available,
  274. const struct sockaddr *addr,
  275. socklen_t addrlen,
  276. int errCode)
  277. {
  278. struct GNUNET_SOCKS_Handshake *ih = cls;
  279. GNUNET_assert (&ih->inend[available] < &ih->inbuf[1024]);
  280. GNUNET_memcpy (ih->inend, buf, available);
  281. ih->inend += available;
  282. SOCKS5_handshake_step (ih);
  283. }
  284. /**
  285. * Register callback to read from the SOCKS5 proxy.
  286. *
  287. * @param client the service
  288. * @param handler function to call with the message
  289. * @param handler_cls closure for @a handler
  290. */
  291. void
  292. register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want)
  293. {
  294. GNUNET_CONNECTION_receive (ih->socks5_connection,
  295. want,
  296. GNUNET_TIME_relative_get_minute_ (),
  297. &receiver,
  298. ih);
  299. }
  300. /**
  301. * Register SOCKS5 handshake sender
  302. *
  303. * @param cls closure (SOCKS handshake)
  304. * @param size number of bytes available in @a buf
  305. * @param buf where the callee should write the message
  306. * @return number of bytes written to @a buf
  307. */
  308. size_t
  309. transmit_ready (void *cls, size_t size, void *buf)
  310. {
  311. struct GNUNET_SOCKS_Handshake *ih = cls;
  312. /* connection.c has many routines that call us with buf == NULL :
  313. * signal_transmit_error() - DNS, etc. active
  314. * connect_fail_continuation()
  315. * connect_probe_continuation() - timeout
  316. * try_connect_using_address() - DNS failure/timeout
  317. * transmit_timeout() - retry failed?
  318. * GNUNET_CONNECTION_notify_transmit_ready() can schedule :
  319. * transmit_timeout() - DNS still working
  320. * connect_error() - DNS done but no socket?
  321. * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
  322. * We'd need to dig into the scheduler to guess at the reason, as
  323. * connection.c tells us nothing itself, but mostly its timouts.
  324. * Initially, we'll simply ignore this and leave massive timeouts, but
  325. * maybe that should change for error handling pruposes. It appears that
  326. * successful operations, including DNS resolution, do not use this. */if (NULL == buf)
  327. {
  328. if (0 == ih->step)
  329. {
  330. LOG (GNUNET_ERROR_TYPE_WARNING,
  331. "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
  332. register_sender (ih);
  333. }
  334. else
  335. {
  336. LOG (GNUNET_ERROR_TYPE_ERROR,
  337. "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
  338. ih->step);
  339. GNUNET_break (0);
  340. }
  341. return 0;
  342. }
  343. GNUNET_assert ((1024 >= size) && (size > 0));
  344. GNUNET_assert ((SOCKS5_step_done > ih->step) && (ih->step >= 0));
  345. unsigned char *b = ih->outstep[ih->step];
  346. unsigned char *e = ih->outstep[ih->step + 1];
  347. GNUNET_assert (e <= &ih->outbuf[1024]);
  348. unsigned int l = e - b;
  349. GNUNET_assert (size >= l);
  350. GNUNET_memcpy (buf, b, l);
  351. register_reciever (ih, register_reciever_wants (ih));
  352. return l;
  353. }
  354. /**
  355. * Register SOCKS5 handshake sender
  356. *
  357. * @param ih handshake
  358. * @return non-NULL if the notify callback was queued,
  359. * NULL if we are already going to notify someone else (busy)
  360. */
  361. struct GNUNET_CONNECTION_TransmitHandle *
  362. register_sender (struct GNUNET_SOCKS_Handshake *ih)
  363. {
  364. struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_MINUTES;
  365. GNUNET_assert (SOCKS5_step_done > ih->step);
  366. GNUNET_assert (ih->step >= 0);
  367. if (0 == ih->step)
  368. timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3);
  369. unsigned char *b = ih->outstep[ih->step];
  370. unsigned char *e = ih->outstep[ih->step + 1];
  371. GNUNET_assert (ih->outbuf <= b && b < e && e < &ih->outbuf[1024]);
  372. ih->th = GNUNET_CONNECTION_notify_transmit_ready (ih->socks5_connection,
  373. e - b,
  374. timeout,
  375. &transmit_ready,
  376. ih);
  377. return ih->th;
  378. }
  379. /**
  380. * Initialize a SOCKS5 handshake for authentication via username and
  381. * password. Tor uses SOCKS username and password authentication to assign
  382. * programs unique circuits.
  383. *
  384. * @param user username for the proxy
  385. * @param pass password for the proxy
  386. * @return Valid SOCKS5 hanbdshake handle
  387. */
  388. struct GNUNET_SOCKS_Handshake *
  389. GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
  390. {
  391. struct GNUNET_SOCKS_Handshake *ih =
  392. GNUNET_new (struct GNUNET_SOCKS_Handshake);
  393. unsigned char *b = ih->outbuf;
  394. ih->outstep[SOCKS5_step_greet] = b;
  395. *(b++) = 5; /* SOCKS5 */
  396. unsigned char *n = b++;
  397. *n = 1; /* Number of authentication methods */
  398. /* We support no authentication even when requesting authentication,
  399. * but this appears harmless, given the way that Tor uses authentication.
  400. * And some SOCKS5 servers might require this. */
  401. *(b++) = SOCKS5_AUTH_NOAUTH;
  402. if (NULL != user)
  403. {
  404. *(b++) = SOCKS5_AUTH_USERPASS;
  405. (*n)++;
  406. }
  407. /* There is no apparent reason to support authentication methods beyond
  408. * username and password since afaik Tor does not support them. */
  409. /* We authenticate with an empty username and password if the server demands
  410. * them but we do not have any. */
  411. if (user == NULL)
  412. user = "";
  413. if (pass == NULL)
  414. pass = "";
  415. ih->outstep[SOCKS5_step_auth] = b;
  416. *(b++) = 1; /* subnegotiation ver.: 1 */
  417. b = SOCK5_proto_string (b, user);
  418. b = SOCK5_proto_string (b, pass);
  419. ih->outstep[SOCKS5_step_cmd] = b;
  420. ih->inend = ih->instart = ih->inbuf;
  421. return ih;
  422. }
  423. /**
  424. * Initialize a SOCKS5 handshake without authentication, thereby possibly
  425. * sharing a Tor circuit with another process.
  426. *
  427. * @return Valid SOCKS5 hanbdshake handle
  428. */
  429. struct GNUNET_SOCKS_Handshake *
  430. GNUNET_SOCKS_init_handshake_noauth ()
  431. {
  432. return GNUNET_SOCKS_init_handshake (NULL, NULL);
  433. }
  434. /**
  435. * Build request that the SOCKS5 proxy open a TCP/IP stream to the given host
  436. * and port.
  437. *
  438. * @param ih SOCKS5 handshake
  439. * @param hostname
  440. * @param port
  441. */
  442. void
  443. GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih,
  444. const char *host,
  445. uint16_t port)
  446. {
  447. union
  448. {
  449. struct in_addr in4;
  450. struct in6_addr in6;
  451. } ia;
  452. unsigned char *b = ih->outstep[SOCKS5_step_cmd];
  453. *(b++) = 5; /* SOCKS5 */
  454. *(b++) = 1; /* Establish a TCP/IP stream */
  455. *(b++) = 0; /* reserved */
  456. /* Specify destination */
  457. if (1 == inet_pton (AF_INET, host, &ia.in4))
  458. {
  459. *(b++) = 1; /* IPv4 */
  460. GNUNET_memcpy (b, &ia.in4, sizeof(struct in_addr));
  461. b += sizeof(struct in_addr); /* 4 */
  462. }
  463. else if (1 == inet_pton (AF_INET6, host, &ia.in6))
  464. {
  465. *(b++) = 4; /* IPv6 */
  466. GNUNET_memcpy (b, &ia.in6, sizeof(struct in6_addr));
  467. b += sizeof(struct in6_addr); /* 16 */
  468. }
  469. else
  470. {
  471. *(b++) = 3; /* hostname */
  472. b = SOCK5_proto_string (b, host);
  473. }
  474. /* Specify port */
  475. *(uint16_t *) b = htons (port);
  476. b += 2;
  477. ih->outstep[SOCKS5_step_done] = b;
  478. }
  479. /**
  480. * Run a SOCKS5 handshake on an open but unused TCP connection.
  481. *
  482. * @param ih SOCKS5 handshake, consumed here.
  483. * @param c open unused connection, consumed here.
  484. * @return Connection handle that becomes usable when the SOCKS5 handshake completes.
  485. */
  486. struct GNUNET_CONNECTION_Handle *
  487. GNUNET_SOCKS_run_handshake (struct GNUNET_SOCKS_Handshake *ih,
  488. struct GNUNET_CONNECTION_Handle *c)
  489. {
  490. ih->socks5_connection = c;
  491. ih->target_connection = GNUNET_CONNECTION_create_proxied_from_handshake (c);
  492. register_sender (ih);
  493. return ih->target_connection;
  494. }
  495. /**
  496. * Check if a SOCKS proxy is required by a service. Do not use local service
  497. * if a SOCKS proxy port is configured as this could deanonymize a user.
  498. *
  499. * @param service_name name of service to connect to
  500. * @param cfg configuration to use
  501. * @return GNUNET_YES if so, GNUNET_NO if not
  502. */
  503. int
  504. GNUNET_SOCKS_check_service (const char *service_name,
  505. const struct GNUNET_CONFIGURATION_Handle *cfg)
  506. {
  507. return GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSPORT") ||
  508. GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSHOST");
  509. }
  510. /**
  511. * Try to connect to a service configured to use a SOCKS5 proxy.
  512. *
  513. * @param service_name name of service to connect to
  514. * @param cfg configuration to use
  515. * @return Connection handle that becomes usable when the handshake completes.
  516. * NULL if SOCKS not configured or not configured properly
  517. */
  518. struct GNUNET_CONNECTION_Handle *
  519. GNUNET_SOCKS_do_connect (const char *service_name,
  520. const struct GNUNET_CONFIGURATION_Handle *cfg)
  521. {
  522. struct GNUNET_SOCKS_Handshake *ih;
  523. struct GNUNET_CONNECTION_Handle *socks5; /* *proxied */
  524. char *host0;
  525. char *host1;
  526. char *user;
  527. char *pass;
  528. unsigned long long port0;
  529. unsigned long long port1;
  530. if (GNUNET_YES != GNUNET_SOCKS_check_service (service_name, cfg))
  531. return NULL;
  532. if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
  533. service_name,
  534. "SOCKSPORT",
  535. &port0))
  536. port0 = 9050;
  537. /* A typical Tor client should usually try port 9150 for the TBB too, but
  538. * GNUnet can probably assume a system Tor installation. */
  539. if ((port0 > 65535) || (port0 <= 0))
  540. {
  541. LOG (GNUNET_ERROR_TYPE_WARNING,
  542. _ (
  543. "Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
  544. port0,
  545. service_name);
  546. return NULL;
  547. }
  548. if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
  549. service_name,
  550. "PORT",
  551. &port1)) ||
  552. (port1 > 65535) || (port1 <= 0) ||
  553. (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
  554. service_name,
  555. "HOSTNAME",
  556. &host1)))
  557. {
  558. LOG (GNUNET_ERROR_TYPE_WARNING,
  559. _ (
  560. "Attempting to proxy service `%s' to invalid port %d or hostname.\n"),
  561. service_name,
  562. port1);
  563. return NULL;
  564. }
  565. /* Appeared to still work after host0 corrupted, so either test case is broken, or
  566. this whole routine is not being called. */
  567. if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
  568. service_name,
  569. "SOCKSHOST",
  570. &host0))
  571. host0 = NULL;
  572. socks5 = GNUNET_CONNECTION_create_from_connect (cfg,
  573. (host0 != NULL) ? host0
  574. : "127.0.0.1",
  575. port0);
  576. GNUNET_free (host0);
  577. /* Sets to NULL if they do not exist */
  578. (void) GNUNET_CONFIGURATION_get_value_string (cfg,
  579. service_name,
  580. "SOCKSUSER",
  581. &user);
  582. (void) GNUNET_CONFIGURATION_get_value_string (cfg,
  583. service_name,
  584. "SOCKSPASS",
  585. &pass);
  586. ih = GNUNET_SOCKS_init_handshake (user, pass);
  587. GNUNET_free (user);
  588. GNUNET_free (pass);
  589. GNUNET_SOCKS_set_handshake_destination (ih, host1, port1);
  590. GNUNET_free (host1);
  591. return GNUNET_SOCKS_run_handshake (ih, socks5);
  592. }
  593. /* socks.c */