commit 1a94be0a770084b61d87bf6da4f9563cfac236ed Author: Mike Perry mikeperry-git@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@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@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 +
tor-commits@lists.torproject.org