[tor-commits] [tor-browser-bundle/master] Bug 11658: Add support for proxies while PT lines are present.

mikeperry at torproject.org mikeperry at torproject.org
Thu May 1 19:38:26 UTC 2014


commit 1a94be0a770084b61d87bf6da4f9563cfac236ed
Author: Mike Perry <mikeperry-git at torproject.org>
Date:   Thu May 1 12:32:43 2014 -0700

    Bug 11658: Add support for proxies while PT lines are present.
    
    This technically backports Bug 8402's patch, which will allow proxies to work
    without PTs again.
    
    However, PT+Proxies remain unsupported until we bump obfs3 to 0.2.9 and solve
    bug #11535. Flashproxy and FTE may need similar bumps+tweaks to fully solve
    bug #8402.
---
 gitian/descriptors/linux/gitian-tor.yml   |    2 +
 gitian/descriptors/mac/gitian-tor.yml     |    2 +
 gitian/descriptors/windows/gitian-tor.yml |    2 +
 gitian/patches/bug8402.patch              |  437 +++++++++++++++++++++++++++++
 4 files changed, 443 insertions(+)

diff --git a/gitian/descriptors/linux/gitian-tor.yml b/gitian/descriptors/linux/gitian-tor.yml
index 826d355..8b1644e 100644
--- a/gitian/descriptors/linux/gitian-tor.yml
+++ b/gitian/descriptors/linux/gitian-tor.yml
@@ -29,6 +29,7 @@ files:
 - "bug11200.patch"
 - "bug11069.patch"
 - "bug9665.patch"
+- "bug8402.patch"
 - "dzip.sh"
 - "openssl-linux32-utils.zip"
 - "openssl-linux64-utils.zip"
@@ -79,6 +80,7 @@ script: |
       git am ~/build/bug11156.patch
       git am ~/build/bug9665.patch
       git am ~/build/bug11200.patch
+      git am ~/build/bug8402.patch
     fi
   fi
   mkdir -p $OUTDIR/src
diff --git a/gitian/descriptors/mac/gitian-tor.yml b/gitian/descriptors/mac/gitian-tor.yml
index c3ae8d8..ca938fc 100644
--- a/gitian/descriptors/mac/gitian-tor.yml
+++ b/gitian/descriptors/mac/gitian-tor.yml
@@ -32,6 +32,7 @@ files:
 - "bug11200.patch"
 - "bug11069.patch"
 - "bug9665.patch"
+- "bug8402.patch"
 - "apple-uni-sdk-10.6_20110407-0.flosoft1_i386.deb"
 - "multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz"
 - "dzip.sh"
@@ -110,6 +111,7 @@ script: |
       git am ~/build/bug11156.patch
       git am ~/build/bug9665.patch
       git am ~/build/bug11200.patch
+      git am ~/build/bug8402.patch
     fi
   fi
   mkdir -p $OUTDIR/src
diff --git a/gitian/descriptors/windows/gitian-tor.yml b/gitian/descriptors/windows/gitian-tor.yml
index 5e452b9..61fc9b5 100644
--- a/gitian/descriptors/windows/gitian-tor.yml
+++ b/gitian/descriptors/windows/gitian-tor.yml
@@ -31,6 +31,7 @@ files:
 - "bug11200.patch"
 - "bug11069.patch"
 - "bug9665.patch"
+- "bug8402.patch"
 - "binutils.tar.bz2"
 - "dzip.sh"
 - "openssl.tar.gz"
@@ -106,6 +107,7 @@ script: |
       git am ~/build/bug11156.patch
       git am ~/build/bug9665.patch
       git am ~/build/bug11200.patch
+      git am ~/build/bug8402.patch
     fi
   fi
   mkdir -p $OUTDIR/src
