Tor  0.4.4.0-alpha-dev
proto_socks.c
Go to the documentation of this file.
1 /* Copyright (c) 2001 Matej Pfajfar.
2  * Copyright (c) 2001-2004, Roger Dingledine.
3  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4  * Copyright (c) 2007-2020, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * @file proto_socks.c
9  * @brief Implementations for SOCKS4 and SOCKS5 protocols.
10  **/
11 
12 #include "core/or/or.h"
14 #include "lib/buf/buffers.h"
17 #include "app/config/config.h"
20 #include "core/proto/proto_socks.h"
21 #include "core/or/reasons.h"
22 
24 
25 #include "trunnel/socks5.h"
26 
27 #define SOCKS_VER_5 0x05 /* First octet of non-auth SOCKS5 messages */
28 #define SOCKS_VER_4 0x04 /* SOCKS4 messages */
29 #define SOCKS_AUTH 0x01 /* SOCKS5 auth messages */
30 
31 typedef enum {
32  SOCKS_RESULT_INVALID = -1, /* Message invalid. */
33  SOCKS_RESULT_TRUNCATED = 0, /* Message incomplete/truncated. */
34  SOCKS_RESULT_DONE = 1, /* OK, we're done. */
35  SOCKS_RESULT_MORE_EXPECTED = 2, /* OK, more messages expected. */
36 } socks_result_t;
37 
39  socks5_reply_status_t reason);
40 
41 static socks_result_t parse_socks(const char *data,
42  size_t datalen,
43  socks_request_t *req,
44  int log_sockstype,
45  int safe_socks,
46  size_t *drain_out);
47 static int parse_socks_client(const uint8_t *data, size_t datalen,
48  int state, char **reason,
49  ssize_t *drain_out);
50 /**
51  * Wait this many seconds before warning the user about using SOCKS unsafely
52  * again. */
53 #define SOCKS_WARN_INTERVAL 5
54 
55 /** Warn that the user application has made an unsafe socks request using
56  * protocol <b>socks_protocol</b> on port <b>port</b>. Don't warn more than
57  * once per SOCKS_WARN_INTERVAL, unless <b>safe_socks</b> is set. */
58 static void
59 log_unsafe_socks_warning(int socks_protocol, const char *address,
60  uint16_t port, int safe_socks)
61 {
62  static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL);
63 
64  if (safe_socks) {
65  log_fn_ratelim(&socks_ratelim, LOG_WARN, LD_APP,
66  "Your application (using socks%d to port %d) is giving "
67  "Tor only an IP address. Applications that do DNS resolves "
68  "themselves may leak information. Consider using Socks4A "
69  "(e.g. via privoxy or socat) instead. For more information, "
70  "please see https://wiki.torproject.org/TheOnionRouter/"
71  "TorFAQ#SOCKSAndDNS.%s",
72  socks_protocol,
73  (int)port,
74  safe_socks ? " Rejecting." : "");
75  }
77  "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d",
78  socks_protocol, address, (int)port);
79 }
80 
81 /** Do not attempt to parse socks messages longer than this. This value is
82  * actually significantly higher than the longest possible socks message. */
83 #define MAX_SOCKS_MESSAGE_LEN 512
84 
85 /** Return a new socks_request_t. */
88 {
89  return tor_malloc_zero(sizeof(socks_request_t));
90 }
91 
92 /** Free all storage held in the socks_request_t <b>req</b>. */
93 void
95 {
96  if (!req)
97  return;
98  if (req->username) {
99  memwipe(req->username, 0x10, req->usernamelen);
100  tor_free(req->username);
101  }
102  if (req->password) {
103  memwipe(req->password, 0x04, req->passwordlen);
104  tor_free(req->password);
105  }
106  memwipe(req, 0xCC, sizeof(socks_request_t));
107  tor_free(req);
108 }
109 
110 /**
111  * Parse a single SOCKS4 request from buffer <b>raw_data</b> of length
112  * <b>datalen</b> and update relevant fields of <b>req</b>. If SOCKS4a
113  * request is detected, set <b>*is_socks4a</b> to true. Set <b>*drain_out</b>
114  * to number of bytes we parsed so far.
115  *
116  * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
117  * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
118  * failed due to incomplete (truncated) input.
119  */
120 static socks_result_t
121 parse_socks4_request(const uint8_t *raw_data, socks_request_t *req,
122  size_t datalen, int *is_socks4a, size_t *drain_out)
123 {
124  // http://ss5.sourceforge.net/socks4.protocol.txt
125  // http://ss5.sourceforge.net/socks4A.protocol.txt
126  socks_result_t res = SOCKS_RESULT_DONE;
127  tor_addr_t destaddr;
128 
129  tor_assert(is_socks4a);
130  tor_assert(drain_out);
131 
132  *is_socks4a = 0;
133  *drain_out = 0;
134 
135  req->socks_version = SOCKS_VER_4;
136 
137  socks4_client_request_t *trunnel_req;
138 
139  ssize_t parsed =
140  socks4_client_request_parse(&trunnel_req, raw_data, datalen);
141 
142  if (parsed == -1) {
143  log_warn(LD_APP, "socks4: parsing failed - invalid request.");
144  res = SOCKS_RESULT_INVALID;
145  goto end;
146  } else if (parsed == -2) {
147  res = SOCKS_RESULT_TRUNCATED;
148  if (datalen >= MAX_SOCKS_MESSAGE_LEN) {
149  log_warn(LD_APP, "socks4: parsing failed - invalid request.");
150  res = SOCKS_RESULT_INVALID;
151  }
152  goto end;
153  }
154 
155  tor_assert(parsed >= 0);
156  *drain_out = (size_t)parsed;
157 
158  uint8_t command = socks4_client_request_get_command(trunnel_req);
159  req->command = command;
160 
161  req->port = socks4_client_request_get_port(trunnel_req);
162  uint32_t dest_ip = socks4_client_request_get_addr(trunnel_req);
163 
164  if ((!req->port && req->command != SOCKS_COMMAND_RESOLVE) ||
165  dest_ip == 0) {
166  log_warn(LD_APP, "socks4: Port or DestIP is zero. Rejecting.");
167  res = SOCKS_RESULT_INVALID;
168  goto end;
169  }
170 
171  *is_socks4a = (dest_ip >> 8) == 0;
172 
173  const char *username = socks4_client_request_get_username(trunnel_req);
174  const size_t usernamelen = username ? strlen(username) : 0;
175  if (username && usernamelen) {
176  if (usernamelen > MAX_SOCKS_MESSAGE_LEN) {
177  log_warn(LD_APP, "Socks4 user name too long; rejecting.");
178  res = SOCKS_RESULT_INVALID;
179  goto end;
180  }
181 
182  tor_free(req->username);
183  req->got_auth = 1;
184  req->username = tor_strdup(username);
185  req->usernamelen = usernamelen;
186  }
187 
188  if (*is_socks4a) {
189  // We cannot rely on trunnel here, as we want to detect if
190  // we have abnormally long hostname field.
191  const char *hostname = (char *)raw_data + SOCKS4_NETWORK_LEN +
192  usernamelen + 1;
193  size_t hostname_len = (char *)raw_data + datalen - hostname;
194 
195  if (hostname_len <= sizeof(req->address)) {
196  const char *trunnel_hostname =
197  socks4_client_request_get_socks4a_addr_hostname(trunnel_req);
198 
199  if (trunnel_hostname)
200  strlcpy(req->address, trunnel_hostname, sizeof(req->address));
201  } else {
202  log_warn(LD_APP, "socks4: Destaddr too long. Rejecting.");
203  res = SOCKS_RESULT_INVALID;
204  goto end;
205  }
206  } else {
207  tor_addr_from_ipv4h(&destaddr, dest_ip);
208 
209  if (!tor_addr_to_str(req->address, &destaddr,
210  MAX_SOCKS_ADDR_LEN, 0)) {
211  res = SOCKS_RESULT_INVALID;
212  goto end;
213  }
214  }
215 
216  end:
217  socks4_client_request_free(trunnel_req);
218 
219  return res;
220 }
221 
222 /**
223  * Validate SOCKS4/4a related fields in <b>req</b>. Expect SOCKS4a
224  * if <b>is_socks4a</b> is true. If <b>log_sockstype</b> is true,
225  * log a notice about possible DNS leaks on local system. If
226  * <b>safe_socks</b> is true, reject insecure usage of SOCKS
227  * protocol.
228  *
229  * Return SOCKS_RESULT_DONE if validation passed or
230  * SOCKS_RESULT_INVALID if it failed.
231  */
232 static socks_result_t
233 process_socks4_request(const socks_request_t *req, int is_socks4a,
234  int log_sockstype, int safe_socks)
235 {
236  if (is_socks4a && !addressmap_have_mapping(req->address, 0)) {
237  log_unsafe_socks_warning(4, req->address, req->port, safe_socks);
238 
239  if (safe_socks)
240  return SOCKS_RESULT_INVALID;
241  }
242 
243  if (req->command != SOCKS_COMMAND_CONNECT &&
244  req->command != SOCKS_COMMAND_RESOLVE) {
245  /* not a connect or resolve? we don't support it. (No resolve_ptr with
246  * socks4.) */
247  log_warn(LD_APP, "socks4: command %d not recognized. Rejecting.",
248  req->command);
249  return SOCKS_RESULT_INVALID;
250  }
251 
252  if (is_socks4a) {
253  if (log_sockstype)
254  log_notice(LD_APP,
255  "Your application (using socks4a to port %d) instructed "
256  "Tor to take care of the DNS resolution itself if "
257  "necessary. This is good.", req->port);
258  }
259 
260  if (!string_is_valid_dest(req->address)) {
261  log_warn(LD_PROTOCOL,
262  "Your application (using socks4 to port %d) gave Tor "
263  "a malformed hostname: %s. Rejecting the connection.",
264  req->port, escaped_safe_str_client(req->address));
265  return SOCKS_RESULT_INVALID;
266  }
267 
268  return SOCKS_RESULT_DONE;
269 }
270 
271 /** Parse a single SOCKS5 version identifier/method selection message
272  * from buffer <b>raw_data</b> (of length <b>datalen</b>). Update
273  * relevant fields of <b>req</b> (if any). Set <b>*have_user_pass</b> to
274  * true if username/password method is found. Set <b>*have_no_auth</b>
275  * if no-auth method is found. Set <b>*drain_out</b> to number of bytes
276  * we parsed so far.
277  *
278  * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
279  * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
280  * failed due to incomplete (truncated) input.
281  */
282 static socks_result_t
283 parse_socks5_methods_request(const uint8_t *raw_data, socks_request_t *req,
284  size_t datalen, int *have_user_pass,
285  int *have_no_auth, size_t *drain_out)
286 {
287  socks_result_t res = SOCKS_RESULT_DONE;
288  socks5_client_version_t *trunnel_req;
289 
290  ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
291  datalen);
292 
293  (void)req;
294 
295  tor_assert(have_no_auth);
296  tor_assert(have_user_pass);
297  tor_assert(drain_out);
298 
299  *drain_out = 0;
300 
301  if (parsed == -1) {
302  log_warn(LD_APP, "socks5: parsing failed - invalid version "
303  "id/method selection message.");
304  res = SOCKS_RESULT_INVALID;
305  goto end;
306  } else if (parsed == -2) {
307  res = SOCKS_RESULT_TRUNCATED;
308  if (datalen > MAX_SOCKS_MESSAGE_LEN) {
309  log_warn(LD_APP, "socks5: parsing failed - invalid version "
310  "id/method selection message.");
311  res = SOCKS_RESULT_INVALID;
312  }
313  goto end;
314  }
315 
316  tor_assert(parsed >= 0);
317  *drain_out = (size_t)parsed;
318 
319  size_t n_methods = (size_t)socks5_client_version_get_n_methods(trunnel_req);
320  if (n_methods == 0) {
321  res = SOCKS_RESULT_INVALID;
322  goto end;
323  }
324 
325  *have_no_auth = 0;
326  *have_user_pass = 0;
327 
328  for (size_t i = 0; i < n_methods; i++) {
329  uint8_t method = socks5_client_version_get_methods(trunnel_req,
330  i);
331 
332  if (method == SOCKS_USER_PASS) {
333  *have_user_pass = 1;
334  } else if (method == SOCKS_NO_AUTH) {
335  *have_no_auth = 1;
336  }
337  }
338 
339  end:
340  socks5_client_version_free(trunnel_req);
341 
342  return res;
343 }
344 
345 /**
346  * Validate and respond to version identifier/method selection message
347  * we parsed in parse_socks5_methods_request (corresponding to <b>req</b>
348  * and having user/pass method if <b>have_user_pass</b> is true, no-auth
349  * method if <b>have_no_auth</b> is true). Set <b>req->reply</b> to
350  * an appropriate response (in SOCKS5 wire format).
351  *
352  * On success, return SOCKS_RESULT_DONE. On failure, return
353  * SOCKS_RESULT_INVALID.
354  */
355 static socks_result_t
357  int have_no_auth)
358 {
359  socks_result_t res = SOCKS_RESULT_DONE;
360  socks5_server_method_t *trunnel_resp = socks5_server_method_new();
361  tor_assert(trunnel_resp);
362 
363  socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
364 
365  if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) {
366  req->auth_type = SOCKS_USER_PASS;
367  socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
368 
369  req->socks_version = SOCKS_VER_5;
370  // FIXME: come up with better way to remember
371  // that we negotiated auth
372 
373  log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
374  } else if (have_no_auth) {
375  req->auth_type = SOCKS_NO_AUTH;
376  socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
377 
378  req->socks_version = SOCKS_VER_5;
379 
380  log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
381  } else {
382  log_warn(LD_APP,
383  "socks5: offered methods don't include 'no auth' or "
384  "username/password. Rejecting.");
385  socks5_server_method_set_method(trunnel_resp, 0xFF); // reject all
386  res = SOCKS_RESULT_INVALID;
387  }
388 
389  const char *errmsg = socks5_server_method_check(trunnel_resp);
390  if (errmsg) {
391  log_warn(LD_APP, "socks5: method selection validation failed: %s",
392  errmsg);
393  res = SOCKS_RESULT_INVALID;
394  } else {
395  ssize_t encoded =
396  socks5_server_method_encode(req->reply, sizeof(req->reply),
397  trunnel_resp);
398 
399  if (encoded < 0) {
400  log_warn(LD_APP, "socks5: method selection encoding failed");
401  res = SOCKS_RESULT_INVALID;
402  } else {
403  req->replylen = (size_t)encoded;
404  }
405  }
406 
407  socks5_server_method_free(trunnel_resp);
408  return res;
409 }
410 
411 /**
412  * Parse SOCKS5/RFC1929 username/password request from buffer
413  * <b>raw_data</b> of length <b>datalen</b> and update relevant
414  * fields of <b>req</b>. Set <b>*drain_out</b> to number of bytes
415  * we parsed so far.
416  *
417  * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
418  * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
419  * failed due to incomplete (truncated) input.
420  */
421 static socks_result_t
422 parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
423  size_t datalen, size_t *drain_out)
424 {
425  socks_result_t res = SOCKS_RESULT_DONE;
426  socks5_client_userpass_auth_t *trunnel_req = NULL;
427  ssize_t parsed = socks5_client_userpass_auth_parse(&trunnel_req, raw_data,
428  datalen);
429  tor_assert(drain_out);
430  *drain_out = 0;
431 
432  if (parsed == -1) {
433  log_warn(LD_APP, "socks5: parsing failed - invalid user/pass "
434  "authentication message.");
435  res = SOCKS_RESULT_INVALID;
436  goto end;
437  } else if (parsed == -2) {
438  res = SOCKS_RESULT_TRUNCATED;
439  goto end;
440  }
441 
442  tor_assert(parsed >= 0);
443  *drain_out = (size_t)parsed;
444 
445  uint8_t usernamelen =
446  socks5_client_userpass_auth_get_username_len(trunnel_req);
447  uint8_t passwordlen =
448  socks5_client_userpass_auth_get_passwd_len(trunnel_req);
449  const char *username =
450  socks5_client_userpass_auth_getconstarray_username(trunnel_req);
451  const char *password =
452  socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
453 
454  if (usernamelen && username) {
455  tor_free(req->username);
456  req->username = tor_memdup_nulterm(username, usernamelen);
457  req->usernamelen = usernamelen;
458  }
459 
460  if (passwordlen && password) {
461  tor_free(req->password);
462  req->password = tor_memdup_nulterm(password, passwordlen);
463  req->passwordlen = passwordlen;
464  }
465 
466  /**
467  * Yes, we allow username and/or password to be empty. Yes, that does
468  * violate RFC 1929. However, some client software can send a username/
469  * password message with these fields being empty and we want to allow them
470  * to be used with Tor.
471  */
472  req->got_auth = 1;
473 
474  end:
475  socks5_client_userpass_auth_free(trunnel_req);
476  return res;
477 }
478 
479 /**
480  * Validate and respond to SOCKS5 username/password request we
481  * parsed in parse_socks5_userpass_auth (corresponding to <b>req</b>.
482  * Set <b>req->reply</b> to appropriate responsed. Return
483  * SOCKS_RESULT_DONE on success or SOCKS_RESULT_INVALID on failure.
484  */
485 static socks_result_t
487 {
488  socks_result_t res = SOCKS_RESULT_DONE;
489  socks5_server_userpass_auth_t *trunnel_resp =
490  socks5_server_userpass_auth_new();
491  tor_assert(trunnel_resp);
492 
493  if (req->socks_version != SOCKS_VER_5) {
494  res = SOCKS_RESULT_INVALID;
495  goto end;
496  }
497 
498  if (req->auth_type != SOCKS_USER_PASS &&
499  req->auth_type != SOCKS_NO_AUTH) {
500  res = SOCKS_RESULT_INVALID;
501  goto end;
502  }
503 
504  socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
505  socks5_server_userpass_auth_set_status(trunnel_resp, 0); // auth OK
506 
507  const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
508  if (errmsg) {
509  log_warn(LD_APP, "socks5: server userpass auth validation failed: %s",
510  errmsg);
511  res = SOCKS_RESULT_INVALID;
512  goto end;
513  }
514 
515  ssize_t encoded = socks5_server_userpass_auth_encode(req->reply,
516  sizeof(req->reply),
517  trunnel_resp);
518 
519  if (encoded < 0) {
520  log_warn(LD_APP, "socks5: server userpass auth encoding failed");
521  res = SOCKS_RESULT_INVALID;
522  goto end;
523  }
524 
525  req->replylen = (size_t)encoded;
526 
527  end:
528  socks5_server_userpass_auth_free(trunnel_resp);
529  return res;
530 }
531 
532 /**
533  * Parse a single SOCKS5 client request (RFC 1928 section 4) from buffer
534  * <b>raw_data</b> of length <b>datalen</b> and update relevant field of
535  * <b>req</b>. Set <b>*drain_out</b> to number of bytes we parsed so far.
536  *
537  * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
538  * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
539  * failed due to incomplete (truncated) input.
540  */
541 static socks_result_t
542 parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req,
543  size_t datalen, size_t *drain_out)
544 {
545  socks_result_t res = SOCKS_RESULT_DONE;
546  tor_addr_t destaddr;
547  socks5_client_request_t *trunnel_req = NULL;
548  ssize_t parsed =
549  socks5_client_request_parse(&trunnel_req, raw_data, datalen);
550  if (parsed == -1) {
551  log_warn(LD_APP, "socks5: parsing failed - invalid client request");
552  res = SOCKS_RESULT_INVALID;
553  goto end;
554  } else if (parsed == -2) {
555  res = SOCKS_RESULT_TRUNCATED;
556  goto end;
557  }
558 
559  tor_assert(parsed >= 0);
560  *drain_out = (size_t)parsed;
561 
562  if (socks5_client_request_get_version(trunnel_req) != 5) {
563  res = SOCKS_RESULT_INVALID;
564  goto end;
565  }
566 
567  req->command = socks5_client_request_get_command(trunnel_req);
568 
569  req->port = socks5_client_request_get_dest_port(trunnel_req);
570 
571  uint8_t atype = socks5_client_request_get_atype(trunnel_req);
572  req->socks5_atyp = atype;
573 
574  switch (atype) {
575  case 1: {
576  uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
577  tor_addr_from_ipv4h(&destaddr, ipv4);
578 
579  tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
580  } break;
581  case 3: {
582  const struct domainname_st *dns_name =
583  socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
584 
585  const char *hostname = domainname_getconstarray_name(dns_name);
586 
587  strlcpy(req->address, hostname, sizeof(req->address));
588  } break;
589  case 4: {
590  const uint8_t *ipv6 =
591  socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
592  tor_addr_from_ipv6_bytes(&destaddr, ipv6);
593 
594  tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
595  } break;
596  default: {
597  res = -1;
598  } break;
599  }
600 
601  end:
602  socks5_client_request_free(trunnel_req);
603  return res;
604 }
605 
606 /**
607  * Validate and respond to SOCKS5 request we parsed in
608  * parse_socks5_client_request (corresponding to <b>req</b>.
609  * Write appropriate response to <b>req->reply</b> (in
610  * SOCKS5 wire format). If <b>log_sockstype</b> is true, log a
611  * notice about possible DNS leaks on local system. If
612  * <b>safe_socks</b> is true, disallow insecure usage of SOCKS
613  * protocol. Return SOCKS_RESULT_DONE on success or
614  * SOCKS_RESULT_INVALID on failure.
615  */
616 static socks_result_t
618  int log_sockstype,
619  int safe_socks)
620 {
621  socks_result_t res = SOCKS_RESULT_DONE;
622  tor_addr_t tmpaddr;
623 
624  if (req->command != SOCKS_COMMAND_CONNECT &&
625  req->command != SOCKS_COMMAND_RESOLVE &&
627  socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
628  res = SOCKS_RESULT_INVALID;
629  goto end;
630  }
631 
632  if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
633  tor_addr_parse(&tmpaddr, req->address) < 0) {
634  socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
635  log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
636  "a malformed address. Rejecting.");
637 
638  res = SOCKS_RESULT_INVALID;
639  goto end;
640  }
641 
642  if (!string_is_valid_dest(req->address)) {
643  socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
644 
645  log_warn(LD_PROTOCOL,
646  "Your application (using socks5 to port %d) gave Tor "
647  "a malformed hostname: %s. Rejecting the connection.",
648  req->port, escaped_safe_str_client(req->address));
649 
650  res = SOCKS_RESULT_INVALID;
651  goto end;
652  }
653 
654  if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
655  if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
656  !addressmap_have_mapping(req->address,0)) {
657  log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
658  if (safe_socks) {
659  socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
660  res = SOCKS_RESULT_INVALID;
661  goto end;
662  }
663  }
664  }
665 
666  if (log_sockstype)
667  log_notice(LD_APP,
668  "Your application (using socks5 to port %d) instructed "
669  "Tor to take care of the DNS resolution itself if "
670  "necessary. This is good.", req->port);
671 
672  end:
673  return res;
674 }
675 
676 /**
677  * Handle (parse, validate, process, respond) a single SOCKS
678  * message in buffer <b>raw_data</b> of length <b>datalen</b>.
679  * Update relevant fields of <b>req</b>. If <b>log_sockstype</b>
680  * is true, log a warning about possible DNS leaks on local
681  * system. If <b>safe_socks</b> is true, disallow insecure
682  * usage of SOCKS protocol. Set <b>*drain_out</b> to number
683  * of bytes in <b>raw_data</b> that we processed so far and
684  * that can be safely drained from buffer.
685  *
686  * Return:
687  * - SOCKS_RESULT_DONE if succeeded and not expecting further
688  * messages from client.
689  * - SOCKS_RESULT_INVALID if any of the steps failed due to
690  * request being invalid or unexpected given current state.
691  * - SOCKS_RESULT_TRUNCATED if we do not found an expected
692  * SOCKS message in its entirety (more stuff has to arrive
693  * from client).
694  * - SOCKS_RESULT_MORE_EXPECTED if we handled current message
695  * successfully, but we expect more messages from the
696  * client.
697  */
698 static socks_result_t
699 handle_socks_message(const uint8_t *raw_data, size_t datalen,
700  socks_request_t *req, int log_sockstype,
701  int safe_socks, size_t *drain_out)
702 {
703  socks_result_t res = SOCKS_RESULT_DONE;
704 
705  uint8_t socks_version = raw_data[0];
706 
707  if (socks_version == SOCKS_AUTH)
708  socks_version = SOCKS_VER_5; // SOCKS5 username/pass subnegotiation
709 
710  if (socks_version == SOCKS_VER_4) {
711  if (datalen < SOCKS4_NETWORK_LEN) {
712  res = 0;
713  goto end;
714  }
715 
716  int is_socks4a = 0;
717  res = parse_socks4_request((const uint8_t *)raw_data, req, datalen,
718  &is_socks4a, drain_out);
719 
720  if (res != SOCKS_RESULT_DONE) {
721  goto end;
722  }
723 
724  res = process_socks4_request(req, is_socks4a,log_sockstype,
725  safe_socks);
726 
727  if (res != SOCKS_RESULT_DONE) {
728  goto end;
729  }
730 
731  goto end;
732  } else if (socks_version == SOCKS_VER_5) {
733  if (datalen < 2) { /* version and another byte */
734  res = 0;
735  goto end;
736  }
737  /* RFC1929 SOCKS5 username/password subnegotiation. */
738  if (!req->got_auth && (raw_data[0] == 1 ||
739  req->auth_type == SOCKS_USER_PASS)) {
740  res = parse_socks5_userpass_auth(raw_data, req, datalen,
741  drain_out);
742 
743  if (res != SOCKS_RESULT_DONE) {
744  goto end;
745  }
746 
747  res = process_socks5_userpass_auth(req);
748  if (res != SOCKS_RESULT_DONE) {
749  goto end;
750  }
751 
752  res = SOCKS_RESULT_MORE_EXPECTED;
753  goto end;
754  } else if (req->socks_version != SOCKS_VER_5) {
755  int have_user_pass=0, have_no_auth=0;
756  res = parse_socks5_methods_request(raw_data, req, datalen,
757  &have_user_pass,
758  &have_no_auth,
759  drain_out);
760 
761  if (res != SOCKS_RESULT_DONE) {
762  goto end;
763  }
764 
765  res = process_socks5_methods_request(req, have_user_pass,
766  have_no_auth);
767 
768  if (res != SOCKS_RESULT_DONE) {
769  goto end;
770  }
771 
772  res = SOCKS_RESULT_MORE_EXPECTED;
773  goto end;
774  } else {
775  res = parse_socks5_client_request(raw_data, req,
776  datalen, drain_out);
777  if (res != SOCKS_RESULT_DONE) {
778  socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
779  goto end;
780  }
781 
782  res = process_socks5_client_request(req, log_sockstype,
783  safe_socks);
784 
785  if (res != SOCKS_RESULT_DONE) {
786  goto end;
787  }
788  }
789  } else {
790  *drain_out = datalen;
791  res = SOCKS_RESULT_INVALID;
792  }
793 
794  end:
795  return res;
796 }
797 
798 /** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
799  * of the forms
800  * - socks4: "socksheader username\\0"
801  * - socks4a: "socksheader username\\0 destaddr\\0"
802  * - socks5 phase one: "version #methods methods"
803  * - socks5 phase two: "version command 0 addresstype..."
804  * If it's a complete and valid handshake, and destaddr fits in
805  * MAX_SOCKS_ADDR_LEN bytes, then pull the handshake off the buf,
806  * assign to <b>req</b>, and return 1.
807  *
808  * If it's invalid or too big, return -1.
809  *
810  * Else it's not all there yet, leave buf alone and return 0.
811  *
812  * If you want to specify the socks reply, write it into <b>req->reply</b>
813  * and set <b>req->replylen</b>, else leave <b>req->replylen</b> alone.
814  *
815  * If <b>log_sockstype</b> is non-zero, then do a notice-level log of whether
816  * the connection is possibly leaking DNS requests locally or not.
817  *
818  * If <b>safe_socks</b> is true, then reject unsafe socks protocols.
819  *
820  * If returning 0 or -1, <b>req->address</b> and <b>req->port</b> are
821  * undefined.
822  */
823 int
825  int log_sockstype, int safe_socks)
826 {
827  int res = 0;
828  size_t datalen = buf_datalen(buf);
829  size_t n_drain;
830  const char *head = NULL;
831  socks_result_t socks_res;
832  size_t n_pullup;
833 
834  if (buf_datalen(buf) < 2) { /* version and another byte */
835  res = 0;
836  goto end;
837  }
838 
839  do {
840  n_drain = 0;
841  n_pullup = MIN(MAX_SOCKS_MESSAGE_LEN, buf_datalen(buf));
842  buf_pullup(buf, n_pullup, &head, &datalen);
843  tor_assert(head && datalen >= 2);
844 
845  socks_res = parse_socks(head, datalen, req, log_sockstype,
846  safe_socks, &n_drain);
847 
848  if (socks_res == SOCKS_RESULT_INVALID)
849  buf_clear(buf);
850  else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
851  buf_drain(buf, n_drain);
852 
853  switch (socks_res) {
854  case SOCKS_RESULT_INVALID:
855  res = -1;
856  break;
857  case SOCKS_RESULT_DONE:
858  res = 1;
859  break;
860  case SOCKS_RESULT_TRUNCATED:
861  if (datalen == n_pullup)
862  return 0;
863  FALLTHROUGH;
864  case SOCKS_RESULT_MORE_EXPECTED:
865  res = 0;
866  break;
867  }
868  } while (res == 0 && head && buf_datalen(buf) >= 2);
869 
870  end:
871  return res;
872 }
873 
874 /** Create a SOCKS5 reply message with <b>reason</b> in its REP field and
875  * have Tor send it as error response to <b>req</b>.
876  */
877 static void
879  socks5_reply_status_t reason)
880 {
881  socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
882  tor_assert(trunnel_resp);
883 
884  socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
885  socks5_server_reply_set_reply(trunnel_resp, reason);
886  socks5_server_reply_set_atype(trunnel_resp, 0x01);
887 
888  const char *errmsg = socks5_server_reply_check(trunnel_resp);
889  if (errmsg) {
890  log_warn(LD_APP, "socks5: reply validation failed: %s",
891  errmsg);
892  goto end;
893  }
894 
895  ssize_t encoded = socks5_server_reply_encode(req->reply,
896  sizeof(req->reply),
897  trunnel_resp);
898  if (encoded < 0) {
899  log_warn(LD_APP, "socks5: reply encoding failed: %d",
900  (int)encoded);
901  } else {
902  req->replylen = (size_t)encoded;
903  }
904 
905  end:
906  socks5_server_reply_free(trunnel_resp);
907 }
908 
909 static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
910  "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
911  "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
912  "<html>\n"
913  "<head>\n"
914  "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
915  "</head>\n"
916  "<body>\n"
917  "<h1>This is a SOCKs proxy, not an HTTP proxy.</h1>\n"
918  "<p>\n"
919  "It appears you have configured your web browser to use this Tor port as\n"
920  "an HTTP proxy.\n"
921  "</p><p>\n"
922  "This is not correct: This port is configured as a SOCKS proxy, not\n"
923  "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
924  "configuration option in place of, or in addition to, SOCKSPort.\n"
925  "Please configure your client accordingly.\n"
926  "</p>\n"
927  "<p>\n"
928  "See <a href=\"https://www.torproject.org/documentation.html\">"
929  "https://www.torproject.org/documentation.html</a> for more "
930  "information.\n"
931  "</p>\n"
932  "</body>\n"
933  "</html>\n";
934 
935 /** Implementation helper to implement fetch_from_*_socks. Instead of looking
936  * at a buffer's contents, we look at the <b>datalen</b> bytes of data in
937  * <b>data</b>. Instead of removing data from the buffer, we set
938  * <b>drain_out</b> to the amount of data that should be removed (or -1 if the
939  * buffer should be cleared). Instead of pulling more data into the first
940  * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes
941  * we'd like to see in the input buffer, if they're available. */
942 static int
943 parse_socks(const char *data, size_t datalen, socks_request_t *req,
944  int log_sockstype, int safe_socks, size_t *drain_out)
945 {
946  uint8_t first_octet;
947 
948  if (datalen < 2) {
949  /* We always need at least 2 bytes. */
950  return 0;
951  }
952 
953  first_octet = get_uint8(data);
954 
955  if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
956  first_octet == SOCKS_AUTH) { // XXX: RFC 1929
957  return handle_socks_message((const uint8_t *)data, datalen, req,
958  log_sockstype, safe_socks, drain_out);
959  }
960 
961  switch (first_octet) { /* which version of socks? */
962  case 'G': /* get */
963  case 'H': /* head */
964  case 'P': /* put/post */
965  case 'C': /* connect */
966  strlcpy((char*)req->reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
967  MAX_SOCKS_REPLY_LEN);
968  req->replylen = strlen((char*)req->reply)+1;
969  FALLTHROUGH;
970  default: /* version is not socks4 or socks5 */
971  log_warn(LD_APP,
972  "Socks version %d not recognized. (This port is not an "
973  "HTTP proxy; did you want to use HTTPTunnelPort?)",
974  *(data));
975  {
976  /* Tell the controller the first 8 bytes. */
977  char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
979  "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
980  escaped(tmp));
981  tor_free(tmp);
982  }
983  return -1;
984  }
985 
986  tor_assert_unreached();
987  return -1;
988 }
989 
990 /** Inspect a reply from SOCKS server stored in <b>buf</b> according
991  * to <b>state</b>, removing the protocol data upon success. Return 0 on
992  * incomplete response, 1 on success and -1 on error, in which case
993  * <b>reason</b> is set to a descriptive message (free() when finished
994  * with it).
995  *
996  * As a special case, 2 is returned when user/pass is required
997  * during SOCKS5 handshake and user/pass is configured.
998  */
999 int
1000 fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
1001 {
1002  ssize_t drain = 0;
1003  int r;
1004  const char *head = NULL;
1005  size_t datalen = 0;
1006 
1007  if (buf_datalen(buf) < 2)
1008  return 0;
1009 
1010  buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, &head, &datalen);
1011  tor_assert(head && datalen >= 2);
1012 
1013  r = parse_socks_client((uint8_t*)head, datalen,
1014  state, reason, &drain);
1015  if (drain > 0)
1016  buf_drain(buf, drain);
1017  else if (drain < 0)
1018  buf_clear(buf);
1019 
1020  return r;
1021 }
1022 
1023 /** Implementation logic for fetch_from_*_socks_client. */
1024 static int
1025 parse_socks_client(const uint8_t *data, size_t datalen,
1026  int state, char **reason,
1027  ssize_t *drain_out)
1028 {
1029  unsigned int addrlen;
1030  *drain_out = 0;
1031  if (datalen < 2)
1032  return 0;
1033 
1034  switch (state) {
1035  case PROXY_SOCKS4_WANT_CONNECT_OK:
1036  /* Wait for the complete response */
1037  if (datalen < 8)
1038  return 0;
1039 
1040  if (data[1] != 0x5a) {
1041  *reason = tor_strdup(socks4_response_code_to_string(data[1]));
1042  return -1;
1043  }
1044 
1045  /* Success */
1046  *drain_out = 8;
1047  return 1;
1048 
1049  case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1050  /* we don't have any credentials */
1051  if (data[1] != 0x00) {
1052  *reason = tor_strdup("server doesn't support any of our "
1053  "available authentication methods");
1054  return -1;
1055  }
1056 
1057  log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
1058  *drain_out = -1;
1059  return 1;
1060 
1061  case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1062  /* we have a username and password. return 1 if we can proceed without
1063  * providing authentication, or 2 otherwise. */
1064  switch (data[1]) {
1065  case 0x00:
1066  log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
1067  "doesn't require authentication.");
1068  *drain_out = -1;
1069  return 1;
1070  case 0x02:
1071  log_info(LD_NET, "SOCKS 5 client: need authentication.");
1072  *drain_out = -1;
1073  return 2;
1074  default:
1075  /* This wasn't supposed to be exhaustive; there are other
1076  * authentication methods too. */
1077  ;
1078  }
1079 
1080  *reason = tor_strdup("server doesn't support any of our available "
1081  "authentication methods");
1082  return -1;
1083 
1084  case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1085  /* handle server reply to rfc1929 authentication */
1086  if (data[1] != 0x00) {
1087  *reason = tor_strdup("authentication failed");
1088  return -1;
1089  }
1090 
1091  log_info(LD_NET, "SOCKS 5 client: authentication successful.");
1092  *drain_out = -1;
1093  return 1;
1094 
1095  case PROXY_SOCKS5_WANT_CONNECT_OK:
1096  /* response is variable length. BND.ADDR, etc, isn't needed
1097  * (don't bother with buf_pullup()), but make sure to eat all
1098  * the data used */
1099 
1100  /* wait for address type field to arrive */
1101  if (datalen < 4)
1102  return 0;
1103 
1104  switch (data[3]) {
1105  case 0x01: /* ip4 */
1106  addrlen = 4;
1107  break;
1108  case 0x04: /* ip6 */
1109  addrlen = 16;
1110  break;
1111  case 0x03: /* fqdn (can this happen here?) */
1112  if (datalen < 5)
1113  return 0;
1114  addrlen = 1 + data[4];
1115  break;
1116  default:
1117  *reason = tor_strdup("invalid response to connect request");
1118  return -1;
1119  }
1120 
1121  /* wait for address and port */
1122  if (datalen < 6 + addrlen)
1123  return 0;
1124 
1125  if (data[1] != 0x00) {
1126  *reason = tor_strdup(socks5_response_code_to_string(data[1]));
1127  return -1;
1128  }
1129 
1130  *drain_out = 6 + addrlen;
1131  return 1;
1132  }
1133 
1134  /* LCOV_EXCL_START */
1135  /* shouldn't get here if the input state is one we know about... */
1136  tor_assert(0);
1137 
1138  return -1;
1139  /* LCOV_EXCL_STOP */
1140 }
tor_free
#define tor_free(p)
Definition: malloc.h:52
memwipe
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
tor_addr_t
Definition: address.h:68
tor_addr_to_str
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
Definition: address.c:328
socks_request_t::password
char * password
Definition: socks_request_st.h:84
MAX_SOCKS_MESSAGE_LEN
#define MAX_SOCKS_MESSAGE_LEN
Definition: proto_socks.c:83
socks5_reply_status_t
socks5_reply_status_t
Definition: socks5_status.h:20
process_socks5_userpass_auth
static socks_result_t process_socks5_userpass_auth(socks_request_t *req)
Definition: proto_socks.c:486
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
parse_socks5_userpass_auth
static socks_result_t parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req, size_t datalen, size_t *drain_out)
Definition: proto_socks.c:422
parse_socks4_request
static socks_result_t parse_socks4_request(const uint8_t *raw_data, socks_request_t *req, size_t datalen, int *is_socks4a, size_t *drain_out)
Definition: proto_socks.c:121
tor_addr_from_ipv6_bytes
void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const uint8_t *ipv6_bytes)
Definition: address.c:891
parse_socks5_methods_request
static socks_result_t parse_socks5_methods_request(const uint8_t *raw_data, socks_request_t *req, size_t datalen, int *have_user_pass, int *have_no_auth, size_t *drain_out)
Definition: proto_socks.c:283
reasons.h
Header file for reasons.c.
socks_request_t::auth_type
uint8_t auth_type
Definition: socks_request_st.h:45
socks_request_st.h
Client request structure.
socks_request_t::passwordlen
uint8_t passwordlen
Definition: socks_request_st.h:77
SOCKS_COMMAND_RESOLVE_PTR
#define SOCKS_COMMAND_RESOLVE_PTR
Definition: socks_request_st.h:27
SOCKS4_NETWORK_LEN
#define SOCKS4_NETWORK_LEN
Definition: or.h:563
escaped_safe_str_client
const char * escaped_safe_str_client(const char *address)
Definition: config.c:1116
crypto_util.h
Common functions for cryptographic routines.
buf_datalen
size_t buf_datalen(const buf_t *buf)
Definition: buffers.c:394
proto_socks.h
Header for proto_socks.c.
socks_request_t::replylen
size_t replylen
Definition: socks_request_st.h:50
tor_addr_from_ipv4h
#define tor_addr_from_ipv4h(dest, v4addr)
Definition: address.h:314
control_event_client_status
int control_event_client_status(int severity, const char *format,...)
Definition: control_events.c:1698
socks_request_t
Definition: socks_request_st.h:37
SOCKS_COMMAND_CONNECT
#define SOCKS_COMMAND_CONNECT
Definition: socks_request_st.h:23
socks_request_set_socks5_error
static void socks_request_set_socks5_error(socks_request_t *req, socks5_reply_status_t reason)
Definition: proto_socks.c:878
escaped
const char * escaped(const char *s)
Definition: escape.c:126
SOCKS_WARN_INTERVAL
#define SOCKS_WARN_INTERVAL
Definition: proto_socks.c:53
parse_socks_client
static int parse_socks_client(const uint8_t *data, size_t datalen, int state, char **reason, ssize_t *drain_out)
Definition: proto_socks.c:1025
parse_socks
static socks_result_t parse_socks(const char *data, size_t datalen, socks_request_t *req, int log_sockstype, int safe_socks, size_t *drain_out)
Definition: proto_socks.c:943
socks_request_t::reply
uint8_t reply[MAX_SOCKS_REPLY_LEN]
Definition: socks_request_st.h:51
buffers.h
Header file for buffers.c.
process_socks5_methods_request
static socks_result_t process_socks5_methods_request(socks_request_t *req, int have_user_pass, int have_no_auth)
Definition: proto_socks.c:356
command
tor_cmdline_mode_t command
Definition: config.c:2444
handle_socks_message
static socks_result_t handle_socks_message(const uint8_t *raw_data, size_t datalen, socks_request_t *req, int log_sockstype, int safe_socks, size_t *drain_out)
Definition: proto_socks.c:699
tor_addr_parse
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1308
socks_request_t::username
char * username
Definition: socks_request_st.h:81
ext_orport.h
Header for ext_orport.c.
control_events.h
Header file for control_events.c.
socks_request_new
socks_request_t * socks_request_new(void)
Definition: proto_socks.c:87
string_is_valid_dest
int string_is_valid_dest(const char *string)
Definition: address.c:2091
addressmap.h
Header for addressmap.c.
socks_request_t::socks_version
uint8_t socks_version
Definition: socks_request_st.h:41
socks5_response_code_to_string
const char * socks5_response_code_to_string(uint8_t code)
Definition: reasons.c:407
log_unsafe_socks_warning
static void log_unsafe_socks_warning(int socks_protocol, const char *address, uint16_t port, int safe_socks)
Definition: proto_socks.c:59
fetch_from_buf_socks
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req, int log_sockstype, int safe_socks)
Definition: proto_socks.c:824
connection.h
Header file for connection.c.
socks_request_t::socks_prefer_no_auth
unsigned int socks_prefer_no_auth
Definition: socks_request_st.h:67
process_socks4_request
static socks_result_t process_socks4_request(const socks_request_t *req, int is_socks4a, int log_sockstype, int safe_socks)
Definition: proto_socks.c:233
log_fn_ratelim
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition: log.h:292
SOCKS_COMMAND_RESOLVE
#define SOCKS_COMMAND_RESOLVE
Definition: socks_request_st.h:25
LOG_WARN
#define LOG_WARN
Definition: log.h:53
socks_request_t::usernamelen
size_t usernamelen
Definition: socks_request_st.h:75
buf_clear
void buf_clear(buf_t *buf)
Definition: buffers.c:381
socks_request_free_
void socks_request_free_(socks_request_t *req)
Definition: proto_socks.c:94
get_uint8
static uint8_t get_uint8(const void *cp)
Definition: bytes.h:23
socks_request_t::address
char address[MAX_SOCKS_ADDR_LEN]
Definition: socks_request_st.h:57
socks_request_t::got_auth
unsigned int got_auth
Definition: socks_request_st.h:63
fetch_from_buf_socks_client
int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
Definition: proto_socks.c:1000
LD_APP
#define LD_APP
Definition: log.h:78
config.h
Header file for config.c.
buf_drain
void buf_drain(buf_t *buf, size_t n)
Definition: buffers.c:330
parse_socks5_client_request
static socks_result_t parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req, size_t datalen, size_t *drain_out)
Definition: proto_socks.c:542
LD_NET
#define LD_NET
Definition: log.h:66
socks_request_t::command
uint8_t command
Definition: socks_request_st.h:47
socks_request_t::port
uint16_t port
Definition: socks_request_st.h:59
process_socks5_client_request
static socks_result_t process_socks5_client_request(socks_request_t *req, int log_sockstype, int safe_socks)
Definition: proto_socks.c:617
buf_pullup
void buf_pullup(buf_t *buf, size_t bytes, const char **head_out, size_t *len_out)
Definition: buffers.c:211
socks4_response_code_to_string
const char * socks4_response_code_to_string(uint8_t code)
Definition: reasons.c:389
addressmap_have_mapping
int addressmap_have_mapping(const char *address, int update_expiry)
Definition: addressmap.c:544
ratelim_t
Definition: ratelim.h:42
or.h
Master header file for Tor-specific functionality.
LD_PROTOCOL
#define LD_PROTOCOL
Definition: log.h:72