Line data Source code
1 : /* Copyright (c) 2011-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : /**
5 : * \file transports.c
6 : * \brief Pluggable Transports related code.
7 : *
8 : * \details
9 : * Each managed proxy is represented by a <b>managed_proxy_t</b>.
10 : * Each managed proxy can support multiple transports.
11 : * Each managed proxy gets configured through a multistep process.
12 : *
13 : * ::managed_proxy_list contains all the managed proxies this tor
14 : * instance is supporting.
15 : * In the ::managed_proxy_list there are ::unconfigured_proxies_n
16 : * managed proxies that are still unconfigured.
17 : *
18 : * In every run_scheduled_event() tick, we attempt to launch and then
19 : * configure the unconfigured managed proxies, using the configuration
20 : * protocol defined in the 180_pluggable_transport.txt proposal. A
21 : * managed proxy might need several ticks to get fully configured.
22 : *
23 : * When a managed proxy is fully configured, we register all its
24 : * transports to the circuitbuild.c subsystem. At that point the
25 : * transports are owned by the circuitbuild.c subsystem.
26 : *
27 : * When a managed proxy fails to follow the 180 configuration
28 : * protocol, it gets marked as broken and gets destroyed.
29 : *
30 : * <b>In a little more detail:</b>
31 : *
32 : * While we are serially parsing torrc, we store all the transports
33 : * that a proxy should spawn in its <em>transports_to_launch</em>
34 : * element.
35 : *
36 : * When we finish reading the torrc, we spawn the managed proxy and
37 : * expect {S,C}METHOD lines from its output. We add transports
38 : * described by METHOD lines to its <em>transports</em> element, as
39 : * transport_t structs.
40 : *
41 : * When the managed proxy stops spitting METHOD lines (signified by a
42 : * '{S,C}METHODS DONE' message) we pass copies of its transports to
43 : * the bridge subsystem. We keep copies of the 'transport_t's on the
44 : * managed proxy to be able to associate the proxy with its
45 : * transports, and we pass copies to the bridge subsystem so that
46 : * transports can be associated with bridges.
47 : * [ XXX We should try see whether the two copies are really needed
48 : * and maybe cut it into a single copy of the 'transport_t' shared
49 : * between the managed proxy and the bridge subsystem. Preliminary
50 : * analysis shows that both copies are needed with the current code
51 : * logic, because of race conditions that can cause dangling
52 : * pointers. ]
53 : *
54 : * <b>In even more detail, this is what happens when a config read
55 : * (like a SIGHUP or a SETCONF) occurs:</b>
56 : *
57 : * We immediately destroy all unconfigured proxies (We shouldn't have
58 : * unconfigured proxies in the first place, except when the config
59 : * read happens immediately after tor is launched.).
60 : *
61 : * We mark all managed proxies and transports to signify that they
62 : * must be removed if they don't contribute by the new torrc
63 : * (we mark using the <b>marked_for_removal</b> element).
64 : * We also mark all managed proxies to signify that they might need to
65 : * be restarted so that they end up supporting all the transports the
66 : * new torrc wants them to support
67 : * (we mark using the <b>was_around_before_config_read</b> element).
68 : * We also clear their <b>transports_to_launch</b> list so that we can
69 : * put there the transports we need to launch according to the new
70 : * torrc.
71 : *
72 : * We then start parsing torrc again.
73 : *
74 : * Every time we encounter a transport line using a managed proxy that
75 : * was around before the config read, we cleanse that proxy from the
76 : * removal mark. We also toggle the <b>check_if_restarts_needed</b>
77 : * flag, so that on the next <b>pt_configure_remaining_proxies</b>
78 : * tick, we investigate whether we need to restart the proxy so that
79 : * it also spawns the new transports. If the post-config-read
80 : * <b>transports_to_launch</b> list is identical to the pre-config-read
81 : * one, it means that no changes were introduced to this proxy during
82 : * the config read and no restart has to take place.
83 : *
84 : * During the post-config-read torrc parsing, we unmark all transports
85 : * spawned by managed proxies that we find in our torrc.
86 : * We do that so that if we don't need to restart a managed proxy, we
87 : * can continue using its old transports normally.
88 : * If we end up restarting the proxy, we destroy and unregister all
89 : * old transports from the circuitbuild.c subsystem.
90 : **/
91 :
92 : #define PT_PRIVATE
93 : #include "core/or/or.h"
94 : #include "feature/client/bridges.h"
95 : #include "app/config/config.h"
96 : #include "core/mainloop/connection.h"
97 : #include "core/or/circuitbuild.h"
98 : #include "feature/client/transports.h"
99 : #include "feature/relay/router.h"
100 : #include "feature/relay/relay_find_addr.h"
101 : /* 31851: split the server transport code out of the client module */
102 : #include "feature/relay/transport_config.h"
103 : #include "app/config/statefile.h"
104 : #include "core/or/connection_or.h"
105 : #include "feature/relay/ext_orport.h"
106 : #include "feature/control/control_events.h"
107 : #include "lib/encoding/confline.h"
108 : #include "lib/encoding/kvline.h"
109 :
110 : #include "lib/process/process.h"
111 : #include "lib/process/env.h"
112 :
113 : static smartlist_t *
114 : create_managed_proxy_environment(const managed_proxy_t *mp);
115 :
116 : static inline int proxy_configuration_finished(const managed_proxy_t *mp);
117 :
118 : static void handle_finished_proxy(managed_proxy_t *mp);
119 : static void parse_method_error(const char *line, int is_server_method);
120 : #define parse_server_method_error(l) parse_method_error(l, 1)
121 : #define parse_client_method_error(l) parse_method_error(l, 0)
122 :
123 : /** Managed proxy protocol strings */
124 : #define PROTO_ENV_ERROR "ENV-ERROR"
125 : #define PROTO_NEG_SUCCESS "VERSION"
126 : #define PROTO_NEG_FAIL "VERSION-ERROR no-version"
127 : #define PROTO_CMETHOD "CMETHOD"
128 : #define PROTO_SMETHOD "SMETHOD"
129 : #define PROTO_CMETHOD_ERROR "CMETHOD-ERROR"
130 : #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
131 : #define PROTO_CMETHODS_DONE "CMETHODS DONE"
132 : #define PROTO_SMETHODS_DONE "SMETHODS DONE"
133 : #define PROTO_PROXY_DONE "PROXY DONE"
134 : #define PROTO_PROXY_ERROR "PROXY-ERROR"
135 : #define PROTO_LOG "LOG"
136 : #define PROTO_STATUS "STATUS"
137 :
138 : /** The first and only supported - at the moment - configuration
139 : protocol version. */
140 : #define PROTO_VERSION_ONE 1
141 :
142 : /** A list of pluggable transports found in torrc. */
143 : static smartlist_t *transport_list = NULL;
144 :
145 : /** Returns a transport_t struct for a transport proxy supporting the
146 : protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
147 : SOCKS version <b>socks_ver</b>. */
148 : STATIC transport_t *
149 12 : transport_new(const tor_addr_t *addr, uint16_t port,
150 : const char *name, int socks_ver,
151 : const char *extra_info_args)
152 : {
153 12 : transport_t *t = tor_malloc_zero(sizeof(transport_t));
154 :
155 12 : tor_addr_copy(&t->addr, addr);
156 12 : t->port = port;
157 12 : t->name = tor_strdup(name);
158 12 : t->socks_version = socks_ver;
159 12 : if (extra_info_args)
160 3 : t->extra_info_args = tor_strdup(extra_info_args);
161 :
162 12 : return t;
163 : }
164 :
165 : /** Free the pluggable transport struct <b>transport</b>. */
166 : void
167 10 : transport_free_(transport_t *transport)
168 : {
169 10 : if (!transport)
170 : return;
171 :
172 10 : tor_free(transport->name);
173 10 : tor_free(transport->extra_info_args);
174 10 : tor_free(transport);
175 : }
176 :
177 : /** Mark every entry of the transport list to be removed on our next call to
178 : * sweep_transport_list unless it has first been un-marked. */
179 : void
180 214 : mark_transport_list(void)
181 : {
182 214 : if (!transport_list)
183 210 : transport_list = smartlist_new();
184 214 : SMARTLIST_FOREACH(transport_list, transport_t *, t,
185 : t->marked_for_removal = 1);
186 214 : }
187 :
188 : /** Remove every entry of the transport list that was marked with
189 : * mark_transport_list if it has not subsequently been un-marked. */
190 : void
191 213 : sweep_transport_list(void)
192 : {
193 213 : if (!transport_list)
194 0 : transport_list = smartlist_new();
195 213 : SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
196 0 : if (t->marked_for_removal) {
197 0 : SMARTLIST_DEL_CURRENT(transport_list, t);
198 0 : transport_free(t);
199 : }
200 0 : } SMARTLIST_FOREACH_END(t);
201 213 : }
202 :
203 : /** Initialize the pluggable transports list to empty, creating it if
204 : * needed. */
205 : static void
206 201 : clear_transport_list(void)
207 : {
208 201 : if (!transport_list)
209 0 : transport_list = smartlist_new();
210 201 : SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
211 201 : smartlist_clear(transport_list);
212 201 : }
213 :
214 : /** Return a deep copy of <b>transport</b>. */
215 : static transport_t *
216 0 : transport_copy(const transport_t *transport)
217 : {
218 0 : transport_t *new_transport = NULL;
219 :
220 0 : tor_assert(transport);
221 :
222 0 : new_transport = tor_malloc_zero(sizeof(transport_t));
223 :
224 0 : new_transport->socks_version = transport->socks_version;
225 0 : new_transport->name = tor_strdup(transport->name);
226 0 : tor_addr_copy(&new_transport->addr, &transport->addr);
227 0 : new_transport->port = transport->port;
228 0 : new_transport->marked_for_removal = transport->marked_for_removal;
229 :
230 0 : return new_transport;
231 : }
232 :
233 : /** Returns the transport in our transport list that has the name <b>name</b>.
234 : * Else returns NULL. */
235 1 : MOCK_IMPL(transport_t *,
236 : transport_get_by_name,(const char *name))
237 : {
238 1 : tor_assert(name);
239 :
240 1 : if (!transport_list)
241 : return NULL;
242 :
243 1 : SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
244 0 : if (!strcmp(transport->name, name))
245 0 : return transport;
246 0 : } SMARTLIST_FOREACH_END(transport);
247 :
248 : return NULL;
249 : }
250 :
251 : /** Resolve any conflicts that the insertion of transport <b>t</b>
252 : * might cause.
253 : * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
254 : * a transport identical to <b>t</b> already registered and -1 if
255 : * <b>t</b> cannot be added due to conflicts. */
256 : static int
257 0 : transport_resolve_conflicts(const transport_t *t)
258 : {
259 : /* This is how we resolve transport conflicts:
260 :
261 : If there is already a transport with the same name and addrport,
262 : we either have duplicate torrc lines OR we are here post-HUP and
263 : this transport was here pre-HUP as well. In any case, mark the
264 : old transport so that it doesn't get removed and ignore the new
265 : one. Our caller has to free the new transport so we return '1' to
266 : signify this.
267 :
268 : If there is already a transport with the same name but different
269 : addrport:
270 : * if it's marked for removal, it means that it either has a lower
271 : priority than 't' in torrc (otherwise the mark would have been
272 : cleared by the paragraph above), or it doesn't exist at all in
273 : the post-HUP torrc. We destroy the old transport and register 't'.
274 : * if it's *not* marked for removal, it means that it was newly
275 : added in the post-HUP torrc or that it's of higher priority, in
276 : this case we ignore 't'. */
277 0 : transport_t *t_tmp = transport_get_by_name(t->name);
278 0 : if (t_tmp) { /* same name */
279 0 : if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
280 : /* same name *and* addrport */
281 0 : t_tmp->marked_for_removal = 0;
282 0 : return 1;
283 : } else { /* same name but different addrport */
284 0 : char *new_transport_addrport =
285 0 : tor_strdup(fmt_addrport(&t->addr, t->port));
286 0 : if (t_tmp->marked_for_removal) { /* marked for removal */
287 0 : log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s' "
288 : "but there was already a transport marked for deletion at "
289 : "'%s'. We deleted the old transport and registered the "
290 : "new one.", t->name, new_transport_addrport,
291 : fmt_addrport(&t_tmp->addr, t_tmp->port));
292 0 : smartlist_remove(transport_list, t_tmp);
293 0 : transport_free(t_tmp);
294 0 : tor_free(new_transport_addrport);
295 : } else { /* *not* marked for removal */
296 0 : log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s' "
297 : "but the same transport already exists at '%s'. "
298 : "Skipping.", t->name, new_transport_addrport,
299 : fmt_addrport(&t_tmp->addr, t_tmp->port));
300 0 : tor_free(new_transport_addrport);
301 0 : return -1;
302 : }
303 0 : tor_free(new_transport_addrport);
304 : }
305 : }
306 :
307 : return 0;
308 : }
309 :
310 : /** Add transport <b>t</b> to the internal list of pluggable
311 : * transports.
312 : * Returns 0 if the transport was added correctly, 1 if the same
313 : * transport was already registered (in this case the caller must
314 : * free the transport) and -1 if there was an error. */
315 : static int
316 0 : transport_add(transport_t *t)
317 : {
318 0 : int r;
319 0 : tor_assert(t);
320 :
321 0 : r = transport_resolve_conflicts(t);
322 :
323 0 : switch (r) {
324 0 : case 0: /* should register transport */
325 0 : if (!transport_list)
326 0 : transport_list = smartlist_new();
327 0 : smartlist_add(transport_list, t);
328 0 : return 0;
329 : default: /* let our caller know the return code */
330 : return r;
331 : }
332 : }
333 :
334 : /** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
335 : * <b>name</b> is set to the name of the protocol this proxy uses.
336 : * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
337 0 : MOCK_IMPL(int,
338 : transport_add_from_config, (const tor_addr_t *addr, uint16_t port,
339 : const char *name, int socks_ver))
340 : {
341 0 : transport_t *t = transport_new(addr, port, name, socks_ver, NULL);
342 :
343 0 : int r = transport_add(t);
344 :
345 0 : switch (r) {
346 0 : case -1:
347 : default:
348 0 : log_notice(LD_GENERAL, "Could not add transport %s at %s. Skipping.",
349 : t->name, fmt_addrport(&t->addr, t->port));
350 0 : transport_free(t);
351 0 : return -1;
352 0 : case 1:
353 0 : log_info(LD_GENERAL, "Successfully registered transport %s at %s.",
354 : t->name, fmt_addrport(&t->addr, t->port));
355 0 : transport_free(t); /* falling */
356 0 : return 0;
357 0 : case 0:
358 0 : log_info(LD_GENERAL, "Successfully registered transport %s at %s.",
359 : t->name, fmt_addrport(&t->addr, t->port));
360 0 : return 0;
361 : }
362 : }
363 :
364 : /** List of unconfigured managed proxies. */
365 : static smartlist_t *managed_proxy_list = NULL;
366 : /** Number of still unconfigured proxies. */
367 : static int unconfigured_proxies_n = 0;
368 : /** Boolean: True iff we might need to restart some proxies. */
369 : static int check_if_restarts_needed = 0;
370 :
371 : /** Return true iff we have a managed_proxy_t in the global list is for the
372 : * given transport name. */
373 : bool
374 0 : managed_proxy_has_transport(const char *transport_name)
375 : {
376 0 : tor_assert(transport_name);
377 :
378 0 : if (!managed_proxy_list) {
379 : return false;
380 : }
381 :
382 0 : SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
383 0 : SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, name) {
384 0 : if (!strcasecmp(name, transport_name)) {
385 : return true;
386 : }
387 0 : } SMARTLIST_FOREACH_END(name);
388 0 : } SMARTLIST_FOREACH_END(mp);
389 :
390 : return false;
391 : }
392 :
393 : /** Return true if there are still unconfigured managed proxies, or proxies
394 : * that need restarting. */
395 : int
396 213 : pt_proxies_configuration_pending(void)
397 : {
398 213 : return unconfigured_proxies_n || check_if_restarts_needed;
399 : }
400 :
401 : /** Assert that the unconfigured_proxies_n value correctly matches the number
402 : * of proxies in a state other than PT_PROTO_COMPLETE. */
403 : static void
404 48 : assert_unconfigured_count_ok(void)
405 : {
406 48 : int n_completed = 0;
407 48 : if (!managed_proxy_list) {
408 0 : tor_assert(unconfigured_proxies_n == 0);
409 : return;
410 : }
411 :
412 97 : SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
413 : if (mp->conf_state == PT_PROTO_COMPLETED)
414 : ++n_completed;
415 : });
416 :
417 48 : tor_assert(n_completed + unconfigured_proxies_n ==
418 : smartlist_len(managed_proxy_list));
419 : }
420 :
421 : /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
422 : static int
423 0 : managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
424 : {
425 0 : char **tmp1=proxy_argv;
426 0 : char **tmp2=mp->argv;
427 :
428 0 : tor_assert(tmp1);
429 0 : tor_assert(tmp2);
430 :
431 0 : while (*tmp1 && *tmp2) {
432 0 : if (strcmp(*tmp1++, *tmp2++))
433 : return 0;
434 : }
435 :
436 0 : if (!*tmp1 && !*tmp2)
437 0 : return 1;
438 :
439 : return 0;
440 : }
441 :
442 : /** Return a managed proxy with the same argv as <b>proxy_argv</b>.
443 : * If no such managed proxy exists, return NULL. */
444 : static managed_proxy_t *
445 15 : get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server)
446 : {
447 15 : if (!managed_proxy_list)
448 : return NULL;
449 :
450 0 : SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
451 0 : if (managed_proxy_has_argv(mp, proxy_argv) &&
452 0 : mp->is_server == is_server)
453 0 : return mp;
454 0 : } SMARTLIST_FOREACH_END(mp);
455 :
456 : return NULL;
457 : }
458 :
459 : /** Add <b>transport</b> to managed proxy <b>mp</b>. */
460 : static void
461 15 : add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
462 : {
463 15 : tor_assert(mp->transports_to_launch);
464 15 : if (!smartlist_contains_string(mp->transports_to_launch, transport))
465 15 : smartlist_add_strdup(mp->transports_to_launch, transport);
466 15 : }
467 :
468 : /** Called when a SIGHUP occurs. Returns true if managed proxy
469 : * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
470 : * torrc. */
471 : static int
472 0 : proxy_needs_restart(const managed_proxy_t *mp)
473 : {
474 0 : int ret = 1;
475 0 : char* proxy_uri;
476 :
477 : /* If the PT proxy config has changed, then all existing pluggable transports
478 : * should be restarted.
479 : */
480 :
481 0 : proxy_uri = get_pt_proxy_uri();
482 0 : if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
483 0 : goto needs_restart;
484 :
485 : /* mp->transport_to_launch is populated with the names of the
486 : transports that must be launched *after* the SIGHUP.
487 : mp->transports is populated with the transports that were
488 : launched *before* the SIGHUP.
489 :
490 : Check if all the transports that need to be launched are already
491 : launched: */
492 :
493 0 : tor_assert(smartlist_len(mp->transports_to_launch) > 0);
494 0 : tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
495 :
496 0 : if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
497 0 : goto needs_restart;
498 :
499 0 : SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
500 0 : if (!smartlist_contains_string(mp->transports_to_launch, t->name))
501 0 : goto needs_restart;
502 :
503 0 : } SMARTLIST_FOREACH_END(t);
504 :
505 : ret = 0;
506 0 : needs_restart:
507 0 : tor_free(proxy_uri);
508 0 : return ret;
509 : }
510 :
511 : /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
512 : * preparations and then flag its state so that it will be relaunched
513 : * in the next tick. */
514 : static void
515 0 : proxy_prepare_for_restart(managed_proxy_t *mp)
516 : {
517 0 : transport_t *t_tmp = NULL;
518 :
519 0 : tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
520 :
521 : /* destroy the process handle and terminate the process. */
522 0 : process_set_data(mp->process, NULL);
523 0 : process_terminate(mp->process);
524 :
525 : /* destroy all its registered transports, since we will no longer
526 : use them. */
527 0 : SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
528 0 : t_tmp = transport_get_by_name(t->name);
529 0 : if (t_tmp)
530 0 : t_tmp->marked_for_removal = 1;
531 0 : } SMARTLIST_FOREACH_END(t);
532 0 : sweep_transport_list();
533 :
534 : /* free the transport in mp->transports */
535 0 : SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
536 0 : smartlist_clear(mp->transports);
537 :
538 : /* Reset the proxy's HTTPS/SOCKS proxy */
539 0 : tor_free(mp->proxy_uri);
540 0 : mp->proxy_uri = get_pt_proxy_uri();
541 0 : mp->proxy_supported = 0;
542 :
543 : /* flag it as an infant proxy so that it gets launched on next tick */
544 0 : mp->conf_state = PT_PROTO_INFANT;
545 0 : unconfigured_proxies_n++;
546 0 : }
547 :
548 : /** Launch managed proxy <b>mp</b>. */
549 : static int
550 0 : launch_managed_proxy(managed_proxy_t *mp)
551 : {
552 0 : tor_assert(mp);
553 :
554 0 : smartlist_t *env = create_managed_proxy_environment(mp);
555 :
556 : /* Configure our process. */
557 0 : process_set_data(mp->process, mp);
558 0 : process_set_stdout_read_callback(mp->process, managed_proxy_stdout_callback);
559 0 : process_set_stderr_read_callback(mp->process, managed_proxy_stderr_callback);
560 0 : process_set_exit_callback(mp->process, managed_proxy_exit_callback);
561 0 : process_set_protocol(mp->process, PROCESS_PROTOCOL_LINE);
562 0 : process_reset_environment(mp->process, env);
563 :
564 : /* Cleanup our env. */
565 0 : SMARTLIST_FOREACH(env, char *, x, tor_free(x));
566 0 : smartlist_free(env);
567 :
568 : /* Skip the argv[0] as we get that from process_new(argv[0]). */
569 0 : for (int i = 1; mp->argv[i] != NULL; ++i)
570 0 : process_append_argument(mp->process, mp->argv[i]);
571 :
572 0 : if (process_exec(mp->process) != PROCESS_STATUS_RUNNING) {
573 0 : log_warn(LD_CONFIG, "Managed proxy at '%s' failed at launch.",
574 : mp->argv[0]);
575 0 : return -1;
576 : }
577 :
578 0 : log_info(LD_CONFIG,
579 : "Managed proxy at '%s' has spawned with PID '%" PRIu64 "'.",
580 : mp->argv[0], process_get_pid(mp->process));
581 0 : mp->conf_state = PT_PROTO_LAUNCHED;
582 :
583 0 : return 0;
584 : }
585 :
586 : /** Check if any of the managed proxies we are currently trying to
587 : * configure has anything new to say. */
588 : void
589 0 : pt_configure_remaining_proxies(void)
590 : {
591 0 : int at_least_a_proxy_config_finished = 0;
592 0 : smartlist_t *tmp = smartlist_new();
593 :
594 0 : log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
595 : unconfigured_proxies_n);
596 :
597 : /* Iterate over tmp, not managed_proxy_list, since configure_proxy can
598 : * remove elements from managed_proxy_list. */
599 0 : smartlist_add_all(tmp, managed_proxy_list);
600 :
601 0 : assert_unconfigured_count_ok();
602 :
603 0 : SMARTLIST_FOREACH_BEGIN(tmp, managed_proxy_t *, mp) {
604 0 : tor_assert(mp->conf_state != PT_PROTO_BROKEN &&
605 : mp->conf_state != PT_PROTO_FAILED_LAUNCH);
606 :
607 0 : if (mp->was_around_before_config_read) {
608 : /* This proxy is marked by a config read. Check whether we need
609 : to restart it. */
610 :
611 0 : mp->was_around_before_config_read = 0;
612 :
613 0 : if (proxy_needs_restart(mp)) {
614 0 : log_info(LD_GENERAL, "Preparing managed proxy '%s' for restart.",
615 : mp->argv[0]);
616 0 : proxy_prepare_for_restart(mp);
617 : } else { /* it doesn't need to be restarted. */
618 0 : log_info(LD_GENERAL, "Nothing changed for managed proxy '%s' after "
619 : "HUP: not restarting.", mp->argv[0]);
620 : }
621 :
622 0 : continue;
623 : }
624 :
625 : /* If the proxy is not fully configured, try to configure it
626 : further. */
627 0 : if (!proxy_configuration_finished(mp))
628 0 : if (configure_proxy(mp) == 1)
629 0 : at_least_a_proxy_config_finished = 1;
630 :
631 0 : } SMARTLIST_FOREACH_END(mp);
632 :
633 0 : smartlist_free(tmp);
634 0 : check_if_restarts_needed = 0;
635 0 : assert_unconfigured_count_ok();
636 :
637 0 : if (at_least_a_proxy_config_finished)
638 0 : mark_my_descriptor_dirty("configured managed proxies");
639 0 : }
640 :
641 : /** Attempt to continue configuring managed proxy <b>mp</b>.
642 : * Return 1 if the transport configuration finished, and return 0
643 : * otherwise (if we still have more configuring to do for this
644 : * proxy). */
645 : STATIC int
646 6 : configure_proxy(managed_proxy_t *mp)
647 : {
648 : /* if we haven't launched the proxy yet, do it now */
649 6 : if (mp->conf_state == PT_PROTO_INFANT) {
650 0 : if (launch_managed_proxy(mp) < 0) { /* launch fail */
651 0 : mp->conf_state = PT_PROTO_FAILED_LAUNCH;
652 0 : handle_finished_proxy(mp);
653 : }
654 0 : return 0;
655 : }
656 :
657 6 : tor_assert(mp->conf_state != PT_PROTO_INFANT);
658 6 : tor_assert(mp->process);
659 6 : return mp->conf_state == PT_PROTO_COMPLETED;
660 : }
661 :
662 : /** Register server managed proxy <b>mp</b> transports to state */
663 : static void
664 1 : register_server_proxy(const managed_proxy_t *mp)
665 : {
666 1 : tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
667 :
668 6 : SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
669 5 : save_transport_to_state(t->name, &t->addr, t->port);
670 5 : log_notice(LD_GENERAL, "Registered server transport '%s' at '%s'",
671 : t->name, fmt_addrport(&t->addr, t->port));
672 5 : control_event_transport_launched("server", t->name, &t->addr, t->port);
673 5 : } SMARTLIST_FOREACH_END(t);
674 1 : }
675 :
676 : /** Register all the transports supported by client managed proxy
677 : * <b>mp</b> to the bridge subsystem. */
678 : static void
679 0 : register_client_proxy(const managed_proxy_t *mp)
680 : {
681 0 : int r;
682 :
683 0 : tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
684 :
685 0 : SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
686 0 : transport_t *transport_tmp = transport_copy(t);
687 0 : r = transport_add(transport_tmp);
688 0 : switch (r) {
689 0 : case -1:
690 0 : log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
691 0 : transport_free(transport_tmp);
692 0 : break;
693 0 : case 0:
694 0 : log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
695 0 : control_event_transport_launched("client", t->name, &t->addr, t->port);
696 0 : break;
697 0 : case 1:
698 0 : log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
699 0 : control_event_transport_launched("client", t->name, &t->addr, t->port);
700 0 : transport_free(transport_tmp);
701 0 : break;
702 : }
703 0 : } SMARTLIST_FOREACH_END(t);
704 0 : }
705 :
706 : /** Register the transports of managed proxy <b>mp</b>. */
707 : static inline void
708 1 : register_proxy(const managed_proxy_t *mp)
709 : {
710 1 : if (mp->is_server)
711 1 : register_server_proxy(mp);
712 : else
713 0 : register_client_proxy(mp);
714 1 : }
715 :
716 : /** Free memory allocated by managed proxy <b>mp</b>. */
717 : STATIC void
718 16 : managed_proxy_destroy(managed_proxy_t *mp,
719 : int also_terminate_process)
720 : {
721 16 : SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
722 :
723 : /* free the transports smartlist */
724 16 : smartlist_free(mp->transports);
725 :
726 : /* free the transports_to_launch smartlist */
727 34 : SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
728 16 : smartlist_free(mp->transports_to_launch);
729 :
730 : /* remove it from the list of managed proxies */
731 16 : if (managed_proxy_list)
732 16 : smartlist_remove(managed_proxy_list, mp);
733 :
734 : /* free the argv */
735 16 : free_execve_args(mp->argv);
736 :
737 : /* free the outgoing proxy URI */
738 16 : tor_free(mp->proxy_uri);
739 :
740 : /* do we want to terminate our process if it's still running? */
741 16 : if (also_terminate_process && mp->process) {
742 : /* Note that we do not call process_free(mp->process) here because we let
743 : * the exit handler in managed_proxy_exit_callback() return `true` which
744 : * makes the process subsystem deallocate the process_t. */
745 15 : process_set_data(mp->process, NULL);
746 15 : process_terminate(mp->process);
747 : }
748 :
749 16 : tor_free(mp);
750 16 : }
751 :
752 : /** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY.
753 : * Return a newly allocated string containing the URI, or NULL if no
754 : * proxy is set. */
755 : STATIC char *
756 25 : get_pt_proxy_uri(void)
757 : {
758 25 : const or_options_t *options = get_options();
759 25 : char *uri = NULL;
760 :
761 : /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
762 : * there isn't a standard URI scheme for some proxy protocols, such as
763 : * haproxy. */
764 25 : if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
765 6 : char addr[TOR_ADDR_BUF_LEN+1];
766 :
767 6 : if (options->Socks4Proxy) {
768 2 : tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
769 2 : tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
770 4 : } else if (options->Socks5Proxy) {
771 2 : tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
772 2 : if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
773 1 : tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
774 : } else {
775 1 : tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
776 : options->Socks5ProxyUsername,
777 1 : options->Socks5ProxyPassword,
778 1 : addr, options->Socks5ProxyPort);
779 : }
780 2 : } else if (options->HTTPSProxy) {
781 2 : tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
782 2 : if (!options->HTTPSProxyAuthenticator) {
783 1 : tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
784 : } else {
785 1 : tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
786 1 : addr, options->HTTPSProxyPort);
787 : }
788 : }
789 : }
790 :
791 25 : return uri;
792 : }
793 :
794 : /** Handle a configured or broken managed proxy <b>mp</b>. */
795 : static void
796 1 : handle_finished_proxy(managed_proxy_t *mp)
797 : {
798 1 : switch (mp->conf_state) {
799 0 : case PT_PROTO_BROKEN: /* if broken: */
800 0 : managed_proxy_destroy(mp, 1); /* annihilate it. */
801 0 : break;
802 0 : case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
803 0 : managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
804 0 : break;
805 1 : case PT_PROTO_CONFIGURED: /* if configured correctly: */
806 1 : if (mp->proxy_uri && !mp->proxy_supported) {
807 0 : log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
808 : "specified outgoing proxy and will be terminated.",
809 : mp->argv[0]);
810 0 : managed_proxy_destroy(mp, 1); /* annihilate it. */
811 0 : break;
812 : }
813 1 : register_proxy(mp); /* register its transports */
814 1 : mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
815 1 : break;
816 0 : case PT_PROTO_INFANT:
817 : case PT_PROTO_LAUNCHED:
818 : case PT_PROTO_ACCEPTING_METHODS:
819 : case PT_PROTO_COMPLETED:
820 : default:
821 0 : log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
822 : (int)mp->conf_state, mp->argv[0]);
823 0 : tor_assert(0);
824 : }
825 :
826 1 : unconfigured_proxies_n--;
827 1 : }
828 :
829 : /** Return true if the configuration of the managed proxy <b>mp</b> is
830 : finished. */
831 : static inline int
832 14 : proxy_configuration_finished(const managed_proxy_t *mp)
833 : {
834 14 : return (mp->conf_state == PT_PROTO_CONFIGURED ||
835 14 : mp->conf_state == PT_PROTO_BROKEN ||
836 : mp->conf_state == PT_PROTO_FAILED_LAUNCH);
837 : }
838 :
839 : /** This function is called when a proxy sends an {S,C}METHODS DONE message. */
840 : static void
841 2 : handle_methods_done(const managed_proxy_t *mp)
842 : {
843 2 : tor_assert(mp->transports);
844 :
845 2 : if (smartlist_len(mp->transports) == 0)
846 0 : log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
847 : "but it didn't launch any pluggable transport listeners!",
848 : mp->argv[0]);
849 :
850 3 : log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
851 : mp->is_server ? "Server" : "Client",
852 : mp->argv[0]);
853 2 : }
854 :
855 : /** Handle a configuration protocol <b>line</b> received from a
856 : * managed proxy <b>mp</b>. */
857 : STATIC void
858 20 : handle_proxy_line(const char *line, managed_proxy_t *mp)
859 : {
860 20 : log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
861 : mp->argv[0], line);
862 :
863 20 : if (!strcmpstart(line, PROTO_ENV_ERROR)) {
864 0 : if (mp->conf_state != PT_PROTO_LAUNCHED)
865 0 : goto err;
866 :
867 0 : parse_env_error(line);
868 0 : goto err;
869 20 : } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
870 0 : if (mp->conf_state != PT_PROTO_LAUNCHED)
871 0 : goto err;
872 :
873 0 : log_warn(LD_CONFIG, "Managed proxy could not pick a "
874 : "configuration protocol version.");
875 0 : goto err;
876 20 : } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
877 3 : if (mp->conf_state != PT_PROTO_LAUNCHED)
878 1 : goto err;
879 :
880 2 : if (parse_version(line,mp) < 0)
881 0 : goto err;
882 :
883 2 : tor_assert(mp->conf_protocol != 0);
884 2 : mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
885 2 : return;
886 17 : } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
887 1 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
888 0 : goto err;
889 :
890 1 : handle_methods_done(mp);
891 :
892 1 : mp->conf_state = PT_PROTO_CONFIGURED;
893 1 : return;
894 16 : } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
895 1 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
896 0 : goto err;
897 :
898 1 : handle_methods_done(mp);
899 :
900 1 : mp->conf_state = PT_PROTO_CONFIGURED;
901 1 : return;
902 15 : } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
903 0 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
904 0 : goto err;
905 :
906 0 : parse_client_method_error(line);
907 0 : goto err;
908 15 : } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
909 0 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
910 0 : goto err;
911 :
912 0 : parse_server_method_error(line);
913 0 : goto err;
914 15 : } else if (!strcmpstart(line, PROTO_CMETHOD)) {
915 2 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
916 1 : goto err;
917 :
918 1 : if (parse_cmethod_line(line, mp) < 0)
919 0 : goto err;
920 :
921 : return;
922 13 : } else if (!strcmpstart(line, PROTO_SMETHOD)) {
923 5 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
924 0 : goto err;
925 :
926 5 : if (parse_smethod_line(line, mp) < 0)
927 0 : goto err;
928 :
929 : return;
930 8 : } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
931 0 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
932 0 : goto err;
933 :
934 0 : if (mp->proxy_uri) {
935 0 : mp->proxy_supported = 1;
936 0 : return;
937 : }
938 :
939 : /* No proxy was configured, this should log */
940 8 : } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
941 0 : if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
942 0 : goto err;
943 :
944 0 : parse_proxy_error(line);
945 0 : goto err;
946 :
947 : /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
948 : * string to make sure we can later extend this big if/else-if table with
949 : * something that begins with "LOG" without having to get the order right.
950 : * */
951 8 : } else if (!strcmpstart(line, PROTO_LOG " ")) {
952 5 : parse_log_line(line, mp);
953 5 : return;
954 3 : } else if (!strcmpstart(line, PROTO_STATUS " ")) {
955 3 : parse_status_line(line, mp);
956 3 : return;
957 : }
958 :
959 0 : log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
960 0 : return;
961 :
962 2 : err:
963 2 : mp->conf_state = PT_PROTO_BROKEN;
964 2 : log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
965 : " and will be destroyed.", mp->argv[0]);
966 : }
967 :
968 : /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
969 : STATIC void
970 0 : parse_env_error(const char *line)
971 : {
972 : /* (Length of the protocol string) plus (a space) and (the first char of
973 : the error message) */
974 0 : if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
975 0 : log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
976 : "message.", PROTO_ENV_ERROR);
977 :
978 0 : log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
979 : "pluggable transport environment variables. (%s)",
980 : line+strlen(PROTO_ENV_ERROR)+1);
981 0 : }
982 :
983 : /** Handles a VERSION <b>line</b>. Updates the configuration protocol
984 : * version in <b>mp</b>. */
985 : STATIC int
986 5 : parse_version(const char *line, managed_proxy_t *mp)
987 : {
988 5 : if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
989 1 : log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
990 : PROTO_NEG_SUCCESS);
991 1 : return -1;
992 : }
993 :
994 4 : if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
995 1 : log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
996 : "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
997 1 : return -1;
998 : }
999 :
1000 3 : mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
1001 3 : return 0;
1002 : }
1003 :
1004 : /** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
1005 : * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
1006 : * otherwise it is a CMETHOD-ERROR. */
1007 : static void
1008 0 : parse_method_error(const char *line, int is_server)
1009 : {
1010 0 : const char* error = is_server ?
1011 0 : PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
1012 :
1013 : /* (Length of the protocol string) plus (a space) and (the first char of
1014 : the error message) */
1015 0 : if (strlen(line) < (strlen(error) + 2))
1016 0 : log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
1017 : "message.", error);
1018 :
1019 0 : log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
1020 : is_server ? "Server" : "Client",
1021 : line+strlen(error)+1);
1022 0 : }
1023 :
1024 : /** A helper for parse_{c,s}method_line(), bootstraps its
1025 : * functionalities. If <b>is_smethod</b> is true then the
1026 : * the line to parse is a SMETHOD line otherwise it is a
1027 : * CMETHOD line*/
1028 : static int
1029 16 : parse_method_line_helper(const char *line,
1030 : managed_proxy_t *mp,
1031 : int is_smethod)
1032 : {
1033 16 : int item_index = 0;
1034 16 : int r;
1035 :
1036 16 : char *transport_name=NULL;
1037 16 : char *args_string=NULL;
1038 16 : char *addrport=NULL;
1039 16 : int socks_ver=PROXY_NONE;
1040 16 : char *address=NULL;
1041 16 : uint16_t port = 0;
1042 :
1043 16 : const char *method_str = is_smethod ? PROTO_SMETHOD : PROTO_CMETHOD;
1044 16 : const int min_args_count = is_smethod ? 3 : 4;
1045 :
1046 16 : tor_addr_t tor_addr;
1047 16 : transport_t *transport=NULL;
1048 16 : smartlist_t *items= smartlist_new();
1049 :
1050 16 : smartlist_split_string(items, line, NULL,
1051 : SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1052 16 : if (smartlist_len(items) < min_args_count) {
1053 2 : log_warn(LD_CONFIG, "Managed proxy sent us a %s line "
1054 : "with too few arguments.", method_str);
1055 2 : goto err;
1056 : }
1057 :
1058 14 : tor_assert(!strcmp(smartlist_get(items, item_index),method_str));
1059 14 : ++item_index;
1060 :
1061 14 : transport_name = smartlist_get(items,item_index);
1062 14 : ++item_index;
1063 14 : if (!string_is_C_identifier(transport_name)) {
1064 0 : log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
1065 : transport_name);
1066 0 : goto err;
1067 : }
1068 :
1069 : /** Check for the proxy method sent to us in CMETHOD line. */
1070 14 : if (!is_smethod) {
1071 4 : const char *socks_ver_str = smartlist_get(items,item_index);
1072 4 : ++item_index;
1073 :
1074 4 : if (!strcmp(socks_ver_str,"socks4")) {
1075 : socks_ver = PROXY_SOCKS4;
1076 3 : } else if (!strcmp(socks_ver_str,"socks5")) {
1077 : socks_ver = PROXY_SOCKS5;
1078 : } else {
1079 1 : log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
1080 : "we don't recognize. (%s)", socks_ver_str);
1081 1 : goto err;
1082 : }
1083 : }
1084 :
1085 13 : addrport = smartlist_get(items, item_index);
1086 13 : ++item_index;
1087 13 : if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) {
1088 0 : log_warn(LD_CONFIG, "Error parsing transport address '%s'", addrport);
1089 0 : goto err;
1090 : }
1091 :
1092 13 : if (!port) {
1093 2 : log_warn(LD_CONFIG,
1094 : "Transport address '%s' has no port.", addrport);
1095 2 : goto err;
1096 : }
1097 :
1098 11 : if (tor_addr_parse(&tor_addr, address) < 0) {
1099 0 : log_warn(LD_CONFIG, "Error parsing transport address '%s'", address);
1100 0 : goto err;
1101 : }
1102 :
1103 : /** Check for options in the SMETHOD line. */
1104 11 : if (is_smethod && smartlist_len(items) > min_args_count) {
1105 : /* Seems like there are also some [options] in the SMETHOD line.
1106 : Let's see if we can parse them. */
1107 2 : char *options_string = smartlist_get(items, item_index);
1108 2 : log_debug(LD_CONFIG, "Got options_string: %s", options_string);
1109 2 : if (!strcmpstart(options_string, "ARGS:")) {
1110 2 : args_string = options_string+strlen("ARGS:");
1111 2 : log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
1112 : }
1113 : }
1114 :
1115 11 : transport = transport_new(&tor_addr, port, transport_name,
1116 : socks_ver, args_string);
1117 :
1118 11 : smartlist_add(mp->transports, transport);
1119 :
1120 : /** Logs info about line parsing success for client or server */
1121 11 : if (is_smethod) {
1122 9 : log_info(LD_CONFIG, "Server transport %s at %s:%d.",
1123 : transport_name, address, (int)port);
1124 : } else {
1125 2 : log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
1126 : "Attached to managed proxy.",
1127 : transport_name, address, (int)port, socks_ver);
1128 : }
1129 :
1130 11 : r=0;
1131 11 : goto done;
1132 :
1133 : err:
1134 : r = -1;
1135 :
1136 16 : done:
1137 68 : SMARTLIST_FOREACH(items, char*, s, tor_free(s));
1138 16 : smartlist_free(items);
1139 16 : tor_free(address);
1140 16 : return r;
1141 : }
1142 :
1143 : /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
1144 : * new transport in <b>mp</b>. */
1145 : STATIC int
1146 11 : parse_smethod_line(const char *line, managed_proxy_t *mp)
1147 : {
1148 : /* Example of legit SMETHOD line:
1149 : SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
1150 11 : return parse_method_line_helper(line, mp, 1);
1151 : }
1152 :
1153 : /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
1154 : * the new transport in <b>mp</b>. */
1155 : STATIC int
1156 5 : parse_cmethod_line(const char *line, managed_proxy_t *mp)
1157 : {
1158 : /* Example of legit CMETHOD line:
1159 : CMETHOD obfs2 socks5 127.0.0.1:35713 */
1160 5 : return parse_method_line_helper(line, mp, 0);
1161 : }
1162 :
1163 : /** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
1164 : STATIC void
1165 0 : parse_proxy_error(const char *line)
1166 : {
1167 : /* (Length of the protocol string) plus (a space) and (the first char of
1168 : the error message) */
1169 0 : if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
1170 0 : log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
1171 : "message.", PROTO_PROXY_ERROR);
1172 :
1173 0 : log_warn(LD_CONFIG, "Managed proxy failed to configure the "
1174 : "pluggable transport's outgoing proxy. (%s)",
1175 : line+strlen(PROTO_PROXY_ERROR)+1);
1176 0 : }
1177 :
1178 : /** Parses a LOG <b>line</b> and emit log events accordingly. */
1179 : STATIC void
1180 5 : parse_log_line(const char *line, managed_proxy_t *mp)
1181 : {
1182 5 : tor_assert(line);
1183 5 : tor_assert(mp);
1184 :
1185 5 : config_line_t *values = NULL;
1186 5 : char *log_message = NULL;
1187 :
1188 5 : if (strlen(line) < (strlen(PROTO_LOG) + 1)) {
1189 0 : log_warn(LD_PT, "Managed proxy sent us a %s line "
1190 : "with missing argument.", PROTO_LOG);
1191 0 : goto done;
1192 : }
1193 :
1194 5 : const char *data = line + strlen(PROTO_LOG) + 1;
1195 5 : values = kvline_parse(data, KV_QUOTED);
1196 :
1197 5 : if (! values) {
1198 0 : log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid LOG message: %s",
1199 : mp->argv[0], data);
1200 0 : goto done;
1201 : }
1202 :
1203 5 : const config_line_t *severity = config_line_find(values, "SEVERITY");
1204 5 : const config_line_t *message = config_line_find(values, "MESSAGE");
1205 :
1206 : /* Check if we got a message. */
1207 5 : if (! message) {
1208 0 : log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1209 : "MESSAGE: %s", mp->argv[0], escaped(data));
1210 0 : goto done;
1211 : }
1212 :
1213 : /* Check if severity is there and whether it's valid. */
1214 5 : if (! severity) {
1215 0 : log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1216 : "SEVERITY: %s", mp->argv[0], escaped(data));
1217 0 : goto done;
1218 : }
1219 :
1220 5 : int log_severity = managed_proxy_severity_parse(severity->value);
1221 :
1222 5 : if (log_severity == -1) {
1223 0 : log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line with an "
1224 : "invalid severity level: %s",
1225 : mp->argv[0], severity->value);
1226 0 : goto done;
1227 : }
1228 :
1229 5 : tor_log(log_severity, LD_PT, "Managed proxy \"%s\": %s",
1230 5 : mp->argv[0], message->value);
1231 :
1232 : /* Prepend the PT name. */
1233 5 : config_line_prepend(&values, "PT", mp->argv[0]);
1234 5 : log_message = kvline_encode(values, KV_QUOTED);
1235 :
1236 : /* Emit control port event. */
1237 5 : control_event_pt_log(log_message);
1238 :
1239 5 : done:
1240 5 : config_free_lines(values);
1241 5 : tor_free(log_message);
1242 5 : }
1243 :
1244 : /** Parses a STATUS <b>line</b> and emit control events accordingly. */
1245 : STATIC void
1246 3 : parse_status_line(const char *line, managed_proxy_t *mp)
1247 : {
1248 3 : tor_assert(line);
1249 3 : tor_assert(mp);
1250 :
1251 3 : config_line_t *values = NULL;
1252 3 : char *status_message = NULL;
1253 :
1254 3 : if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
1255 0 : log_warn(LD_PT, "Managed proxy sent us a %s line "
1256 : "with missing argument.", PROTO_STATUS);
1257 0 : goto done;
1258 : }
1259 :
1260 3 : const char *data = line + strlen(PROTO_STATUS) + 1;
1261 :
1262 3 : values = kvline_parse(data, KV_QUOTED);
1263 :
1264 3 : if (! values) {
1265 0 : log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
1266 : "STATUS message: %s", mp->argv[0], escaped(data));
1267 0 : goto done;
1268 : }
1269 :
1270 : /* We check if we received the TRANSPORT parameter, which is the only
1271 : * *required* value. */
1272 3 : const config_line_t *type = config_line_find(values, "TRANSPORT");
1273 :
1274 3 : if (! type) {
1275 0 : log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
1276 : "TRANSPORT: %s", mp->argv[0], escaped(data));
1277 0 : goto done;
1278 : }
1279 :
1280 : /* Prepend the PT name. */
1281 3 : config_line_prepend(&values, "PT", mp->argv[0]);
1282 3 : status_message = kvline_encode(values, KV_QUOTED);
1283 :
1284 : /* We have checked that TRANSPORT is there, we can now emit the STATUS event
1285 : * via the control port. */
1286 3 : control_event_pt_status(status_message);
1287 :
1288 3 : done:
1289 3 : config_free_lines(values);
1290 3 : tor_free(status_message);
1291 3 : }
1292 :
1293 : /** Return a newly allocated string that tor should place in
1294 : * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
1295 : * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
1296 : STATIC char *
1297 2 : get_transport_options_for_server_proxy(const managed_proxy_t *mp)
1298 : {
1299 2 : char *options_string = NULL;
1300 2 : smartlist_t *string_sl = smartlist_new();
1301 :
1302 2 : tor_assert(mp->is_server);
1303 :
1304 : /** Loop over the transports of the proxy. If we have options for
1305 : any of them, format them appropriately and place them in our
1306 : smartlist. Finally, join our smartlist to get the final
1307 : string. */
1308 5 : SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
1309 3 : smartlist_t *options_tmp_sl = NULL;
1310 3 : options_tmp_sl = pt_get_options_for_server_transport(transport);
1311 3 : if (!options_tmp_sl)
1312 1 : continue;
1313 :
1314 : /** Loop over the options of this transport, escape them, and
1315 : place them in the smartlist. */
1316 6 : SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
1317 4 : char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
1318 4 : smartlist_add_asprintf(string_sl, "%s:%s",
1319 : transport, escaped_opts);
1320 4 : tor_free(escaped_opts);
1321 4 : } SMARTLIST_FOREACH_END(options);
1322 :
1323 6 : SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
1324 2 : smartlist_free(options_tmp_sl);
1325 3 : } SMARTLIST_FOREACH_END(transport);
1326 :
1327 2 : if (smartlist_len(string_sl)) {
1328 1 : options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
1329 : }
1330 :
1331 6 : SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
1332 2 : smartlist_free(string_sl);
1333 :
1334 2 : return options_string;
1335 : }
1336 :
1337 : /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
1338 : * while configuring the server managed proxy in <b>mp</b>. The
1339 : * string is stored in the heap, and it's the responsibility of
1340 : * the caller to deallocate it after its use. */
1341 : static char *
1342 0 : get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
1343 : {
1344 0 : char *bindaddr_result = NULL;
1345 0 : char *bindaddr_tmp = NULL;
1346 0 : smartlist_t *string_tmp = smartlist_new();
1347 :
1348 0 : tor_assert(mp->is_server);
1349 :
1350 0 : SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
1351 0 : bindaddr_tmp = get_stored_bindaddr_for_server_transport(t);
1352 :
1353 0 : smartlist_add_asprintf(string_tmp, "%s-%s", t, bindaddr_tmp);
1354 :
1355 0 : tor_free(bindaddr_tmp);
1356 0 : } SMARTLIST_FOREACH_END(t);
1357 :
1358 0 : bindaddr_result = smartlist_join_strings(string_tmp, ",", 0, NULL);
1359 :
1360 0 : SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
1361 0 : smartlist_free(string_tmp);
1362 :
1363 0 : return bindaddr_result;
1364 : }
1365 :
1366 : /** Return a newly allocated process_environment_t * for <b>mp</b>'s
1367 : * process. */
1368 : static smartlist_t *
1369 0 : create_managed_proxy_environment(const managed_proxy_t *mp)
1370 : {
1371 0 : const or_options_t *options = get_options();
1372 :
1373 : /* Environment variables to be added to or set in mp's environment. */
1374 0 : smartlist_t *envs = smartlist_new();
1375 : /* XXXX The next time someone touches this code, shorten the name of
1376 : * set_environment_variable_in_smartlist, add a
1377 : * set_env_var_in_smartlist_asprintf function, and get rid of the
1378 : * silly extra envs smartlist. */
1379 :
1380 : /* The final environment to be passed to mp. */
1381 0 : smartlist_t *merged_env_vars = get_current_process_environment_variables();
1382 :
1383 : {
1384 0 : char *state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
1385 0 : smartlist_add_asprintf(envs, "TOR_PT_STATE_LOCATION=%s", state_tmp);
1386 0 : tor_free(state_tmp);
1387 : }
1388 :
1389 0 : smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
1390 :
1391 : {
1392 0 : char *transports_to_launch =
1393 0 : smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
1394 :
1395 0 : smartlist_add_asprintf(envs,
1396 0 : mp->is_server ?
1397 : "TOR_PT_SERVER_TRANSPORTS=%s" :
1398 : "TOR_PT_CLIENT_TRANSPORTS=%s",
1399 : transports_to_launch);
1400 :
1401 0 : tor_free(transports_to_launch);
1402 : }
1403 :
1404 0 : if (mp->is_server) {
1405 : {
1406 0 : char *orport_tmp =
1407 0 : get_first_listener_addrport_string(CONN_TYPE_OR_LISTENER);
1408 0 : if (orport_tmp) {
1409 0 : smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
1410 0 : tor_free(orport_tmp);
1411 : }
1412 : }
1413 :
1414 : {
1415 0 : char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
1416 0 : smartlist_add_asprintf(envs, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
1417 0 : tor_free(bindaddr_tmp);
1418 : }
1419 :
1420 : {
1421 0 : char *server_transport_options =
1422 0 : get_transport_options_for_server_proxy(mp);
1423 0 : if (server_transport_options) {
1424 0 : smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1425 : server_transport_options);
1426 0 : tor_free(server_transport_options);
1427 : }
1428 : }
1429 :
1430 : /* XXXX Remove the '=' here once versions of obfsproxy which
1431 : * assert that this env var exists are sufficiently dead.
1432 : *
1433 : * (If we remove this line entirely, some joker will stick this
1434 : * variable in Tor's environment and crash PTs that try to parse
1435 : * it even when not run in server mode.) */
1436 :
1437 0 : if (options->ExtORPort_lines) {
1438 0 : char *ext_or_addrport_tmp =
1439 0 : get_first_listener_addrport_string(CONN_TYPE_EXT_OR_LISTENER);
1440 0 : char *cookie_file_loc = get_ext_or_auth_cookie_file_name();
1441 :
1442 0 : if (ext_or_addrport_tmp) {
1443 0 : smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1444 : ext_or_addrport_tmp);
1445 : }
1446 0 : if (cookie_file_loc) {
1447 0 : smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s",
1448 : cookie_file_loc);
1449 : }
1450 :
1451 0 : tor_free(ext_or_addrport_tmp);
1452 0 : tor_free(cookie_file_loc);
1453 :
1454 : } else {
1455 0 : smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
1456 : }
1457 : } else {
1458 : /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
1459 : * TOR_PT_PROXY line.
1460 : */
1461 :
1462 0 : if (mp->proxy_uri) {
1463 0 : smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
1464 : }
1465 : }
1466 :
1467 : /* All new versions of tor will keep stdin open, so PTs can use it
1468 : * as a reliable termination detection mechanism.
1469 : */
1470 0 : smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
1471 :
1472 : /* Specify which IPv4 and IPv6 addresses the PT should make its outgoing
1473 : * connections from. See: https://bugs.torproject.org/5304 for more
1474 : * information about this. */
1475 : {
1476 : /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V4. */
1477 0 : const tor_addr_t *ipv4_addr = managed_proxy_outbound_address(options,
1478 : AF_INET);
1479 :
1480 : /* managed_proxy_outbound_address() only returns a non-NULL value if
1481 : * tor_addr_is_null() was false, which means we don't have to check that
1482 : * here. */
1483 0 : if (ipv4_addr) {
1484 0 : char *ipv4_addr_str = tor_addr_to_str_dup(ipv4_addr);
1485 0 : smartlist_add_asprintf(envs,
1486 : "TOR_PT_OUTBOUND_BIND_ADDRESS_V4=%s",
1487 : ipv4_addr_str);
1488 0 : tor_free(ipv4_addr_str);
1489 : }
1490 :
1491 : /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V6. */
1492 0 : const tor_addr_t *ipv6_addr = managed_proxy_outbound_address(options,
1493 : AF_INET6);
1494 0 : if (ipv6_addr) {
1495 0 : char *ipv6_addr_str = tor_addr_to_str_dup(ipv6_addr);
1496 0 : smartlist_add_asprintf(envs,
1497 : "TOR_PT_OUTBOUND_BIND_ADDRESS_V6=[%s]",
1498 : ipv6_addr_str);
1499 0 : tor_free(ipv6_addr_str);
1500 : }
1501 : }
1502 :
1503 0 : SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
1504 0 : set_environment_variable_in_smartlist(merged_env_vars, env_var,
1505 : tor_free_, 1);
1506 0 : } SMARTLIST_FOREACH_END(env_var);
1507 :
1508 0 : smartlist_free(envs);
1509 :
1510 0 : return merged_env_vars;
1511 : }
1512 :
1513 : /** Create and return a new managed proxy for <b>transport</b> using
1514 : * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
1515 : * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
1516 : * <b>proxy_argv</b>.
1517 : *
1518 : * Requires that proxy_argv have at least one element. */
1519 : STATIC managed_proxy_t *
1520 18 : managed_proxy_create(const smartlist_t *with_transport_list,
1521 : char **proxy_argv, int is_server)
1522 : {
1523 18 : managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
1524 18 : mp->conf_state = PT_PROTO_INFANT;
1525 18 : mp->is_server = is_server;
1526 18 : mp->argv = proxy_argv;
1527 18 : mp->transports = smartlist_new();
1528 18 : mp->proxy_uri = get_pt_proxy_uri();
1529 18 : mp->process = process_new(proxy_argv[0]);
1530 :
1531 18 : mp->transports_to_launch = smartlist_new();
1532 33 : SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1533 : add_transport_to_proxy(transport, mp));
1534 :
1535 : /* register the managed proxy */
1536 18 : if (!managed_proxy_list)
1537 17 : managed_proxy_list = smartlist_new();
1538 18 : smartlist_add(managed_proxy_list, mp);
1539 18 : unconfigured_proxies_n++;
1540 :
1541 18 : assert_unconfigured_count_ok();
1542 :
1543 18 : return mp;
1544 : }
1545 :
1546 : /** Register proxy with <b>proxy_argv</b>, supporting transports in
1547 : * <b>transport_list</b>, to the managed proxy subsystem.
1548 : * If <b>is_server</b> is true, then the proxy is a server proxy.
1549 : *
1550 : * Takes ownership of proxy_argv.
1551 : *
1552 : * Requires that proxy_argv be a NULL-terminated array of command-line
1553 : * elements, containing at least one element.
1554 : **/
1555 15 : MOCK_IMPL(void,
1556 : pt_kickstart_proxy, (const smartlist_t *with_transport_list,
1557 : char **proxy_argv, int is_server))
1558 : {
1559 15 : managed_proxy_t *mp=NULL;
1560 15 : transport_t *old_transport = NULL;
1561 :
1562 15 : if (!proxy_argv || !proxy_argv[0]) {
1563 : return;
1564 : }
1565 :
1566 15 : mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
1567 :
1568 15 : if (!mp) { /* we haven't seen this proxy before */
1569 15 : managed_proxy_create(with_transport_list, proxy_argv, is_server);
1570 :
1571 : } else { /* known proxy. add its transport to its transport list */
1572 0 : if (mp->was_around_before_config_read) {
1573 : /* If this managed proxy was around even before we read the
1574 : config this time, it means that it was already enabled before
1575 : and is not useless and should be kept. If it's marked for
1576 : removal, unmark it and make sure that we check whether it
1577 : needs to be restarted. */
1578 0 : if (mp->marked_for_removal) {
1579 0 : mp->marked_for_removal = 0;
1580 0 : check_if_restarts_needed = 1;
1581 : }
1582 :
1583 : /* For each new transport, check if the managed proxy used to
1584 : support it before the SIGHUP. If that was the case, make sure
1585 : it doesn't get removed because we might reuse it. */
1586 0 : SMARTLIST_FOREACH_BEGIN(with_transport_list, const char *, transport) {
1587 0 : old_transport = transport_get_by_name(transport);
1588 0 : if (old_transport)
1589 0 : old_transport->marked_for_removal = 0;
1590 0 : } SMARTLIST_FOREACH_END(transport);
1591 : }
1592 :
1593 0 : SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1594 : add_transport_to_proxy(transport, mp));
1595 0 : free_execve_args(proxy_argv);
1596 : }
1597 : }
1598 :
1599 : /** Frees the array of pointers in <b>arg</b> used as arguments to
1600 : execve(2). */
1601 : STATIC void
1602 18 : free_execve_args(char **arg)
1603 : {
1604 18 : char **tmp = arg;
1605 36 : while (*tmp) /* use the fact that the last element of the array is a
1606 : NULL pointer to know when to stop freeing */
1607 18 : tor_free_(*tmp++);
1608 :
1609 18 : tor_free(arg);
1610 18 : }
1611 :
1612 : /** Tor will read its config.
1613 : * Prepare the managed proxy list so that proxies not used in the new
1614 : * config will shutdown, and proxies that need to spawn different
1615 : * transports will do so. */
1616 : void
1617 213 : pt_prepare_proxy_list_for_config_read(void)
1618 : {
1619 213 : if (!managed_proxy_list)
1620 : return;
1621 :
1622 0 : assert_unconfigured_count_ok();
1623 0 : SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1624 : /* Destroy unconfigured proxies. */
1625 0 : if (mp->conf_state != PT_PROTO_COMPLETED) {
1626 0 : SMARTLIST_DEL_CURRENT(managed_proxy_list, mp);
1627 0 : managed_proxy_destroy(mp, 1);
1628 0 : unconfigured_proxies_n--;
1629 0 : continue;
1630 : }
1631 :
1632 0 : tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1633 :
1634 : /* Mark all proxies for removal, and also note that they have been
1635 : here before the config read. */
1636 0 : mp->marked_for_removal = 1;
1637 0 : mp->was_around_before_config_read = 1;
1638 0 : SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
1639 0 : smartlist_clear(mp->transports_to_launch);
1640 0 : } SMARTLIST_FOREACH_END(mp);
1641 :
1642 0 : assert_unconfigured_count_ok();
1643 :
1644 0 : tor_assert(unconfigured_proxies_n == 0);
1645 : }
1646 :
1647 : /** Return a smartlist containing the ports where our pluggable
1648 : * transports are listening. */
1649 : smartlist_t *
1650 0 : get_transport_proxy_ports(void)
1651 : {
1652 0 : smartlist_t *sl = NULL;
1653 :
1654 0 : if (!managed_proxy_list)
1655 : return NULL;
1656 :
1657 : /** XXX assume that external proxy ports have been forwarded
1658 : manually */
1659 0 : SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1660 0 : if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED)
1661 0 : continue;
1662 :
1663 0 : if (!sl) sl = smartlist_new();
1664 :
1665 0 : tor_assert(mp->transports);
1666 0 : SMARTLIST_FOREACH(mp->transports, const transport_t *, t,
1667 : smartlist_add_asprintf(sl, "%u:%u", t->port, t->port));
1668 :
1669 0 : } SMARTLIST_FOREACH_END(mp);
1670 :
1671 : return sl;
1672 : }
1673 :
1674 : /** Return the pluggable transport string that we should display in
1675 : * our extra-info descriptor. If we shouldn't display such a string,
1676 : * or we have nothing to display, return NULL. The string is
1677 : * allocated on the heap and it's the responsibility of the caller to
1678 : * free it. */
1679 : char *
1680 1 : pt_get_extra_info_descriptor_string(void)
1681 : {
1682 1 : char *the_string = NULL;
1683 1 : smartlist_t *string_chunks = NULL;
1684 :
1685 1 : if (!managed_proxy_list)
1686 : return NULL;
1687 :
1688 1 : string_chunks = smartlist_new();
1689 :
1690 : /* For each managed proxy, add its transports to the chunks list. */
1691 3 : SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1692 2 : if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
1693 0 : continue;
1694 :
1695 2 : tor_assert(mp->transports);
1696 :
1697 4 : SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1698 2 : char *transport_args = NULL;
1699 2 : const char *addrport = NULL;
1700 :
1701 : /* If the transport proxy returned "0.0.0.0" as its address, and
1702 : * we know our external IP address, use it. Otherwise, use the
1703 : * returned address. */
1704 2 : if (tor_addr_is_null(&t->addr)) {
1705 0 : tor_addr_t addr;
1706 : /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
1707 : * can't find it. */
1708 0 : bool found = relay_find_addr_to_publish(get_options(), AF_INET,
1709 : RELAY_FIND_ADDR_NO_FLAG,
1710 : &addr);
1711 0 : if (!found) {
1712 0 : found = relay_find_addr_to_publish(get_options(), AF_INET6,
1713 : RELAY_FIND_ADDR_NO_FLAG, &addr);
1714 : }
1715 0 : if (!found) {
1716 0 : log_err(LD_PT, "Unable to find address for transport %s", t->name);
1717 0 : continue;
1718 : }
1719 0 : addrport = fmt_addrport(&addr, t->port);
1720 : } else {
1721 2 : addrport = fmt_addrport(&t->addr, t->port);
1722 : }
1723 :
1724 : /* If this transport has any arguments with it, prepend a space
1725 : to them so that we can add them to the transport line. */
1726 2 : if (t->extra_info_args)
1727 1 : tor_asprintf(&transport_args, " %s", t->extra_info_args);
1728 :
1729 4 : smartlist_add_asprintf(string_chunks,
1730 : "transport %s %s%s",
1731 2 : t->name, addrport,
1732 2 : transport_args ? transport_args : "");
1733 2 : tor_free(transport_args);
1734 2 : } SMARTLIST_FOREACH_END(t);
1735 :
1736 2 : } SMARTLIST_FOREACH_END(mp);
1737 :
1738 1 : if (smartlist_len(string_chunks) == 0) {
1739 0 : smartlist_free(string_chunks);
1740 0 : return NULL;
1741 : }
1742 :
1743 : /* Join all the chunks into the final string. */
1744 1 : the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1745 :
1746 3 : SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1747 1 : smartlist_free(string_chunks);
1748 :
1749 1 : return the_string;
1750 : }
1751 :
1752 : /** Stringify the SOCKS arguments in <b>socks_args</b> according to
1753 : * 180_pluggable_transport.txt. The string is allocated on the heap
1754 : * and it's the responsibility of the caller to free it after use. */
1755 : char *
1756 52 : pt_stringify_socks_args(const smartlist_t *socks_args)
1757 : {
1758 : /* tmp place to store escaped socks arguments, so that we can
1759 : concatenate them up afterwards */
1760 52 : smartlist_t *sl_tmp = NULL;
1761 52 : char *escaped_string = NULL;
1762 52 : char *new_string = NULL;
1763 :
1764 52 : tor_assert(socks_args);
1765 52 : tor_assert(smartlist_len(socks_args) > 0);
1766 :
1767 52 : sl_tmp = smartlist_new();
1768 :
1769 122 : SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
1770 : /* Escape ';' and '\'. */
1771 70 : escaped_string = tor_escape_str_for_pt_args(s, ";\\");
1772 70 : if (!escaped_string)
1773 0 : goto done;
1774 :
1775 70 : smartlist_add(sl_tmp, escaped_string);
1776 70 : } SMARTLIST_FOREACH_END(s);
1777 :
1778 52 : new_string = smartlist_join_strings(sl_tmp, ";", 0, NULL);
1779 :
1780 52 : done:
1781 122 : SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
1782 52 : smartlist_free(sl_tmp);
1783 :
1784 52 : return new_string;
1785 : }
1786 :
1787 : /** Return a string of the SOCKS arguments that we should pass to the
1788 : * pluggable transports proxy in <b>addr</b>:<b>port</b> according to
1789 : * 180_pluggable_transport.txt. The string is allocated on the heap
1790 : * and it's the responsibility of the caller to free it after use. */
1791 : char *
1792 0 : pt_get_socks_args_for_proxy_addrport(const tor_addr_t *addr, uint16_t port)
1793 : {
1794 0 : const smartlist_t *socks_args = NULL;
1795 :
1796 0 : socks_args = get_socks_args_by_bridge_addrport(addr, port);
1797 0 : if (!socks_args)
1798 : return NULL;
1799 :
1800 0 : return pt_stringify_socks_args(socks_args);
1801 : }
1802 :
1803 : /** The tor config was read.
1804 : * Destroy all managed proxies that were marked by a previous call to
1805 : * prepare_proxy_list_for_config_read() and are not used by the new
1806 : * config. */
1807 : void
1808 213 : sweep_proxy_list(void)
1809 : {
1810 213 : if (!managed_proxy_list)
1811 : return;
1812 15 : assert_unconfigured_count_ok();
1813 30 : SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1814 15 : if (mp->marked_for_removal) {
1815 0 : SMARTLIST_DEL_CURRENT(managed_proxy_list, mp);
1816 0 : managed_proxy_destroy(mp, 1);
1817 : }
1818 15 : } SMARTLIST_FOREACH_END(mp);
1819 15 : assert_unconfigured_count_ok();
1820 : }
1821 :
1822 : /** Release all storage held by the pluggable transports subsystem. */
1823 : void
1824 235 : pt_free_all(void)
1825 : {
1826 235 : if (transport_list) {
1827 201 : clear_transport_list();
1828 201 : smartlist_free(transport_list);
1829 201 : transport_list = NULL;
1830 : }
1831 :
1832 235 : if (managed_proxy_list) {
1833 : /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1834 : transports and it's the duty of the circuitbuild.c subsystem to
1835 : free them. Otherwise, it hasn't registered its transports yet
1836 : and we should free them here. */
1837 30 : SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
1838 : SMARTLIST_DEL_CURRENT(managed_proxy_list, mp);
1839 : managed_proxy_destroy(mp, 1);
1840 : });
1841 :
1842 15 : smartlist_free(managed_proxy_list);
1843 15 : managed_proxy_list=NULL;
1844 : }
1845 235 : }
1846 :
1847 : /** Return a newly allocated string equal to <b>string</b>, except that every
1848 : * character in <b>chars_to_escape</b> is preceded by a backslash. */
1849 : char *
1850 79 : tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
1851 : {
1852 79 : char *new_string = NULL;
1853 79 : char *new_cp = NULL;
1854 79 : size_t length, new_length;
1855 :
1856 79 : tor_assert(string);
1857 :
1858 79 : length = strlen(string);
1859 :
1860 79 : if (!length) /* If we were given the empty string, return the same. */
1861 1 : return tor_strdup("");
1862 : /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
1863 : (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
1864 78 : if (length > (SIZE_MAX - 1)/2) /* check for overflow */
1865 : return NULL;
1866 :
1867 : /* this should be enough even if all characters must be escaped */
1868 78 : new_length = (length * 2) + 1;
1869 :
1870 78 : new_string = new_cp = tor_malloc(new_length);
1871 :
1872 3051 : while (*string) {
1873 2973 : if (strchr(chars_to_escape, *string))
1874 8 : *new_cp++ = '\\';
1875 :
1876 2973 : *new_cp++ = *string++;
1877 : }
1878 :
1879 78 : *new_cp = '\0'; /* NUL-terminate the new string */
1880 :
1881 78 : return new_string;
1882 : }
1883 :
1884 : /** Callback function that is called when our PT process have data on its
1885 : * stdout. Our process can be found in <b>process</b>, the data can be found in
1886 : * <b>line</b> and the length of our line is given in <b>size</b>. */
1887 : STATIC void
1888 14 : managed_proxy_stdout_callback(process_t *process,
1889 : const char *line,
1890 : size_t size)
1891 : {
1892 14 : tor_assert(process);
1893 14 : tor_assert(line);
1894 :
1895 14 : (void)size;
1896 :
1897 14 : managed_proxy_t *mp = process_get_data(process);
1898 :
1899 14 : if (mp == NULL)
1900 : return;
1901 :
1902 14 : handle_proxy_line(line, mp);
1903 :
1904 14 : if (proxy_configuration_finished(mp))
1905 1 : handle_finished_proxy(mp);
1906 : }
1907 :
1908 : /** Callback function that is called when our PT process have data on its
1909 : * stderr. Our process can be found in <b>process</b>, the data can be found in
1910 : * <b>line</b> and the length of our line is given in <b>size</b>. */
1911 : STATIC void
1912 0 : managed_proxy_stderr_callback(process_t *process,
1913 : const char *line,
1914 : size_t size)
1915 : {
1916 0 : tor_assert(process);
1917 0 : tor_assert(line);
1918 :
1919 0 : (void)size;
1920 :
1921 0 : managed_proxy_t *mp = process_get_data(process);
1922 :
1923 0 : if (BUG(mp == NULL))
1924 0 : return;
1925 :
1926 0 : log_info(LD_PT,
1927 : "Managed proxy at '%s' reported via standard error: %s",
1928 : mp->argv[0], line);
1929 : }
1930 :
1931 : /** Callback function that is called when our PT process terminates. The
1932 : * process exit code can be found in <b>exit_code</b> and our process can be
1933 : * found in <b>process</b>. Returns true iff we want the process subsystem to
1934 : * free our process_t handle for us. */
1935 : STATIC bool
1936 0 : managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
1937 : {
1938 0 : tor_assert(process);
1939 :
1940 0 : log_warn(LD_PT,
1941 : "Pluggable Transport process terminated with status code %" PRIu64,
1942 : exit_code);
1943 :
1944 : /* Returning true here means that the process subsystem will take care of
1945 : * calling process_free() on our process_t. */
1946 0 : return true;
1947 : }
1948 :
1949 : /** Returns a valid integer log severity level from <b>severity</b> that
1950 : * is compatible with Tor's logging functions. Returns <b>-1</b> on
1951 : * error. */
1952 : STATIC int
1953 5 : managed_proxy_severity_parse(const char *severity)
1954 : {
1955 5 : tor_assert(severity);
1956 :
1957 : /* Slightly different than log.c's parse_log_level :-( */
1958 5 : if (! strcmp(severity, "debug"))
1959 : return LOG_DEBUG;
1960 :
1961 4 : if (! strcmp(severity, "info"))
1962 : return LOG_INFO;
1963 :
1964 3 : if (! strcmp(severity, "notice"))
1965 : return LOG_NOTICE;
1966 :
1967 2 : if (! strcmp(severity, "warning"))
1968 : return LOG_WARN;
1969 :
1970 1 : if (! strcmp(severity, "error"))
1971 1 : return LOG_ERR;
1972 :
1973 : return -1;
1974 : }
1975 :
1976 : /** Return the outbound address from the given <b>family</b>. Returns NULL if
1977 : * the user haven't specified a specific outbound address in either
1978 : * OutboundBindAddress or OutboundBindAddressPT. */
1979 : STATIC const tor_addr_t *
1980 0 : managed_proxy_outbound_address(const or_options_t *options, sa_family_t family)
1981 : {
1982 0 : tor_assert(options);
1983 :
1984 0 : const tor_addr_t *address = NULL;
1985 0 : int family_index;
1986 :
1987 0 : switch (family) {
1988 : case AF_INET:
1989 : family_index = 0;
1990 : break;
1991 0 : case AF_INET6:
1992 0 : family_index = 1;
1993 0 : break;
1994 0 : default:
1995 : /* LCOV_EXCL_START */
1996 : tor_assert_unreached();
1997 : return NULL;
1998 : /* LCOV_EXCL_STOP */
1999 : }
2000 :
2001 : /* We start by checking if the user specified an address in
2002 : * OutboundBindAddressPT. */
2003 0 : address = &options->OutboundBindAddresses[OUTBOUND_ADDR_PT][family_index];
2004 :
2005 0 : if (! tor_addr_is_null(address))
2006 : return address;
2007 :
2008 : /* We fallback to check if the user specified an address in
2009 : * OutboundBindAddress. */
2010 0 : address = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY][family_index];
2011 :
2012 0 : if (! tor_addr_is_null(address))
2013 0 : return address;
2014 :
2015 : /* The user have not specified a preference for outgoing connections. */
2016 : return NULL;
2017 : }
|