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