tor  0.4.2.1-alpha-dev
proto_socks.c
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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 #include "core/or/or.h"
8 #include "feature/client/addressmap.h"
9 #include "lib/buf/buffers.h"
12 #include "app/config/config.h"
14 #include "feature/relay/ext_orport.h"
15 #include "core/proto/proto_socks.h"
16 #include "core/or/reasons.h"
17 
18 #include "core/or/socks_request_st.h"
19 
20 #include "trunnel/socks5.h"
21 
22 #define SOCKS_VER_5 0x05 /* First octet of non-auth SOCKS5 messages */
23 #define SOCKS_VER_4 0x04 /* SOCKS4 messages */
24 #define SOCKS_AUTH 0x01 /* SOCKS5 auth messages */
25 
26 typedef enum {
27  SOCKS_RESULT_INVALID = -1, /* Message invalid. */
28  SOCKS_RESULT_TRUNCATED = 0, /* Message incomplete/truncated. */
29  SOCKS_RESULT_DONE = 1, /* OK, we're done. */
30  SOCKS_RESULT_MORE_EXPECTED = 2, /* OK, more messages expected. */
31 } socks_result_t;
32 
33 static void socks_request_set_socks5_error(socks_request_t *req,
34  socks5_reply_status_t reason);
35 
36 static socks_result_t parse_socks(const char *data,
37  size_t datalen,
38  socks_request_t *req,
39  int log_sockstype,
40  int safe_socks,
41  size_t *drain_out);
42 static int parse_socks_client(const uint8_t *data, size_t datalen,
43  int state, char **reason,
44  ssize_t *drain_out);
48 #define SOCKS_WARN_INTERVAL 5
49 
53 static void
54 log_unsafe_socks_warning(int socks_protocol, const char *address,
55  uint16_t port, int safe_socks)
56 {
57  static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL);
58 
59  if (safe_socks) {
60  log_fn_ratelim(&socks_ratelim, LOG_WARN, LD_APP,
61  "Your application (using socks%d to port %d) is giving "
62  "Tor only an IP address. Applications that do DNS resolves "
63  "themselves may leak information. Consider using Socks4A "
64  "(e.g. via privoxy or socat) instead. For more information, "
65  "please see https://wiki.torproject.org/TheOnionRouter/"
66  "TorFAQ#SOCKSAndDNS.%s",
67  socks_protocol,
68  (int)port,
69  safe_socks ? " Rejecting." : "");
70  }
72  "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d",
73  socks_protocol, address, (int)port);
74 }
75 
78 #define MAX_SOCKS_MESSAGE_LEN 512
79 
82 socks_request_new(void)
83 {
84  return tor_malloc_zero(sizeof(socks_request_t));
85 }
86 
88 void
89 socks_request_free_(socks_request_t *req)
90 {
91  if (!req)
92  return;
93  if (req->username) {
94  memwipe(req->username, 0x10, req->usernamelen);
95  tor_free(req->username);
96  }
97  if (req->password) {
98  memwipe(req->password, 0x04, req->passwordlen);
99  tor_free(req->password);
100  }
101  memwipe(req, 0xCC, sizeof(socks_request_t));
102  tor_free(req);
103 }
104 
115 static socks_result_t
116 parse_socks4_request(const uint8_t *raw_data, socks_request_t *req,
117  size_t datalen, int *is_socks4a, size_t *drain_out)
118 {
119  // http://ss5.sourceforge.net/socks4.protocol.txt
120  // http://ss5.sourceforge.net/socks4A.protocol.txt
121  socks_result_t res = SOCKS_RESULT_DONE;
122  tor_addr_t destaddr;
123 
124  tor_assert(is_socks4a);
125  tor_assert(drain_out);
126 
127  *is_socks4a = 0;
128  *drain_out = 0;
129 
130  req->socks_version = SOCKS_VER_4;
131 
132  socks4_client_request_t *trunnel_req;
133 
134  ssize_t parsed =
135  socks4_client_request_parse(&trunnel_req, raw_data, datalen);
136 
137  if (parsed == -1) {
138  log_warn(LD_APP, "socks4: parsing failed - invalid request.");
139  res = SOCKS_RESULT_INVALID;
140  goto end;
141  } else if (parsed == -2) {
142  res = SOCKS_RESULT_TRUNCATED;
143  if (datalen >= MAX_SOCKS_MESSAGE_LEN) {
144  log_warn(LD_APP, "socks4: parsing failed - invalid request.");
145  res = SOCKS_RESULT_INVALID;
146  }
147  goto end;
148  }
149 
150  tor_assert(parsed >= 0);
151  *drain_out = (size_t)parsed;
152 
153  uint8_t command = socks4_client_request_get_command(trunnel_req);
154  req->command = command;
155 
156  req->port = socks4_client_request_get_port(trunnel_req);
157  uint32_t dest_ip = socks4_client_request_get_addr(trunnel_req);
158 
159  if ((!req->port && req->command != SOCKS_COMMAND_RESOLVE) ||
160  dest_ip == 0) {
161  log_warn(LD_APP, "socks4: Port or DestIP is zero. Rejecting.");
162  res = SOCKS_RESULT_INVALID;
163  goto end;
164  }
165 
166  *is_socks4a = (dest_ip >> 8) == 0;
167 
168  const char *username = socks4_client_request_get_username(trunnel_req);
169  const size_t usernamelen = username ? strlen(username) : 0;
170  if (username && usernamelen) {
171  if (usernamelen > MAX_SOCKS_MESSAGE_LEN) {
172  log_warn(LD_APP, "Socks4 user name too long; rejecting.");
173  res = SOCKS_RESULT_INVALID;
174  goto end;
175  }
176 
177  tor_free(req->username);
178  req->got_auth = 1;
179  req->username = tor_strdup(username);
180  req->usernamelen = usernamelen;
181  }
182 
183  if (*is_socks4a) {
184  // We cannot rely on trunnel here, as we want to detect if
185  // we have abnormally long hostname field.
186  const char *hostname = (char *)raw_data + SOCKS4_NETWORK_LEN +
187  usernamelen + 1;
188  size_t hostname_len = (char *)raw_data + datalen - hostname;
189 
190  if (hostname_len <= sizeof(req->address)) {
191  const char *trunnel_hostname =
192  socks4_client_request_get_socks4a_addr_hostname(trunnel_req);
193 
194  if (trunnel_hostname)
195  strlcpy(req->address, trunnel_hostname, sizeof(req->address));
196  } else {
197  log_warn(LD_APP, "socks4: Destaddr too long. Rejecting.");
198  res = SOCKS_RESULT_INVALID;
199  goto end;
200  }
201  } else {
202  tor_addr_from_ipv4h(&destaddr, dest_ip);
203 
204  if (!tor_addr_to_str(req->address, &destaddr,
205  MAX_SOCKS_ADDR_LEN, 0)) {
206  res = SOCKS_RESULT_INVALID;
207  goto end;
208  }
209  }
210 
211  end:
212  socks4_client_request_free(trunnel_req);
213 
214  return res;
215 }
216 
227 static socks_result_t
228 process_socks4_request(const socks_request_t *req, int is_socks4a,
229  int log_sockstype, int safe_socks)
230 {
231  if (is_socks4a && !addressmap_have_mapping(req->address, 0)) {
232  log_unsafe_socks_warning(4, req->address, req->port, safe_socks);
233 
234  if (safe_socks)
235  return SOCKS_RESULT_INVALID;
236  }
237 
238  if (req->command != SOCKS_COMMAND_CONNECT &&
239  req->command != SOCKS_COMMAND_RESOLVE) {
240  /* not a connect or resolve? we don't support it. (No resolve_ptr with
241  * socks4.) */
242  log_warn(LD_APP, "socks4: command %d not recognized. Rejecting.",
243  req->command);
244  return SOCKS_RESULT_INVALID;
245  }
246 
247  if (is_socks4a) {
248  if (log_sockstype)
249  log_notice(LD_APP,
250  "Your application (using socks4a to port %d) instructed "
251  "Tor to take care of the DNS resolution itself if "
252  "necessary. This is good.", req->port);
253  }
254 
255  if (!string_is_valid_dest(req->address)) {
256  log_warn(LD_PROTOCOL,
257  "Your application (using socks4 to port %d) gave Tor "
258  "a malformed hostname: %s. Rejecting the connection.",
259  req->port, escaped_safe_str_client(req->address));
260  return SOCKS_RESULT_INVALID;
261  }
262 
263  return SOCKS_RESULT_DONE;
264 }
265 
277 static socks_result_t
278 parse_socks5_methods_request(const uint8_t *raw_data, socks_request_t *req,
279  size_t datalen, int *have_user_pass,
280  int *have_no_auth, size_t *drain_out)
281 {
282  socks_result_t res = SOCKS_RESULT_DONE;
283  socks5_client_version_t *trunnel_req;
284 
285  ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
286  datalen);
287 
288  (void)req;
289 
290  tor_assert(have_no_auth);
291  tor_assert(have_user_pass);
292  tor_assert(drain_out);
293 
294  *drain_out = 0;
295 
296  if (parsed == -1) {
297  log_warn(LD_APP, "socks5: parsing failed - invalid version "
298  "id/method selection message.");
299  res = SOCKS_RESULT_INVALID;
300  goto end;
301  } else if (parsed == -2) {
302  res = SOCKS_RESULT_TRUNCATED;
303  if (datalen > MAX_SOCKS_MESSAGE_LEN) {
304  log_warn(LD_APP, "socks5: parsing failed - invalid version "
305  "id/method selection message.");
306  res = SOCKS_RESULT_INVALID;
307  }
308  goto end;
309  }
310 
311  tor_assert(parsed >= 0);
312  *drain_out = (size_t)parsed;
313 
314  size_t n_methods = (size_t)socks5_client_version_get_n_methods(trunnel_req);
315  if (n_methods == 0) {
316  res = SOCKS_RESULT_INVALID;
317  goto end;
318  }
319 
320  *have_no_auth = 0;
321  *have_user_pass = 0;
322 
323  for (size_t i = 0; i < n_methods; i++) {
324  uint8_t method = socks5_client_version_get_methods(trunnel_req,
325  i);
326 
327  if (method == SOCKS_USER_PASS) {
328  *have_user_pass = 1;
329  } else if (method == SOCKS_NO_AUTH) {
330  *have_no_auth = 1;
331  }
332  }
333 
334  end:
335  socks5_client_version_free(trunnel_req);
336 
337  return res;
338 }
339 
350 static socks_result_t
351 process_socks5_methods_request(socks_request_t *req, int have_user_pass,
352  int have_no_auth)
353 {
354  socks_result_t res = SOCKS_RESULT_DONE;
355  socks5_server_method_t *trunnel_resp = socks5_server_method_new();
356  tor_assert(trunnel_resp);
357 
358  socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
359 
360  if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) {
361  req->auth_type = SOCKS_USER_PASS;
362  socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
363 
364  req->socks_version = SOCKS_VER_5;
365  // FIXME: come up with better way to remember
366  // that we negotiated auth
367 
368  log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
369  } else if (have_no_auth) {
370  req->auth_type = SOCKS_NO_AUTH;
371  socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
372 
373  req->socks_version = SOCKS_VER_5;
374 
375  log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
376  } else {
377  log_warn(LD_APP,
378  "socks5: offered methods don't include 'no auth' or "
379  "username/password. Rejecting.");
380  socks5_server_method_set_method(trunnel_resp, 0xFF); // reject all
381  res = SOCKS_RESULT_INVALID;
382  }
383 
384  const char *errmsg = socks5_server_method_check(trunnel_resp);
385  if (errmsg) {
386  log_warn(LD_APP, "socks5: method selection validation failed: %s",
387  errmsg);
388  res = SOCKS_RESULT_INVALID;
389  } else {
390  ssize_t encoded =
391  socks5_server_method_encode(req->reply, sizeof(req->reply),
392  trunnel_resp);
393 
394  if (encoded < 0) {
395  log_warn(LD_APP, "socks5: method selection encoding failed");
396  res = SOCKS_RESULT_INVALID;
397  } else {
398  req->replylen = (size_t)encoded;
399  }
400  }
401 
402  socks5_server_method_free(trunnel_resp);
403  return res;
404 }
405 
416 static socks_result_t
417 parse_socks5_userpass_auth(const uint8_t *raw_data, socks_request_t *req,
418  size_t datalen, size_t *drain_out)
419 {
420  socks_result_t res = SOCKS_RESULT_DONE;
421  socks5_client_userpass_auth_t *trunnel_req = NULL;
422  ssize_t parsed = socks5_client_userpass_auth_parse(&trunnel_req, raw_data,
423  datalen);
424  tor_assert(drain_out);
425  *drain_out = 0;
426 
427  if (parsed == -1) {
428  log_warn(LD_APP, "socks5: parsing failed - invalid user/pass "
429  "authentication message.");
430  res = SOCKS_RESULT_INVALID;
431  goto end;
432  } else if (parsed == -2) {
433  res = SOCKS_RESULT_TRUNCATED;
434  goto end;
435  }
436 
437  tor_assert(parsed >= 0);
438  *drain_out = (size_t)parsed;
439 
440  uint8_t usernamelen =
441  socks5_client_userpass_auth_get_username_len(trunnel_req);
442  uint8_t passwordlen =
443  socks5_client_userpass_auth_get_passwd_len(trunnel_req);
444  const char *username =
445  socks5_client_userpass_auth_getconstarray_username(trunnel_req);
446  const char *password =
447  socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
448 
449  if (usernamelen && username) {
450  tor_free(req->username);
451  req->username = tor_memdup_nulterm(username, usernamelen);
452  req->usernamelen = usernamelen;
453  }
454 
455  if (passwordlen && password) {
456  tor_free(req->password);
457  req->password = tor_memdup_nulterm(password, passwordlen);
458  req->passwordlen = passwordlen;
459  }
460 
467  req->got_auth = 1;
468 
469  end:
470  socks5_client_userpass_auth_free(trunnel_req);
471  return res;
472 }
473 
480 static socks_result_t
481 process_socks5_userpass_auth(socks_request_t *req)
482 {
483  socks_result_t res = SOCKS_RESULT_DONE;
484  socks5_server_userpass_auth_t *trunnel_resp =
485  socks5_server_userpass_auth_new();
486  tor_assert(trunnel_resp);
487 
488  if (req->socks_version != SOCKS_VER_5) {
489  res = SOCKS_RESULT_INVALID;
490  goto end;
491  }
492 
493  if (req->auth_type != SOCKS_USER_PASS &&
494  req->auth_type != SOCKS_NO_AUTH) {
495  res = SOCKS_RESULT_INVALID;
496  goto end;
497  }
498 
499  socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
500  socks5_server_userpass_auth_set_status(trunnel_resp, 0); // auth OK
501 
502  const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
503  if (errmsg) {
504  log_warn(LD_APP, "socks5: server userpass auth validation failed: %s",
505  errmsg);
506  res = SOCKS_RESULT_INVALID;
507  goto end;
508  }
509 
510  ssize_t encoded = socks5_server_userpass_auth_encode(req->reply,
511  sizeof(req->reply),
512  trunnel_resp);
513 
514  if (encoded < 0) {
515  log_warn(LD_APP, "socks5: server userpass auth encoding failed");
516  res = SOCKS_RESULT_INVALID;
517  goto end;
518  }
519 
520  req->replylen = (size_t)encoded;
521 
522  end:
523  socks5_server_userpass_auth_free(trunnel_resp);
524  return res;
525 }
526 
536 static socks_result_t
537 parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req,
538  size_t datalen, size_t *drain_out)
539 {
540  socks_result_t res = SOCKS_RESULT_DONE;
541  tor_addr_t destaddr;
542  socks5_client_request_t *trunnel_req = NULL;
543  ssize_t parsed =
544  socks5_client_request_parse(&trunnel_req, raw_data, datalen);
545  if (parsed == -1) {
546  log_warn(LD_APP, "socks5: parsing failed - invalid client request");
547  res = SOCKS_RESULT_INVALID;
548  goto end;
549  } else if (parsed == -2) {
550  res = SOCKS_RESULT_TRUNCATED;
551  goto end;
552  }
553 
554  tor_assert(parsed >= 0);
555  *drain_out = (size_t)parsed;
556 
557  if (socks5_client_request_get_version(trunnel_req) != 5) {
558  res = SOCKS_RESULT_INVALID;
559  goto end;
560  }
561 
562  req->command = socks5_client_request_get_command(trunnel_req);
563 
564  req->port = socks5_client_request_get_dest_port(trunnel_req);
565 
566  uint8_t atype = socks5_client_request_get_atype(trunnel_req);
567  req->socks5_atyp = atype;
568 
569  switch (atype) {
570  case 1: {
571  uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
572  tor_addr_from_ipv4h(&destaddr, ipv4);
573 
574  tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
575  } break;
576  case 3: {
577  const struct domainname_st *dns_name =
578  socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
579 
580  const char *hostname = domainname_getconstarray_name(dns_name);
581 
582  strlcpy(req->address, hostname, sizeof(req->address));
583  } break;
584  case 4: {
585  const char *ipv6 =
586  (const char *)socks5_client_request_getarray_dest_addr_ipv6(
587  trunnel_req);
588  tor_addr_from_ipv6_bytes(&destaddr, ipv6);
589 
590  tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
591  } break;
592  default: {
593  res = -1;
594  } break;
595  }
596 
597  end:
598  socks5_client_request_free(trunnel_req);
599  return res;
600 }
601 
612 static socks_result_t
613 process_socks5_client_request(socks_request_t *req,
614  int log_sockstype,
615  int safe_socks)
616 {
617  socks_result_t res = SOCKS_RESULT_DONE;
618 
619  if (req->command != SOCKS_COMMAND_CONNECT &&
620  req->command != SOCKS_COMMAND_RESOLVE &&
621  req->command != SOCKS_COMMAND_RESOLVE_PTR) {
622  socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
623  res = SOCKS_RESULT_INVALID;
624  goto end;
625  }
626 
627  if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
630  socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
631  log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
632  "hostname type. Rejecting.");
633 
634  res = SOCKS_RESULT_INVALID;
635  goto end;
636  }
637 
638  if (!string_is_valid_dest(req->address)) {
639  socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
640 
641  log_warn(LD_PROTOCOL,
642  "Your application (using socks5 to port %d) gave Tor "
643  "a malformed hostname: %s. Rejecting the connection.",
644  req->port, escaped_safe_str_client(req->address));
645 
646  res = SOCKS_RESULT_INVALID;
647  goto end;
648  }
649 
650  if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
651  if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
652  !addressmap_have_mapping(req->address,0)) {
653  log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
654  if (safe_socks) {
655  socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
656  res = SOCKS_RESULT_INVALID;
657  goto end;
658  }
659  }
660  }
661 
662  if (log_sockstype)
663  log_notice(LD_APP,
664  "Your application (using socks5 to port %d) instructed "
665  "Tor to take care of the DNS resolution itself if "
666  "necessary. This is good.", req->port);
667 
668  end:
669  return res;
670 }
671 
694 static socks_result_t
695 handle_socks_message(const uint8_t *raw_data, size_t datalen,
696  socks_request_t *req, int log_sockstype,
697  int safe_socks, size_t *drain_out)
698 {
699  socks_result_t res = SOCKS_RESULT_DONE;
700 
701  uint8_t socks_version = raw_data[0];
702 
703  if (socks_version == SOCKS_AUTH)
704  socks_version = SOCKS_VER_5; // SOCKS5 username/pass subnegotiation
705 
706  if (socks_version == SOCKS_VER_4) {
707  if (datalen < SOCKS4_NETWORK_LEN) {
708  res = 0;
709  goto end;
710  }
711 
712  int is_socks4a = 0;
713  res = parse_socks4_request((const uint8_t *)raw_data, req, datalen,
714  &is_socks4a, drain_out);
715 
716  if (res != SOCKS_RESULT_DONE) {
717  goto end;
718  }
719 
720  res = process_socks4_request(req, is_socks4a,log_sockstype,
721  safe_socks);
722 
723  if (res != SOCKS_RESULT_DONE) {
724  goto end;
725  }
726 
727  goto end;
728  } else if (socks_version == SOCKS_VER_5) {
729  if (datalen < 2) { /* version and another byte */
730  res = 0;
731  goto end;
732  }
733  /* RFC1929 SOCKS5 username/password subnegotiation. */
734  if (!req->got_auth && (raw_data[0] == 1 ||
735  req->auth_type == SOCKS_USER_PASS)) {
736  res = parse_socks5_userpass_auth(raw_data, req, datalen,
737  drain_out);
738 
739  if (res != SOCKS_RESULT_DONE) {
740  goto end;
741  }
742 
743  res = process_socks5_userpass_auth(req);
744  if (res != SOCKS_RESULT_DONE) {
745  goto end;
746  }
747 
748  res = SOCKS_RESULT_MORE_EXPECTED;
749  goto end;
750  } else if (req->socks_version != SOCKS_VER_5) {
751  int have_user_pass=0, have_no_auth=0;
752  res = parse_socks5_methods_request(raw_data, req, datalen,
753  &have_user_pass,
754  &have_no_auth,
755  drain_out);
756 
757  if (res != SOCKS_RESULT_DONE) {
758  goto end;
759  }
760 
761  res = process_socks5_methods_request(req, have_user_pass,
762  have_no_auth);
763 
764  if (res != SOCKS_RESULT_DONE) {
765  goto end;
766  }
767 
768  res = SOCKS_RESULT_MORE_EXPECTED;
769  goto end;
770  } else {
771  res = parse_socks5_client_request(raw_data, req,
772  datalen, drain_out);
773  if (res != SOCKS_RESULT_DONE) {
774  socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
775  goto end;
776  }
777 
778  res = process_socks5_client_request(req, log_sockstype,
779  safe_socks);
780 
781  if (res != SOCKS_RESULT_DONE) {
782  goto end;
783  }
784  }
785  } else {
786  *drain_out = datalen;
787  res = SOCKS_RESULT_INVALID;
788  }
789 
790  end:
791  return res;
792 }
793 
819 int
820 fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
821  int log_sockstype, int safe_socks)
822 {
823  int res = 0;
824  size_t datalen = buf_datalen(buf);
825  size_t n_drain;
826  const char *head = NULL;
827  socks_result_t socks_res;
828  size_t n_pullup;
829 
830  if (buf_datalen(buf) < 2) { /* version and another byte */
831  res = 0;
832  goto end;
833  }
834 
835  do {
836  n_drain = 0;
837  n_pullup = MIN(MAX_SOCKS_MESSAGE_LEN, buf_datalen(buf));
838  buf_pullup(buf, n_pullup, &head, &datalen);
839  tor_assert(head && datalen >= 2);
840 
841  socks_res = parse_socks(head, datalen, req, log_sockstype,
842  safe_socks, &n_drain);
843 
844  if (socks_res == SOCKS_RESULT_INVALID)
845  buf_clear(buf);
846  else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
847  buf_drain(buf, n_drain);
848 
849  switch (socks_res) {
850  case SOCKS_RESULT_INVALID:
851  res = -1;
852  break;
853  case SOCKS_RESULT_DONE:
854  res = 1;
855  break;
856  case SOCKS_RESULT_TRUNCATED:
857  if (datalen == n_pullup)
858  return 0;
859  /* FALLTHRU */
860  case SOCKS_RESULT_MORE_EXPECTED:
861  res = 0;
862  break;
863  }
864  } while (res == 0 && head && buf_datalen(buf) >= 2);
865 
866  end:
867  return res;
868 }
869 
873 static void
874 socks_request_set_socks5_error(socks_request_t *req,
875  socks5_reply_status_t reason)
876 {
877  socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
878  tor_assert(trunnel_resp);
879 
880  socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
881  socks5_server_reply_set_reply(trunnel_resp, reason);
882  socks5_server_reply_set_atype(trunnel_resp, 0x01);
883 
884  const char *errmsg = socks5_server_reply_check(trunnel_resp);
885  if (errmsg) {
886  log_warn(LD_APP, "socks5: reply validation failed: %s",
887  errmsg);
888  goto end;
889  }
890 
891  ssize_t encoded = socks5_server_reply_encode(req->reply,
892  sizeof(req->reply),
893  trunnel_resp);
894  if (encoded < 0) {
895  log_warn(LD_APP, "socks5: reply encoding failed: %d",
896  (int)encoded);
897  } else {
898  req->replylen = (size_t)encoded;
899  }
900 
901  end:
902  socks5_server_reply_free(trunnel_resp);
903 }
904 
905 static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
906  "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
907  "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
908  "<html>\n"
909  "<head>\n"
910  "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
911  "</head>\n"
912  "<body>\n"
913  "<h1>This is a SOCKs proxy, not an HTTP proxy.</h1>\n"
914  "<p>\n"
915  "It appears you have configured your web browser to use this Tor port as\n"
916  "an HTTP proxy.\n"
917  "</p><p>\n"
918  "This is not correct: This port is configured as a SOCKS proxy, not\n"
919  "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
920  "configuration option in place of, or in addition to, SOCKSPort.\n"
921  "Please configure your client accordingly.\n"
922  "</p>\n"
923  "<p>\n"
924  "See <a href=\"https://www.torproject.org/documentation.html\">"
925  "https://www.torproject.org/documentation.html</a> for more "
926  "information.\n"
927  "</p>\n"
928  "</body>\n"
929  "</html>\n";
930 
938 static int
939 parse_socks(const char *data, size_t datalen, socks_request_t *req,
940  int log_sockstype, int safe_socks, size_t *drain_out)
941 {
942  uint8_t first_octet;
943 
944  if (datalen < 2) {
945  /* We always need at least 2 bytes. */
946  return 0;
947  }
948 
949  first_octet = get_uint8(data);
950 
951  if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
952  first_octet == SOCKS_AUTH) { // XXX: RFC 1929
953  return handle_socks_message((const uint8_t *)data, datalen, req,
954  log_sockstype, safe_socks, drain_out);
955  }
956 
957  switch (first_octet) { /* which version of socks? */
958  case 'G': /* get */
959  case 'H': /* head */
960  case 'P': /* put/post */
961  case 'C': /* connect */
962  strlcpy((char*)req->reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
963  MAX_SOCKS_REPLY_LEN);
964  req->replylen = strlen((char*)req->reply)+1;
965  /* fall through */
966  default: /* version is not socks4 or socks5 */
967  log_warn(LD_APP,
968  "Socks version %d not recognized. (This port is not an "
969  "HTTP proxy; did you want to use HTTPTunnelPort?)",
970  *(data));
971  {
972  /* Tell the controller the first 8 bytes. */
973  char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
975  "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
976  escaped(tmp));
977  tor_free(tmp);
978  }
979  return -1;
980  }
981 
982  tor_assert_unreached();
983  return -1;
984 }
985 
995 int
996 fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
997 {
998  ssize_t drain = 0;
999  int r;
1000  const char *head = NULL;
1001  size_t datalen = 0;
1002 
1003  if (buf_datalen(buf) < 2)
1004  return 0;
1005 
1006  buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, &head, &datalen);
1007  tor_assert(head && datalen >= 2);
1008 
1009  r = parse_socks_client((uint8_t*)head, datalen,
1010  state, reason, &drain);
1011  if (drain > 0)
1012  buf_drain(buf, drain);
1013  else if (drain < 0)
1014  buf_clear(buf);
1015 
1016  return r;
1017 }
1018 
1020 static int
1021 parse_socks_client(const uint8_t *data, size_t datalen,
1022  int state, char **reason,
1023  ssize_t *drain_out)
1024 {
1025  unsigned int addrlen;
1026  *drain_out = 0;
1027  if (datalen < 2)
1028  return 0;
1029 
1030  switch (state) {
1031  case PROXY_SOCKS4_WANT_CONNECT_OK:
1032  /* Wait for the complete response */
1033  if (datalen < 8)
1034  return 0;
1035 
1036  if (data[1] != 0x5a) {
1037  *reason = tor_strdup(socks4_response_code_to_string(data[1]));
1038  return -1;
1039  }
1040 
1041  /* Success */
1042  *drain_out = 8;
1043  return 1;
1044 
1045  case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1046  /* we don't have any credentials */
1047  if (data[1] != 0x00) {
1048  *reason = tor_strdup("server doesn't support any of our "
1049  "available authentication methods");
1050  return -1;
1051  }
1052 
1053  log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
1054  *drain_out = -1;
1055  return 1;
1056 
1057  case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1058  /* we have a username and password. return 1 if we can proceed without
1059  * providing authentication, or 2 otherwise. */
1060  switch (data[1]) {
1061  case 0x00:
1062  log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
1063  "doesn't require authentication.");
1064  *drain_out = -1;
1065  return 1;
1066  case 0x02:
1067  log_info(LD_NET, "SOCKS 5 client: need authentication.");
1068  *drain_out = -1;
1069  return 2;
1070  /* fall through */
1071  }
1072 
1073  *reason = tor_strdup("server doesn't support any of our available "
1074  "authentication methods");
1075  return -1;
1076 
1077  case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1078  /* handle server reply to rfc1929 authentication */
1079  if (data[1] != 0x00) {
1080  *reason = tor_strdup("authentication failed");
1081  return -1;
1082  }
1083 
1084  log_info(LD_NET, "SOCKS 5 client: authentication successful.");
1085  *drain_out = -1;
1086  return 1;
1087 
1088  case PROXY_SOCKS5_WANT_CONNECT_OK:
1089  /* response is variable length. BND.ADDR, etc, isn't needed
1090  * (don't bother with buf_pullup()), but make sure to eat all
1091  * the data used */
1092 
1093  /* wait for address type field to arrive */
1094  if (datalen < 4)
1095  return 0;
1096 
1097  switch (data[3]) {
1098  case 0x01: /* ip4 */
1099  addrlen = 4;
1100  break;
1101  case 0x04: /* ip6 */
1102  addrlen = 16;
1103  break;
1104  case 0x03: /* fqdn (can this happen here?) */
1105  if (datalen < 5)
1106  return 0;
1107  addrlen = 1 + data[4];
1108  break;
1109  default:
1110  *reason = tor_strdup("invalid response to connect request");
1111  return -1;
1112  }
1113 
1114  /* wait for address and port */
1115  if (datalen < 6 + addrlen)
1116  return 0;
1117 
1118  if (data[1] != 0x00) {
1119  *reason = tor_strdup(socks5_response_code_to_string(data[1]));
1120  return -1;
1121  }
1122 
1123  *drain_out = 6 + addrlen;
1124  return 1;
1125  }
1126 
1127  /* LCOV_EXCL_START */
1128  /* shouldn't get here if the input state is one we know about... */
1129  tor_assert(0);
1130 
1131  return -1;
1132  /* LCOV_EXCL_STOP */
1133 }
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
Definition: address.c:328
void buf_pullup(buf_t *buf, size_t bytes, const char **head_out, size_t *len_out)
Definition: buffers.c:209
int string_is_valid_ipv4_address(const char *string)
Definition: address.c:2016
uint8_t reply[MAX_SOCKS_REPLY_LEN]
Header file for connection.c.
int addressmap_have_mapping(const char *address, int update_expiry)
Definition: addressmap.c:545
char address[MAX_SOCKS_ADDR_LEN]
Header file for config.c.
#define tor_free(p)
Definition: malloc.h:52
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:57
unsigned int got_auth
#define LD_APP
Definition: log.h:76
Common functions for cryptographic routines.
tor_assert(buffer)
#define tor_addr_from_ipv4h(dest, v4addr)
Definition: address.h:287
void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *ipv6_bytes)
Definition: address.c:885
Master header file for Tor-specific functionality.
#define LOG_WARN
Definition: log.h:51
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition: log.h:279
socks5_reply_status_t
Definition: socks5_status.h:20
int control_event_client_status(int severity, const char *format,...)
void buf_drain(buf_t *buf, size_t n)
Definition: buffers.c:328
const char * socks5_response_code_to_string(uint8_t code)
Definition: reasons.c:407
const char * escaped(const char *s)
Definition: escape.c:126
int string_is_valid_ipv6_address(const char *string)
Definition: address.c:2027
int string_is_valid_dest(const char *string)
Definition: address.c:2038
Header file for buffers.c.
Header file for reasons.c.
#define LD_NET
Definition: log.h:64
const char * socks4_response_code_to_string(uint8_t code)
Definition: reasons.c:389
void buf_clear(buf_t *buf)
Definition: buffers.c:379
Header file for control_events.c.
#define LD_PROTOCOL
Definition: log.h:70
const char * escaped_safe_str_client(const char *address)
Definition: config.c:1137
#define SOCKS4_NETWORK_LEN
Definition: or.h:563
unsigned int socks_prefer_no_auth