Ticket #8402: 0001-Allow-ClientTransportPlugins-to-use-proxies_ver2.patch

File 0001-Allow-ClientTransportPlugins-to-use-proxies_ver2.patch, 14.0 KB (added by yawning, 6 years ago)

Version 2 of the patch that supports SIGHUP

  • src/or/config.c

    From 61bea59e46f043ff457d4cbee273ea1e82080f2e Mon Sep 17 00:00:00 2001
    From: Yawning Angel <yawning@schwanenlied.me>
    Date: Thu, 20 Mar 2014 02:40:10 +0000
    Subject: [PATCH] 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.
    ---
     src/or/config.c     |  24 +++++++----
     src/or/connection.c |  32 ++++++++++++---
     src/or/transports.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++--
     src/or/transports.h |   4 ++
     4 files changed, 157 insertions(+), 16 deletions(-)
    
    diff --git a/src/or/config.c b/src/or/config.c
    index 19a91ca..7140cad 100644
    a b static int options_transition_affects_descriptor( 
    535535      const or_options_t *old_options, const or_options_t *new_options);
    536536static int check_nickname_list(char **lst, const char *name, char **msg);
    537537
    538 static int parse_client_transport_line(const char *line, int validate_only);
     538static int parse_client_transport_line(const or_options_t *options,
     539                                       const char *line,
     540                                       int validate_only);
    539541
    540542static int parse_server_transport_line(const char *line, int validate_only);
    541543static char *get_bindaddr_from_transport_listen_line(const char *line,
    options_act(const or_options_t *old_options) 
    14001402  pt_prepare_proxy_list_for_config_read();
    14011403  if (options->ClientTransportPlugin) {
    14021404    for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
    1403       if (parse_client_transport_line(cl->value, 0)<0) {
     1405      if (parse_client_transport_line(options, cl->value, 0)<0) {
    14041406        log_warn(LD_BUG,
    14051407                 "Previously validated ClientTransportPlugin line "
    14061408                 "could not be added!");
    options_validate(or_options_t *old_options, or_options_t *options, 
    31233125    }
    31243126  }
    31253127
    3126   /* Check if more than one proxy type has been enabled. */
     3128  /* Check if more than one exclusive proxy type has been enabled. */
    31273129  if (!!options->Socks4Proxy + !!options->Socks5Proxy +
    3128       !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
     3130      !!options->HTTPSProxy > 1)
    31293131    REJECT("You have configured more than one proxy type. "
    3130            "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
     3132           "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
    31313133
    31323134  /* Check if the proxies will give surprising behavior. */
    31333135  if (options->HTTPProxy && !(options->Socks4Proxy ||
    options_validate(or_options_t *old_options, or_options_t *options, 
    32403242  }
    32413243
    32423244  for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
    3243     if (parse_client_transport_line(cl->value, 1)<0)
     3245    if (parse_client_transport_line(options, cl->value, 1)<0)
    32443246      REJECT("Transport line did not parse. See logs for details.");
    32453247  }
    32463248
    parse_bridge_line(const char *line) 
    46124614 * our internal transport list.
    46134615 * - If it's a managed proxy line, launch the managed proxy. */
    46144616static int
    4615 parse_client_transport_line(const char *line, int validate_only)
     4617parse_client_transport_line(const or_options_t *options, const char *line,
     4618                            int validate_only)
    46164619{
    46174620  smartlist_t *items = NULL;
    46184621  int r;
    parse_client_transport_line(const char *line, int validate_only) 
    47034706      pt_kickstart_client_proxy(transport_list, proxy_argv);
    47044707    }
    47054708  } else { /* external */
     4709    /* ClientTransportPlugins connecting through a proxy is managed only. */
     4710    if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
     4711      log_warn(LD_CONFIG, "You have configured an external proxy with another "
     4712                          "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
     4713      goto err;
     4714    }
     4715
    47064716    if (smartlist_len(transport_list) != 1) {
    47074717      log_warn(LD_CONFIG, "You can't have an external proxy with "
    47084718               "more than one transports.");
  • src/or/connection.c

    diff --git a/src/or/connection.c b/src/or/connection.c
    index 1994416..ac51f24 100644
    a b get_proxy_type(void) 
    16711671{
    16721672  const or_options_t *options = get_options();
    16731673
    1674   if (options->HTTPSProxy)
     1674  if (options->ClientTransportPlugin)
     1675    return PROXY_PLUGGABLE;
     1676  else if (options->HTTPSProxy)
    16751677    return PROXY_CONNECT;
    16761678  else if (options->Socks4Proxy)
    16771679    return PROXY_SOCKS4;
    16781680  else if (options->Socks5Proxy)
    16791681    return PROXY_SOCKS5;
    1680   else if (options->ClientTransportPlugin)
    1681     return PROXY_PLUGGABLE;
    16821682  else
    16831683    return PROXY_NONE;
    16841684}
    get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, 
    47454745{
    47464746  const or_options_t *options = get_options();
    47474747
     4748  /* Client Transport Plugins can use another proxy, but that should be hidden
     4749   * from the rest of tor (as the plugin is responsible for dealing with the
     4750   * proxy), check it first, then check the rest of the proxy types to allow
     4751   * the config to have unused ClientTransportPlugin entries.
     4752   *
     4753   * Yes, this duplicates code with the Bridge case, but this needs to be
     4754   * checked first, and Bridges need to be checked last (Connect to a bridge
     4755   * over a proxy).
     4756   */
     4757  if (options->ClientTransportPlugin) {
     4758    const transport_t *transport = NULL;
     4759    int r;
     4760    r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
     4761    if (r<0)
     4762      return -1;
     4763    if (transport) { /* transport found */
     4764      tor_addr_copy(addr, &transport->addr);
     4765      *port = transport->port;
     4766      *proxy_type = transport->socks_version;
     4767      return 0;
     4768    }
     4769  }
     4770
    47484771  if (options->HTTPSProxy) {
    47494772    tor_addr_copy(addr, &options->HTTPSProxyAddr);
    47504773    *port = options->HTTPSProxyPort;
    get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, 
    47604783    *port = options->Socks5ProxyPort;
    47614784    *proxy_type = PROXY_SOCKS5;
    47624785    return 0;
    4763   } else if (options->ClientTransportPlugin ||
    4764              options->Bridges) {
     4786  } else if (options->Bridges) {
    47654787    const transport_t *transport = NULL;
    47664788    int r;
    47674789    r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
  • src/or/transports.c

    diff --git a/src/or/transports.c b/src/or/transports.c
    index 8b4a118..a4f2da3 100644
    a b create_managed_proxy_environment(const managed_proxy_t *mp); 
    105105
    106106static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
    107107
     108static char *get_pt_proxy_uri(void);
    108109static void handle_finished_proxy(managed_proxy_t *mp);
    109110static void parse_method_error(const char *line, int is_server_method);
    110111#define parse_server_method_error(l) parse_method_error(l, 1)
    static INLINE void free_execve_args(char **arg); 
    122123#define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
    123124#define PROTO_CMETHODS_DONE "CMETHODS DONE"
    124125#define PROTO_SMETHODS_DONE "SMETHODS DONE"
     126#define PROTO_PROXY_TRUE "PROXY true"
     127#define PROTO_PROXY_ERROR "PROXY-ERROR"
    125128
    126129/** The first and only supported - at the moment - configuration
    127130    protocol version. */
    add_transport_to_proxy(const char *transport, managed_proxy_t *mp) 
    437440static int
    438441proxy_needs_restart(const managed_proxy_t *mp)
    439442{
     443  int ret = 1;
     444  char* proxy_uri;
     445
     446  /* If the PT proxy config has changed, then all existing pluggable transports
     447   * should be restarted.
     448   */
     449
     450  proxy_uri = get_pt_proxy_uri();
     451  if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
     452    goto needs_restart;
     453
    440454  /* mp->transport_to_launch is populated with the names of the
    441455     transports that must be launched *after* the SIGHUP.
    442456     mp->transports is populated with the transports that were
    proxy_needs_restart(const managed_proxy_t *mp) 
    457471
    458472  } SMARTLIST_FOREACH_END(t);
    459473
    460   return 0;
    461 
    462  needs_restart:
    463   return 1;
     474  ret = 0;
     475needs_restart:
     476  tor_free(proxy_uri);
     477  return ret;
    464478}
    465479
    466480/** Managed proxy <b>mp</b> must be restarted. Do all the necessary
    proxy_prepare_for_restart(managed_proxy_t *mp) 
    491505  SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
    492506  smartlist_clear(mp->transports);
    493507
     508  /* Reset the proxy's HTTPS/SOCKS proxy */
     509  tor_free(mp->proxy_uri);
     510  mp->proxy_uri = get_pt_proxy_uri();
     511  mp->acked_proxy = 0;
     512
    494513  /* flag it as an infant proxy so that it gets launched on next tick */
    495514  mp->conf_state = PT_PROTO_INFANT;
    496515  unconfigured_proxies_n++;
    managed_proxy_destroy(managed_proxy_t *mp, 
    725744  /* free the argv */
    726745  free_execve_args(mp->argv);
    727746
     747  /* free the outgoing proxy URI */
     748  tor_free(mp->proxy_uri);
     749
    728750  tor_process_handle_destroy(mp->process_handle, also_terminate_process);
    729751  mp->process_handle = NULL;
    730752
    731753  tor_free(mp);
    732754}
    733755
     756/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. */
     757static char *
     758get_pt_proxy_uri(void)
     759{
     760  const or_options_t *options = get_options();
     761  char *uri = NULL;
     762
     763  if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
     764    char addr[TOR_ADDR_BUF_LEN+1];
     765
     766    if (options->Socks4Proxy) {
     767      tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
     768      tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
     769    } else if (options->Socks5Proxy) {
     770      tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
     771      if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
     772        tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
     773      } else {
     774        tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
     775                     options->Socks5ProxyUsername,
     776                     options->Socks5ProxyPassword,
     777                     addr, options->Socks5ProxyPort);
     778      }
     779    } else if (options->HTTPSProxy) {
     780      tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
     781      if (!options->HTTPSProxyAuthenticator) {
     782        tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
     783      } else {
     784        tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
     785                     addr, options->HTTPSProxyPort);
     786      }
     787    }
     788  }
     789
     790  return uri;
     791}
     792
    734793/** Handle a configured or broken managed proxy <b>mp</b>. */
    735794static void
    736795handle_finished_proxy(managed_proxy_t *mp)
    handle_finished_proxy(managed_proxy_t *mp) 
    743802    managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
    744803    break;
    745804  case PT_PROTO_CONFIGURED: /* if configured correctly: */
     805    if (mp->proxy_uri && !mp->acked_proxy) {
     806      log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
     807               "specified outgoing proxy.", mp->argv[0]);
     808      managed_proxy_destroy(mp, 1); /* annihilate it. */
     809      break;
     810    }
    746811    register_proxy(mp); /* register its transports */
    747812    mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
    748813    break;
    handle_proxy_line(const char *line, managed_proxy_t *mp) 
    860925      goto err;
    861926
    862927    return;
     928  } else if (!strcmpstart(line, PROTO_PROXY_TRUE)) {
     929    if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
     930      goto err;
     931
     932    if (mp->proxy_uri) {
     933      mp->acked_proxy = 1;
     934      return;
     935    }
     936
     937    /* No proxy was configured, this should log */
     938  } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
     939    if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
     940      goto err;
     941
     942    parse_proxy_error(line);
     943    goto err;
    863944  } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) {
    864945    /* managed proxy launch failed: parse error message to learn why. */
    865946    int retval, child_state, saved_errno;
    parse_cmethod_line(const char *line, managed_proxy_t *mp) 
    11261207  return r;
    11271208}
    11281209
     1210/** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
     1211STATIC void
     1212parse_proxy_error(const char *line)
     1213{
     1214  /* (Length of the protocol string) plus (a space) and (the first char of
     1215     the error message) */
     1216  if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
     1217    log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
     1218               "message.", PROTO_PROXY_ERROR);
     1219
     1220  log_warn(LD_CONFIG, "Managed proxy failed to configure the "
     1221           "pluggable transport's outgoing proxy. (%s)",
     1222           line+strlen(PROTO_PROXY_ERROR)+1);
     1223}
     1224
    11291225/** Return a newly allocated string that tor should place in
    11301226 * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
    11311227 * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
    create_managed_proxy_environment(const managed_proxy_t *mp) 
    12861382    } else {
    12871383      smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
    12881384    }
     1385  } else {
     1386    /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
     1387     * TOR_PT_PROXY line.
     1388     */
     1389
     1390    if (mp->proxy_uri) {
     1391      smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
     1392    }
    12891393  }
    12901394
    12911395  SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
    managed_proxy_create(const smartlist_t *transport_list, 
    13181422  mp->is_server = is_server;
    13191423  mp->argv = proxy_argv;
    13201424  mp->transports = smartlist_new();
     1425  mp->proxy_uri = get_pt_proxy_uri();
    13211426
    13221427  mp->transports_to_launch = smartlist_new();
    13231428  SMARTLIST_FOREACH(transport_list, const char *, transport,
  • src/or/transports.h

    diff --git a/src/or/transports.h b/src/or/transports.h
    index 7b524f2..f988a98 100644
    a b typedef struct { 
    8181  char **argv; /* the cli arguments of this proxy */
    8282  int conf_protocol; /* the configuration protocol version used */
    8383
     84  char *proxy_uri;  /* the outgoing proxy in TOR_PT_PROXY URI format */
     85  int acked_proxy : 1; /* the proxy claims to honor TOR_PT_PROXY */
     86
    8487  int is_server; /* is it a server proxy? */
    8588
    8689  /* A pointer to the process handle of this managed proxy. */
    STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp); 
    112115
    113116STATIC int parse_version(const char *line, managed_proxy_t *mp);
    114117STATIC void parse_env_error(const char *line);
     118STATIC void parse_proxy_error(const char *line);
    115119STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp);
    116120STATIC char *get_transport_options_for_server_proxy(const managed_proxy_t *mp);
    117121