Tor 0.4.9.1-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-2021, 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"
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
31typedef 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
40
41static 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);
47static 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. */
58static void
59log_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://2019.www.torproject.org/docs/faq.html.en"
71 "#WarningsAboutSOCKSandDNSInformationLeaks.%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>. */
93void
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 */
120static socks_result_t
121parse_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 */
232static socks_result_t
233process_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 &&
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.",
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 */
282static socks_result_t
283parse_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 */
355static 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 */
421static socks_result_t
422parse_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 /* Detect invalid SOCKS5 extended-parameter requests. */
455 if (usernamelen >= 8 &&
456 tor_memeq(username, "<torS0X>", 8)) {
457 /* This is indeed an extended-parameter request. */
458 if (usernamelen != 9 ||
459 tor_memneq(username, "<torS0X>0", 9)) {
460 /* This request is an unrecognized version, or it includes an Arti RPC
461 * object ID (which we do not recognize). */
462 res = SOCKS_RESULT_INVALID;
463 goto end;
464 }
465 }
466
467 if (usernamelen && username) {
468 tor_free(req->username);
469 req->username = tor_memdup_nulterm(username, usernamelen);
470 req->usernamelen = usernamelen;
471 }
472
473 if (passwordlen && password) {
474 tor_free(req->password);
475 req->password = tor_memdup_nulterm(password, passwordlen);
476 req->passwordlen = passwordlen;
477 }
478
479 /**
480 * Yes, we allow username and/or password to be empty. Yes, that does
481 * violate RFC 1929. However, some client software can send a username/
482 * password message with these fields being empty and we want to allow them
483 * to be used with Tor.
484 */
485 req->got_auth = 1;
486
487 end:
488 socks5_client_userpass_auth_free(trunnel_req);
489 return res;
490}
491
492/**
493 * Validate and respond to SOCKS5 username/password request we
494 * parsed in parse_socks5_userpass_auth (corresponding to <b>req</b>.
495 * Set <b>req->reply</b> to appropriate response. Return
496 * SOCKS_RESULT_DONE on success or SOCKS_RESULT_INVALID on failure.
497 */
498static socks_result_t
500{
501 socks_result_t res = SOCKS_RESULT_DONE;
502 socks5_server_userpass_auth_t *trunnel_resp =
503 socks5_server_userpass_auth_new();
504 tor_assert(trunnel_resp);
505
506 if (req->socks_version != SOCKS_VER_5) {
507 res = SOCKS_RESULT_INVALID;
508 goto end;
509 }
510
511 if (req->auth_type != SOCKS_USER_PASS &&
512 req->auth_type != SOCKS_NO_AUTH) {
513 res = SOCKS_RESULT_INVALID;
514 goto end;
515 }
516
517 socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
518 socks5_server_userpass_auth_set_status(trunnel_resp, 0); // auth OK
519
520 const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
521 if (errmsg) {
522 log_warn(LD_APP, "socks5: server userpass auth validation failed: %s",
523 errmsg);
524 res = SOCKS_RESULT_INVALID;
525 goto end;
526 }
527
528 ssize_t encoded = socks5_server_userpass_auth_encode(req->reply,
529 sizeof(req->reply),
530 trunnel_resp);
531
532 if (encoded < 0) {
533 log_warn(LD_APP, "socks5: server userpass auth encoding failed");
534 res = SOCKS_RESULT_INVALID;
535 goto end;
536 }
537
538 req->replylen = (size_t)encoded;
539
540 end:
541 socks5_server_userpass_auth_free(trunnel_resp);
542 return res;
543}
544
545/**
546 * Parse a single SOCKS5 client request (RFC 1928 section 4) from buffer
547 * <b>raw_data</b> of length <b>datalen</b> and update relevant field of
548 * <b>req</b>. Set <b>*drain_out</b> to number of bytes we parsed so far.
549 *
550 * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
551 * parsing failed because of invalid input or SOCKS_RESULT_TRUNCATED if it
552 * failed due to incomplete (truncated) input.
553 */
554static socks_result_t
555parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req,
556 size_t datalen, size_t *drain_out)
557{
558 socks_result_t res = SOCKS_RESULT_DONE;
559 tor_addr_t destaddr;
560 socks5_client_request_t *trunnel_req = NULL;
561 ssize_t parsed =
562 socks5_client_request_parse(&trunnel_req, raw_data, datalen);
563 if (parsed == -1) {
564 log_warn(LD_APP, "socks5: parsing failed - invalid client request");
565 res = SOCKS_RESULT_INVALID;
566 socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
567 goto end;
568 } else if (parsed == -2) {
569 res = SOCKS_RESULT_TRUNCATED;
570 goto end;
571 }
572
573 tor_assert(parsed >= 0);
574 *drain_out = (size_t)parsed;
575
576 if (socks5_client_request_get_version(trunnel_req) != 5) {
577 res = SOCKS_RESULT_INVALID;
578 socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
579 goto end;
580 }
581
582 req->command = socks5_client_request_get_command(trunnel_req);
583
584 req->port = socks5_client_request_get_dest_port(trunnel_req);
585
586 uint8_t atype = socks5_client_request_get_atype(trunnel_req);
587 req->socks5_atyp = atype;
588
589 switch (atype) {
590 case 1: {
591 uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
592 tor_addr_from_ipv4h(&destaddr, ipv4);
593
594 tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
595 } break;
596 case 3: {
597 const struct domainname_st *dns_name =
598 socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
599
600 const char *hostname = domainname_getconstarray_name(dns_name);
601
602 strlcpy(req->address, hostname, sizeof(req->address));
603 } break;
604 case 4: {
605 const uint8_t *ipv6 =
606 socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
607 tor_addr_from_ipv6_bytes(&destaddr, ipv6);
608
609 tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
610 } break;
611 default: {
612 socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
613 res = -1;
614 } break;
615 }
616
617 end:
618 socks5_client_request_free(trunnel_req);
619 return res;
620}
621
622/**
623 * Validate and respond to SOCKS5 request we parsed in
624 * parse_socks5_client_request (corresponding to <b>req</b>.
625 * Write appropriate response to <b>req->reply</b> (in
626 * SOCKS5 wire format). If <b>log_sockstype</b> is true, log a
627 * notice about possible DNS leaks on local system. If
628 * <b>safe_socks</b> is true, disallow insecure usage of SOCKS
629 * protocol. Return SOCKS_RESULT_DONE on success or
630 * SOCKS_RESULT_INVALID on failure.
631 */
632static socks_result_t
634 int log_sockstype,
635 int safe_socks)
636{
637 socks_result_t res = SOCKS_RESULT_DONE;
638 tor_addr_t tmpaddr;
639
640 if (req->command != SOCKS_COMMAND_CONNECT &&
643 socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
644 res = SOCKS_RESULT_INVALID;
645 goto end;
646 }
647
649 tor_addr_parse(&tmpaddr, req->address) < 0) {
650 socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
651 log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
652 "a malformed address. Rejecting.");
653
654 res = SOCKS_RESULT_INVALID;
655 goto end;
656 }
657
658 if (!string_is_valid_dest(req->address)) {
659 socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
660
661 log_warn(LD_PROTOCOL,
662 "Your application (using socks5 to port %d) gave Tor "
663 "a malformed hostname: %s. Rejecting the connection.",
665
666 res = SOCKS_RESULT_INVALID;
667 goto end;
668 }
669
670 if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
673 log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
674 if (safe_socks) {
675 socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
676 res = SOCKS_RESULT_INVALID;
677 goto end;
678 }
679 }
680 }
681
682 if (log_sockstype)
683 log_notice(LD_APP,
684 "Your application (using socks5 to port %d) instructed "
685 "Tor to take care of the DNS resolution itself if "
686 "necessary. This is good.", req->port);
687
688 end:
689 return res;
690}
691
692/**
693 * Handle (parse, validate, process, respond) a single SOCKS
694 * message in buffer <b>raw_data</b> of length <b>datalen</b>.
695 * Update relevant fields of <b>req</b>. If <b>log_sockstype</b>
696 * is true, log a warning about possible DNS leaks on local
697 * system. If <b>safe_socks</b> is true, disallow insecure
698 * usage of SOCKS protocol. Set <b>*drain_out</b> to number
699 * of bytes in <b>raw_data</b> that we processed so far and
700 * that can be safely drained from buffer.
701 *
702 * Return:
703 * - SOCKS_RESULT_DONE if succeeded and not expecting further
704 * messages from client.
705 * - SOCKS_RESULT_INVALID if any of the steps failed due to
706 * request being invalid or unexpected given current state.
707 * - SOCKS_RESULT_TRUNCATED if we do not found an expected
708 * SOCKS message in its entirety (more stuff has to arrive
709 * from client).
710 * - SOCKS_RESULT_MORE_EXPECTED if we handled current message
711 * successfully, but we expect more messages from the
712 * client.
713 */
714static socks_result_t
715handle_socks_message(const uint8_t *raw_data, size_t datalen,
716 socks_request_t *req, int log_sockstype,
717 int safe_socks, size_t *drain_out)
718{
719 socks_result_t res = SOCKS_RESULT_DONE;
720
721 uint8_t socks_version = raw_data[0];
722
723 if (socks_version == SOCKS_AUTH)
724 socks_version = SOCKS_VER_5; // SOCKS5 username/pass subnegotiation
725
726 if (socks_version == SOCKS_VER_4) {
727 if (datalen < SOCKS4_NETWORK_LEN) {
728 res = 0;
729 goto end;
730 }
731
732 int is_socks4a = 0;
733 res = parse_socks4_request((const uint8_t *)raw_data, req, datalen,
734 &is_socks4a, drain_out);
735
736 if (res != SOCKS_RESULT_DONE) {
737 goto end;
738 }
739
740 res = process_socks4_request(req, is_socks4a,log_sockstype,
741 safe_socks);
742
743 if (res != SOCKS_RESULT_DONE) {
744 goto end;
745 }
746
747 goto end;
748 } else if (socks_version == SOCKS_VER_5) {
749 if (datalen < 2) { /* version and another byte */
750 res = 0;
751 goto end;
752 }
753 /* RFC1929 SOCKS5 username/password subnegotiation. */
754 if (!req->got_auth && (raw_data[0] == 1 ||
755 req->auth_type == SOCKS_USER_PASS)) {
756 res = parse_socks5_userpass_auth(raw_data, req, datalen,
757 drain_out);
758
759 if (res != SOCKS_RESULT_DONE) {
760 goto end;
761 }
762
764 if (res != SOCKS_RESULT_DONE) {
765 goto end;
766 }
767
768 res = SOCKS_RESULT_MORE_EXPECTED;
769 goto end;
770 } else if (req->socks_version != SOCKS_VER_5) {
771 int have_user_pass=0, have_no_auth=0;
772 res = parse_socks5_methods_request(raw_data, req, datalen,
773 &have_user_pass,
774 &have_no_auth,
775 drain_out);
776
777 if (res != SOCKS_RESULT_DONE) {
778 goto end;
779 }
780
781 res = process_socks5_methods_request(req, have_user_pass,
782 have_no_auth);
783
784 if (res != SOCKS_RESULT_DONE) {
785 goto end;
786 }
787
788 res = SOCKS_RESULT_MORE_EXPECTED;
789 goto end;
790 } else {
791 res = parse_socks5_client_request(raw_data, req,
792 datalen, drain_out);
793 if (BUG(res == SOCKS_RESULT_INVALID && req->replylen == 0)) {
794 socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
795 }
796 if (res != SOCKS_RESULT_DONE) {
797 goto end;
798 }
799
800 res = process_socks5_client_request(req, log_sockstype,
801 safe_socks);
802
803 if (res != SOCKS_RESULT_DONE) {
804 goto end;
805 }
806 }
807 } else {
808 *drain_out = datalen;
809 res = SOCKS_RESULT_INVALID;
810 }
811
812 end:
813 return res;
814}
815
816/** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
817 * of the forms
818 * - socks4: "socksheader username\\0"
819 * - socks4a: "socksheader username\\0 destaddr\\0"
820 * - socks5 phase one: "version #methods methods"
821 * - socks5 phase two: "version command 0 addresstype..."
822 * If it's a complete and valid handshake, and destaddr fits in
823 * MAX_SOCKS_ADDR_LEN bytes, then pull the handshake off the buf,
824 * assign to <b>req</b>, and return 1.
825 *
826 * If it's invalid or too big, return -1.
827 *
828 * Else it's not all there yet, leave buf alone and return 0.
829 *
830 * If you want to specify the socks reply, write it into <b>req->reply</b>
831 * and set <b>req->replylen</b>, else leave <b>req->replylen</b> alone.
832 *
833 * If <b>log_sockstype</b> is non-zero, then do a notice-level log of whether
834 * the connection is possibly leaking DNS requests locally or not.
835 *
836 * If <b>safe_socks</b> is true, then reject unsafe socks protocols.
837 *
838 * If returning 0 or -1, <b>req->address</b> and <b>req->port</b> are
839 * undefined.
840 */
841int
843 int log_sockstype, int safe_socks)
844{
845 int res = 0;
846 size_t datalen = buf_datalen(buf);
847 size_t n_drain;
848 const char *head = NULL;
849 socks_result_t socks_res;
850 size_t n_pullup;
851
852 if (buf_datalen(buf) < 2) { /* version and another byte */
853 res = 0;
854 goto end;
855 }
856
857 do {
858 n_drain = 0;
859 n_pullup = MIN(MAX_SOCKS_MESSAGE_LEN, buf_datalen(buf));
860 buf_pullup(buf, n_pullup, &head, &datalen);
861 tor_assert(head && datalen >= 2);
862
863 socks_res = parse_socks(head, datalen, req, log_sockstype,
864 safe_socks, &n_drain);
865
866 if (socks_res == SOCKS_RESULT_INVALID)
867 buf_clear(buf);
868 else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
869 buf_drain(buf, n_drain);
870
871 switch (socks_res) {
872 case SOCKS_RESULT_INVALID:
873 res = -1;
874 break;
875 case SOCKS_RESULT_DONE:
876 res = 1;
877 break;
878 case SOCKS_RESULT_TRUNCATED:
879 if (datalen == n_pullup)
880 return 0;
881 FALLTHROUGH;
882 case SOCKS_RESULT_MORE_EXPECTED:
883 res = 0;
884 break;
885 }
886 } while (res == 0 && head && buf_datalen(buf) >= 2);
887
888 end:
889 return res;
890}
891
892/** Create a SOCKS5 reply message with <b>reason</b> in its REP field and
893 * have Tor send it as error response to <b>req</b>.
894 */
895static void
898{
899 socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
900 tor_assert(trunnel_resp);
901
902 socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
903 socks5_server_reply_set_reply(trunnel_resp, reason);
904 socks5_server_reply_set_atype(trunnel_resp, 0x01);
905
906 const char *errmsg = socks5_server_reply_check(trunnel_resp);
907 if (errmsg) {
908 log_warn(LD_APP, "socks5: reply validation failed: %s",
909 errmsg);
910 goto end;
911 }
912
913 ssize_t encoded = socks5_server_reply_encode(req->reply,
914 sizeof(req->reply),
915 trunnel_resp);
916 if (encoded < 0) {
917 log_warn(LD_APP, "socks5: reply encoding failed: %d",
918 (int)encoded);
919 } else {
920 req->replylen = (size_t)encoded;
921 }
922
923 end:
924 socks5_server_reply_free(trunnel_resp);
925}
926
927static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
928 "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
929 "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
930 "<html>\n"
931 "<head>\n"
932 "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
933 "</head>\n"
934 "<body>\n"
935 "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
936 "<p>\n"
937 "It appears you have configured your web browser to use this Tor port as\n"
938 "an HTTP proxy.\n"
939 "</p>\n"
940 "<p>\n"
941 "This is not correct: This port is configured as a SOCKS proxy, not\n"
942 "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
943 "configuration option in place of, or in addition to, SOCKSPort.\n"
944 "Please configure your client accordingly.\n"
945 "</p>\n"
946 "<p>\n"
947 "See <a href=\"https://www.torproject.org/documentation.html\">"
948 "https://www.torproject.org/documentation.html</a> for more "
949 "information.\n"
950 "</p>\n"
951 "</body>\n"
952 "</html>\n";
953
954/** Implementation helper to implement fetch_from_*_socks. Instead of looking
955 * at a buffer's contents, we look at the <b>datalen</b> bytes of data in
956 * <b>data</b>. Instead of removing data from the buffer, we set
957 * <b>drain_out</b> to the amount of data that should be removed (or -1 if the
958 * buffer should be cleared). Instead of pulling more data into the first
959 * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes
960 * we'd like to see in the input buffer, if they're available. */
961static socks_result_t
962parse_socks(const char *data, size_t datalen, socks_request_t *req,
963 int log_sockstype, int safe_socks, size_t *drain_out)
964{
965 uint8_t first_octet;
966
967 if (datalen < 2) {
968 /* We always need at least 2 bytes. */
969 return SOCKS_RESULT_TRUNCATED;
970 }
971
972 first_octet = get_uint8(data);
973
974 if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
975 first_octet == SOCKS_AUTH) { // XXX: RFC 1929
976 return handle_socks_message((const uint8_t *)data, datalen, req,
977 log_sockstype, safe_socks, drain_out);
978 }
979
980 switch (first_octet) { /* which version of socks? */
981 case 'G': /* get */
982 case 'H': /* head */
983 case 'P': /* put/post */
984 case 'C': /* connect */
985 strlcpy((char*)req->reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
986 MAX_SOCKS_REPLY_LEN);
987 req->replylen = strlen((char*)req->reply)+1;
988 FALLTHROUGH;
989 default: /* version is not socks4 or socks5 */
990 log_warn(LD_APP,
991 "Socks version %d not recognized. (This port is not an "
992 "HTTP proxy; did you want to use HTTPTunnelPort?)",
993 *(data));
994 {
995 /* Tell the controller the first 8 bytes. */
996 char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
998 "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
999 escaped(tmp));
1000 tor_free(tmp);
1001 }
1002 return SOCKS_RESULT_INVALID;
1003 }
1004
1005 tor_assert_unreached();
1006 return SOCKS_RESULT_INVALID;
1007}
1008
1009/** Inspect a reply from SOCKS server stored in <b>buf</b> according
1010 * to <b>state</b>, removing the protocol data upon success. Return 0 on
1011 * incomplete response, 1 on success and -1 on error, in which case
1012 * <b>reason</b> is set to a descriptive message (free() when finished
1013 * with it).
1014 *
1015 * As a special case, 2 is returned when user/pass is required
1016 * during SOCKS5 handshake and user/pass is configured.
1017 */
1018int
1019fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
1020{
1021 ssize_t drain = 0;
1022 int r;
1023 const char *head = NULL;
1024 size_t datalen = 0;
1025
1026 if (buf_datalen(buf) < 2)
1027 return 0;
1028
1029 buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, &head, &datalen);
1030 tor_assert(head && datalen >= 2);
1031
1032 r = parse_socks_client((uint8_t*)head, datalen,
1033 state, reason, &drain);
1034 if (drain > 0)
1035 buf_drain(buf, drain);
1036 else if (drain < 0)
1037 buf_clear(buf);
1038
1039 return r;
1040}
1041
1042/** Implementation logic for fetch_from_*_socks_client. */
1043static int
1044parse_socks_client(const uint8_t *data, size_t datalen,
1045 int state, char **reason,
1046 ssize_t *drain_out)
1047{
1048 unsigned int addrlen;
1049 *drain_out = 0;
1050 if (datalen < 2)
1051 return 0;
1052
1053 switch (state) {
1054 case PROXY_SOCKS4_WANT_CONNECT_OK:
1055 /* Wait for the complete response */
1056 if (datalen < 8)
1057 return 0;
1058
1059 if (data[1] != 0x5a) {
1060 *reason = tor_strdup(socks4_response_code_to_string(data[1]));
1061 return -1;
1062 }
1063
1064 /* Success */
1065 *drain_out = 8;
1066 return 1;
1067
1068 case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1069 /* we don't have any credentials */
1070 if (data[1] != 0x00) {
1071 *reason = tor_strdup("server doesn't support any of our "
1072 "available authentication methods");
1073 return -1;
1074 }
1075
1076 log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
1077 *drain_out = -1;
1078 return 1;
1079
1080 case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1081 /* we have a username and password. return 1 if we can proceed without
1082 * providing authentication, or 2 otherwise. */
1083 switch (data[1]) {
1084 case 0x00:
1085 log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
1086 "doesn't require authentication.");
1087 *drain_out = -1;
1088 return 1;
1089 case 0x02:
1090 log_info(LD_NET, "SOCKS 5 client: need authentication.");
1091 *drain_out = -1;
1092 return 2;
1093 default:
1094 /* This wasn't supposed to be exhaustive; there are other
1095 * authentication methods too. */
1096 ;
1097 }
1098
1099 *reason = tor_strdup("server doesn't support any of our available "
1100 "authentication methods");
1101 return -1;
1102
1103 case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1104 /* handle server reply to rfc1929 authentication */
1105 if (data[1] != 0x00) {
1106 *reason = tor_strdup("authentication failed");
1107 return -1;
1108 }
1109
1110 log_info(LD_NET, "SOCKS 5 client: authentication successful.");
1111 *drain_out = -1;
1112 return 1;
1113
1114 case PROXY_SOCKS5_WANT_CONNECT_OK:
1115 /* response is variable length. BND.ADDR, etc, isn't needed
1116 * (don't bother with buf_pullup()), but make sure to eat all
1117 * the data used */
1118
1119 /* wait for address type field to arrive */
1120 if (datalen < 4)
1121 return 0;
1122
1123 switch (data[3]) {
1124 case 0x01: /* ip4 */
1125 addrlen = 4;
1126 break;
1127 case 0x04: /* ip6 */
1128 addrlen = 16;
1129 break;
1130 case 0x03: /* fqdn (can this happen here?) */
1131 if (datalen < 5)
1132 return 0;
1133 addrlen = 1 + data[4];
1134 break;
1135 default:
1136 *reason = tor_strdup("invalid response to connect request");
1137 return -1;
1138 }
1139
1140 /* wait for address and port */
1141 if (datalen < 6 + addrlen)
1142 return 0;
1143
1144 if (data[1] != 0x00) {
1145 *reason = tor_strdup(socks5_response_code_to_string(data[1]));
1146 return -1;
1147 }
1148
1149 *drain_out = 6 + addrlen;
1150 return 1;
1151 }
1152
1153 /* LCOV_EXCL_START */
1154 /* shouldn't get here if the input state is one we know about... */
1155 tor_assert(0);
1156
1157 return -1;
1158 /* LCOV_EXCL_STOP */
1159}
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1349
int string_is_valid_dest(const char *string)
Definition: address.c:2155
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
Definition: address.c:328
void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const uint8_t *ipv6_bytes)
Definition: address.c:900
#define tor_addr_from_ipv4h(dest, v4addr)
Definition: address.h:327
int addressmap_have_mapping(const char *address, int update_expiry)
Definition: addressmap.c:544
Header for addressmap.c.
void buf_clear(buf_t *buf)
Definition: buffers.c:381
void buf_drain(buf_t *buf, size_t n)
Definition: buffers.c:330
size_t buf_datalen(const buf_t *buf)
Definition: buffers.c:394
void buf_pullup(buf_t *buf, size_t bytes, const char **head_out, size_t *len_out)
Definition: buffers.c:211
Header file for buffers.c.
static uint8_t get_uint8(const void *cp)
Definition: bytes.h:23
const char * escaped_safe_str_client(const char *address)
Definition: config.c:1136
tor_cmdline_mode_t command
Definition: config.c:2468
Header file for config.c.
Header file for connection.c.
int control_event_client_status(int severity, const char *format,...)
Header file for control_events.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
int tor_memeq(const void *a, const void *b, size_t sz)
Definition: di_ops.c:107
#define tor_memneq(a, b, sz)
Definition: di_ops.h:21
const char * escaped(const char *s)
Definition: escape.c:126
Header for ext_orport.c.
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition: log.h:288
#define LD_APP
Definition: log.h:78
#define LD_PROTOCOL
Definition: log.h:72
#define LD_NET
Definition: log.h:66
#define LOG_WARN
Definition: log.h:53
#define tor_free(p)
Definition: malloc.h:56
Master header file for Tor-specific functionality.
#define SOCKS4_NETWORK_LEN
Definition: or.h:452
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
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
static socks_result_t process_socks5_client_request(socks_request_t *req, int log_sockstype, int safe_socks)
Definition: proto_socks.c:633
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
#define MAX_SOCKS_MESSAGE_LEN
Definition: proto_socks.c:83
static socks_result_t process_socks5_userpass_auth(socks_request_t *req)
Definition: proto_socks.c:499
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
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req, int log_sockstype, int safe_socks)
Definition: proto_socks.c:842
void socks_request_free_(socks_request_t *req)
Definition: proto_socks.c:94
socks_request_t * socks_request_new(void)
Definition: proto_socks.c:87
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:555
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:715
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
int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
Definition: proto_socks.c:1019
#define SOCKS_WARN_INTERVAL
Definition: proto_socks.c:53
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:962
static void socks_request_set_socks5_error(socks_request_t *req, socks5_reply_status_t reason)
Definition: proto_socks.c:896
static void log_unsafe_socks_warning(int socks_protocol, const char *address, uint16_t port, int safe_socks)
Definition: proto_socks.c:59
static int parse_socks_client(const uint8_t *data, size_t datalen, int state, char **reason, ssize_t *drain_out)
Definition: proto_socks.c:1044
Header for proto_socks.c.
const char * socks5_response_code_to_string(uint8_t code)
Definition: reasons.c:411
const char * socks4_response_code_to_string(uint8_t code)
Definition: reasons.c:393
Header file for reasons.c.
socks5_reply_status_t
Definition: socks5_status.h:20
Client request structure.
#define SOCKS_COMMAND_RESOLVE_PTR
#define SOCKS_COMMAND_CONNECT
#define SOCKS_COMMAND_RESOLVE
unsigned int socks_prefer_no_auth
unsigned int got_auth
uint8_t reply[MAX_SOCKS_REPLY_LEN]
char address[MAX_SOCKS_ADDR_LEN]
#define tor_assert(expr)
Definition: util_bug.h:103