25#include "trunnel/socks5.h"
27#define SOCKS_VER_5 0x05
28#define SOCKS_VER_4 0x04
29#define SOCKS_AUTH 0x01
32 SOCKS_RESULT_INVALID = -1,
33 SOCKS_RESULT_TRUNCATED = 0,
34 SOCKS_RESULT_DONE = 1,
35 SOCKS_RESULT_MORE_EXPECTED = 2,
48 int state,
char **reason,
53#define SOCKS_WARN_INTERVAL 5
60 uint16_t port,
int safe_socks,
int warn_every_time)
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",
77 safe_socks ?
" Rejecting." :
"",
82 "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d",
83 socks_protocol, address, (
int)port);
88#define MAX_SOCKS_MESSAGE_LEN 512
127 size_t datalen,
int *is_socks4a,
size_t *drain_out)
131 socks_result_t res = SOCKS_RESULT_DONE;
142 socks4_client_request_t *trunnel_req;
145 socks4_client_request_parse(&trunnel_req, raw_data, datalen);
148 log_warn(
LD_APP,
"socks4: parsing failed - invalid request.");
149 res = SOCKS_RESULT_INVALID;
151 }
else if (parsed == -2) {
152 res = SOCKS_RESULT_TRUNCATED;
154 log_warn(
LD_APP,
"socks4: parsing failed - invalid request.");
155 res = SOCKS_RESULT_INVALID;
161 *drain_out = (size_t)parsed;
163 uint8_t
command = socks4_client_request_get_command(trunnel_req);
166 req->
port = socks4_client_request_get_port(trunnel_req);
167 uint32_t dest_ip = socks4_client_request_get_addr(trunnel_req);
171 log_warn(
LD_APP,
"socks4: Port or DestIP is zero. Rejecting.");
172 res = SOCKS_RESULT_INVALID;
176 *is_socks4a = (dest_ip >> 8) == 0;
178 const char *username = socks4_client_request_get_username(trunnel_req);
179 const size_t usernamelen = username ? strlen(username) : 0;
180 if (username && usernamelen) {
182 log_warn(
LD_APP,
"Socks4 user name too long; rejecting.");
183 res = SOCKS_RESULT_INVALID;
189 req->
username = tor_strdup(username);
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;
200 size_t hostname_len = strlen(trunnel_hostname);
201 if (hostname_len <
sizeof(req->
address)) {
204 log_warn(
LD_APP,
"socks4: Destaddr too long. Rejecting.");
205 res = SOCKS_RESULT_INVALID;
212 MAX_SOCKS_ADDR_LEN, 0)) {
213 res = SOCKS_RESULT_INVALID;
219 socks4_client_request_free(trunnel_req);
236 int log_sockstype,
int safe_socks)
240 safe_socks || log_sockstype);
243 return SOCKS_RESULT_INVALID;
250 log_warn(
LD_APP,
"socks4: command %d not recognized. Rejecting.",
252 return SOCKS_RESULT_INVALID;
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);
265 "Your application (using socks4 to port %d) gave Tor "
266 "a malformed hostname: %s. Rejecting the connection.",
268 return SOCKS_RESULT_INVALID;
271 return SOCKS_RESULT_DONE;
287 size_t datalen,
int *have_user_pass,
288 int *have_no_auth,
size_t *drain_out)
290 socks_result_t res = SOCKS_RESULT_DONE;
291 socks5_client_version_t *trunnel_req;
293 ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
305 log_warn(
LD_APP,
"socks5: parsing failed - invalid version "
306 "id/method selection message.");
307 res = SOCKS_RESULT_INVALID;
309 }
else if (parsed == -2) {
310 res = SOCKS_RESULT_TRUNCATED;
312 log_warn(
LD_APP,
"socks5: parsing failed - invalid version "
313 "id/method selection message.");
314 res = SOCKS_RESULT_INVALID;
320 *drain_out = (size_t)parsed;
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;
331 for (
size_t i = 0; i < n_methods; i++) {
332 uint8_t method = socks5_client_version_get_methods(trunnel_req,
335 if (method == SOCKS_USER_PASS) {
337 }
else if (method == SOCKS_NO_AUTH) {
343 socks5_client_version_free(trunnel_req);
362 socks_result_t res = SOCKS_RESULT_DONE;
363 socks5_server_method_t *trunnel_resp = socks5_server_method_new();
366 socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
370 socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
376 log_debug(
LD_APP,
"socks5: accepted method 2 (username/password)");
377 }
else if (have_no_auth) {
379 socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
383 log_debug(
LD_APP,
"socks5: accepted method 0 (no authentication)");
386 "socks5: offered methods don't include 'no auth' or "
387 "username/password. Rejecting.");
388 socks5_server_method_set_method(trunnel_resp, 0xFF);
389 res = SOCKS_RESULT_INVALID;
392 const char *errmsg = socks5_server_method_check(trunnel_resp);
394 log_warn(
LD_APP,
"socks5: method selection validation failed: %s",
396 res = SOCKS_RESULT_INVALID;
399 socks5_server_method_encode(req->
reply,
sizeof(req->
reply),
403 log_warn(
LD_APP,
"socks5: method selection encoding failed");
404 res = SOCKS_RESULT_INVALID;
410 socks5_server_method_free(trunnel_resp);
426 size_t datalen,
size_t *drain_out)
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,
436 log_warn(
LD_APP,
"socks5: parsing failed - invalid user/pass "
437 "authentication message.");
438 res = SOCKS_RESULT_INVALID;
440 }
else if (parsed == -2) {
441 res = SOCKS_RESULT_TRUNCATED;
446 *drain_out = (size_t)parsed;
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);
458 if (usernamelen >= 8 &&
461 if (usernamelen != 9 ||
465 res = SOCKS_RESULT_INVALID;
470 if (usernamelen && username) {
472 req->
username = tor_memdup_nulterm(username, usernamelen);
476 if (passwordlen && password) {
478 req->
password = tor_memdup_nulterm(password, passwordlen);
491 socks5_client_userpass_auth_free(trunnel_req);
504 socks_result_t res = SOCKS_RESULT_DONE;
505 socks5_server_userpass_auth_t *trunnel_resp =
506 socks5_server_userpass_auth_new();
510 res = SOCKS_RESULT_INVALID;
516 res = SOCKS_RESULT_INVALID;
520 socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
521 socks5_server_userpass_auth_set_status(trunnel_resp, 0);
523 const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
525 log_warn(
LD_APP,
"socks5: server userpass auth validation failed: %s",
527 res = SOCKS_RESULT_INVALID;
531 ssize_t encoded = socks5_server_userpass_auth_encode(req->
reply,
536 log_warn(
LD_APP,
"socks5: server userpass auth encoding failed");
537 res = SOCKS_RESULT_INVALID;
544 socks5_server_userpass_auth_free(trunnel_resp);
559 size_t datalen,
size_t *drain_out)
561 socks_result_t res = SOCKS_RESULT_DONE;
563 socks5_client_request_t *trunnel_req = NULL;
565 socks5_client_request_parse(&trunnel_req, raw_data, datalen);
567 log_warn(
LD_APP,
"socks5: parsing failed - invalid client request");
568 res = SOCKS_RESULT_INVALID;
571 }
else if (parsed == -2) {
572 res = SOCKS_RESULT_TRUNCATED;
577 *drain_out = (size_t)parsed;
579 if (socks5_client_request_get_version(trunnel_req) != 5) {
580 res = SOCKS_RESULT_INVALID;
585 req->
command = socks5_client_request_get_command(trunnel_req);
587 req->
port = socks5_client_request_get_dest_port(trunnel_req);
589 uint8_t atype = socks5_client_request_get_atype(trunnel_req);
590 req->socks5_atyp = atype;
594 uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
600 const struct domainname_st *dns_name =
601 socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
603 const char *hostname = domainname_getconstarray_name(dns_name);
608 const uint8_t *ipv6 =
609 socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
621 socks5_client_request_free(trunnel_req);
640 socks_result_t res = SOCKS_RESULT_DONE;
647 res = SOCKS_RESULT_INVALID;
654 log_warn(
LD_APP,
"socks5 received RESOLVE_PTR command with "
655 "a malformed address. Rejecting.");
657 res = SOCKS_RESULT_INVALID;
665 "Your application (using socks5 to port %d) gave Tor "
666 "a malformed hostname: %s. Rejecting the connection.",
669 res = SOCKS_RESULT_INVALID;
673 if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
677 safe_socks || log_sockstype);
680 res = SOCKS_RESULT_INVALID;
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);
721 int safe_socks,
size_t *drain_out)
723 socks_result_t res = SOCKS_RESULT_DONE;
725 uint8_t socks_version = raw_data[0];
727 if (socks_version == SOCKS_AUTH)
728 socks_version = SOCKS_VER_5;
730 if (socks_version == SOCKS_VER_4) {
738 &is_socks4a, drain_out);
740 if (res != SOCKS_RESULT_DONE) {
747 if (res != SOCKS_RESULT_DONE) {
752 }
else if (socks_version == SOCKS_VER_5) {
758 if (!req->
got_auth && (raw_data[0] == 1 ||
763 if (res != SOCKS_RESULT_DONE) {
768 if (res != SOCKS_RESULT_DONE) {
772 res = SOCKS_RESULT_MORE_EXPECTED;
775 int have_user_pass=0, have_no_auth=0;
781 if (res != SOCKS_RESULT_DONE) {
788 if (res != SOCKS_RESULT_DONE) {
792 res = SOCKS_RESULT_MORE_EXPECTED;
797 if (BUG(res == SOCKS_RESULT_INVALID && req->
replylen == 0)) {
800 if (res != SOCKS_RESULT_DONE) {
807 if (res != SOCKS_RESULT_DONE) {
812 *drain_out = datalen;
813 res = SOCKS_RESULT_INVALID;
847 int log_sockstype,
int safe_socks)
852 const char *head = NULL;
853 socks_result_t socks_res;
867 socks_res =
parse_socks(head, datalen, req, log_sockstype,
868 safe_socks, &n_drain);
870 if (socks_res == SOCKS_RESULT_INVALID)
872 else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
876 case SOCKS_RESULT_INVALID:
879 case SOCKS_RESULT_DONE:
882 case SOCKS_RESULT_TRUNCATED:
883 if (datalen == n_pullup)
886 case SOCKS_RESULT_MORE_EXPECTED:
890 }
while (res == 0 && head &&
buf_datalen(buf) >= 2);
903 socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
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);
910 const char *errmsg = socks5_server_reply_check(trunnel_resp);
912 log_warn(
LD_APP,
"socks5: reply validation failed: %s",
917 ssize_t encoded = socks5_server_reply_encode(req->
reply,
921 log_warn(
LD_APP,
"socks5: reply encoding failed: %d",
928 socks5_server_reply_free(trunnel_resp);
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"
936 "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
939 "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
941 "It appears you have configured your web browser to use this Tor port as\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"
951 "See <a href=\"https://www.torproject.org/documentation.html\">"
952 "https://www.torproject.org/documentation.html</a> for more "
967 int log_sockstype,
int safe_socks,
size_t *drain_out)
973 return SOCKS_RESULT_TRUNCATED;
978 if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
979 first_octet == SOCKS_AUTH) {
981 log_sockstype, safe_socks, drain_out);
984 switch (first_octet) {
989 strlcpy((
char*)req->
reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
990 MAX_SOCKS_REPLY_LEN);
995 "Socks version %d not recognized. (This port is not an "
996 "HTTP proxy; did you want to use HTTPTunnelPort?)",
1000 char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
1002 "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
1006 return SOCKS_RESULT_INVALID;
1009 tor_assert_unreached();
1010 return SOCKS_RESULT_INVALID;
1027 const char *head = NULL;
1037 state, reason, &drain);
1049 int state,
char **reason,
1052 unsigned int addrlen;
1058 case PROXY_SOCKS4_WANT_CONNECT_OK:
1063 if (data[1] != 0x5a) {
1072 case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1074 if (data[1] != 0x00) {
1075 *reason = tor_strdup(
"server doesn't support any of our "
1076 "available authentication methods");
1080 log_info(
LD_NET,
"SOCKS 5 client: continuing without authentication");
1084 case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1089 log_info(
LD_NET,
"SOCKS 5 client: we have auth details but server "
1090 "doesn't require authentication.");
1094 log_info(
LD_NET,
"SOCKS 5 client: need authentication.");
1103 *reason = tor_strdup(
"server doesn't support any of our available "
1104 "authentication methods");
1107 case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1109 if (data[1] != 0x00) {
1110 *reason = tor_strdup(
"authentication failed");
1114 log_info(
LD_NET,
"SOCKS 5 client: authentication successful.");
1118 case PROXY_SOCKS5_WANT_CONNECT_OK:
1137 addrlen = 1 + data[4];
1140 *reason = tor_strdup(
"invalid response to connect request");
1145 if (datalen < 6 + addrlen)
1148 if (data[1] != 0x00) {
1153 *drain_out = 6 + addrlen;
int tor_addr_parse(tor_addr_t *addr, const char *src)
int string_is_valid_dest(const char *string)
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const uint8_t *ipv6_bytes)
#define tor_addr_from_ipv4h(dest, v4addr)
int addressmap_have_mapping(const char *address, int update_expiry)
void buf_clear(buf_t *buf)
void buf_drain(buf_t *buf, size_t n)
size_t buf_datalen(const buf_t *buf)
void buf_pullup(buf_t *buf, size_t bytes, const char **head_out, size_t *len_out)
Header file for buffers.c.
static uint8_t get_uint8(const void *cp)
const char * escaped_safe_str_client(const char *address)
tor_cmdline_mode_t command
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)
Common functions for cryptographic routines.
int tor_memeq(const void *a, const void *b, size_t sz)
#define tor_memneq(a, b, sz)
const char * escaped(const char *s)
Master header file for Tor-specific functionality.
#define SOCKS4_NETWORK_LEN
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
static void log_unsafe_socks_warning(int socks_protocol, const char *address, uint16_t port, int safe_socks, int warn_every_time)
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)
socks_request_t * socks_request_new(void)
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
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)
const char * socks5_response_code_to_string(uint8_t code)
const char * socks4_response_code_to_string(uint8_t code)
Header file for reasons.c.
Client request structure.
#define SOCKS_COMMAND_RESOLVE_PTR
#define SOCKS_COMMAND_CONNECT
#define SOCKS_COMMAND_RESOLVE
unsigned int socks_prefer_no_auth
uint8_t reply[MAX_SOCKS_REPLY_LEN]
char address[MAX_SOCKS_ADDR_LEN]