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