LCOV - code coverage report
Current view: top level - feature/relay - transport_config.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 100 113 88.5 %
Date: 2021-11-24 03:28:48 Functions: 5 6 83.3 %

          Line data    Source code
       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           8 : get_bindaddr_from_transport_listen_line(const char *line,
      44             :                                         const char *transport)
      45             : {
      46           8 :   smartlist_t *items = NULL;
      47           8 :   const char *parsed_transport = NULL;
      48           8 :   char *addrport = NULL;
      49           8 :   tor_addr_t addr;
      50           8 :   uint16_t port = 0;
      51             : 
      52           8 :   items = smartlist_new();
      53           8 :   smartlist_split_string(items, line, NULL,
      54             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
      55             : 
      56           8 :   if (smartlist_len(items) < 2) {
      57           1 :     log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
      58           1 :     goto err;
      59             :   }
      60             : 
      61           7 :   parsed_transport = smartlist_get(items, 0);
      62           7 :   addrport = tor_strdup(smartlist_get(items, 1));
      63             : 
      64             :   /* If 'transport' is given, check if it matches the one on the line */
      65           7 :   if (transport && strcmp(transport, parsed_transport))
      66           0 :     goto err;
      67             : 
      68             :   /* Validate addrport */
      69           7 :   if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
      70           1 :     log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
      71             :              "address '%s'", addrport);
      72           1 :     goto err;
      73             :   }
      74             : 
      75           6 :   goto done;
      76             : 
      77           2 :  err:
      78           2 :   tor_free(addrport);
      79           2 :   addrport = NULL;
      80             : 
      81           8 :  done:
      82          23 :   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
      83           8 :   smartlist_free(items);
      84             : 
      85           8 :   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           0 : pt_get_bindaddr_from_config(const char *transport)
      94             : {
      95           0 :   config_line_t *cl;
      96           0 :   const or_options_t *options = get_options();
      97             : 
      98           0 :   for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
      99           0 :     char *bindaddr =
     100           0 :       get_bindaddr_from_transport_listen_line(cl->value, transport);
     101           0 :     if (bindaddr)
     102           0 :       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          20 : get_options_from_transport_options_line(const char *line,
     118             :                                         const char *transport)
     119             : {
     120          20 :   smartlist_t *items = smartlist_new();
     121          20 :   smartlist_t *pt_options = smartlist_new();
     122          20 :   const char *parsed_transport = NULL;
     123             : 
     124          20 :   smartlist_split_string(items, line, NULL,
     125             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
     126             : 
     127          20 :   if (smartlist_len(items) < 2) {
     128           2 :     log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
     129           2 :     goto err;
     130             :   }
     131             : 
     132          18 :   parsed_transport = smartlist_get(items, 0);
     133             :   /* If 'transport' is given, check if it matches the one on the line */
     134          18 :   if (transport && strcmp(transport, parsed_transport))
     135           7 :     goto err;
     136             : 
     137          35 :   SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
     138          26 :     if (option_sl_idx == 0) /* skip the transport field (first field)*/
     139          11 :       continue;
     140             : 
     141             :     /* validate that it's a k=v value */
     142          15 :     if (!string_is_key_value(LOG_WARN, option)) {
     143           2 :       log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
     144           2 :       goto err;
     145             :     }
     146             : 
     147             :     /* add it to the options smartlist */
     148          13 :     smartlist_add_strdup(pt_options, option);
     149          13 :     log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
     150          24 :   } SMARTLIST_FOREACH_END(option);
     151             : 
     152           9 :   goto done;
     153             : 
     154          11 :  err:
     155          11 :   SMARTLIST_FOREACH(pt_options, char*, s, tor_free(s));
     156          11 :   smartlist_free(pt_options);
     157          11 :   pt_options = NULL;
     158             : 
     159          20 :  done:
     160          68 :   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
     161          20 :   smartlist_free(items);
     162             : 
     163          20 :   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           3 : pt_get_options_for_server_transport(const char *transport)
     172             : {
     173           3 :   config_line_t *cl;
     174           3 :   const or_options_t *options = get_options();
     175             : 
     176           9 :   for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
     177           8 :     smartlist_t *options_sl =
     178           8 :       get_options_from_transport_options_line(cl->value, transport);
     179           8 :     if (options_sl)
     180           2 :       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         447 : options_validate_server_transport(const or_options_t *old_options,
     195             :                                   or_options_t *options,
     196             :                                   char **msg)
     197             : {
     198         447 :   (void)old_options;
     199             : 
     200         447 :   if (BUG(!options))
     201           0 :     return -1;
     202             : 
     203         447 :   if (BUG(!msg))
     204           0 :     return -1;
     205             : 
     206         447 :   config_line_t *cl;
     207             : 
     208         447 :   if (options->ServerTransportPlugin && !server_mode(options)) {
     209          11 :     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         447 :   if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
     216           2 :     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         466 :   for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
     222          20 :     if (pt_parse_transport_line(options, cl->value, 1, 1) < 0)
     223           1 :       REJECT("Invalid server transport line. See logs for details.");
     224             :   }
     225             : 
     226         452 :   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           8 :     char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
     231           8 :     if (!bindaddr)
     232           2 :       REJECT("ServerTransportListenAddr did not parse. See logs for details.");
     233           6 :     tor_free(bindaddr);
     234             :   }
     235             : 
     236         449 :   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          14 :     smartlist_t *options_sl =
     241           7 :       get_options_from_transport_options_line(cl->value, NULL);
     242           7 :     if (!options_sl)
     243           2 :       REJECT("ServerTransportOptions did not parse. See logs for details.");
     244             : 
     245          10 :     SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
     246           5 :     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         213 : options_act_server_transport(const or_options_t *old_options)
     264             : {
     265         213 :   (void)old_options;
     266             : 
     267         213 :   config_line_t *cl;
     268         213 :   const or_options_t *options = get_options();
     269         213 :   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         213 :   if (options->ServerTransportPlugin &&
     274          15 :       !options->ExtORPort_lines) {
     275           3 :     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         217 :   if (running_tor &&
     286           4 :       init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
     287           0 :     log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
     288           0 :     return -1;
     289             :   }
     290             : 
     291         213 :   if (!options->DisableNetwork) {
     292         175 :     if (options->ServerTransportPlugin) {
     293          30 :       for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
     294          15 :         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             : }

Generated by: LCOV version 1.14