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 */
8 * @file transport_config.c
9 * @brief Code to interpret the user's configuration of Tor's server
10 * pluggable transports.
14 #define RELAY_TRANSPORT_CONFIG_PRIVATE
15 #include "feature/relay/transport_config.h"
17 #include "lib/encoding/confline.h"
18 #include "lib/encoding/keyval.h"
20 #include "lib/container/smartlist.h"
22 /* Required for dirinfo_type_t in or_options_t */
23 #include "core/or/or.h"
24 #include "app/config/config.h"
26 #include "feature/relay/ext_orport.h"
27 #include "feature/relay/routermode.h"
29 /* Copied from config.c, we will refactor later in 29211. */
31 STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
33 /** Given a ServerTransportListenAddr <b>line</b>, return its
34 * <address:port> string. Return NULL if the line was not
37 * If <b>transport</b> is set, return NULL if the line is not
38 * referring to <b>transport</b>.
40 * The returned string is allocated on the heap and it's the
41 * responsibility of the caller to free it. */
43 get_bindaddr_from_transport_listen_line(const char *line
,
44 const char *transport
)
46 smartlist_t
*items
= NULL
;
47 const char *parsed_transport
= NULL
;
48 char *addrport
= NULL
;
52 items
= smartlist_new();
53 smartlist_split_string(items
, line
, NULL
,
54 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
56 if (smartlist_len(items
) < 2) {
57 log_warn(LD_CONFIG
,"Too few arguments on ServerTransportListenAddr line.");
61 parsed_transport
= smartlist_get(items
, 0);
62 addrport
= tor_strdup(smartlist_get(items
, 1));
64 /* If 'transport' is given, check if it matches the one on the line */
65 if (transport
&& strcmp(transport
, parsed_transport
))
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
);
82 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
83 smartlist_free(items
);
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. */
93 pt_get_bindaddr_from_config(const char *transport
)
96 const or_options_t
*options
= get_options();
98 for (cl
= options
->ServerTransportListenAddr
; cl
; cl
= cl
->next
) {
100 get_bindaddr_from_transport_listen_line(cl
->value
, transport
);
108 /** Given a ServerTransportOptions <b>line</b>, return a smartlist
109 * with the options. Return NULL if the line was not well-formed.
111 * If <b>transport</b> is set, return NULL if the line is not
112 * referring to <b>transport</b>.
114 * The returned smartlist and its strings are allocated on the heap
115 * and it's the responsibility of the caller to free it. */
117 get_options_from_transport_options_line(const char *line
,
118 const char *transport
)
120 smartlist_t
*items
= smartlist_new();
121 smartlist_t
*pt_options
= smartlist_new();
122 const char *parsed_transport
= NULL
;
124 smartlist_split_string(items
, line
, NULL
,
125 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
127 if (smartlist_len(items
) < 2) {
128 log_warn(LD_CONFIG
,"Too few arguments on ServerTransportOptions line.");
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
))
137 SMARTLIST_FOREACH_BEGIN(items
, const char *, option
) {
138 if (option_sl_idx
== 0) /* skip the transport field (first field)*/
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
));
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
);
155 SMARTLIST_FOREACH(pt_options
, char*, s
, tor_free(s
));
156 smartlist_free(pt_options
);
160 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
161 smartlist_free(items
);
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. */
171 pt_get_options_for_server_transport(const char *transport
)
174 const or_options_t
*options
= get_options();
176 for (cl
= options
->ServerTransportOptions
; cl
; cl
= cl
->next
) {
177 smartlist_t
*options_sl
=
178 get_options_from_transport_options_line(cl
->value
, transport
);
187 * Legacy validation/normalization function for the server transport options.
188 * Uses old_options as the previous options.
190 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
194 options_validate_server_transport(const or_options_t
*old_options
,
195 or_options_t
*options
,
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
));
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.");
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.");
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
);
232 REJECT("ServerTransportListenAddr did not parse. See logs for details.");
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
);
243 REJECT("ServerTransportOptions did not parse. See logs for details.");
245 SMARTLIST_FOREACH(options_sl
, char *, cp
, tor_free(cp
));
246 smartlist_free(options_sl
);
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.
256 * Return 0 if all goes well, return -1 if it's time to die.
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
263 options_act_server_transport(const or_options_t
*old_options
)
268 const or_options_t
*options
= get_options();
269 int running_tor
= options
->command
== CMD_RUN_TOR
;
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').");
284 /* If we have an ExtORPort, initialize its auth cookie. */
286 init_ext_or_cookie_authentication(!!options
->ExtORPort_lines
) < 0) {
287 log_warn(LD_CONFIG
,"Error creating Extended ORPort cookie file.");
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) {
297 "Previously validated ServerTransportPlugin line "
298 "could not be added!");