[tor-commits] [tor/master] Add support for managed {Client, Server}TransportPlugin parsing.

nickm at torproject.org nickm at torproject.org
Fri Oct 7 20:03:16 UTC 2011


commit 73a1e98cb971f7d1105f2b6b2399ae2eeec36a96
Author: George Kadianakis <desnacked at gmail.com>
Date:   Wed Jul 13 18:58:11 2011 +0200

    Add support for managed {Client,Server}TransportPlugin parsing.
---
 src/or/config.c |  219 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 src/or/or.h     |    3 +
 2 files changed, 194 insertions(+), 28 deletions(-)

diff --git a/src/or/config.c b/src/or/config.c
index 0082ff9..111b28b 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -33,7 +33,9 @@
 #include "rendservice.h"
 #include "rephist.h"
 #include "router.h"
+#include "util.h"
 #include "routerlist.h"
+#include "pluggable_transports.h"
 #ifdef MS_WINDOWS
 #include <shlobj.h>
 #endif
@@ -298,6 +300,7 @@ static config_var_t _option_vars[] = {
   V(HTTPProxyAuthenticator,      STRING,   NULL),
   V(HTTPSProxy,                  STRING,   NULL),
   V(HTTPSProxyAuthenticator,     STRING,   NULL),
+  VAR("ServerTransportPlugin",   LINELIST, ServerTransportPlugin,  NULL),
   V(Socks4Proxy,                 STRING,   NULL),
   V(Socks5Proxy,                 STRING,   NULL),
   V(Socks5ProxyUsername,         STRING,   NULL),
@@ -572,6 +575,8 @@ static void config_register_addressmaps(or_options_t *options);
 
 static int parse_bridge_line(const char *line, int validate_only);
 static int parse_client_transport_line(const char *line, int validate_only);
+
+static int parse_server_transport_line(const char *line, int validate_only);
 static int parse_dir_server_line(const char *line,
                                  dirinfo_type_t required_type,
                                  int validate_only);
@@ -1219,6 +1224,18 @@ options_act(or_options_t *old_options)
     }
   }
 
