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