[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Second phase of SOCKS5
commit bcbd3fb71e1a729f5b499a1452da7d07deeebf39
Author: rl1987 <rl1987@xxxxxxxxxxxxxxxx>
Date: Mon May 21 17:33:28 2018 +0200
Second phase of SOCKS5
---
src/or/proto_socks.c | 157 +++++++++++++++++++++++++++++++++++++++++++---
src/or/socks_request_st.h | 2 +
src/test/test_socks.c | 3 +-
3 files changed, 151 insertions(+), 11 deletions(-)
diff --git a/src/or/proto_socks.c b/src/or/proto_socks.c
index 8fdb72235..84ea58778 100644
--- a/src/or/proto_socks.c
+++ b/src/or/proto_socks.c
@@ -454,10 +454,134 @@ process_socks5_userpass_auth(socks_request_t *req)
}
static int
+parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req,
+ size_t datalen, size_t *drain_out)
+{
+ int res = 1;
+ tor_addr_t destaddr;
+ socks5_client_request_t *trunnel_req = NULL;
+ ssize_t parsed = socks5_client_request_parse(&trunnel_req, raw_data, datalen);
+ if (parsed == -1) {
+ log_warn(LD_APP, "socks5: parsing failed - invalid client request");
+ res = -1;
+ goto end;
+ } else if (parsed == -2) {
+ res = 0;
+ goto end;
+ }
+
+ tor_assert(parsed >= 0);
+ *drain_out = (size_t)parsed;
+
+ if (socks5_client_request_get_version(trunnel_req) != 5) {
+ res = -1;
+ goto end;
+ }
+
+ req->command = socks5_client_request_get_command(trunnel_req);
+
+ req->port = socks5_client_request_get_dest_port(trunnel_req);
+
+ uint8_t atype = socks5_client_request_get_atype(trunnel_req);
+ req->socks5_atyp = atype;
+
+ switch (atype) {
+ case 1: {
+ uint32_t ipv4 = socks5_client_request_get_dest_addr_ipv4(trunnel_req);
+ tor_addr_from_ipv4h(&destaddr, ipv4);
+
+ tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
+ } break;
+ case 3: {
+ const struct domainname_st *dns_name =
+ socks5_client_request_getconst_dest_addr_domainname(trunnel_req);
+
+ const char *hostname = domainname_getconstarray_name(dns_name);
+
+ strlcpy(req->address, hostname, sizeof(req->address));
+ } break;
+ case 4: {
+ const char *ipv6 =
+ (const char *)socks5_client_request_getarray_dest_addr_ipv6(trunnel_req);
+ tor_addr_from_ipv6_bytes(&destaddr, ipv6);
+
+ tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1);
+ } break;
+ default: {
+ res = -1;
+ } break;
+ }
+
+ end:
+ socks5_client_request_free(trunnel_req);
+ return res;
+}
+
+static int
+process_socks5_client_request(socks_request_t *req,
+ int log_sockstype,
+ int safe_socks)
+{
+ int res = 1;
+
+ if (req->command != SOCKS_COMMAND_CONNECT &&
+ req->command != SOCKS_COMMAND_RESOLVE &&
+ req->command != SOCKS_COMMAND_RESOLVE_PTR) {
+ socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
+ res = -1;
+ goto end;
+ }
+
+ if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
+ !string_is_valid_ipv4_address(req->address) &&
+ !string_is_valid_ipv6_address(req->address)) {
+ socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
+ log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
+ "hostname type. Rejecting.");
+
+ res = -1;
+ goto end;
+ }
+
+ if (!string_is_valid_dest(req->address)) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
+
+ log_warn(LD_PROTOCOL,
+ "Your application (using socks5 to port %d) gave Tor "
+ "a malformed hostname: %s. Rejecting the connection.",
+ req->port, escaped_safe_str_client(req->address));
+
+ res = -1;
+ goto end;;
+ }
+
+ if (req->socks5_atyp == 1 || req->socks5_atyp == 4) {
+ if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
+ !addressmap_have_mapping(req->address,0)) {
+ log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
+ if (safe_socks) {
+ socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
+ res = -1;
+ goto end;
+ }
+ }
+ }
+
+ if (log_sockstype)
+ log_notice(LD_APP,
+ "Your application (using socks5 to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
+
+ end:
+ return res;
+}
+
+static int
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)
{
- int res = 0;
+ int res = 1;
uint8_t socks_version = raw_data[0];
@@ -497,8 +621,8 @@ handle_socks_message(const uint8_t *raw_data, size_t datalen, socks_request_t *r
goto end;
}
/* RFC1929 SOCKS5 username/password subnegotiation. */
- if ((!req->got_auth && raw_data[0] == 1) ||
- req->auth_type == SOCKS_USER_PASS) {
+ if (!req->got_auth && (raw_data[0] == 1 ||
+ req->auth_type == SOCKS_USER_PASS)) {
int parse_status = parse_socks5_userpass_auth(raw_data, req, datalen,
drain_out);
@@ -540,6 +664,23 @@ handle_socks_message(const uint8_t *raw_data, size_t datalen, socks_request_t *r
res = 0;
goto end;
+ } else {
+ int parse_status = parse_socks5_client_request(raw_data, req,
+ datalen, drain_out);
+ if (parse_status != 1) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
+ res = parse_status;
+ goto end;
+ }
+
+ int process_status = process_socks5_client_request(req,
+ log_sockstype,
+ safe_socks);
+
+ if (process_status != 1) {
+ res = process_status;
+ goto end;
+ }
}
} else {
*drain_out = datalen;
@@ -590,11 +731,10 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
goto end;
}
- buf_pullup(buf, datalen, &head, &datalen); // XXX
-
do {
n_drain = 0;
- //buf_pullup(buf, want_length, &head, &datalen);
+ buf_pullup(buf, MAX(want_length, buf_datalen(buf)),
+ &head, &datalen);
tor_assert(head && datalen >= 2);
want_length = 0;
@@ -605,10 +745,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
buf_clear(buf);
else if (n_drain > 0)
buf_drain(buf, n_drain);
-
- datalen = buf_datalen(buf);
- } while (res == 0 && head && want_length < buf_datalen(buf) &&
- buf_datalen(buf) >= 2);
+ } while (res == 0 && head && buf_datalen(buf) >= 2);
end:
return res;
diff --git a/src/or/socks_request_st.h b/src/or/socks_request_st.h
index c650a5773..bdef21a0d 100644
--- a/src/or/socks_request_st.h
+++ b/src/or/socks_request_st.h
@@ -53,6 +53,8 @@ struct socks_request_t {
/** The negotiated password value if any (for socks5). This value is NOT
* nul-terminated; see passwordlen for its length. */
char *password;
+
+ uint8_t socks5_atyp; /* SOCKS5 address type */
};
#endif
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index cf34e9d43..9645ea32a 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -646,7 +646,8 @@ test_socks_5_malformed_commands(void *ptr)
tt_int_op(5,OP_EQ,socks->socks_version);
tt_int_op(10,OP_EQ,socks->replylen);
tt_int_op(5,OP_EQ,socks->reply[0]);
- tt_int_op(SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED,OP_EQ,socks->reply[1]);
+ /* trunnel parsing will fail with -1 */
+ tt_int_op(SOCKS5_GENERAL_ERROR,OP_EQ,socks->reply[1]);
tt_int_op(1,OP_EQ,socks->reply[3]);
done:
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits