From 41d2b4d3af01b34beb2951028cdbc45b5f41e08e Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Tue, 25 Mar 2014 07:21:22 +0000 Subject: [PATCH 1/6] 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. --- src/or/config.c | 13 +++-- src/or/connection.c | 62 +++++++++++++++++------- src/or/transports.c | 112 ++++++++++++++++++++++++++++++++++++++++++-- src/or/transports.h | 6 +++ src/test/test_pt.c | 81 ++++++++++++++++++++++++++++++++ 5 files changed, 251 insertions(+), 23 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index 0f7b1d2a2e..b33098e542 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3174,11 +3174,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 || @@ -4842,6 +4842,13 @@ parse_client_transport_line(const or_options_t *options, 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 cef9172ff1..b32cddf1f1 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -86,6 +86,8 @@ 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); +static int get_bridge_pt_addrport(tor_addr_t *addr, uint16_t *port, + int *proxy_type, const connection_t *conn); /** 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. @@ -1689,14 +1691,14 @@ get_proxy_type(void) { const or_options_t *options = get_options(); - if (options->HTTPSProxy) + if (options->ClientTransportPlugin) + return PROXY_PLUGGABLE; + else 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; } @@ -4770,6 +4772,35 @@ assert_connection_ok(connection_t *conn, time_t now) } } +/** Fills addr and port with the details of the global + * pluggable transport or bridge we are using. + * conn contains the connection we are using the PT/bridge for. + * + * Return 0 on success, -1 on failure. + */ +static int +get_bridge_pt_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, + const connection_t *conn) +{ + const or_options_t *options = get_options(); + + if (options->ClientTransportPlugin || options->Bridges) { + const transport_t *transport = NULL; + int r; + r = get_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; + } + } + + return -1; +} + /** Fills addr and port with the details of the global * proxy server we are using. * conn contains the connection we are using the proxy for. @@ -4782,6 +4813,16 @@ 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) { + if (get_bridge_pt_addrport(addr, port, proxy_type, conn) == 0) + return 0; + } + if (options->HTTPSProxy) { tor_addr_copy(addr, &options->HTTPSProxyAddr); *port = options->HTTPSProxyPort; @@ -4797,19 +4838,8 @@ 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 = get_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; - } + } else if (options->Bridges) { + return get_bridge_pt_addrport(addr, port, proxy_type, conn); } tor_addr_make_unspec(addr); diff --git a/src/or/transports.c b/src/or/transports.c index dc30754162..b810315d57 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -124,6 +124,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. */ @@ -439,6 +441,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 @@ -459,10 +472,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 mp must be restarted. Do all the necessary @@ -493,6 +506,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++; @@ -727,12 +745,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 mp. */ static void handle_finished_proxy(managed_proxy_t *mp) @@ -745,6 +803,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; @@ -862,6 +926,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; @@ -1128,6 +1208,21 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp) return r; } +/** Parses an PROXY-ERROR line 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 a newly allocated string that tor should place in * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server * manged proxy in mp. Return NULL if no such options are found. */ @@ -1292,6 +1387,14 @@ create_managed_proxy_environment(const managed_proxy_t *mp) } else { smartlist_add_asprintf(envs, "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) { @@ -1324,6 +1427,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 1365ead006..bc2331d01b 100644 --- a/src/or/transports.h +++ b/src/or/transports.h @@ -81,6 +81,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. */ @@ -112,6 +115,7 @@ STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp); STATIC int parse_version(const char *line, managed_proxy_t *mp); STATIC void parse_env_error(const char *line); +STATIC void parse_proxy_error(const char *line); STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp); STATIC char *get_transport_options_for_server_proxy(const managed_proxy_t *mp); @@ -123,6 +127,8 @@ STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list, STATIC int configure_proxy(managed_proxy_t *mp); +STATIC char* get_pt_proxy_uri(void); + #endif #endif diff --git a/src/test/test_pt.c b/src/test/test_pt.c index f71627df1e..788d4205cc 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -450,6 +450,85 @@ test_pt_configure_proxy(void *arg) tor_free(mp); } +/* Test the get_pt_proxy_uri() function. */ +static void +test_get_pt_proxy_uri(void *arg) +{ + or_options_t *options = get_options_mutable(); + char *uri = NULL; + int ret; + (void) arg; + + /* Test with no proxy. */ + uri = get_pt_proxy_uri(); + tt_assert(uri == NULL); + + /* Test with a SOCKS4 proxy. */ + options->Socks4Proxy = "192.0.2.1:1080"; + ret = tor_addr_port_lookup(options->Socks4Proxy, + &options->Socks4ProxyAddr, + &options->Socks4ProxyPort); + tt_assert(ret == 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks4a://192.0.2.1:1080"); + tor_free(uri); + + options->Socks4Proxy = NULL; + + /* Test with a SOCKS5 proxy, no username/password. */ + options->Socks5Proxy = "192.0.2.1:1080"; + ret = tor_addr_port_lookup(options->Socks5Proxy, + &options->Socks5ProxyAddr, + &options->Socks5ProxyPort); + tt_assert(ret == 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks5://192.0.2.1:1080"); + tor_free(uri); + + /* Test with a SOCKS5 proxy, with username/password. */ + options->Socks5ProxyUsername = "hwest"; + options->Socks5ProxyPassword = "r34n1m470r"; + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks5://hwest:r34n1m470r@192.0.2.1:1080"); + tor_free(uri); + + options->Socks5Proxy = NULL; + + /* Test with a HTTPS proxy, no authenticator. */ + options->HTTPSProxy = "192.0.2.1:80"; + ret = tor_addr_port_lookup(options->HTTPSProxy, + &options->HTTPSProxyAddr, + &options->HTTPSProxyPort); + tt_assert(ret == 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "http://192.0.2.1:80"); + tor_free(uri); + + /* Test with a HTTPS proxy, with authenticator. */ + options->HTTPSProxyAuthenticator = "hwest:r34n1m470r"; + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "http://hwest:r34n1m470r@192.0.2.1:80"); + tor_free(uri); + + options->HTTPSProxy = NULL; + + /* Token nod to the fact that IPv6 exists. */ + options->Socks4Proxy = "[2001:db8::1]:1080"; + ret = tor_addr_port_lookup(options->Socks4Proxy, + &options->Socks4ProxyAddr, + &options->Socks4ProxyPort); + tt_assert(ret == 0); + uri = get_pt_proxy_uri(); + tt_str_op(uri, ==, "socks4a://[2001:db8::1]:1080"); + tor_free(uri); + + + done: + if (uri) + tor_free(uri); +} + + #define PT_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name } @@ -462,6 +541,8 @@ struct testcase_t pt_tests[] = { NULL, NULL }, { "configure_proxy",test_pt_configure_proxy, TT_FORK, NULL, NULL }, + { "get_pt_proxy_uri", test_get_pt_proxy_uri, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; From 7a18ac7454f16a2ac592312e041f9bb9f30cae31 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Mon, 14 Apr 2014 21:51:34 +0000 Subject: [PATCH 2/6] Fixed the test build with --enable-gcc-warnings --- src/test/test_pt.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/test_pt.c b/src/test/test_pt.c index 788d4205cc..cfbd084226 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -464,7 +464,7 @@ test_get_pt_proxy_uri(void *arg) tt_assert(uri == NULL); /* Test with a SOCKS4 proxy. */ - options->Socks4Proxy = "192.0.2.1:1080"; + options->Socks4Proxy = tor_strdup("192.0.2.1:1080"); ret = tor_addr_port_lookup(options->Socks4Proxy, &options->Socks4ProxyAddr, &options->Socks4ProxyPort); @@ -472,11 +472,10 @@ test_get_pt_proxy_uri(void *arg) uri = get_pt_proxy_uri(); tt_str_op(uri, ==, "socks4a://192.0.2.1:1080"); tor_free(uri); - - options->Socks4Proxy = NULL; + tor_free(options->Socks4Proxy); /* Test with a SOCKS5 proxy, no username/password. */ - options->Socks5Proxy = "192.0.2.1:1080"; + options->Socks5Proxy = tor_strdup("192.0.2.1:1080"); ret = tor_addr_port_lookup(options->Socks5Proxy, &options->Socks5ProxyAddr, &options->Socks5ProxyPort); @@ -486,16 +485,17 @@ test_get_pt_proxy_uri(void *arg) tor_free(uri); /* Test with a SOCKS5 proxy, with username/password. */ - options->Socks5ProxyUsername = "hwest"; - options->Socks5ProxyPassword = "r34n1m470r"; + options->Socks5ProxyUsername = tor_strdup("hwest"); + options->Socks5ProxyPassword = tor_strdup("r34n1m470r"); uri = get_pt_proxy_uri(); tt_str_op(uri, ==, "socks5://hwest:r34n1m470r@192.0.2.1:1080"); tor_free(uri); - - options->Socks5Proxy = NULL; + tor_free(options->Socks5Proxy); + tor_free(options->Socks5ProxyUsername); + tor_free(options->Socks5ProxyPassword); /* Test with a HTTPS proxy, no authenticator. */ - options->HTTPSProxy = "192.0.2.1:80"; + options->HTTPSProxy = tor_strdup("192.0.2.1:80"); ret = tor_addr_port_lookup(options->HTTPSProxy, &options->HTTPSProxyAddr, &options->HTTPSProxyPort); @@ -505,15 +505,15 @@ test_get_pt_proxy_uri(void *arg) tor_free(uri); /* Test with a HTTPS proxy, with authenticator. */ - options->HTTPSProxyAuthenticator = "hwest:r34n1m470r"; + options->HTTPSProxyAuthenticator = tor_strdup("hwest:r34n1m470r"); uri = get_pt_proxy_uri(); tt_str_op(uri, ==, "http://hwest:r34n1m470r@192.0.2.1:80"); tor_free(uri); - - options->HTTPSProxy = NULL; + tor_free(options->HTTPSProxy); + tor_free(options->HTTPSProxyAuthenticator); /* Token nod to the fact that IPv6 exists. */ - options->Socks4Proxy = "[2001:db8::1]:1080"; + options->Socks4Proxy = tor_strdup("[2001:db8::1]:1080"); ret = tor_addr_port_lookup(options->Socks4Proxy, &options->Socks4ProxyAddr, &options->Socks4ProxyPort); @@ -521,7 +521,7 @@ test_get_pt_proxy_uri(void *arg) uri = get_pt_proxy_uri(); tt_str_op(uri, ==, "socks4a://[2001:db8::1]:1080"); tor_free(uri); - + tor_free(options->Socks4Proxy); done: if (uri) From cd56b1a86ea255ba4bfc77959a88bfcd616ef516 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 1 May 2014 03:30:09 +0000 Subject: [PATCH 3/6] Remove get_bridge_pt_addrport(). The code was not disambiguating ClientTransportPlugin configured and not used, and ClientTransportPlugin configured, but in a failed state. The right thing to do is to undo moving the get_transport_by_addrport() call back into get_proxy_addrport(), and remove and explicit check for using a Bridge since by the time the check is made, if a Bridge is being used, it is PT/proxy-less. --- src/or/connection.c | 46 ++++++++++++--------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/src/or/connection.c b/src/or/connection.c index b32cddf1f1..ff8cdf1b4a 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -86,8 +86,6 @@ 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); -static int get_bridge_pt_addrport(tor_addr_t *addr, uint16_t *port, - int *proxy_type, const connection_t *conn); /** 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. @@ -4772,35 +4770,6 @@ assert_connection_ok(connection_t *conn, time_t now) } } -/** Fills addr and port with the details of the global - * pluggable transport or bridge we are using. - * conn contains the connection we are using the PT/bridge for. - * - * Return 0 on success, -1 on failure. - */ -static int -get_bridge_pt_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, - const connection_t *conn) -{ - const or_options_t *options = get_options(); - - if (options->ClientTransportPlugin || options->Bridges) { - const transport_t *transport = NULL; - int r; - r = get_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; - } - } - - return -1; -} - /** Fills addr and port with the details of the global * proxy server we are using. * conn contains the connection we are using the proxy for. @@ -4819,8 +4788,19 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, * the config to have unused ClientTransportPlugin entries. */ if (options->ClientTransportPlugin) { - if (get_bridge_pt_addrport(addr, port, proxy_type, conn) == 0) + const transport_t *transport = NULL; + int r; + r = get_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) { @@ -4838,8 +4818,6 @@ 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->Bridges) { - return get_bridge_pt_addrport(addr, port, proxy_type, conn); } tor_addr_make_unspec(addr); From 1210bdf146d707e3166c9ce881fdee67e5fa32ac Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 1 May 2014 03:43:53 +0000 Subject: [PATCH 4/6] Log the correct proxy type on failure. get_proxy_addrport fills in proxy_type with the correct value, so there is no point in logging something that's a "best guess" based off the config. --- src/or/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/connection.c b/src/or/connection.c index ff8cdf1b4a..5069ed6412 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -4841,7 +4841,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)); } From 60ac9f1c90f6036356f778513f0eb3e2f9760fa3 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 1 May 2014 18:58:53 +0000 Subject: [PATCH 5/6] 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 b810315d57..eee159d374 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -805,7 +805,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; } From cae44838fecc550f2df16de44b0ef297ecb509a6 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Tue, 9 Sep 2014 18:21:19 +0000 Subject: [PATCH 6/6] Fix issues brought up in nickm's review. * Update pt_get_proxy_uri() documentation. * proxy_supported is now unsigned. * Added a changes file. --- changes/bug8402 | 5 +++++ src/or/transports.c | 4 +++- src/or/transports.h | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 changes/bug8402 diff --git a/changes/bug8402 b/changes/bug8402 new file mode 100644 index 0000000000..96a3084ecf --- /dev/null +++ b/changes/bug8402 @@ -0,0 +1,5 @@ + o Major features (bridges): + - Expose the outgoing upstream HTTP/SOCKS proxy to pluggable + transports if they are configured via the "TOR_PT_PROXY" + enviorment variable. Implements proposal 232. Resolves + ticket 8402. diff --git a/src/or/transports.c b/src/or/transports.c index eee159d374..8dc2cfd4bd 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -754,7 +754,9 @@ managed_proxy_destroy(managed_proxy_t *mp, tor_free(mp); } -/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. */ +/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. + * Return a newly allocated string containing the URI, or NULL if no + * proxy is set. */ STATIC char * get_pt_proxy_uri(void) { diff --git a/src/or/transports.h b/src/or/transports.h index bc2331d01b..25fe5a29a9 100644 --- a/src/or/transports.h +++ b/src/or/transports.h @@ -82,7 +82,7 @@ typedef struct { 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 */ + unsigned int proxy_supported : 1; /* the proxy honors TOR_PT_PROXY */ int is_server; /* is it a server proxy? */