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)
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",
74 safe_socks ?
" Rejecting." :
"");
77 "DANGEROUS_SOCKS PROTOCOL=SOCKS%d ADDRESS=%s:%d",
78 socks_protocol, address, (
int)port);
83 #define MAX_SOCKS_MESSAGE_LEN 512
120 static socks_result_t
122 size_t datalen,
int *is_socks4a,
size_t *drain_out)
126 socks_result_t res = SOCKS_RESULT_DONE;
137 socks4_client_request_t *trunnel_req;
140 socks4_client_request_parse(&trunnel_req, raw_data, datalen);
143 log_warn(
LD_APP,
"socks4: parsing failed - invalid request.");
144 res = SOCKS_RESULT_INVALID;
146 }
else if (parsed == -2) {
147 res = SOCKS_RESULT_TRUNCATED;
149 log_warn(
LD_APP,
"socks4: parsing failed - invalid request.");
150 res = SOCKS_RESULT_INVALID;
156 *drain_out = (size_t)parsed;
158 uint8_t
command = socks4_client_request_get_command(trunnel_req);
161 req->
port = socks4_client_request_get_port(trunnel_req);
162 uint32_t dest_ip = socks4_client_request_get_addr(trunnel_req);
166 log_warn(
LD_APP,
"socks4: Port or DestIP is zero. Rejecting.");
167 res = SOCKS_RESULT_INVALID;
171 *is_socks4a = (dest_ip >> 8) == 0;
173 const char *username = socks4_client_request_get_username(trunnel_req);
174 const size_t usernamelen = username ? strlen(username) : 0;
175 if (username && usernamelen) {
177 log_warn(
LD_APP,
"Socks4 user name too long; rejecting.");
178 res = SOCKS_RESULT_INVALID;
184 req->
username = tor_strdup(username);
193 size_t hostname_len = (
char *)raw_data + datalen - hostname;
195 if (hostname_len <=
sizeof(req->
address)) {
196 const char *trunnel_hostname =
197 socks4_client_request_get_socks4a_addr_hostname(trunnel_req);
199 if (trunnel_hostname)
202 log_warn(
LD_APP,
"socks4: Destaddr too long. Rejecting.");
203 res = SOCKS_RESULT_INVALID;
210 MAX_SOCKS_ADDR_LEN, 0)) {
211 res = SOCKS_RESULT_INVALID;
217 socks4_client_request_free(trunnel_req);
232 static socks_result_t
234 int log_sockstype,
int safe_socks)
240 return SOCKS_RESULT_INVALID;
247 log_warn(
LD_APP,
"socks4: command %d not recognized. Rejecting.",
249 return SOCKS_RESULT_INVALID;
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);
262 "Your application (using socks4 to port %d) gave Tor "
263 "a malformed hostname: %s. Rejecting the connection.",
265 return SOCKS_RESULT_INVALID;
268 return SOCKS_RESULT_DONE;
282 static socks_result_t
284 size_t datalen,
int *have_user_pass,
285 int *have_no_auth,
size_t *drain_out)
287 socks_result_t res = SOCKS_RESULT_DONE;
288 socks5_client_version_t *trunnel_req;
290 ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
302 log_warn(
LD_APP,
"socks5: parsing failed - invalid version "
303 "id/method selection message.");
304 res = SOCKS_RESULT_INVALID;
306 }
else if (parsed == -2) {
307 res = SOCKS_RESULT_TRUNCATED;
309 log_warn(
LD_APP,
"socks5: parsing failed - invalid version "
310 "id/method selection message.");
311 res = SOCKS_RESULT_INVALID;
317 *drain_out = (size_t)parsed;
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;
328 for (
size_t i = 0; i < n_methods; i++) {
329 uint8_t method = socks5_client_version_get_methods(trunnel_req,
332 if (method == SOCKS_USER_PASS) {
334 }
else if (method == SOCKS_NO_AUTH) {
340 socks5_client_version_free(trunnel_req);
355 static socks_result_t
359 socks_result_t res = SOCKS_RESULT_DONE;
360 socks5_server_method_t *trunnel_resp = socks5_server_method_new();
363 socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
367 socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
373 log_debug(
LD_APP,
"socks5: accepted method 2 (username/password)");
374 }
else if (have_no_auth) {
376 socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
380 log_debug(
LD_APP,
"socks5: accepted method 0 (no authentication)");
383 "socks5: offered methods don't include 'no auth' or "
384 "username/password. Rejecting.");
385 socks5_server_method_set_method(trunnel_resp, 0xFF);
386 res = SOCKS_RESULT_INVALID;
389 const char *errmsg = socks5_server_method_check(trunnel_resp);
391 log_warn(
LD_APP,
"socks5: method selection validation failed: %s",
393 res = SOCKS_RESULT_INVALID;
396 socks5_server_method_encode(req->
reply,
sizeof(req->
reply),
400 log_warn(
LD_APP,
"socks5: method selection encoding failed");
401 res = SOCKS_RESULT_INVALID;
407 socks5_server_method_free(trunnel_resp);
421 static socks_result_t
423 size_t datalen,
size_t *drain_out)
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,
433 log_warn(
LD_APP,
"socks5: parsing failed - invalid user/pass "
434 "authentication message.");
435 res = SOCKS_RESULT_INVALID;
437 }
else if (parsed == -2) {
438 res = SOCKS_RESULT_TRUNCATED;
443 *drain_out = (size_t)parsed;
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);
454 if (usernamelen && username) {
456 req->
username = tor_memdup_nulterm(username, usernamelen);
460 if (passwordlen && password) {
462 req->
password = tor_memdup_nulterm(password, passwordlen);
475 socks5_client_userpass_auth_free(trunnel_req);
485 static socks_result_t
488 socks_result_t res = SOCKS_RESULT_DONE;
489 socks5_server_userpass_auth_t *trunnel_resp =
490 socks5_server_userpass_auth_new();
494 res = SOCKS_RESULT_INVALID;
500 res = SOCKS_RESULT_INVALID;
504 socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
505 socks5_server_userpass_auth_set_status(trunnel_resp, 0);
507 const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
509 log_warn(
LD_APP,
"socks5: server userpass auth validation failed: %s",
511 res = SOCKS_RESULT_INVALID;
515 ssize_t encoded = socks5_server_userpass_auth_encode(req->
reply,
520 log_warn(
LD_APP,
"socks5: server userpass auth encoding failed");
521 res = SOCKS_RESULT_INVALID;
528 socks5_server_userpass_auth_free(trunnel_resp);
541 static socks_result_t
543 size_t datalen,
size_t *drain_out)
545 socks_result_t res = SOCKS_RESULT_DONE;
547 socks5_client_request_t *trunnel_req = NULL;
549 socks5_client_request_parse(&trunnel_req, raw_data, datalen);
551 log_warn(
LD_APP,
"socks5: parsing failed - invalid client request");
552 res = SOCKS_RESULT_INVALID;
555 }
else if (parsed == -2) {
556 res = SOCKS_RESULT_TRUNCATED;
561 *drain_out = (size_t)parsed;
563 if (socks5_client_request_get_version(trunnel_req) != 5) {
564 res = SOCKS_RESULT_INVALID;
569 req->
command = socks5_client_request_get_command(trunnel_req);
571 req->
port = socks5_client_request_get_dest_port(trunnel_req);
573 uint8_t atype = socks5_client_request_get_atype(trunnel_req);
574 req->socks5_atyp = atype;
578 uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
584 const struct domainname_st *dns_name =
585 socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
587 const char *hostname = domainname_getconstarray_name(dns_name);
592 const uint8_t *ipv6 =
593 socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
605 socks5_client_request_free(trunnel_req);
619 static socks_result_t
624 socks_result_t res = SOCKS_RESULT_DONE;
631 res = SOCKS_RESULT_INVALID;
638 log_warn(
LD_APP,
"socks5 received RESOLVE_PTR command with "
639 "a malformed address. Rejecting.");
641 res = SOCKS_RESULT_INVALID;
649 "Your application (using socks5 to port %d) gave Tor "
650 "a malformed hostname: %s. Rejecting the connection.",
653 res = SOCKS_RESULT_INVALID;
657 if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
663 res = SOCKS_RESULT_INVALID;
671 "Your application (using socks5 to port %d) instructed "
672 "Tor to take care of the DNS resolution itself if "
673 "necessary. This is good.", req->
port);
701 static socks_result_t
704 int safe_socks,
size_t *drain_out)
706 socks_result_t res = SOCKS_RESULT_DONE;
708 uint8_t socks_version = raw_data[0];
710 if (socks_version == SOCKS_AUTH)
711 socks_version = SOCKS_VER_5;
713 if (socks_version == SOCKS_VER_4) {
721 &is_socks4a, drain_out);
723 if (res != SOCKS_RESULT_DONE) {
730 if (res != SOCKS_RESULT_DONE) {
735 }
else if (socks_version == SOCKS_VER_5) {
741 if (!req->
got_auth && (raw_data[0] == 1 ||
746 if (res != SOCKS_RESULT_DONE) {
751 if (res != SOCKS_RESULT_DONE) {
755 res = SOCKS_RESULT_MORE_EXPECTED;
758 int have_user_pass=0, have_no_auth=0;
764 if (res != SOCKS_RESULT_DONE) {
771 if (res != SOCKS_RESULT_DONE) {
775 res = SOCKS_RESULT_MORE_EXPECTED;
780 if (BUG(res == SOCKS_RESULT_INVALID && req->
replylen == 0)) {
783 if (res != SOCKS_RESULT_DONE) {
790 if (res != SOCKS_RESULT_DONE) {
795 *drain_out = datalen;
796 res = SOCKS_RESULT_INVALID;
830 int log_sockstype,
int safe_socks)
835 const char *head = NULL;
836 socks_result_t socks_res;
850 socks_res =
parse_socks(head, datalen, req, log_sockstype,
851 safe_socks, &n_drain);
853 if (socks_res == SOCKS_RESULT_INVALID)
855 else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
859 case SOCKS_RESULT_INVALID:
862 case SOCKS_RESULT_DONE:
865 case SOCKS_RESULT_TRUNCATED:
866 if (datalen == n_pullup)
869 case SOCKS_RESULT_MORE_EXPECTED:
873 }
while (res == 0 && head &&
buf_datalen(buf) >= 2);
886 socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
889 socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
890 socks5_server_reply_set_reply(trunnel_resp, reason);
891 socks5_server_reply_set_atype(trunnel_resp, 0x01);
893 const char *errmsg = socks5_server_reply_check(trunnel_resp);
895 log_warn(
LD_APP,
"socks5: reply validation failed: %s",
900 ssize_t encoded = socks5_server_reply_encode(req->
reply,
904 log_warn(
LD_APP,
"socks5: reply encoding failed: %d",
911 socks5_server_reply_free(trunnel_resp);
914 static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
915 "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
916 "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
919 "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
922 "<h1>This is a SOCKs proxy, not an HTTP proxy.</h1>\n"
924 "It appears you have configured your web browser to use this Tor port as\n"
927 "This is not correct: This port is configured as a SOCKS proxy, not\n"
928 "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
929 "configuration option in place of, or in addition to, SOCKSPort.\n"
930 "Please configure your client accordingly.\n"
933 "See <a href=\"https://www.torproject.org/documentation.html\">"
934 "https://www.torproject.org/documentation.html</a> for more "
949 int log_sockstype,
int safe_socks,
size_t *drain_out)
960 if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
961 first_octet == SOCKS_AUTH) {
963 log_sockstype, safe_socks, drain_out);
966 switch (first_octet) {
971 strlcpy((
char*)req->
reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
972 MAX_SOCKS_REPLY_LEN);
977 "Socks version %d not recognized. (This port is not an "
978 "HTTP proxy; did you want to use HTTPTunnelPort?)",
982 char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
984 "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
991 tor_assert_unreached();
1009 const char *head = NULL;
1019 state, reason, &drain);
1031 int state,
char **reason,
1034 unsigned int addrlen;
1040 case PROXY_SOCKS4_WANT_CONNECT_OK:
1045 if (data[1] != 0x5a) {
1054 case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1056 if (data[1] != 0x00) {
1057 *reason = tor_strdup(
"server doesn't support any of our "
1058 "available authentication methods");
1062 log_info(
LD_NET,
"SOCKS 5 client: continuing without authentication");
1066 case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1071 log_info(
LD_NET,
"SOCKS 5 client: we have auth details but server "
1072 "doesn't require authentication.");
1076 log_info(
LD_NET,
"SOCKS 5 client: need authentication.");
1085 *reason = tor_strdup(
"server doesn't support any of our available "
1086 "authentication methods");
1089 case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1091 if (data[1] != 0x00) {
1092 *reason = tor_strdup(
"authentication failed");
1096 log_info(
LD_NET,
"SOCKS 5 client: authentication successful.");
1100 case PROXY_SOCKS5_WANT_CONNECT_OK:
1119 addrlen = 1 + data[4];
1122 *reason = tor_strdup(
"invalid response to connect request");
1127 if (datalen < 6 + addrlen)
1130 if (data[1] != 0x00) {
1135 *drain_out = 6 + addrlen;
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
int tor_addr_parse(tor_addr_t *addr, const char *src)
int string_is_valid_dest(const char *string)
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.
const char * escaped(const char *s)
#define log_fn_ratelim(ratelim, severity, domain, args,...)
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 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)
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_socks(const char *data, size_t datalen, socks_request_t *req, int log_sockstype, int safe_socks, size_t *drain_out)
socks_request_t * socks_request_new(void)
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 void socks_request_set_socks5_error(socks_request_t *req, socks5_reply_status_t reason)
static void log_unsafe_socks_warning(int socks_protocol, const char *address, uint16_t port, int safe_socks)
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.
const char * socks4_response_code_to_string(uint8_t code)
const char * socks5_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]