diff --git a/gitian/patches/bug8402.patch b/gitian/patches/bug8402.patch
new file mode 100644
index 0000000..2aa74c6
--- /dev/null
+++ b/gitian/patches/bug8402.patch
@@ -0,0 +1,437 @@
+From 88ddabbce1e15627f51b1bd6aef06f1b3515dd15 Mon Sep 17 00:00:00 2001
+From: Yawning Angel <yawning at schwanenlied.me>
+Date: Thu, 1 May 2014 03:57:29 +0000
+Subject: [PATCH 1/2] Allow ClientTransportPlugins to use proxies
+
+This change allows using Socks4Proxy, Socks5Proxy and HTTPSProxy with
+ClientTransportPlugins via the TOR_PT_PROXY extension to the
+pluggable transport specification.
+
+This fixes bug #8402.
+
+WARNING:
+
+This is a backport to tor-0.2.4.x of a unmerged patch.  Differences
+at the time of writing from my real branch are:
+ * Unit tests.
+ * get_proxy_type() is removed in the backport, 0.2.5.x uses the
+   routine elsewhere, so it is left intact (with modifications).
+---
+ src/or/config.c     |  24 +++++++----
+ src/or/connection.c |  55 ++++++++++---------------
+ src/or/transports.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++--
+ src/or/transports.h |   3 ++
+ 4 files changed, 152 insertions(+), 44 deletions(-)
+
+diff --git a/src/or/config.c b/src/or/config.c
+index 09fdc0c..3fe5b73 100644
+--- a/src/or/config.c
++++ b/src/or/config.c
+@@ -490,7 +490,9 @@ static int options_transition_affects_descriptor(
+ static int check_nickname_list(const char *lst, const char *name, char **msg);
+ 
+ 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_client_transport_line(const or_options_t *options,
++                                       const char *line,
++                                       int validate_only);
+ 
+ static int parse_server_transport_line(const char *line, int validate_only);
+ static char *get_bindaddr_from_transport_listen_line(const char *line,
+@@ -1337,7 +1339,7 @@ options_act(const or_options_t *old_options)
+   pt_prepare_proxy_list_for_config_read();
+   if (options->ClientTransportPlugin) {
+     for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+-      if (parse_client_transport_line(cl->value, 0)<0) {
++      if (parse_client_transport_line(options, cl->value, 0)<0) {
+         log_warn(LD_BUG,
+                  "Previously validated ClientTransportPlugin line "
+                  "could not be added!");
+@@ -2954,11 +2956,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
+     }
+   }
+ 
+-  /* Check if more than one proxy type has been enabled. */
++  /* Check if more than one exclusive proxy type has been enabled. */
+   if (!!options->Socks4Proxy + !!options->Socks5Proxy +
+-      !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
++      !!options->HTTPSProxy > 1)
+     REJECT("You have configured more than one proxy type. "
+-           "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
++           "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ 
+   /* Check if the proxies will give surprising behavior. */
+   if (options->HTTPProxy && !(options->Socks4Proxy ||
+@@ -3073,7 +3075,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
+   }
+ 
+   for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+-    if (parse_client_transport_line(cl->value, 1)<0)
++    if (parse_client_transport_line(options, cl->value, 1)<0)
+       REJECT("Transport line did not parse. See logs for details.");
+   }
+ 
+@@ -4229,7 +4231,8 @@ parse_bridge_line(const char *line, int validate_only)
+  * 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)
++parse_client_transport_line(const or_options_t *options, const char *line,
++                            int validate_only)
+ {
+   smartlist_t *items = NULL;
+   int r;
+@@ -4308,6 +4311,13 @@ parse_client_transport_line(const char *line, int validate_only)
+       pt_kickstart_client_proxy(transport_list, proxy_argv);
+     }
+   } else { /* external */
++    /* ClientTransportPlugins connecting through a proxy is managed only. */
++    if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
++      log_warn(LD_CONFIG, "You have configured an external proxy with another "
++                          "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
++      goto err;
++    }
++
+     if (smartlist_len(transport_list) != 1) {
+       log_warn(LD_CONFIG, "You can't have an external proxy with "
+                "more than one transports.");
+diff --git a/src/or/connection.c b/src/or/connection.c
+index 4f74a1d..683cf46 100644
+--- a/src/or/connection.c
++++ b/src/or/connection.c
+@@ -81,7 +81,6 @@ static const char *connection_proxy_state_to_string(int state);
+ static int connection_read_https_proxy_response(connection_t *conn);
+ static void connection_send_socks5_connect(connection_t *conn);
+ static const char *proxy_type_to_string(int proxy_type);
+-static int get_proxy_type(void);
+ 
+ /** The last addresses that our network interface seemed to have been
+  * binding to.  We use this as one way to detect when our IP changes.
+@@ -4390,6 +4389,27 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
+ {
+   const or_options_t *options = get_options();
+ 
++  /* Client Transport Plugins can use another proxy, but that should be hidden
++   * from the rest of tor (as the plugin is responsible for dealing with the
++   * proxy), check it first, then check the rest of the proxy types to allow
++   * the config to have unused ClientTransportPlugin entries.
++   */
++  if (options->ClientTransportPlugin) {
++    const transport_t *transport = NULL;
++    int r;
++    r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
++    if (r<0)
++      return -1;
++    if (transport) { /* transport found */
++      tor_addr_copy(addr, &transport->addr);
++      *port = transport->port;
++      *proxy_type = transport->socks_version;
++      return 0;
++    }
++
++    /* Unused ClientTransportPlugin. */
++  }
++
+   if (options->HTTPSProxy) {
+     tor_addr_copy(addr, &options->HTTPSProxyAddr);
+     *port = options->HTTPSProxyPort;
+@@ -4405,43 +4425,12 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
+     *port = options->Socks5ProxyPort;
+     *proxy_type = PROXY_SOCKS5;
+     return 0;
+-  } else if (options->ClientTransportPlugin ||
+-             options->Bridges) {
+-    const transport_t *transport = NULL;
+-    int r;
+-    r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
+-    if (r<0)
+-      return -1;
+-    if (transport) { /* transport found */
+-      tor_addr_copy(addr, &transport->addr);
+-      *port = transport->port;
+-      *proxy_type = transport->socks_version;
+-      return 0;
+-    }
+   }
+ 
+   *proxy_type = PROXY_NONE;
+   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
+@@ -4457,7 +4446,7 @@ log_failed_proxy_connection(connection_t *conn)
+   log_warn(LD_NET,
+            "The connection to the %s proxy server at %s just failed. "
+            "Make sure that the proxy server is up and running.",
+-           proxy_type_to_string(get_proxy_type()),
++           proxy_type_to_string(proxy_type),
+            fmt_addrport(&proxy_addr, proxy_port));
+ }
+ 
+diff --git a/src/or/transports.c b/src/or/transports.c
+index 3749d6b..cae1f31 100644
+--- a/src/or/transports.c
++++ b/src/or/transports.c
+@@ -103,6 +103,8 @@ static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
+ 
+ static void managed_proxy_destroy(managed_proxy_t *mp,
+                                   int also_terminate_process);
++static char* get_pt_proxy_uri(void);
++static void parse_proxy_error(const char *line);
+ 
+ static void handle_finished_proxy(managed_proxy_t *mp);
+ static int configure_proxy(managed_proxy_t *mp);
+@@ -123,6 +125,8 @@ static INLINE void free_execve_args(char **arg);
+ #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
+ #define PROTO_CMETHODS_DONE "CMETHODS DONE"
+ #define PROTO_SMETHODS_DONE "SMETHODS DONE"
++#define PROTO_PROXY_DONE "PROXY DONE"
++#define PROTO_PROXY_ERROR "PROXY-ERROR"
+ 
+ /** The first and only supported - at the moment - configuration
+     protocol version. */
+@@ -434,6 +438,17 @@ add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
+ static int
+ proxy_needs_restart(const managed_proxy_t *mp)
+ {
++  int ret = 1;
++  char* proxy_uri;
++
++  /* If the PT proxy config has changed, then all existing pluggable transports
++   * should be restarted.
++   */
++
++  proxy_uri = get_pt_proxy_uri();
++  if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
++    goto needs_restart;
++
+   /* mp->transport_to_launch is populated with the names of the
+      transports that must be launched *after* the SIGHUP.
+      mp->transports is populated with the transports that were
+@@ -454,10 +469,10 @@ proxy_needs_restart(const managed_proxy_t *mp)
+ 
+   } SMARTLIST_FOREACH_END(t);
+ 
+-  return 0;
+-
+- needs_restart:
+-  return 1;
++  ret = 0;
++needs_restart:
++  tor_free(proxy_uri);
++  return ret;
+ }
+ 
+ /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
+@@ -488,6 +503,11 @@ proxy_prepare_for_restart(managed_proxy_t *mp)
+   SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+   smartlist_clear(mp->transports);
+ 
++  /* Reset the proxy's HTTPS/SOCKS proxy */
++  tor_free(mp->proxy_uri);
++  mp->proxy_uri = get_pt_proxy_uri();
++  mp->proxy_supported = 0;
++
+   /* flag it as an infant proxy so that it gets launched on next tick */
+   mp->conf_state = PT_PROTO_INFANT;
+   unconfigured_proxies_n++;
+@@ -718,12 +738,52 @@ managed_proxy_destroy(managed_proxy_t *mp,
+   /* free the argv */
+   free_execve_args(mp->argv);
+ 
++  /* free the outgoing proxy URI */
++  tor_free(mp->proxy_uri);
++
+   tor_process_handle_destroy(mp->process_handle, also_terminate_process);
+   mp->process_handle = NULL;
+ 
+   tor_free(mp);
+ }
+ 
++/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. */
++static char *
++get_pt_proxy_uri(void)
++{
++  const or_options_t *options = get_options();
++  char *uri = NULL;
++
++  if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
++    char addr[TOR_ADDR_BUF_LEN+1];
++
++    if (options->Socks4Proxy) {
++      tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
++      tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
++    } else if (options->Socks5Proxy) {
++      tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
++      if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
++        tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
++      } else {
++        tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
++                     options->Socks5ProxyUsername,
++                     options->Socks5ProxyPassword,
++                     addr, options->Socks5ProxyPort);
++      }
++    } else if (options->HTTPSProxy) {
++      tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
++      if (!options->HTTPSProxyAuthenticator) {
++        tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
++      } else {
++        tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
++                     addr, options->HTTPSProxyPort);
++      }
++    }
++  }
++
++  return uri;
++}
++
+ /** Handle a configured or broken managed proxy <b>mp</b>. */
+ static void
+ handle_finished_proxy(managed_proxy_t *mp)
+@@ -736,6 +796,12 @@ handle_finished_proxy(managed_proxy_t *mp)
+     managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
+     break;
+   case PT_PROTO_CONFIGURED: /* if configured correctly: */
++    if (mp->proxy_uri && !mp->proxy_supported) {
++      log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
++               "specified outgoing proxy.", mp->argv[0]);
++      managed_proxy_destroy(mp, 1); /* annihilate it. */
++      break;
++    }
+     register_proxy(mp); /* register its transports */
+     mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
+     break;
+@@ -854,6 +920,22 @@ handle_proxy_line(const char *line, managed_proxy_t *mp)
+       goto err;
+ 
+     return;
++  } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
++    if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
++      goto err;
++
++    if (mp->proxy_uri) {
++      mp->proxy_supported = 1;
++      return;
++    }
++
++    /* No proxy was configured, this should log */
++  } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
++    if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
++      goto err;
++
++    parse_proxy_error(line);
++    goto err;
+   } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) {
+     /* managed proxy launch failed: parse error message to learn why. */
+     int retval, child_state, saved_errno;
+@@ -1105,6 +1187,21 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp)
+   return r;
+ }
+ 
++/** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
++static void
++parse_proxy_error(const char *line)
++{
++  /* (Length of the protocol string) plus (a space) and (the first char of
++     the error message) */
++  if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
++    log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
++               "message.", PROTO_PROXY_ERROR);
++
++  log_warn(LD_CONFIG, "Managed proxy failed to configure the "
++           "pluggable transport's outgoing proxy. (%s)",
++           line+strlen(PROTO_PROXY_ERROR)+1);
++}
++
+ /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
+  *  while configuring the server managed proxy in <b>mp</b>. The
+  *  string is stored in the heap, and it's the the responsibility of
+@@ -1193,6 +1290,14 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
+      * variable in Tor's environment and crash PTs that try to parse
+      * it even when not run in server mode.) */
+     smartlist_add(envs, tor_strdup("TOR_PT_EXTENDED_SERVER_PORT="));
++  } else {
++    /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
++     * TOR_PT_PROXY line.
++     */
++
++    if (mp->proxy_uri) {
++      smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
++    }
+   }
+ 
+   SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
+@@ -1225,6 +1330,7 @@ managed_proxy_create(const smartlist_t *transport_list,
+   mp->is_server = is_server;
+   mp->argv = proxy_argv;
+   mp->transports = smartlist_new();
++  mp->proxy_uri = get_pt_proxy_uri();
+ 
+   mp->transports_to_launch = smartlist_new();
+   SMARTLIST_FOREACH(transport_list, const char *, transport,
+diff --git a/src/or/transports.h b/src/or/transports.h
+index 6ee82f4..f13de5d 100644
+--- a/src/or/transports.h
++++ b/src/or/transports.h
+@@ -74,6 +74,9 @@ typedef struct {
+   char **argv; /* the cli arguments of this proxy */
+   int conf_protocol; /* the configuration protocol version used */
+ 
++  char *proxy_uri;  /* the outgoing proxy in TOR_PT_PROXY URI format */
++  int proxy_supported : 1; /* the proxy claims to honor TOR_PT_PROXY */
++
+   int is_server; /* is it a server proxy? */
+ 
+   /* A pointer to the process handle of this managed proxy. */
+-- 
+1.8.1.2
+
+From 34004139ee9380c5c468d28037520d02681dd7cf Mon Sep 17 00:00:00 2001
+From: Yawning Angel <yawning at schwanenlied.me>
+Date: Thu, 1 May 2014 19:01:34 +0000
+Subject: [PATCH 2/2] Improve the log message when a transport doesn't support
+ proxies.
+
+Per feedback, explicltly note that the transport will be killed when it
+does not acknowledge the configured outgoing proxy.
+---
+ src/or/transports.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/or/transports.c b/src/or/transports.c
+index cae1f31..917d12a 100644
+--- a/src/or/transports.c
++++ b/src/or/transports.c
+@@ -798,7 +798,8 @@ handle_finished_proxy(managed_proxy_t *mp)
+   case PT_PROTO_CONFIGURED: /* if configured correctly: */
+     if (mp->proxy_uri && !mp->proxy_supported) {
+       log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
+-               "specified outgoing proxy.", mp->argv[0]);
++               "specified outgoing proxy and will be terminated.",
++               mp->argv[0]);
+       managed_proxy_destroy(mp, 1); /* annihilate it. */
+       break;
+     }
+-- 
+1.8.1.2
+



More information about the tor-commits mailing list