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
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);
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;
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);
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);
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);
455 if (usernamelen >= 8 &&
458 if (usernamelen != 9 ||
462 res = SOCKS_RESULT_INVALID;
467 if (usernamelen && username) {
469 req->
username = tor_memdup_nulterm(username, usernamelen);
473 if (passwordlen && password) {
475 req->
password = tor_memdup_nulterm(password, passwordlen);
488 socks5_client_userpass_auth_free(trunnel_req);
501 socks_result_t res = SOCKS_RESULT_DONE;
502 socks5_server_userpass_auth_t *trunnel_resp =
503 socks5_server_userpass_auth_new();
507 res = SOCKS_RESULT_INVALID;
513 res = SOCKS_RESULT_INVALID;
517 socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
518 socks5_server_userpass_auth_set_status(trunnel_resp, 0);
520 const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
522 log_warn(
LD_APP,
"socks5: server userpass auth validation failed: %s",
524 res = SOCKS_RESULT_INVALID;
528 ssize_t encoded = socks5_server_userpass_auth_encode(req->
reply,
533 log_warn(
LD_APP,
"socks5: server userpass auth encoding failed");
534 res = SOCKS_RESULT_INVALID;
541 socks5_server_userpass_auth_free(trunnel_resp);
556 size_t datalen,
size_t *drain_out)
558 socks_result_t res = SOCKS_RESULT_DONE;
560 socks5_client_request_t *trunnel_req = NULL;
562 socks5_client_request_parse(&trunnel_req, raw_data, datalen);
564 log_warn(
LD_APP,
"socks5: parsing failed - invalid client request");
565 res = SOCKS_RESULT_INVALID;
568 }
else if (parsed == -2) {
569 res = SOCKS_RESULT_TRUNCATED;
574 *drain_out = (size_t)parsed;
576 if (socks5_client_request_get_version(trunnel_req) != 5) {
577 res = SOCKS_RESULT_INVALID;
582 req->
command = socks5_client_request_get_command(trunnel_req);
584 req->
port = socks5_client_request_get_dest_port(trunnel_req);
586 uint8_t atype = socks5_client_request_get_atype(trunnel_req);
587 req->socks5_atyp = atype;
591 uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
597 const struct domainname_st *dns_name =
598 socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
600 const char *hostname = domainname_getconstarray_name(dns_name);
605 const uint8_t *ipv6 =
606 socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
618 socks5_client_request_free(trunnel_req);
637 socks_result_t res = SOCKS_RESULT_DONE;
644 res = SOCKS_RESULT_INVALID;
651 log_warn(
LD_APP,
"socks5 received RESOLVE_PTR command with "
652 "a malformed address. Rejecting.");
654 res = SOCKS_RESULT_INVALID;
662 "Your application (using socks5 to port %d) gave Tor "
663 "a malformed hostname: %s. Rejecting the connection.",
666 res = SOCKS_RESULT_INVALID;
670 if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
676 res = SOCKS_RESULT_INVALID;
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);
717 int safe_socks,
size_t *drain_out)
719 socks_result_t res = SOCKS_RESULT_DONE;
721 uint8_t socks_version = raw_data[0];
723 if (socks_version == SOCKS_AUTH)
724 socks_version = SOCKS_VER_5;
726 if (socks_version == SOCKS_VER_4) {
734 &is_socks4a, drain_out);
736 if (res != SOCKS_RESULT_DONE) {
743 if (res != SOCKS_RESULT_DONE) {
748 }
else if (socks_version == SOCKS_VER_5) {
754 if (!req->
got_auth && (raw_data[0] == 1 ||
759 if (res != SOCKS_RESULT_DONE) {
764 if (res != SOCKS_RESULT_DONE) {
768 res = SOCKS_RESULT_MORE_EXPECTED;
771 int have_user_pass=0, have_no_auth=0;
777 if (res != SOCKS_RESULT_DONE) {
784 if (res != SOCKS_RESULT_DONE) {
788 res = SOCKS_RESULT_MORE_EXPECTED;
793 if (BUG(res == SOCKS_RESULT_INVALID && req->
replylen == 0)) {
796 if (res != SOCKS_RESULT_DONE) {
803 if (res != SOCKS_RESULT_DONE) {
808 *drain_out = datalen;
809 res = SOCKS_RESULT_INVALID;
843 int log_sockstype,
int safe_socks)
848 const char *head = NULL;
849 socks_result_t socks_res;
863 socks_res =
parse_socks(head, datalen, req, log_sockstype,
864 safe_socks, &n_drain);
866 if (socks_res == SOCKS_RESULT_INVALID)
868 else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
872 case SOCKS_RESULT_INVALID:
875 case SOCKS_RESULT_DONE:
878 case SOCKS_RESULT_TRUNCATED:
879 if (datalen == n_pullup)
882 case SOCKS_RESULT_MORE_EXPECTED:
886 }
while (res == 0 && head &&
buf_datalen(buf) >= 2);
899 socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
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);
906 const char *errmsg = socks5_server_reply_check(trunnel_resp);
908 log_warn(
LD_APP,
"socks5: reply validation failed: %s",
913 ssize_t encoded = socks5_server_reply_encode(req->
reply,
917 log_warn(
LD_APP,
"socks5: reply encoding failed: %d",
924 socks5_server_reply_free(trunnel_resp);
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"
932 "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
935 "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
937 "It appears you have configured your web browser to use this Tor port as\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"
947 "See <a href=\"https://www.torproject.org/documentation.html\">"
948 "https://www.torproject.org/documentation.html</a> for more "
963 int log_sockstype,
int safe_socks,
size_t *drain_out)
969 return SOCKS_RESULT_TRUNCATED;
974 if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
975 first_octet == SOCKS_AUTH) {
977 log_sockstype, safe_socks, drain_out);
980 switch (first_octet) {
985 strlcpy((
char*)req->
reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
986 MAX_SOCKS_REPLY_LEN);
991 "Socks version %d not recognized. (This port is not an "
992 "HTTP proxy; did you want to use HTTPTunnelPort?)",
996 char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
998 "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
1002 return SOCKS_RESULT_INVALID;
1005 tor_assert_unreached();
1006 return SOCKS_RESULT_INVALID;
1023 const char *head = NULL;
1033 state, reason, &drain);
1045 int state,
char **reason,
1048 unsigned int addrlen;
1054 case PROXY_SOCKS4_WANT_CONNECT_OK:
1059 if (data[1] != 0x5a) {
1068 case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1070 if (data[1] != 0x00) {
1071 *reason = tor_strdup(
"server doesn't support any of our "
1072 "available authentication methods");
1076 log_info(
LD_NET,
"SOCKS 5 client: continuing without authentication");
1080 case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1085 log_info(
LD_NET,
"SOCKS 5 client: we have auth details but server "
1086 "doesn't require authentication.");
1090 log_info(
LD_NET,
"SOCKS 5 client: need authentication.");
1099 *reason = tor_strdup(
"server doesn't support any of our available "
1100 "authentication methods");
1103 case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1105 if (data[1] != 0x00) {
1106 *reason = tor_strdup(
"authentication failed");
1110 log_info(
LD_NET,
"SOCKS 5 client: authentication successful.");
1114 case PROXY_SOCKS5_WANT_CONNECT_OK:
1133 addrlen = 1 + data[4];
1136 *reason = tor_strdup(
"invalid response to connect request");
1141 if (datalen < 6 + addrlen)
1144 if (data[1] != 0x00) {
1149 *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)
#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)
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 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 * 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]