|
@@ -44,6 +44,7 @@
|
|
|
#include "router.h"
|
|
|
#include "transports.h"
|
|
|
#include "routerparse.h"
|
|
|
+#include "transports.h"
|
|
|
|
|
|
#ifdef USE_BUFFEREVENTS
|
|
|
#include <event2/event.h>
|
|
@@ -1560,6 +1561,32 @@ connection_proxy_state_to_string(int state)
|
|
|
return states[state];
|
|
|
}
|
|
|
|
|
|
+/** Returns the global proxy type used by tor. Use this function for
|
|
|
+ * logging or high-level purposes, don't use it to fill the
|
|
|
+ * <b>proxy_type</b> field of or_connection_t; use the actual proxy
|
|
|
+ * protocol instead.*/
|
|
|
+static int
|
|
|
+get_proxy_type(void)
|
|
|
+{
|
|
|
+ const or_options_t *options = get_options();
|
|
|
+
|
|
|
+ if (options->HTTPSProxy)
|
|
|
+ return PROXY_CONNECT;
|
|
|
+ else if (options->Socks4Proxy)
|
|
|
+ return PROXY_SOCKS4;
|
|
|
+ else if (options->Socks5Proxy)
|
|
|
+ return PROXY_SOCKS5;
|
|
|
+ else if (options->ClientTransportPlugin)
|
|
|
+ return PROXY_PLUGGABLE;
|
|
|
+ else
|
|
|
+ return PROXY_NONE;
|
|
|
+}
|
|
|
+
|
|
|
+/* One byte for the version, one for the command, two for the
|
|
|
+ port, and four for the addr... and, one more for the
|
|
|
+ username NUL: */
|
|
|
+#define SOCKS4_STANDARD_BUFFER_SIZE 1 + 1 + 2 + 4 + 1
|
|
|
+
|
|
|
/** Write a proxy request of <b>type</b> (socks4, socks5, https) to conn
|
|
|
* for conn->addr:conn->port, authenticating with the auth details given
|
|
|
* in the configuration (if available). SOCKS 5 and HTTP CONNECT proxies
|
|
@@ -1614,17 +1641,45 @@ connection_proxy_connect(connection_t *conn, int type)
|
|
|
}
|
|
|
|
|
|
case PROXY_SOCKS4: {
|
|
|
- unsigned char buf[9];
|
|
|
+ unsigned char *buf;
|
|
|
uint16_t portn;
|
|
|
uint32_t ip4addr;
|
|
|
+ size_t buf_size = 0;
|
|
|
+ char *socks_args_string = NULL;
|
|
|
|
|
|
- /* Send a SOCKS4 connect request with empty user id */
|
|
|
+ /* Send a SOCKS4 connect request */
|
|
|
|
|
|
if (tor_addr_family(&conn->addr) != AF_INET) {
|
|
|
log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6");
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ { /* If we are here because we are trying to connect to a
|
|
|
+ pluggable transport proxy, check if we have any SOCKS
|
|
|
+ arguments to transmit. If we do, compress all arguments to
|
|
|
+ a single string in 'socks_args_string': */
|
|
|
+
|
|
|
+ if (get_proxy_type() == PROXY_PLUGGABLE) {
|
|
|
+ socks_args_string =
|
|
|
+ pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port);
|
|
|
+ if (socks_args_string)
|
|
|
+ log_debug(LD_NET, "Sending out '%s' as our SOCKS argument string.",
|
|
|
+ socks_args_string);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ { /* Figure out the buffer size we need for the SOCKS message: */
|
|
|
+
|
|
|
+ buf_size = SOCKS4_STANDARD_BUFFER_SIZE;
|
|
|
+
|
|
|
+ /* If we have a SOCKS argument string, consider its size when
|
|
|
+ calculating the buffer size: */
|
|
|
+ if (socks_args_string)
|
|
|
+ buf_size += strlen(socks_args_string);
|
|
|
+ }
|
|
|
+
|
|
|
+ buf = tor_malloc_zero(buf_size);
|
|
|
+
|
|
|
ip4addr = tor_addr_to_ipv4n(&conn->addr);
|
|
|
portn = htons(conn->port);
|
|
|
|
|
@@ -1632,9 +1687,20 @@ connection_proxy_connect(connection_t *conn, int type)
|
|
|
buf[1] = SOCKS_COMMAND_CONNECT; /* command */
|
|
|
memcpy(buf + 2, &portn, 2); /* port */
|
|
|
memcpy(buf + 4, &ip4addr, 4); /* addr */
|
|
|
- buf[8] = 0; /* userid (empty) */
|
|
|
|
|
|
- connection_write_to_buf((char *)buf, sizeof(buf), conn);
|
|
|
+ if (socks_args_string) { /* place the SOCKS args string: */
|
|
|
+ tor_assert(strlen(socks_args_string) > 0);
|
|
|
+ tor_assert(buf_size >=
|
|
|
+ SOCKS4_STANDARD_BUFFER_SIZE + strlen(socks_args_string));
|
|
|
+ strlcpy((char *)buf + 8, socks_args_string, buf_size - 8);
|
|
|
+ tor_free(socks_args_string);
|
|
|
+ } else {
|
|
|
+ buf[8] = 0; /* no userid */
|
|
|
+ }
|
|
|
+
|
|
|
+ connection_write_to_buf((char *)buf, buf_size, conn);
|
|
|
+ tor_free(buf);
|
|
|
+
|
|
|
conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK;
|
|
|
break;
|
|
|
}
|
|
@@ -4339,24 +4405,6 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/** Returns the global proxy type used by tor. */
|
|
|
-static int
|
|
|
-get_proxy_type(void)
|
|
|
-{
|
|
|
- const or_options_t *options = get_options();
|
|
|
-
|
|
|
- if (options->HTTPSProxy)
|
|
|
- return PROXY_CONNECT;
|
|
|
- else if (options->Socks4Proxy)
|
|
|
- return PROXY_SOCKS4;
|
|
|
- else if (options->Socks5Proxy)
|
|
|
- return PROXY_SOCKS5;
|
|
|
- else if (options->ClientTransportPlugin)
|
|
|
- return PROXY_PLUGGABLE;
|
|
|
- else
|
|
|
- return PROXY_NONE;
|
|
|
-}
|
|
|
-
|
|
|
/** Log a failed connection to a proxy server.
|
|
|
* <b>conn</b> is the connection we use the proxy server for. */
|
|
|
void
|