tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

transport_config.c (9985B)


      1 /* Copyright (c) 2001 Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * @file transport_config.c
      9 * @brief Code to interpret the user's configuration of Tor's server
     10 *        pluggable transports.
     11 **/
     12 
     13 #include "orconfig.h"
     14 #define RELAY_TRANSPORT_CONFIG_PRIVATE
     15 #include "feature/relay/transport_config.h"
     16 
     17 #include "lib/encoding/confline.h"
     18 #include "lib/encoding/keyval.h"
     19 
     20 #include "lib/container/smartlist.h"
     21 
     22 /* Required for dirinfo_type_t in or_options_t */
     23 #include "core/or/or.h"
     24 #include "app/config/config.h"
     25 
     26 #include "feature/relay/ext_orport.h"
     27 #include "feature/relay/routermode.h"
     28 
     29 /* Copied from config.c, we will refactor later in 29211. */
     30 #define REJECT(arg) \
     31  STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
     32 
     33 /** Given a ServerTransportListenAddr <b>line</b>, return its
     34 *  <address:port> string. Return NULL if the line was not
     35 *  well-formed.
     36 *
     37 *  If <b>transport</b> is set, return NULL if the line is not
     38 *  referring to <b>transport</b>.
     39 *
     40 *  The returned string is allocated on the heap and it's the
     41 *  responsibility of the caller to free it. */
     42 static char *
     43 get_bindaddr_from_transport_listen_line(const char *line,
     44                                        const char *transport)
     45 {
     46  smartlist_t *items = NULL;
     47  const char *parsed_transport = NULL;
     48  char *addrport = NULL;
     49  tor_addr_t addr;
     50  uint16_t port = 0;
     51 
     52  items = smartlist_new();
     53  smartlist_split_string(items, line, NULL,
     54                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
     55 
     56  if (smartlist_len(items) < 2) {
     57    log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
     58    goto err;
     59  }
     60 
     61  parsed_transport = smartlist_get(items, 0);
     62  addrport = tor_strdup(smartlist_get(items, 1));
     63 
     64  /* If 'transport' is given, check if it matches the one on the line */
     65  if (transport && strcmp(transport, parsed_transport))
     66    goto err;
     67 
     68  /* Validate addrport */
     69  if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
     70    log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
     71             "address '%s'", addrport);
     72    goto err;
     73  }
     74 
     75  goto done;
     76 
     77 err:
     78  tor_free(addrport);
     79  addrport = NULL;
     80 
     81 done:
     82  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
     83  smartlist_free(items);
     84 
     85  return addrport;
     86 }
     87 
     88 /** Given the name of a pluggable transport in <b>transport</b>, check
     89 *  the configuration file to see if the user has explicitly asked for
     90 *  it to listen on a specific port. Return a <address:port> string if
     91 *  so, otherwise NULL. */
     92 char *
     93 pt_get_bindaddr_from_config(const char *transport)
     94 {
     95  config_line_t *cl;
     96  const or_options_t *options = get_options();
     97 
     98  for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
     99    char *bindaddr =
    100      get_bindaddr_from_transport_listen_line(cl->value, transport);
    101    if (bindaddr)
    102      return bindaddr;
    103  }
    104 
    105  return NULL;
    106 }
    107 
    108 /** Given a ServerTransportOptions <b>line</b>, return a smartlist
    109 *  with the options. Return NULL if the line was not well-formed.
    110 *
    111 *  If <b>transport</b> is set, return NULL if the line is not
    112 *  referring to <b>transport</b>.
    113 *
    114 *  The returned smartlist and its strings are allocated on the heap
    115 *  and it's the responsibility of the caller to free it. */
    116 STATIC smartlist_t *
    117 get_options_from_transport_options_line(const char *line,
    118                                        const char *transport)
    119 {
    120  smartlist_t *items = smartlist_new();
    121  smartlist_t *pt_options = smartlist_new();
    122  const char *parsed_transport = NULL;
    123 
    124  smartlist_split_string(items, line, NULL,
    125                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    126 
    127  if (smartlist_len(items) < 2) {
    128    log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
    129    goto err;
    130  }
    131 
    132  parsed_transport = smartlist_get(items, 0);
    133  /* If 'transport' is given, check if it matches the one on the line */
    134  if (transport && strcmp(transport, parsed_transport))
    135    goto err;
    136 
    137  SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
    138    if (option_sl_idx == 0) /* skip the transport field (first field)*/
    139      continue;
    140 
    141    /* validate that it's a k=v value */
    142    if (!string_is_key_value(LOG_WARN, option)) {
    143      log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
    144      goto err;
    145    }
    146 
    147    /* add it to the options smartlist */
    148    smartlist_add_strdup(pt_options, option);
    149    log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
    150  } SMARTLIST_FOREACH_END(option);
    151 
    152  goto done;
    153 
    154 err:
    155  SMARTLIST_FOREACH(pt_options, char*, s, tor_free(s));
    156  smartlist_free(pt_options);
    157  pt_options = NULL;
    158 
    159 done:
    160  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    161  smartlist_free(items);
    162 
    163  return pt_options;
    164 }
    165 
    166 /** Given the name of a pluggable transport in <b>transport</b>, check
    167 *  the configuration file to see if the user has asked us to pass any
    168 *  parameters to the pluggable transport. Return a smartlist
    169 *  containing the parameters, otherwise NULL. */
    170 smartlist_t *
    171 pt_get_options_for_server_transport(const char *transport)
    172 {
    173  config_line_t *cl;
    174  const or_options_t *options = get_options();
    175 
    176  for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
    177    smartlist_t *options_sl =
    178      get_options_from_transport_options_line(cl->value, transport);
    179    if (options_sl)
    180      return options_sl;
    181  }
    182 
    183  return NULL;
    184 }
    185 
    186 /**
    187 * Legacy validation/normalization function for the server transport options.
    188 * Uses old_options as the previous options.
    189 *
    190 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
    191 * on error.
    192 */
    193 int
    194 options_validate_server_transport(const or_options_t *old_options,
    195                                  or_options_t *options,
    196                                  char **msg)
    197 {
    198  (void)old_options;
    199 
    200  if (BUG(!options))
    201    return -1;
    202 
    203  if (BUG(!msg))
    204    return -1;
    205 
    206  config_line_t *cl;
    207 
    208  if (options->ServerTransportPlugin && !server_mode(options)) {
    209    log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
    210               " a ServerTransportPlugin line (%s). The ServerTransportPlugin "
    211               "line will be ignored.",
    212               escaped(options->ServerTransportPlugin->value));
    213  }
    214 
    215  if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
    216    log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
    217               "specify a transport listen address. The "
    218               "ServerTransportListenAddr line will be ignored.");
    219  }
    220 
    221  for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
    222    if (pt_parse_transport_line(options, cl->value, 1, 1) < 0)
    223      REJECT("Invalid server transport line. See logs for details.");
    224  }
    225 
    226  for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
    227    /** If get_bindaddr_from_transport_listen_line() fails with
    228        'transport' being NULL, it means that something went wrong
    229        while parsing the ServerTransportListenAddr line. */
    230    char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
    231    if (!bindaddr)
    232      REJECT("ServerTransportListenAddr did not parse. See logs for details.");
    233    tor_free(bindaddr);
    234  }
    235 
    236  for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
    237    /** If get_options_from_transport_options_line() fails with
    238        'transport' being NULL, it means that something went wrong
    239        while parsing the ServerTransportOptions line. */
    240    smartlist_t *options_sl =
    241      get_options_from_transport_options_line(cl->value, NULL);
    242    if (!options_sl)
    243      REJECT("ServerTransportOptions did not parse. See logs for details.");
    244 
    245    SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
    246    smartlist_free(options_sl);
    247  }
    248 
    249  return 0;
    250 }
    251 
    252 /** Fetch the active option list, and take server pluggable transport actions
    253 * based on it. All of the things we do should survive being done repeatedly.
    254 * If present, <b>old_options</b> contains the previous value of the options.
    255 *
    256 * Return 0 if all goes well, return -1 if it's time to die.
    257 *
    258 * Note: We haven't moved all the "act on new configuration" logic
    259 * into the options_act* functions yet.  Some is still in do_hup() and other
    260 * places.
    261 */
    262 int
    263 options_act_server_transport(const or_options_t *old_options)
    264 {
    265  (void)old_options;
    266 
    267  config_line_t *cl;
    268  const or_options_t *options = get_options();
    269  int running_tor = options->command == CMD_RUN_TOR;
    270 
    271  /* If we are a bridge with a pluggable transport proxy but no
    272     Extended ORPort, inform the user that they are missing out. */
    273  if (options->ServerTransportPlugin &&
    274      !options->ExtORPort_lines) {
    275    log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
    276               "ORPort is disabled. Tor and your pluggable transports proxy "
    277               "communicate with each other via the Extended ORPort so it "
    278               "is suggested you enable it: it will also allow your Bridge "
    279               "to collect statistics about its clients that use pluggable "
    280               "transports. Please enable it using the ExtORPort torrc option "
    281               "(e.g. set 'ExtORPort auto').");
    282  }
    283 
    284  /* If we have an ExtORPort, initialize its auth cookie. */
    285  if (running_tor &&
    286      init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
    287    log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
    288    return -1;
    289  }
    290 
    291  if (!options->DisableNetwork) {
    292    if (options->ServerTransportPlugin) {
    293      for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
    294        if (pt_parse_transport_line(options, cl->value, 0, 1) < 0) {
    295          // LCOV_EXCL_START
    296          log_warn(LD_BUG,
    297                   "Previously validated ServerTransportPlugin line "
    298                   "could not be added!");
    299          return -1;
    300          // LCOV_EXCL_STOP
    301        }
    302      }
    303    }
    304  }
    305 
    306  return 0;
    307 }