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);
189 const char *trunnel_hostname =
190 socks4_client_request_get_socks4a_addr_hostname(trunnel_req);
191 if (BUG(!trunnel_hostname)) {
192 res = SOCKS_RESULT_INVALID;
195 size_t hostname_len = strlen(trunnel_hostname);
196 if (hostname_len <
sizeof(req->
address)) {
199 log_warn(
LD_APP,
"socks4: Destaddr too long. Rejecting.");
200 res = SOCKS_RESULT_INVALID;
207 MAX_SOCKS_ADDR_LEN, 0)) {
208 res = SOCKS_RESULT_INVALID;
214 socks4_client_request_free(trunnel_req);
231 int log_sockstype,
int safe_socks)
237 return SOCKS_RESULT_INVALID;
244 log_warn(
LD_APP,
"socks4: command %d not recognized. Rejecting.",
246 return SOCKS_RESULT_INVALID;
252 "Your application (using socks4a to port %d) instructed "
253 "Tor to take care of the DNS resolution itself if "
254 "necessary. This is good.", req->
port);
259 "Your application (using socks4 to port %d) gave Tor "
260 "a malformed hostname: %s. Rejecting the connection.",
262 return SOCKS_RESULT_INVALID;
265 return SOCKS_RESULT_DONE;
281 size_t datalen,
int *have_user_pass,
282 int *have_no_auth,
size_t *drain_out)
284 socks_result_t res = SOCKS_RESULT_DONE;
285 socks5_client_version_t *trunnel_req;
287 ssize_t parsed = socks5_client_version_parse(&trunnel_req, raw_data,
299 log_warn(
LD_APP,
"socks5: parsing failed - invalid version "
300 "id/method selection message.");
301 res = SOCKS_RESULT_INVALID;
303 }
else if (parsed == -2) {
304 res = SOCKS_RESULT_TRUNCATED;
306 log_warn(
LD_APP,
"socks5: parsing failed - invalid version "
307 "id/method selection message.");
308 res = SOCKS_RESULT_INVALID;
314 *drain_out = (size_t)parsed;
316 size_t n_methods = (size_t)socks5_client_version_get_n_methods(trunnel_req);
317 if (n_methods == 0) {
318 res = SOCKS_RESULT_INVALID;
325 for (
size_t i = 0; i < n_methods; i++) {
326 uint8_t method = socks5_client_version_get_methods(trunnel_req,
329 if (method == SOCKS_USER_PASS) {
331 }
else if (method == SOCKS_NO_AUTH) {
337 socks5_client_version_free(trunnel_req);
356 socks_result_t res = SOCKS_RESULT_DONE;
357 socks5_server_method_t *trunnel_resp = socks5_server_method_new();
360 socks5_server_method_set_version(trunnel_resp, SOCKS_VER_5);
364 socks5_server_method_set_method(trunnel_resp, SOCKS_USER_PASS);
370 log_debug(
LD_APP,
"socks5: accepted method 2 (username/password)");
371 }
else if (have_no_auth) {
373 socks5_server_method_set_method(trunnel_resp, SOCKS_NO_AUTH);
377 log_debug(
LD_APP,
"socks5: accepted method 0 (no authentication)");
380 "socks5: offered methods don't include 'no auth' or "
381 "username/password. Rejecting.");
382 socks5_server_method_set_method(trunnel_resp, 0xFF);
383 res = SOCKS_RESULT_INVALID;
386 const char *errmsg = socks5_server_method_check(trunnel_resp);
388 log_warn(
LD_APP,
"socks5: method selection validation failed: %s",
390 res = SOCKS_RESULT_INVALID;
393 socks5_server_method_encode(req->
reply,
sizeof(req->
reply),
397 log_warn(
LD_APP,
"socks5: method selection encoding failed");
398 res = SOCKS_RESULT_INVALID;
404 socks5_server_method_free(trunnel_resp);
420 size_t datalen,
size_t *drain_out)
422 socks_result_t res = SOCKS_RESULT_DONE;
423 socks5_client_userpass_auth_t *trunnel_req = NULL;
424 ssize_t parsed = socks5_client_userpass_auth_parse(&trunnel_req, raw_data,
430 log_warn(
LD_APP,
"socks5: parsing failed - invalid user/pass "
431 "authentication message.");
432 res = SOCKS_RESULT_INVALID;
434 }
else if (parsed == -2) {
435 res = SOCKS_RESULT_TRUNCATED;
440 *drain_out = (size_t)parsed;
442 uint8_t usernamelen =
443 socks5_client_userpass_auth_get_username_len(trunnel_req);
444 uint8_t passwordlen =
445 socks5_client_userpass_auth_get_passwd_len(trunnel_req);
446 const char *username =
447 socks5_client_userpass_auth_getconstarray_username(trunnel_req);
448 const char *password =
449 socks5_client_userpass_auth_getconstarray_passwd(trunnel_req);
452 if (usernamelen >= 8 &&
455 if (usernamelen != 9 ||
459 res = SOCKS_RESULT_INVALID;
464 if (usernamelen && username) {
466 req->
username = tor_memdup_nulterm(username, usernamelen);
470 if (passwordlen && password) {
472 req->
password = tor_memdup_nulterm(password, passwordlen);
485 socks5_client_userpass_auth_free(trunnel_req);
498 socks_result_t res = SOCKS_RESULT_DONE;
499 socks5_server_userpass_auth_t *trunnel_resp =
500 socks5_server_userpass_auth_new();
504 res = SOCKS_RESULT_INVALID;
510 res = SOCKS_RESULT_INVALID;
514 socks5_server_userpass_auth_set_version(trunnel_resp, SOCKS_AUTH);
515 socks5_server_userpass_auth_set_status(trunnel_resp, 0);
517 const char *errmsg = socks5_server_userpass_auth_check(trunnel_resp);
519 log_warn(
LD_APP,
"socks5: server userpass auth validation failed: %s",
521 res = SOCKS_RESULT_INVALID;
525 ssize_t encoded = socks5_server_userpass_auth_encode(req->
reply,
530 log_warn(
LD_APP,
"socks5: server userpass auth encoding failed");
531 res = SOCKS_RESULT_INVALID;
538 socks5_server_userpass_auth_free(trunnel_resp);
553 size_t datalen,
size_t *drain_out)
555 socks_result_t res = SOCKS_RESULT_DONE;
557 socks5_client_request_t *trunnel_req = NULL;
559 socks5_client_request_parse(&trunnel_req, raw_data, datalen);
561 log_warn(
LD_APP,
"socks5: parsing failed - invalid client request");
562 res = SOCKS_RESULT_INVALID;
565 }
else if (parsed == -2) {
566 res = SOCKS_RESULT_TRUNCATED;
571 *drain_out = (size_t)parsed;
573 if (socks5_client_request_get_version(trunnel_req) != 5) {
574 res = SOCKS_RESULT_INVALID;
579 req->
command = socks5_client_request_get_command(trunnel_req);
581 req->
port = socks5_client_request_get_dest_port(trunnel_req);
583 uint8_t atype = socks5_client_request_get_atype(trunnel_req);
584 req->socks5_atyp = atype;
588 uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
594 const struct domainname_st *dns_name =
595 socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
597 const char *hostname = domainname_getconstarray_name(dns_name);
602 const uint8_t *ipv6 =
603 socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
615 socks5_client_request_free(trunnel_req);
634 socks_result_t res = SOCKS_RESULT_DONE;
641 res = SOCKS_RESULT_INVALID;
648 log_warn(
LD_APP,
"socks5 received RESOLVE_PTR command with "
649 "a malformed address. Rejecting.");
651 res = SOCKS_RESULT_INVALID;
659 "Your application (using socks5 to port %d) gave Tor "
660 "a malformed hostname: %s. Rejecting the connection.",
663 res = SOCKS_RESULT_INVALID;
667 if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
673 res = SOCKS_RESULT_INVALID;
681 "Your application (using socks5 to port %d) instructed "
682 "Tor to take care of the DNS resolution itself if "
683 "necessary. This is good.", req->
port);
714 int safe_socks,
size_t *drain_out)
716 socks_result_t res = SOCKS_RESULT_DONE;
718 uint8_t socks_version = raw_data[0];
720 if (socks_version == SOCKS_AUTH)
721 socks_version = SOCKS_VER_5;
723 if (socks_version == SOCKS_VER_4) {
731 &is_socks4a, drain_out);
733 if (res != SOCKS_RESULT_DONE) {
740 if (res != SOCKS_RESULT_DONE) {
745 }
else if (socks_version == SOCKS_VER_5) {
751 if (!req->
got_auth && (raw_data[0] == 1 ||
756 if (res != SOCKS_RESULT_DONE) {
761 if (res != SOCKS_RESULT_DONE) {
765 res = SOCKS_RESULT_MORE_EXPECTED;
768 int have_user_pass=0, have_no_auth=0;
774 if (res != SOCKS_RESULT_DONE) {
781 if (res != SOCKS_RESULT_DONE) {
785 res = SOCKS_RESULT_MORE_EXPECTED;
790 if (BUG(res == SOCKS_RESULT_INVALID && req->
replylen == 0)) {
793 if (res != SOCKS_RESULT_DONE) {
800 if (res != SOCKS_RESULT_DONE) {
805 *drain_out = datalen;
806 res = SOCKS_RESULT_INVALID;
840 int log_sockstype,
int safe_socks)
845 const char *head = NULL;
846 socks_result_t socks_res;
860 socks_res =
parse_socks(head, datalen, req, log_sockstype,
861 safe_socks, &n_drain);
863 if (socks_res == SOCKS_RESULT_INVALID)
865 else if (socks_res != SOCKS_RESULT_TRUNCATED && n_drain > 0)
869 case SOCKS_RESULT_INVALID:
872 case SOCKS_RESULT_DONE:
875 case SOCKS_RESULT_TRUNCATED:
876 if (datalen == n_pullup)
879 case SOCKS_RESULT_MORE_EXPECTED:
883 }
while (res == 0 && head &&
buf_datalen(buf) >= 2);
896 socks5_server_reply_t *trunnel_resp = socks5_server_reply_new();
899 socks5_server_reply_set_version(trunnel_resp, SOCKS_VER_5);
900 socks5_server_reply_set_reply(trunnel_resp, reason);
901 socks5_server_reply_set_atype(trunnel_resp, 0x01);
903 const char *errmsg = socks5_server_reply_check(trunnel_resp);
905 log_warn(
LD_APP,
"socks5: reply validation failed: %s",
910 ssize_t encoded = socks5_server_reply_encode(req->
reply,
914 log_warn(
LD_APP,
"socks5: reply encoding failed: %d",
921 socks5_server_reply_free(trunnel_resp);
924static const char SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG[] =
925 "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
926 "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
929 "<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>\n"
932 "<h1>This is a SOCKS proxy, not an HTTP proxy.</h1>\n"
934 "It appears you have configured your web browser to use this Tor port as\n"
938 "This is not correct: This port is configured as a SOCKS proxy, not\n"
939 "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n"
940 "configuration option in place of, or in addition to, SOCKSPort.\n"
941 "Please configure your client accordingly.\n"
944 "See <a href=\"https://www.torproject.org/documentation.html\">"
945 "https://www.torproject.org/documentation.html</a> for more "
960 int log_sockstype,
int safe_socks,
size_t *drain_out)
966 return SOCKS_RESULT_TRUNCATED;
971 if (first_octet == SOCKS_VER_5 || first_octet == SOCKS_VER_4 ||
972 first_octet == SOCKS_AUTH) {
974 log_sockstype, safe_socks, drain_out);
977 switch (first_octet) {
982 strlcpy((
char*)req->
reply, SOCKS_PROXY_IS_NOT_AN_HTTP_PROXY_MSG,
983 MAX_SOCKS_REPLY_LEN);
988 "Socks version %d not recognized. (This port is not an "
989 "HTTP proxy; did you want to use HTTPTunnelPort?)",
993 char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
995 "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
999 return SOCKS_RESULT_INVALID;
1002 tor_assert_unreached();
1003 return SOCKS_RESULT_INVALID;
1020 const char *head = NULL;
1030 state, reason, &drain);
1042 int state,
char **reason,
1045 unsigned int addrlen;
1051 case PROXY_SOCKS4_WANT_CONNECT_OK:
1056 if (data[1] != 0x5a) {
1065 case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
1067 if (data[1] != 0x00) {
1068 *reason = tor_strdup(
"server doesn't support any of our "
1069 "available authentication methods");
1073 log_info(
LD_NET,
"SOCKS 5 client: continuing without authentication");
1077 case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
1082 log_info(
LD_NET,
"SOCKS 5 client: we have auth details but server "
1083 "doesn't require authentication.");
1087 log_info(
LD_NET,
"SOCKS 5 client: need authentication.");
1096 *reason = tor_strdup(
"server doesn't support any of our available "
1097 "authentication methods");
1100 case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
1102 if (data[1] != 0x00) {
1103 *reason = tor_strdup(
"authentication failed");
1107 log_info(
LD_NET,
"SOCKS 5 client: authentication successful.");
1111 case PROXY_SOCKS5_WANT_CONNECT_OK:
1130 addrlen = 1 + data[4];
1133 *reason = tor_strdup(
"invalid response to connect request");
1138 if (datalen < 6 + addrlen)
1141 if (data[1] != 0x00) {
1146 *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]