Browse Source

Send SOCKS arguments when doing SOCKS4.

George Kadianakis 11 years ago
parent
commit
14b84858c0
6 changed files with 107 additions and 23 deletions
  1. 70 22
      src/or/connection.c
  2. 11 0
      src/or/entrynodes.c
  3. 3 0
      src/or/entrynodes.h
  4. 3 1
      src/or/or.h
  5. 17 0
      src/or/transports.c
  6. 3 0
      src/or/transports.h

+ 70 - 22
src/or/connection.c

@@ -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

+ 11 - 0
src/or/entrynodes.c

@@ -1751,6 +1751,17 @@ find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
   return 0;
 }
 
+/** Return a smartlist containing all the SOCKS arguments that we
+ *  should pass to the SOCKS proxy. */
+const smartlist_t *
+get_socks_args_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
+{
+  bridge_info_t *bridge = get_configured_bridge_by_addr_port_digest(addr,
+                                                                    port,
+                                                                    NULL);
+  return bridge ? bridge->socks_args : NULL;
+}
+
 /** We need to ask <b>bridge</b> for its server descriptor. */
 static void
 launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)

+ 3 - 0
src/or/entrynodes.h

@@ -110,6 +110,9 @@ int any_pending_bridge_descriptor_fetches(void);
 int entries_known_but_down(const or_options_t *options);
 void entries_retry_all(const or_options_t *options);
 
+const smartlist_t *get_socks_args_by_bridge_addrport(const tor_addr_t *addr,
+                                                     uint16_t port);
+
 int any_bridges_dont_support_microdescriptors(void);
 
 void entry_guards_free_all(void);

+ 3 - 1
src/or/or.h

@@ -240,7 +240,9 @@ typedef enum {
 #define PROXY_SOCKS5 3
 /* !!!! If there is ever a PROXY_* type over 2, we must grow the proxy_type
  * field in or_connection_t */
-/* pluggable transports proxy type */
+
+/* Pluggable transport proxy type. Don't use this in or_connection_t,
+ * instead use the actual underlying proxy type (see above).  */
 #define PROXY_PLUGGABLE 4
 
 /* Proxy client handshake states */

+ 17 - 0
src/or/transports.c

@@ -95,6 +95,7 @@
 #include "util.h"
 #include "router.h"
 #include "statefile.h"
+#include "entrynodes.h"
 
 static process_environment_t *
 create_managed_proxy_environment(const managed_proxy_t *mp);
@@ -1459,6 +1460,22 @@ pt_stringify_socks_args(const smartlist_t *socks_args)
   return new_string;
 }
 
+/** Return a string of the SOCKS arguments that we should pass to the
+ *  pluggable transports proxy in <b>addr</b>:<b>port</b> according to
+ *  180_pluggable_transport.txt.  The string is allocated on the heap
+ *  and it's the responsibility of the caller to free it after use. */
+char *
+pt_get_socks_args_for_proxy_addrport(const tor_addr_t *addr, uint16_t port)
+{
+  const smartlist_t *socks_args = NULL;
+
+  socks_args = get_socks_args_by_bridge_addrport(addr, port);
+  if (!socks_args)
+    return NULL;
+
+  return pt_stringify_socks_args(socks_args);
+}
+
 /** The tor config was read.
  *  Destroy all managed proxies that were marked by a previous call to
  *  prepare_proxy_list_for_config_read() and are not used by the new

+ 3 - 0
src/or/transports.h

@@ -57,6 +57,9 @@ void sweep_proxy_list(void);
 smartlist_t *get_transport_proxy_ports(void);
 char *pt_stringify_socks_args(const smartlist_t *socks_args);
 
+char *pt_get_socks_args_for_proxy_addrport(const tor_addr_t *addr,
+                                            uint16_t port);
+
 #ifdef PT_PRIVATE
 /** State of the managed proxy configuration protocol. */
 enum pt_proto_state {