+  clear_transport_list();
+  if (options->ServerTransportPlugin) {
+    for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+      if (parse_server_transport_line(cl->value, 0)<0) {
+        log_warn(LD_BUG,
+                 "Previously validated ServerTransportPlugin line "
+                 "could not be added!");
+        return -1;
+      }
+    }
+  }
+
   if (options->Bridges) {
     mark_bridge_list();
     for (cl = options->Bridges; cl; cl = cl->next) {
@@ -3686,14 +3703,19 @@ options_validate(or_options_t *old_options, or_options_t *options,
   if (options->UseBridges && !options->TunnelDirConns)
     REJECT("TunnelDirConns set to 0 only works with UseBridges set to 0");
 
+  for (cl = options->Bridges; cl; cl = cl->next) {
+    if (parse_bridge_line(cl->value, 1)<0)
+      REJECT("Bridge line did not parse. See logs for details.");
+  }
+
   for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
     if (parse_client_transport_line(cl->value, 1)<0)
       REJECT("Transport line did not parse. See logs for details.");
   }
 
-  for (cl = options->Bridges; cl; cl = cl->next) {
-    if (parse_bridge_line(cl->value, 1)<0)
-      REJECT("Bridge line did not parse. See logs for details.");
+  for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+    if (parse_server_transport_line(cl->value, 1)<0)
+      REJECT("Server transport line did not parse. See logs for details.");
   }
 
   if (options->ConstrainedSockets) {
@@ -4652,28 +4674,35 @@ parse_bridge_line(const char *line, int validate_only)
   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
   smartlist_free(items);
   tor_free(addrport);
-  tor_free(fingerprint);
   tor_free(transport_name);
+  tor_free(fingerprint);
   return r;
 }
 
 /** Read the contents of a ClientTransportPlugin line from
  * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
- * isn't. If <b>validate_only</b> is 0, and the line is well-formed,
- * then add the transport described in the line to our internal
- * transport list.
-*/
+ * isn't.
+ *
+ * If <b>validate_only</b> is 0, and the line is well-formed:
+ * - If it's an external proxy line, add the transport described in the line to
+ * our internal transport list.
+ * - If it's a managed proxy line, launch the managed proxy. */
 static int
 parse_client_transport_line(const char *line, int validate_only)
 {
   smartlist_t *items = NULL;
   int r;
-  char *socks_ver_str=NULL;
+  char *field2=NULL;
+
   char *name=NULL;
   char *addrport=NULL;
-  int socks_ver;
   tor_addr_t addr;
   uint16_t port = 0;
+  int socks_ver=PROXY_NONE;
+
+  /* managed proxy options */
+  int is_managed=0;
+  char **proxy_argv=NULL;
 
   items = smartlist_create();
   smartlist_split_string(items, line, NULL,
@@ -4685,39 +4714,171 @@ parse_client_transport_line(const char *line, int validate_only)
   }
 
   name = smartlist_get(items, 0);
+  smartlist_del_keeporder(items, 0);
 
-  socks_ver_str = smartlist_get(items, 1);
+  /* field2 is either a SOCKS version or "exec" */
+  field2 = smartlist_get(items, 0);
+  smartlist_del_keeporder(items, 0);
 
-  if (!strcmp(socks_ver_str,"socks4"))
+  if (!strcmp(field2,"socks4")) {
     socks_ver = PROXY_SOCKS4;
-  else if (!strcmp(socks_ver_str,"socks5"))
+  } else if (!strcmp(field2,"socks5")) {
     socks_ver = PROXY_SOCKS5;
-  else {
-    log_warn(LD_CONFIG, "Strange ClientTransportPlugin proxy type '%s'.",
-             socks_ver_str);
+  } else if (!strcmp(field2,"exec")) {
+    is_managed=1;
+  } else {
+    log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.",
+             field2);
     goto err;
   }
 
-  addrport = smartlist_get(items, 2);
+  if (!is_managed) {
+    addrport = smartlist_get(items, 0);
+    smartlist_del_keeporder(items, 0);
 
-  if (tor_addr_port_parse(addrport, &addr, &port)<0) {
-    log_warn(LD_CONFIG, "Error parsing transport "
-              "address '%s'", addrport);
-    goto err;
+    if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+      log_warn(LD_CONFIG, "Error parsing transport "
+               "address '%s'", addrport);
+      goto err;
+    }
+    if (!port) {
+      log_warn(LD_CONFIG,
+               "Transport address '%s' has no port.", addrport);
+      goto err;
+    }
   }
 
-  if (!port) {
-    log_warn(LD_CONFIG,
-              "Transport address '%s' has no port.", addrport);
+  if (!validate_only) {
+    if (is_managed) { /* if it's managed, and we are planning on
+                         launching the proxy, use the rest of the line
+                         as the argv. */
+      char **tmp;
+      char *tmp_arg;
+      proxy_argv = tor_malloc_zero(sizeof(char*)*(smartlist_len(items)+1));
+      tmp = proxy_argv;
+      while (smartlist_len(items)) {
+        tmp_arg = smartlist_get(items, 0);
+        smartlist_del_keeporder(items, 0);
+        *tmp++ = tor_strdup(tmp_arg);
+        tor_free(tmp_arg);
+      }
+      *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+
+      if (pt_managed_launch_client_proxy(name, proxy_argv) < 0) {
+        log_warn(LD_CONFIG, "Error while launching managed proxy at '%s'",
+                 proxy_argv[0]);
+        goto err;
+      }
+    } else { /* external */
+      if (transport_add_from_config(&addr, port, name,
+                                    socks_ver) < 0) {
+        goto err;
+      }
+      log_debug(LD_DIR, "Transport %s found at %s:%d", name,
+                fmt_addr(&addr), (int)port);
+    }
+  }
+
+  r = 0;
+  goto done;
+
+ err:
+  r = -1;
+
+ done:
+  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+  smartlist_free(items);
+  tor_free(name);
+  tor_free(field2);
+  tor_free(addrport);
+  return r;
+}
+
+/** Read the contents of a ServerTransportPlugin line from
+ * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ * If <b>validate_only</b> is 0, the line is well-formed, and it's a
+ * managed proxy line, launch the managed proxy. */
+static int
+parse_server_transport_line(const char *line, int validate_only)
+{
+  smartlist_t *items = NULL;
+  int r;
+  char *name=NULL;
+  char *field2=NULL;
+  char *addrport=NULL;
+  tor_addr_t addr;
+  uint16_t port = 0;
+
+  /* managed proxy options */
+  int is_managed=0;
+  char **proxy_argv=NULL;
+
+  items = smartlist_create();
+  smartlist_split_string(items, line, NULL,
+                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+  if (smartlist_len(items) < 3) {
+    log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line.");
     goto err;
   }
 
-  if (!validate_only) {
-    log_debug(LD_DIR, "Transport %s found at %s:%d", name,
-              fmt_addr(&addr), (int)port);
+  name = smartlist_get(items, 0);
+  smartlist_del_keeporder(items, 0);
+
+  /* field2 is either <addr:port> or "exec" */
+  field2 = smartlist_get(items, 0);
+  smartlist_del_keeporder(items, 0);
 
-    if (transport_add_from_config(&addr, port, name, socks_ver) < 0)
+  if (!(strstr(field2, ".") || strstr(field2, ":"))) { /* managed proxy */
+    if (strcmp(field2, "exec")) {
+      log_warn(LD_CONFIG, "Unrecognizable field '%s' in "
+               "ServerTransportPlugin line", field2);
+      goto err;
+    }
+    is_managed=1;
+  }
+
+  if (!is_managed) {
+    addrport = field2;
+
+    if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+      log_warn(LD_CONFIG, "Error parsing transport "
+               "address '%s'", addrport);
+      goto err;
+    }
+    if (!port) {
+      log_warn(LD_CONFIG,
+               "Transport address '%s' has no port.", addrport);
       goto err;
+    }
+  }
+
+  if (!validate_only) {
+    if (is_managed) { /* if it's managed, and we are planning on
+                         launching the proxy, use the rest of the line
+                         as the argv. */
+      char **tmp;
+      char *tmp_arg;
+      proxy_argv = tor_malloc_zero(sizeof(char*)*(smartlist_len(items)+1));
+      tmp = proxy_argv;
+      while (smartlist_len(items)) {
+        tmp_arg = smartlist_get(items, 0);
+        smartlist_del_keeporder(items, 0);
+        *tmp++ = tor_strdup(tmp_arg);
+        tor_free(tmp_arg);
+      }
+      *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+
+      if (pt_managed_launch_server_proxy(name, proxy_argv) < 0) {
+        log_warn(LD_CONFIG, "Error while launching managed proxy at '%s'",
+                 proxy_argv[0]);
+        goto err;
+      }
+    } else {
+      log_warn(LD_DIR, "Transport %s at %s:%d", name,
+               fmt_addr(&addr), (int)port);
+    }
   }
 
   r = 0;
@@ -4729,6 +4890,8 @@ parse_client_transport_line(const char *line, int validate_only)
  done:
   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
   smartlist_free(items);
+  tor_free(name);
+  tor_free(field2);
   return r;
 }
 
diff --git a/src/or/or.h b/src/or/or.h
index d1817d4..8bcfc82 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2679,6 +2679,9 @@ typedef struct {
   config_line_t *ClientTransportPlugin; /**< List of client
                                            transport plugins. */
 
+  config_line_t *ServerTransportPlugin; /**< List of client
+                                           transport plugins. */
+
   int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
                     * this explicit so we can change how we behave in the
                     * future. */





More information about the tor-commits mailing list