Tor  0.4.7.0-alpha-dev
transport_config.c
Go to the documentation of this file.
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
16 
17 #include "lib/encoding/confline.h"
18 #include "lib/encoding/keyval.h"
19 
21 
22 /* Required for dirinfo_type_t in or_options_t */
23 #include "core/or/or.h"
24 #include "app/config/config.h"
25 
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 *
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. */
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 *
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
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 =
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
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 }
int tor_addr_port_parse(int severity, const char *addrport, tor_addr_t *address_out, uint16_t *port_out, int default_port)
Definition: address.c:1857
int pt_parse_transport_line(const or_options_t *options, const char *line, int validate_only, int server)
Definition: config.c:5275
const or_options_t * get_options(void)
Definition: config.c:919
Header file for config.c.
Header for confline.c.
const char * escaped(const char *s)
Definition: escape.c:126
Header for ext_orport.c.
int string_is_key_value(int severity, const char *string)
Definition: keyval.c:25
Header for keyval.c.
#define LD_BUG
Definition: log.h:86
#define LD_GENERAL
Definition: log.h:62
#define LD_CONFIG
Definition: log.h:68
#define LOG_WARN
Definition: log.h:53
#define tor_free(p)
Definition: malloc.h:52
Master header file for Tor-specific functionality.
int server_mode(const or_options_t *options)
Definition: routermode.c:34
Header file for routermode.c.
Header for smartlist.c.
smartlist_t * smartlist_new(void)
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
struct config_line_t * ServerTransportOptions
struct config_line_t * ServerTransportListenAddr
struct config_line_t * ExtORPort_lines
struct config_line_t * ServerTransportPlugin
tor_cmdline_mode_t command
Definition: or_options_st.h:68
#define STATIC
Definition: testsupport.h:32
@ CMD_RUN_TOR
char * pt_get_bindaddr_from_config(const char *transport)
int options_act_server_transport(const or_options_t *old_options)
int options_validate_server_transport(const or_options_t *old_options, or_options_t *options, char **msg)
STATIC smartlist_t * get_options_from_transport_options_line(const char *line, const char *transport)
static char * get_bindaddr_from_transport_listen_line(const char *line, const char *transport)
smartlist_t * pt_get_options_for_server_transport(const char *transport)
Header for feature/relay/transport_config.c.