Tor 0.4.9.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
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. */
42static 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. */
92char *
93pt_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. */
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 */
193int
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 */
262int
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:5308
const or_options_t * get_options(void)
Definition: config.c:944
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:56
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.
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
smartlist_t * smartlist_new(void)
#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
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)
int options_act_server_transport(const or_options_t *old_options)
STATIC smartlist_t * get_options_from_transport_options_line(const char *line, const char *transport)
char * pt_get_bindaddr_from_config(const char *transport)
int options_validate_server_transport(const or_options_t *old_options, or_options_t *options, char **msg)
Header for feature/relay/transport_config.c.