commit 2e6604f42ee614156ceeb29bdcab5c78cc1d84ba Author: Nick Mathewson nickm@torproject.org Date: Wed Jun 29 12:31:17 2011 -0400
Record username/password data in socks_request_t
This change also requires us to add and use a pair of allocator/deallocator functions for socks_request_t, instead of using tor_malloc_zero/tor_free directly. --- src/or/buffers.c | 43 +++++++++++++++++++++++++++++++++++++++---- src/or/buffers.h | 2 ++ src/or/connection.c | 8 +++----- src/or/or.h | 12 ++++++++++++ src/test/test.c | 20 ++++++++++---------- 5 files changed, 66 insertions(+), 19 deletions(-)
diff --git a/src/or/buffers.c b/src/or/buffers.c index 7b212a7..0e2dbbe 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1475,6 +1475,25 @@ log_unsafe_socks_warning(int socks_protocol, const char *address, socks_protocol, address, (int)port); }
+/** Return a new socks_request_t. */ +socks_request_t * +socks_request_new(void) +{ + return tor_malloc_zero(sizeof(socks_request_t)); +} + +/** Free all storage held in the socks_request_t <b>req</b>. */ +void +socks_request_free(socks_request_t *req) +{ + if (!req) + return; + tor_free(req->username); + tor_free(req->password); + memset(req, 0xCC, sizeof(socks_request_t)); + tor_free(req); +} + /** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one * of the forms * - socks4: "socksheader username\0" @@ -1631,7 +1650,6 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, tor_addr_t destaddr; uint32_t destip; uint8_t socksver; - enum {socks4, socks4a} socks4_prot = socks4a; char *next, *startaddr; unsigned char usernamelen, passlen; struct in_addr in; @@ -1662,6 +1680,14 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, req->reply[1] = 0; /* authentication successful */ log_debug(LD_APP, "socks5: Accepted username/password without checking."); + if (usernamelen) { + req->username = tor_memdup(data+2u, usernamelen); + req->usernamelen = usernamelen; + } + if (passlen) { + req->password = tor_memdup(data+3u+usernamelen, passlen); + req->passwordlen = passlen; + } *drain_out = 2u + usernamelen + 1u + passlen; req->got_auth = 1; return 0; @@ -1813,7 +1839,9 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, return -1; } tor_assert(0); - case 4: /* socks4 */ + case 4: { /* socks4 */ + enum {socks4, socks4a} socks4_prot = socks4a; + const char *authstart, *authend; /* http://ss5.sourceforge.net/socks4.protocol.txt */ /* http://ss5.sourceforge.net/socks4A.protocol.txt */
@@ -1854,7 +1882,8 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, socks4_prot = socks4; }
- next = memchr(data+SOCKS4_NETWORK_LEN, 0, + authstart = data + SOCKS4_NETWORK_LEN; + next = memchr(authstart, 0, datalen-SOCKS4_NETWORK_LEN); if (!next) { if (datalen >= 1024) { @@ -1865,6 +1894,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, *want_length_out = datalen+1024; /* ???? */ return 0; } + authend = next; tor_assert(next < data+datalen);
startaddr = NULL; @@ -1914,10 +1944,15 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, req->port, escaped(req->address)); return -1; } + if (authend != authstart) { + req->got_auth = 1; + req->usernamelen = authend - authstart; + req->username = tor_memdup(authstart, authend - authstart); + } /* next points to the final \0 on inbuf */ *drain_out = next - data + 1; return 1; - + } case 'G': /* get */ case 'H': /* head */ case 'P': /* put/post */ diff --git a/src/or/buffers.h b/src/or/buffers.h index 35c1dd2..fad509e 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -41,6 +41,8 @@ int fetch_from_buf_http(buf_t *buf, char **headers_out, size_t max_headerlen, char **body_out, size_t *body_used, size_t max_bodylen, int force_complete); +socks_request_t *socks_request_new(void); +void socks_request_free(socks_request_t *req); int fetch_from_buf_socks(buf_t *buf, socks_request_t *req, int log_sockstype, int safe_socks); int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason); diff --git a/src/or/connection.c b/src/or/connection.c index 6f9ae20..2a4a6f7 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -246,7 +246,7 @@ edge_connection_new(int type, int socket_family) tor_assert(type == CONN_TYPE_EXIT || type == CONN_TYPE_AP); connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family); if (type == CONN_TYPE_AP) - edge_conn->socks_request = tor_malloc_zero(sizeof(socks_request_t)); + edge_conn->socks_request = socks_request_new(); return edge_conn; }
@@ -440,10 +440,8 @@ _connection_free(connection_t *conn) if (CONN_IS_EDGE(conn)) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); tor_free(edge_conn->chosen_exit_name); - if (edge_conn->socks_request) { - memset(edge_conn->socks_request, 0xcc, sizeof(socks_request_t)); - tor_free(edge_conn->socks_request); - } + if (edge_conn->socks_request) + socks_request_free(edge_conn->socks_request);
rend_data_free(edge_conn->rend_data); } diff --git a/src/or/or.h b/src/or/or.h index bc80e39..3c76444 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3109,6 +3109,18 @@ struct socks_request_t { * make sure we send back a socks reply for * every connection. */ unsigned int got_auth : 1; /**< Have we received any authentication data? */ + + /** Number of bytes in username; 0 if username is NULL */ + uint8_t usernamelen; + /** Number of bytes in password; 0 if password is NULL */ + uint8_t passwordlen; + /** The negotiated username value if any (for socks5), or the entire + * authentication string (for socks4). This value is NOT nul-terminated; + * see usernamelen for its length. */ + char *username; + /** The negotiated password value if any (for socks5). This value is NOT + * nul-terminated; see usernamelen for its length. */ + char *password; };
/********************************* circuitbuild.c **********************/ diff --git a/src/test/test.c b/src/test/test.c index d0e24d1..38729cf 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -627,54 +627,54 @@ test_buffers(void)
/* Test fetch_from_buf_socks() */ buf = buf_new_with_capacity(256); - socks = tor_malloc_zero(sizeof(socks_request_t));; + socks = socks_request_new(); config_register_addressmaps(get_options());
/* Sending auth credentials before we've negotiated a method */ test_buffers_socks5_auth_before_negotiation_helper(cp, buf, socks);
- tor_free(socks); + socks_request_free(socks); buf_free(buf); buf = NULL; buf = buf_new_with_capacity(256); - socks = tor_malloc_zero(sizeof(socks_request_t));; + socks = socks_request_new();
/* A SOCKS 5 client that only supports authentication */ test_buffers_socks5_authenticate_helper(cp, buf, socks); test_buffers_socks5_supported_commands_helper(cp, buf, socks); test_buffers_socks5_unsupported_commands_helper(cp, buf, socks);
- tor_free(socks); + socks_request_free(socks); buf_free(buf); buf = NULL; buf = buf_new_with_capacity(256); - socks = tor_malloc_zero(sizeof(socks_request_t));; + socks = socks_request_new();
/* A SOCKS 5 client that sends credentials and data in one go */ test_buffers_socks5_authenticate_with_data_helper(cp, buf, socks);
- tor_free(socks); + socks_request_free(socks); buf_free(buf); buf = NULL; buf = buf_new_with_capacity(256); - socks = tor_malloc_zero(sizeof(socks_request_t));; + socks = socks_request_new();
/* A SOCKS 5 client that doesn't want authentication */ test_buffers_socks5_no_authenticate_helper(cp, buf, socks); test_buffers_socks5_supported_commands_helper(cp, buf, socks); test_buffers_socks5_unsupported_commands_helper(cp, buf, socks);
- tor_free(socks); + socks_request_free(socks); buf_free(buf); buf = NULL; buf = buf_new_with_capacity(256); - socks = tor_malloc_zero(sizeof(socks_request_t));; + socks = socks_request_new();
/* A SOCKS 4(a) client */ test_buffers_socks4_supported_commands_helper(cp, buf, socks); test_buffers_socks4_unsupported_commands_helper(cp, buf, socks);
- tor_free(socks); + socks_request_free(socks); buf_free(buf); buf = NULL;
tor-commits@lists.torproject.org