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