Tor 0.4.9.3-alpha-dev
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"
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
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
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
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);
680}
681
682/** Register all the transports supported by client managed proxy
683 * <b>mp</b> to the bridge subsystem. */
684static void
685register_client_proxy(const managed_proxy_t *mp)
686{
687 int r;
688
689 tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
690
691 SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
692 transport_t *transport_tmp = transport_copy(t);
693 r = transport_add(transport_tmp);
694 switch (r) {
695 case -1:
696 log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
697 transport_free(transport_tmp);
698 break;
699 case 0:
700 log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
701 control_event_transport_launched("client", t->name, &t->addr, t->port);
702 break;
703 case 1:
704 log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
705 control_event_transport_launched("client", t->name, &t->addr, t->port);
706 transport_free(transport_tmp);
707 break;
708 }
709 } SMARTLIST_FOREACH_END(t);
710}
711
712/** Register the transports of managed proxy <b>mp</b>. */
713static inline void
714register_proxy(const managed_proxy_t *mp)
715{
716 if (mp->is_server)
718 else
720}
721
722/** Free memory allocated by managed proxy <b>mp</b>. */
723STATIC void
724managed_proxy_destroy(managed_proxy_t *mp,
725 int also_terminate_process)
726{
727 SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
728
729 /* free the transports smartlist */
730 smartlist_free(mp->transports);
731
732 /* free the transports_to_launch smartlist */
733 SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
734 smartlist_free(mp->transports_to_launch);
735
736 /* remove it from the list of managed proxies */
739
740 /* free the argv */
741 free_execve_args(mp->argv);
742
743 /* free the outgoing proxy URI */
744 tor_free(mp->proxy_uri);
745
746 /* free our version, if any is set. */
747 tor_free(mp->version);
748 tor_free(mp->implementation);
749
750 /* do we want to terminate our process if it's still running? */
751 if (also_terminate_process && mp->process) {
752 /* Note that we do not call process_free(mp->process) here because we let
753 * the exit handler in managed_proxy_exit_callback() return `true` which
754 * makes the process subsystem deallocate the process_t. */
755 process_set_data(mp->process, NULL);
756 process_terminate(mp->process);
757 }
758
759 tor_free(mp);
760}
761
762/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY.
763 * Return a newly allocated string containing the URI, or NULL if no
764 * proxy is set. */
765STATIC char *
767{
768 const or_options_t *options = get_options();
769 char *uri = NULL;
770
771 /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
772 * there isn't a standard URI scheme for some proxy protocols, such as
773 * haproxy. */
774 if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
775 char addr[TOR_ADDR_BUF_LEN+1];
776
777 if (options->Socks4Proxy) {
778 tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
779 tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
780 } else if (options->Socks5Proxy) {
781 tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
782 if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
783 tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
784 } else {
785 tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
786 options->Socks5ProxyUsername,
787 options->Socks5ProxyPassword,
788 addr, options->Socks5ProxyPort);
789 }
790 } else if (options->HTTPSProxy) {
791 tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
792 if (!options->HTTPSProxyAuthenticator) {
793 tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
794 } else {
795 tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
796 addr, options->HTTPSProxyPort);
797 }
798 }
799 }
800
801 return uri;
802}
803
804/** Handle a configured or broken managed proxy <b>mp</b>. */
805static void
806handle_finished_proxy(managed_proxy_t *mp)
807{
808 switch (mp->conf_state) {
809 case PT_PROTO_BROKEN: /* if broken: */
810 managed_proxy_destroy(mp, 1); /* annihilate it. */
811 break;
812 case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
813 managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
814 break;
815 case PT_PROTO_CONFIGURED: /* if configured correctly: */
816 if (mp->proxy_uri && !mp->proxy_supported) {
817 log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
818 "specified outgoing proxy and will be terminated.",
819 mp->argv[0]);
820 managed_proxy_destroy(mp, 1); /* annihilate it. */
821 break;
822 }
823
824 /* register its transports */
825 register_proxy(mp);
826
827 /* and mark it as completed. */
828 managed_proxy_set_state(mp, PT_PROTO_COMPLETED);
829 break;
830 case PT_PROTO_INFANT:
831 case PT_PROTO_LAUNCHED:
832 case PT_PROTO_ACCEPTING_METHODS:
833 case PT_PROTO_COMPLETED:
834 default:
835 log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
836 (int)mp->conf_state, mp->argv[0]);
837 tor_assert(0);
838 }
839
841}
842
843/** Return true if the configuration of the managed proxy <b>mp</b> is
844 finished. */
845static inline int
846proxy_configuration_finished(const managed_proxy_t *mp)
847{
848 return (mp->conf_state == PT_PROTO_CONFIGURED ||
849 mp->conf_state == PT_PROTO_BROKEN ||
850 mp->conf_state == PT_PROTO_FAILED_LAUNCH);
851}
852
853/** This function is called when a proxy sends an {S,C}METHODS DONE message. */
854static void
855handle_methods_done(const managed_proxy_t *mp)
856{
857 tor_assert(mp->transports);
858
859 if (smartlist_len(mp->transports) == 0)
860 log_warn(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
861 "but it didn't launch any pluggable transport listeners!",
862 mp->argv[0]);
863
864 log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
865 mp->is_server ? "Server" : "Client",
866 mp->argv[0]);
867}
868
869/** Handle a configuration protocol <b>line</b> received from a
870 * managed proxy <b>mp</b>. */
871STATIC void
872handle_proxy_line(const char *line, managed_proxy_t *mp)
873{
874 log_info(LD_PT, "Got a line from managed proxy '%s': (%s)",
875 mp->argv[0], line);
876
877 if (!strcmpstart(line, PROTO_ENV_ERROR)) {
878 if (mp->conf_state != PT_PROTO_LAUNCHED)
879 goto err;
880
881 parse_env_error(line);
882 goto err;
883 } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
884 if (mp->conf_state != PT_PROTO_LAUNCHED)
885 goto err;
886
887 log_warn(LD_CONFIG, "Managed proxy could not pick a "
888 "configuration protocol version.");
889 goto err;
890 } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
891 if (mp->conf_state != PT_PROTO_LAUNCHED)
892 goto err;
893
894 if (parse_version(line,mp) < 0)
895 goto err;
896
897 tor_assert(mp->conf_protocol != 0);
898 managed_proxy_set_state(mp, PT_PROTO_ACCEPTING_METHODS);
899 return;
900 } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
901 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
902 goto err;
903
905
906 managed_proxy_set_state(mp, PT_PROTO_CONFIGURED);
907 return;
908 } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
909 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
910 goto err;
911
913
914 managed_proxy_set_state(mp, PT_PROTO_CONFIGURED);
915 return;
916 } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
917 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
918 goto err;
919
920 /* Log the error but do not kill the managed proxy.
921 * A proxy may contain several transports and if one
922 * of them is misconfigured, we still want to use
923 * the other transports. A managed proxy with no usable
924 * transports will log a warning.
925 * See https://gitlab.torproject.org/tpo/core/tor/-/issues/7362
926 * */
927 parse_client_method_error(line);
928 return;
929 } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
930 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
931 goto err;
932
933 /* Log the error but do not kill the managed proxy */
934 parse_server_method_error(line);
935 return;
936 } else if (!strcmpstart(line, PROTO_CMETHOD)) {
937 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
938 goto err;
939
940 if (parse_cmethod_line(line, mp) < 0)
941 goto err;
942
943 return;
944 } else if (!strcmpstart(line, PROTO_SMETHOD)) {
945 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
946 goto err;
947
948 if (parse_smethod_line(line, mp) < 0)
949 goto err;
950
951 return;
952 } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
953 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
954 goto err;
955
956 if (mp->proxy_uri) {
957 mp->proxy_supported = 1;
958 return;
959 }
960
961 /* No proxy was configured, this should log */
962 } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
963 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
964 goto err;
965
966 parse_proxy_error(line);
967 goto err;
968
969 /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
970 * string to make sure we can later extend this big if/else-if table with
971 * something that begins with "LOG" without having to get the order right.
972 * */
973 } else if (!strcmpstart(line, PROTO_LOG " ")) {
974 parse_log_line(line, mp);
975 return;
976 } else if (!strcmpstart(line, PROTO_STATUS " ")) {
977 parse_status_line(line, mp);
978 return;
979 }
980
981 log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
982 return;
983
984 err:
985 managed_proxy_set_state(mp, PT_PROTO_BROKEN);
986 log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
987 " and will be destroyed.", mp->argv[0]);
988}
989
990/** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
991STATIC void
992parse_env_error(const char *line)
993{
994 /* (Length of the protocol string) plus (a space) and (the first char of
995 the error message) */
996 if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
997 log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
998 "message.", PROTO_ENV_ERROR);
999
1000 log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
1001 "pluggable transport environment variables. (%s)",
1002 line+strlen(PROTO_ENV_ERROR)+1);
1003}
1004
1005/** Handles a VERSION <b>line</b>. Updates the configuration protocol
1006 * version in <b>mp</b>. */
1007STATIC int
1008parse_version(const char *line, managed_proxy_t *mp)
1009{
1010 if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
1011 log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
1012 PROTO_NEG_SUCCESS);
1013 return -1;
1014 }
1015
1016 if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
1017 log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
1018 "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
1019 return -1;
1020 }
1021
1022 mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
1023 return 0;
1024}
1025
1026/** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
1027 * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
1028 * otherwise it is a CMETHOD-ERROR. */
1029static void
1030parse_method_error(const char *line, int is_server)
1031{
1032 const char* error = is_server ?
1033 PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
1034
1035 /* (Length of the protocol string) plus (a space) and (the first char of
1036 the error message) */
1037 if (strlen(line) < (strlen(error) + 2))
1038 log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
1039 "message.", error);
1040
1041 log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
1042 is_server ? "Server" : "Client",
1043 line+strlen(error)+1);
1044}
1045
1046/** A helper for parse_{c,s}method_line(), bootstraps its
1047 * functionalities. If <b>is_smethod</b> is true then the
1048 * the line to parse is a SMETHOD line otherwise it is a
1049 * CMETHOD line*/
1050static int
1052 managed_proxy_t *mp,
1053 int is_smethod)
1054{
1055 int item_index = 0;
1056 int r;
1057
1058 char *transport_name=NULL;
1059 char *args_string=NULL;
1060 char *addrport=NULL;
1061 int socks_ver=PROXY_NONE;
1062 char *address=NULL;
1063 uint16_t port = 0;
1064
1065 const char *method_str = is_smethod ? PROTO_SMETHOD : PROTO_CMETHOD;
1066 const int min_args_count = is_smethod ? 3 : 4;
1067
1068 tor_addr_t tor_addr;
1069 transport_t *transport=NULL;
1070 smartlist_t *items= smartlist_new();
1071
1072 smartlist_split_string(items, line, NULL,
1073 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1074 if (smartlist_len(items) < min_args_count) {
1075 log_warn(LD_CONFIG, "Managed proxy sent us a %s line "
1076 "with too few arguments.", method_str);
1077 goto err;
1078 }
1079
1080 tor_assert(!strcmp(smartlist_get(items, item_index),method_str));
1081 ++item_index;
1082
1083 transport_name = smartlist_get(items,item_index);
1084 ++item_index;
1085 if (!string_is_C_identifier(transport_name)) {
1086 log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
1087 transport_name);
1088 goto err;
1089 }
1090
1091 /** Check for the proxy method sent to us in CMETHOD line. */
1092 if (!is_smethod) {
1093 const char *socks_ver_str = smartlist_get(items,item_index);
1094 ++item_index;
1095
1096 if (!strcmp(socks_ver_str,"socks4")) {
1097 socks_ver = PROXY_SOCKS4;
1098 } else if (!strcmp(socks_ver_str,"socks5")) {
1099 socks_ver = PROXY_SOCKS5;
1100 } else {
1101 log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
1102 "we don't recognize. (%s)", socks_ver_str);
1103 goto err;
1104 }
1105 }
1106
1107 addrport = smartlist_get(items, item_index);
1108 ++item_index;
1109 if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) {
1110 log_warn(LD_CONFIG, "Error parsing transport address '%s'", addrport);
1111 goto err;
1112 }
1113
1114 if (!port) {
1115 log_warn(LD_CONFIG,
1116 "Transport address '%s' has no port.", addrport);
1117 goto err;
1118 }
1119
1120 if (tor_addr_parse(&tor_addr, address) < 0) {
1121 log_warn(LD_CONFIG, "Error parsing transport address '%s'", address);
1122 goto err;
1123 }
1124
1125 /** Check for options in the SMETHOD line. */
1126 if (is_smethod && smartlist_len(items) > min_args_count) {
1127 /* Seems like there are also some [options] in the SMETHOD line.
1128 Let's see if we can parse them. */
1129 char *options_string = smartlist_get(items, item_index);
1130 log_debug(LD_CONFIG, "Got options_string: %s", options_string);
1131 if (!strcmpstart(options_string, "ARGS:")) {
1132 args_string = options_string+strlen("ARGS:");
1133 log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
1134 }
1135 }
1136
1137 transport = transport_new(&tor_addr, port, transport_name,
1138 socks_ver, args_string);
1139
1140 smartlist_add(mp->transports, transport);
1141
1142 /** Logs info about line parsing success for client or server */
1143 if (is_smethod) {
1144 log_info(LD_CONFIG, "Server transport %s at %s:%d.",
1145 transport_name, address, (int)port);
1146 } else {
1147 log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
1148 "Attached to managed proxy.",
1149 transport_name, address, (int)port, socks_ver);
1150 }
1151
1152 r=0;
1153 goto done;
1154
1155 err:
1156 r = -1;
1157
1158 done:
1159 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
1160 smartlist_free(items);
1161 tor_free(address);
1162 return r;
1163}
1164
1165/** Parses an SMETHOD <b>line</b> and if well-formed it registers the
1166 * new transport in <b>mp</b>. */
1167STATIC int
1168parse_smethod_line(const char *line, managed_proxy_t *mp)
1169{
1170 /* Example of legit SMETHOD line:
1171 SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
1172 return parse_method_line_helper(line, mp, 1);
1173}
1174
1175/** Parses a CMETHOD <b>line</b>, and if well-formed it registers
1176 * the new transport in <b>mp</b>. */
1177STATIC int
1178parse_cmethod_line(const char *line, managed_proxy_t *mp)
1179{
1180 /* Example of legit CMETHOD line:
1181 CMETHOD obfs2 socks5 127.0.0.1:35713 */
1182 return parse_method_line_helper(line, mp, 0);
1183}
1184
1185/** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
1186STATIC void
1187parse_proxy_error(const char *line)
1188{
1189 /* (Length of the protocol string) plus (a space) and (the first char of
1190 the error message) */
1191 if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
1192 log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
1193 "message.", PROTO_PROXY_ERROR);
1194
1195 log_warn(LD_CONFIG, "Managed proxy failed to configure the "
1196 "pluggable transport's outgoing proxy. (%s)",
1197 line+strlen(PROTO_PROXY_ERROR)+1);
1198}
1199
1200/** Parses a LOG <b>line</b> and emit log events accordingly. */
1201STATIC void
1202parse_log_line(const char *line, managed_proxy_t *mp)
1203{
1204 tor_assert(line);
1205 tor_assert(mp);
1206
1207 config_line_t *values = NULL;
1208 char *log_message = NULL;
1209
1210 if (strlen(line) < (strlen(PROTO_LOG) + 1)) {
1211 log_warn(LD_PT, "Managed proxy sent us a %s line "
1212 "with missing argument.", PROTO_LOG);
1213 goto done;
1214 }
1215
1216 const char *data = line + strlen(PROTO_LOG) + 1;
1217 values = kvline_parse(data, KV_QUOTED);
1218
1219 if (! values) {
1220 log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid LOG message: %s",
1221 mp->argv[0], data);
1222 goto done;
1223 }
1224
1225 const config_line_t *severity = config_line_find(values, "SEVERITY");
1226 const config_line_t *message = config_line_find(values, "MESSAGE");
1227
1228 /* Check if we got a message. */
1229 if (! message) {
1230 log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1231 "MESSAGE: %s", mp->argv[0], escaped(data));
1232 goto done;
1233 }
1234
1235 /* Check if severity is there and whether it's valid. */
1236 if (! severity) {
1237 log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1238 "SEVERITY: %s", mp->argv[0], escaped(data));
1239 goto done;
1240 }
1241
1242 int log_severity = managed_proxy_severity_parse(severity->value);
1243
1244 if (log_severity == -1) {
1245 log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line with an "
1246 "invalid severity level: %s",
1247 mp->argv[0], severity->value);
1248 goto done;
1249 }
1250
1251 tor_log(log_severity, LD_PT, "Managed proxy \"%s\": %s",
1252 mp->argv[0], message->value);
1253
1254 /* Prepend the PT name. */
1255 config_line_prepend(&values, "PT", mp->argv[0]);
1256 log_message = kvline_encode(values, KV_QUOTED);
1257
1258 /* Emit control port event. */
1259 control_event_pt_log(log_message);
1260
1261 done:
1262 config_free_lines(values);
1263 tor_free(log_message);
1264}
1265
1266/** Parses a STATUS <b>line</b> and emit control events accordingly. */
1267STATIC void
1268parse_status_line(const char *line, managed_proxy_t *mp)
1269{
1270 tor_assert(line);
1271 tor_assert(mp);
1272
1273 config_line_t *values = NULL;
1274 char *status_message = NULL;
1275
1276 if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
1277 log_warn(LD_PT, "Managed proxy sent us a %s line "
1278 "with missing argument.", PROTO_STATUS);
1279 goto done;
1280 }
1281
1282 const char *data = line + strlen(PROTO_STATUS) + 1;
1283
1284 values = kvline_parse(data, KV_QUOTED);
1285
1286 if (! values) {
1287 log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
1288 "STATUS message: %s", mp->argv[0], escaped(data));
1289 goto done;
1290 }
1291
1292 /* Handle the different messages. */
1293 handle_status_message(values, mp);
1294
1295 /* Prepend the PT name. */
1296 config_line_prepend(&values, "PT", mp->argv[0]);
1297 status_message = kvline_encode(values, KV_QUOTED);
1298
1299 /* We have checked that TRANSPORT is there, we can now emit the STATUS event
1300 * via the control port. */
1301 control_event_pt_status(status_message);
1302
1303 done:
1304 config_free_lines(values);
1305 tor_free(status_message);
1306}
1307
1308STATIC void
1309handle_status_message(const config_line_t *values,
1310 managed_proxy_t *mp)
1311{
1312 if (config_count_key(values, "TYPE") > 1) {
1313 log_warn(LD_PT, "Managed proxy \"%s\" has multiple TYPE key which "
1314 "is not allowed.", mp->argv[0]);
1315 return;
1316 }
1317 const config_line_t *message_type = config_line_find(values, "TYPE");
1318
1319 /* Check if we have a TYPE field? */
1320 if (message_type == NULL) {
1321 log_debug(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
1322 "a defined message TYPE", mp->argv[0]);
1323 return;
1324 }
1325
1326 /* Handle VERSION messages. */
1327 if (! strcasecmp(message_type->value, "version")) {
1328 const config_line_t *version = config_line_find(values, "VERSION");
1329 const config_line_t *implementation = config_line_find(values,
1330 "IMPLEMENTATION");
1331
1332 if (version == NULL) {
1333 log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS TYPE=version line "
1334 "with a missing VERSION field", mp->argv[0]);
1335 return;
1336 }
1337
1338 if (implementation == NULL) {
1339 log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS TYPE=version line "
1340 "with a missing IMPLEMENTATION field", mp->argv[0]);
1341 return;
1342 }
1343
1344 tor_free(mp->version);
1345 mp->version = tor_strdup(version->value);
1346
1347 tor_free(mp->implementation);
1348 mp->implementation = tor_strdup(implementation->value);
1349
1350 return;
1351 }
1352}
1353
1354/** Return a newly allocated string that tor should place in
1355 * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
1356 * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
1357STATIC char *
1359{
1360 char *options_string = NULL;
1361 smartlist_t *string_sl = smartlist_new();
1362
1363 tor_assert(mp->is_server);
1364
1365 /** Loop over the transports of the proxy. If we have options for
1366 any of them, format them appropriately and place them in our
1367 smartlist. Finally, join our smartlist to get the final
1368 string. */
1369 SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
1370 smartlist_t *options_tmp_sl = NULL;
1371 options_tmp_sl = pt_get_options_for_server_transport(transport);
1372 if (!options_tmp_sl)
1373 continue;
1374
1375 /** Loop over the options of this transport, escape them, and
1376 place them in the smartlist. */
1377 SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
1378 char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
1379 smartlist_add_asprintf(string_sl, "%s:%s",
1380 transport, escaped_opts);
1381 tor_free(escaped_opts);
1382 } SMARTLIST_FOREACH_END(options);
1383
1384 SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
1385 smartlist_free(options_tmp_sl);
1386 } SMARTLIST_FOREACH_END(transport);
1387
1388 if (smartlist_len(string_sl)) {
1389 options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
1390 }
1391
1392 SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
1393 smartlist_free(string_sl);
1394
1395 return options_string;
1396}
1397
1398/** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
1399 * while configuring the server managed proxy in <b>mp</b>. The
1400 * string is stored in the heap, and it's the responsibility of
1401 * the caller to deallocate it after its use. */
1402static char *
1403get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
1404{
1405 char *bindaddr_result = NULL;
1406 char *bindaddr_tmp = NULL;
1407 smartlist_t *string_tmp = smartlist_new();
1408
1409 tor_assert(mp->is_server);
1410
1411 SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
1413
1414 smartlist_add_asprintf(string_tmp, "%s-%s", t, bindaddr_tmp);
1415
1416 tor_free(bindaddr_tmp);
1417 } SMARTLIST_FOREACH_END(t);
1418
1419 bindaddr_result = smartlist_join_strings(string_tmp, ",", 0, NULL);
1420
1421 SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
1422 smartlist_free(string_tmp);
1423
1424 return bindaddr_result;
1425}
1426
1427/** Return a newly allocated process_environment_t * for <b>mp</b>'s
1428 * process. */
1429static smartlist_t *
1430create_managed_proxy_environment(const managed_proxy_t *mp)
1431{
1432 const or_options_t *options = get_options();
1433
1434 /* Environment variables to be added to or set in mp's environment. */
1435 smartlist_t *envs = smartlist_new();
1436 /* XXXX The next time someone touches this code, shorten the name of
1437 * set_environment_variable_in_smartlist, add a
1438 * set_env_var_in_smartlist_asprintf function, and get rid of the
1439 * silly extra envs smartlist. */
1440
1441 /* The final environment to be passed to mp. */
1443
1444 {
1445 char *state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
1446 smartlist_add_asprintf(envs, "TOR_PT_STATE_LOCATION=%s", state_tmp);
1447 tor_free(state_tmp);
1448 }
1449
1450 smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
1451
1452 {
1453 char *transports_to_launch =
1454 smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
1455
1457 mp->is_server ?
1458 "TOR_PT_SERVER_TRANSPORTS=%s" :
1459 "TOR_PT_CLIENT_TRANSPORTS=%s",
1460 transports_to_launch);
1461
1462 tor_free(transports_to_launch);
1463 }
1464
1465 if (mp->is_server) {
1466 {
1467 char *orport_tmp =
1469 if (orport_tmp) {
1470 smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
1471 tor_free(orport_tmp);
1472 }
1473 }
1474
1475 {
1476 char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
1477 smartlist_add_asprintf(envs, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
1478 tor_free(bindaddr_tmp);
1479 }
1480
1481 {
1482 char *server_transport_options =
1484 if (server_transport_options) {
1485 smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1486 server_transport_options);
1487 tor_free(server_transport_options);
1488 }
1489 }
1490
1491 /* XXXX Remove the '=' here once versions of obfsproxy which
1492 * assert that this env var exists are sufficiently dead.
1493 *
1494 * (If we remove this line entirely, some joker will stick this
1495 * variable in Tor's environment and crash PTs that try to parse
1496 * it even when not run in server mode.) */
1497
1498 if (options->ExtORPort_lines) {
1499 char *ext_or_addrport_tmp =
1501 char *cookie_file_loc = get_ext_or_auth_cookie_file_name();
1502
1503 if (ext_or_addrport_tmp) {
1504 smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1505 ext_or_addrport_tmp);
1506 }
1507 if (cookie_file_loc) {
1508 smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s",
1509 cookie_file_loc);
1510 }
1511
1512 tor_free(ext_or_addrport_tmp);
1513 tor_free(cookie_file_loc);
1514
1515 } else {
1516 smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
1517 }
1518 } else {
1519 /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
1520 * TOR_PT_PROXY line.
1521 */
1522
1523 if (mp->proxy_uri) {
1524 smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
1525 }
1526 }
1527
1528 /* All new versions of tor will keep stdin open, so PTs can use it
1529 * as a reliable termination detection mechanism.
1530 */
1531 smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
1532
1533 /* Specify which IPv4 and IPv6 addresses the PT should make its outgoing
1534 * connections from. See: https://bugs.torproject.org/5304 for more
1535 * information about this. */
1536 {
1537 /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V4. */
1538 const tor_addr_t *ipv4_addr = managed_proxy_outbound_address(options,
1539 AF_INET);
1540
1541 /* managed_proxy_outbound_address() only returns a non-NULL value if
1542 * tor_addr_is_null() was false, which means we don't have to check that
1543 * here. */
1544 if (ipv4_addr) {
1545 char *ipv4_addr_str = tor_addr_to_str_dup(ipv4_addr);
1547 "TOR_PT_OUTBOUND_BIND_ADDRESS_V4=%s",
1548 ipv4_addr_str);
1549 tor_free(ipv4_addr_str);
1550 }
1551
1552 /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V6. */
1553 const tor_addr_t *ipv6_addr = managed_proxy_outbound_address(options,
1554 AF_INET6);
1555 if (ipv6_addr) {
1556 char *ipv6_addr_str = tor_addr_to_str_dup(ipv6_addr);
1558 "TOR_PT_OUTBOUND_BIND_ADDRESS_V6=[%s]",
1559 ipv6_addr_str);
1560 tor_free(ipv6_addr_str);
1561 }
1562 }
1563
1564 SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
1565 set_environment_variable_in_smartlist(merged_env_vars, env_var,
1566 tor_free_, 1);
1567 } SMARTLIST_FOREACH_END(env_var);
1568
1569 smartlist_free(envs);
1570
1571 return merged_env_vars;
1572}
1573
1574/** Create and return a new managed proxy for <b>transport</b> using
1575 * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
1576 * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
1577 * <b>proxy_argv</b>.
1578 *
1579 * Requires that proxy_argv have at least one element. */
1580STATIC managed_proxy_t *
1581managed_proxy_create(const smartlist_t *with_transport_list,
1582 char **proxy_argv, int is_server)
1583{
1584 managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
1585 managed_proxy_set_state(mp, PT_PROTO_INFANT);
1586 mp->is_server = is_server;
1587 mp->argv = proxy_argv;
1588 mp->transports = smartlist_new();
1589 mp->proxy_uri = get_pt_proxy_uri();
1590
1591 /* Gets set in launch_managed_proxy(). */
1592 mp->process = NULL;
1593
1594 mp->transports_to_launch = smartlist_new();
1595 SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1596 add_transport_to_proxy(transport, mp));
1597
1598 /* register the managed proxy */
1599 if (!managed_proxy_list)
1603
1605
1606 return mp;
1607}
1608
1609/** Register proxy with <b>proxy_argv</b>, supporting transports in
1610 * <b>transport_list</b>, to the managed proxy subsystem.
1611 * If <b>is_server</b> is true, then the proxy is a server proxy.
1612 *
1613 * Takes ownership of proxy_argv.
1614 *
1615 * Requires that proxy_argv be a NULL-terminated array of command-line
1616 * elements, containing at least one element.
1617 **/
1618MOCK_IMPL(void,
1619pt_kickstart_proxy, (const smartlist_t *with_transport_list,
1620 char **proxy_argv, int is_server))
1621{
1622 managed_proxy_t *mp=NULL;
1623 transport_t *old_transport = NULL;
1624
1625 if (!proxy_argv || !proxy_argv[0]) {
1626 return;
1627 }
1628
1629 mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
1630
1631 if (!mp) { /* we haven't seen this proxy before */
1632 managed_proxy_create(with_transport_list, proxy_argv, is_server);
1633
1634 } else { /* known proxy. add its transport to its transport list */
1635 if (mp->was_around_before_config_read) {
1636 /* If this managed proxy was around even before we read the
1637 config this time, it means that it was already enabled before
1638 and is not useless and should be kept. If it's marked for
1639 removal, unmark it and make sure that we check whether it
1640 needs to be restarted. */
1641 if (mp->marked_for_removal) {
1642 mp->marked_for_removal = 0;
1644 }
1645
1646 /* For each new transport, check if the managed proxy used to
1647 support it before the SIGHUP. If that was the case, make sure
1648 it doesn't get removed because we might reuse it. */
1649 SMARTLIST_FOREACH_BEGIN(with_transport_list, const char *, transport) {
1650 old_transport = transport_get_by_name(transport);
1651 if (old_transport)
1652 old_transport->marked_for_removal = 0;
1653 } SMARTLIST_FOREACH_END(transport);
1654 }
1655
1656 SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1657 add_transport_to_proxy(transport, mp));
1658 free_execve_args(proxy_argv);
1659 }
1660}
1661
1662/** Frees the array of pointers in <b>arg</b> used as arguments to
1663 execve(2). */
1664STATIC void
1666{
1667 char **tmp = arg;
1668 while (*tmp) /* use the fact that the last element of the array is a
1669 NULL pointer to know when to stop freeing */
1670 tor_free_(*tmp++);
1671
1672 tor_free(arg);
1673}
1674
1675/** Tor will read its config.
1676 * Prepare the managed proxy list so that proxies not used in the new
1677 * config will shutdown, and proxies that need to spawn different
1678 * transports will do so. */
1679void
1681{
1682 if (!managed_proxy_list)
1683 return;
1684
1686 SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1687 /* Destroy unconfigured proxies. */
1688 if (mp->conf_state != PT_PROTO_COMPLETED) {
1690 managed_proxy_destroy(mp, 1);
1692 continue;
1693 }
1694
1695 tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1696
1697 /* Mark all proxies for removal, and also note that they have been
1698 here before the config read. */
1699 mp->marked_for_removal = 1;
1700 mp->was_around_before_config_read = 1;
1701 SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
1702 smartlist_clear(mp->transports_to_launch);
1703 } SMARTLIST_FOREACH_END(mp);
1704
1706
1708}
1709
1710/** Return a smartlist containing the ports where our pluggable
1711 * transports are listening. */
1714{
1715 smartlist_t *sl = NULL;
1716
1717 if (!managed_proxy_list)
1718 return NULL;
1719
1720 /** XXX assume that external proxy ports have been forwarded
1721 manually */
1722 SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1723 if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED)
1724 continue;
1725
1726 if (!sl) sl = smartlist_new();
1727
1728 tor_assert(mp->transports);
1729 SMARTLIST_FOREACH(mp->transports, const transport_t *, t,
1730 smartlist_add_asprintf(sl, "%u:%u", t->port, t->port));
1731
1732 } SMARTLIST_FOREACH_END(mp);
1733
1734 return sl;
1735}
1736
1737/** Return the pluggable transport string that we should display in
1738 * our extra-info descriptor. If we shouldn't display such a string,
1739 * or we have nothing to display, return NULL. The string is
1740 * allocated on the heap and it's the responsibility of the caller to
1741 * free it. */
1742char *
1744{
1745 char *the_string = NULL;
1746 smartlist_t *string_chunks = NULL;
1747
1748 if (!managed_proxy_list)
1749 return NULL;
1750
1751 string_chunks = smartlist_new();
1752
1753 /* For each managed proxy, add its transports to the chunks list. */
1754 SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1755 if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
1756 continue;
1757
1758 tor_assert(mp->transports);
1759
1760 SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1761 char *transport_args = NULL;
1762 const char *addrport = NULL;
1763
1764 /* If the transport proxy returned "0.0.0.0" as its address, and
1765 * we know our external IP address, use it. Otherwise, use the
1766 * returned address. */
1767 if (tor_addr_is_null(&t->addr)) {
1768 tor_addr_t addr;
1769 /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
1770 * can't find it. */
1771 bool found = relay_find_addr_to_publish(get_options(), AF_INET,
1772 RELAY_FIND_ADDR_NO_FLAG,
1773 &addr);
1774 if (!found) {
1775 found = relay_find_addr_to_publish(get_options(), AF_INET6,
1776 RELAY_FIND_ADDR_NO_FLAG, &addr);
1777 }
1778 if (!found) {
1779 log_err(LD_PT, "Unable to find address for transport %s", t->name);
1780 continue;
1781 }
1782 addrport = fmt_addrport(&addr, t->port);
1783 } else {
1784 addrport = fmt_addrport(&t->addr, t->port);
1785 }
1786
1787 /* If this transport has any arguments with it, prepend a space
1788 to them so that we can add them to the transport line. */
1789 if (t->extra_info_args)
1790 tor_asprintf(&transport_args, " %s", t->extra_info_args);
1791
1792 smartlist_add_asprintf(string_chunks,
1793 "transport %s %s%s",
1794 t->name, addrport,
1795 transport_args ? transport_args : "");
1796
1797 tor_free(transport_args);
1798 } SMARTLIST_FOREACH_END(t);
1799
1800 /* Set transport-info line. */
1801 {
1802 char *version = NULL;
1803 char *impl = NULL;
1804
1805 if (mp->version) {
1806 tor_asprintf(&version, " version=%s", mp->version);
1807 }
1808 if (mp->implementation) {
1809 tor_asprintf(&impl, " implementation=%s", mp->implementation);
1810 }
1811 /* Always put in the line even if empty. Else, we don't know to which
1812 * transport this applies to. */
1813 smartlist_add_asprintf(string_chunks, "transport-info%s%s",
1814 version ? version: "", impl ? impl: "");
1815 tor_free(version);
1816 tor_free(impl);
1817 }
1818 } SMARTLIST_FOREACH_END(mp);
1819
1820 if (smartlist_len(string_chunks) == 0) {
1821 smartlist_free(string_chunks);
1822 return NULL;
1823 }
1824
1825 /* Join all the chunks into the final string. */
1826 the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1827
1828 SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1829 smartlist_free(string_chunks);
1830
1831 return the_string;
1832}
1833
1834/** Log the bridge lines that clients can use to connect. */
1835void
1837{
1838 char fingerprint[FINGERPRINT_LEN+1];
1839 smartlist_t *string_chunks = NULL;
1840
1842 return;
1843
1844 if (crypto_pk_get_fingerprint(get_server_identity_key(), fingerprint, 0)<0) {
1845 log_err(LD_BUG, "Error computing fingerprint");
1846 return;
1847 }
1848
1849 string_chunks = smartlist_new();
1850
1851 SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1852 if (!mp->is_server)
1853 continue;
1854
1855 tor_assert(mp->transports);
1856
1857 SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1858 char *transport_args = NULL;
1859 const char *saddr = NULL;
1860
1861 /* If the transport proxy returned "0.0.0.0" as its address, display
1862 * our external address if we know it, or a placeholder if we don't */
1863 if (tor_addr_is_null(&t->addr)) {
1864 tor_addr_t addr;
1865 /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
1866 * can't find it. */
1867 bool found = relay_find_addr_to_publish(get_options(), AF_INET,
1868 RELAY_FIND_ADDR_NO_FLAG,
1869 &addr);
1870 if (!found) {
1871 found = relay_find_addr_to_publish(get_options(), AF_INET6,
1872 RELAY_FIND_ADDR_NO_FLAG, &addr);
1873 }
1874 if (found && !tor_addr_is_null(&addr)) {
1875 saddr = fmt_and_decorate_addr(&addr);
1876 } else {
1877 saddr = "<IP ADDRESS>";
1878 }
1879 } else {
1880 saddr = fmt_and_decorate_addr(&t->addr);
1881 }
1882
1883 /* If this transport has any arguments with it, prepend a space
1884 * to them so that we can add them to the transport line, and replace
1885 * commas with spaces to make it a valid bridge line. */
1886 if (t->extra_info_args) {
1887 tor_asprintf(&transport_args, " %s", t->extra_info_args);
1888 for (int i = 0; transport_args[i]; i++) {
1889 if (transport_args[i] == ',') {
1890 transport_args[i] = ' ';
1891 }
1892 }
1893 }
1894
1895 smartlist_add_asprintf(string_chunks, "Bridge %s %s:%d %s%s",
1896 t->name, saddr, t->port, fingerprint,
1897 transport_args ? transport_args : "");
1898 tor_free(transport_args);
1899 } SMARTLIST_FOREACH_END(t);
1900 } SMARTLIST_FOREACH_END(mp);
1901
1902 /* If we have any valid bridgelines, join them into a single string, and
1903 * save them to disk. Don't create an empty file. */
1904 if (smartlist_len(string_chunks) != 0) {
1905 char *str = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1906 char *fname = get_datadir_fname("bridgelines");
1907 if (write_str_to_file_if_not_equal(fname, str)) {
1908 log_warn(LD_FS, "Couldn't save bridge lines to disk");
1909 } else {
1910 log_info(LD_FS, "Saved bridge lines to disk");
1911 }
1912 tor_free(fname);
1913 tor_free(str);
1914 }
1915
1916 SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1917 smartlist_free(string_chunks);
1918}
1919
1920/** Stringify the SOCKS arguments in <b>socks_args</b> according to
1921 * 180_pluggable_transport.txt. The string is allocated on the heap
1922 * and it's the responsibility of the caller to free it after use. */
1923char *
1925{
1926 /* tmp place to store escaped socks arguments, so that we can
1927 concatenate them up afterwards */
1928 smartlist_t *sl_tmp = NULL;
1929 char *escaped_string = NULL;
1930 char *new_string = NULL;
1931
1932 tor_assert(socks_args);
1933 tor_assert(smartlist_len(socks_args) > 0);
1934
1935 sl_tmp = smartlist_new();
1936
1937 SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
1938 /* Escape ';' and '\'. */
1939 escaped_string = tor_escape_str_for_pt_args(s, ";\\");
1940 if (!escaped_string)
1941 goto done;
1942
1943 smartlist_add(sl_tmp, escaped_string);
1944 } SMARTLIST_FOREACH_END(s);
1945
1946 new_string = smartlist_join_strings(sl_tmp, ";", 0, NULL);
1947
1948 done:
1949 SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
1950 smartlist_free(sl_tmp);
1951
1952 return new_string;
1953}
1954
1955/** Return a string of the SOCKS arguments that we should pass to the
1956 * pluggable transports proxy in <b>addr</b>:<b>port</b> according to
1957 * 180_pluggable_transport.txt. The string is allocated on the heap
1958 * and it's the responsibility of the caller to free it after use. */
1959char *
1961{
1962 const smartlist_t *socks_args = NULL;
1963
1964 socks_args = get_socks_args_by_bridge_addrport(addr, port);
1965 if (!socks_args)
1966 return NULL;
1967
1968 return pt_stringify_socks_args(socks_args);
1969}
1970
1971/** The tor config was read.
1972 * Destroy all managed proxies that were marked by a previous call to
1973 * prepare_proxy_list_for_config_read() and are not used by the new
1974 * config. */
1975void
1977{
1978 if (!managed_proxy_list)
1979 return;
1981 SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1982 if (mp->marked_for_removal) {
1984 managed_proxy_destroy(mp, 1);
1985 }
1986 } SMARTLIST_FOREACH_END(mp);
1988}
1989
1990/** Release all storage held by the pluggable transports subsystem. */
1991void
1993{
1994 if (transport_list) {
1996 smartlist_free(transport_list);
1997 transport_list = NULL;
1998 }
1999
2000 if (managed_proxy_list) {
2001 /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
2002 transports and it's the duty of the circuitbuild.c subsystem to
2003 free them. Otherwise, it hasn't registered its transports yet
2004 and we should free them here. */
2005 SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
2007 managed_proxy_destroy(mp, 1);
2008 });
2009
2010 smartlist_free(managed_proxy_list);
2011 managed_proxy_list=NULL;
2012 }
2013}
2014
2015/** Return a newly allocated string equal to <b>string</b>, except that every
2016 * character in <b>chars_to_escape</b> is preceded by a backslash. */
2017char *
2018tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
2019{
2020 char *new_string = NULL;
2021 char *new_cp = NULL;
2022 size_t length, new_length;
2023
2024 tor_assert(string);
2025
2026 length = strlen(string);
2027
2028 if (!length) /* If we were given the empty string, return the same. */
2029 return tor_strdup("");
2030 /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
2031 (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
2032 if (length > (SIZE_MAX - 1)/2) /* check for overflow */
2033 return NULL;
2034
2035 /* this should be enough even if all characters must be escaped */
2036 new_length = (length * 2) + 1;
2037
2038 new_string = new_cp = tor_malloc(new_length);
2039
2040 while (*string) {
2041 if (strchr(chars_to_escape, *string))
2042 *new_cp++ = '\\';
2043
2044 *new_cp++ = *string++;
2045 }
2046
2047 *new_cp = '\0'; /* NUL-terminate the new string */
2048
2049 return new_string;
2050}
2051
2052/** Callback function that is called when our PT process have data on its
2053 * stdout. Our process can be found in <b>process</b>, the data can be found in
2054 * <b>line</b> and the length of our line is given in <b>size</b>. */
2055STATIC void
2057 const char *line,
2058 size_t size)
2059{
2060 tor_assert(process);
2061 tor_assert(line);
2062
2063 (void)size;
2064
2065 managed_proxy_t *mp = process_get_data(process);
2066
2067 if (mp == NULL)
2068 return;
2069
2070 handle_proxy_line(line, mp);
2071
2074}
2075
2076/** Callback function that is called when our PT process have data on its
2077 * stderr. Our process can be found in <b>process</b>, the data can be found in
2078 * <b>line</b> and the length of our line is given in <b>size</b>. */
2079STATIC void
2081 const char *line,
2082 size_t size)
2083{
2084 tor_assert(process);
2085 tor_assert(line);
2086
2087 (void)size;
2088
2089 managed_proxy_t *mp = process_get_data(process);
2090
2091 if (BUG(mp == NULL))
2092 return;
2093
2094 log_info(LD_PT,
2095 "Managed proxy at '%s' reported via standard error: %s",
2096 mp->argv[0], line);
2097}
2098
2099/** Callback function that is called when our PT process terminates. The
2100 * process exit code can be found in <b>exit_code</b> and our process can be
2101 * found in <b>process</b>. Returns true iff we want the process subsystem to
2102 * free our process_t handle for us. */
2103STATIC bool
2104managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
2105{
2106 tor_assert(process);
2107
2108 managed_proxy_t *mp = process_get_data(process);
2109 const char *name = mp ? mp->argv[0] : "N/A";
2110
2111 log_warn(LD_PT,
2112 "Managed proxy \"%s\" process terminated with status code %" PRIu64,
2113 name, exit_code);
2114
2115 if (mp) {
2116 /* We remove this process_t from the mp. */
2117 tor_assert(mp->process == process);
2118 mp->process = NULL;
2119
2120 /* Prepare the proxy for restart. */
2122
2123 /* We have proxies we want to restart? */
2125 }
2126
2127 /* Returning true here means that the process subsystem will take care of
2128 * calling process_free() on our process_t. */
2129 return true;
2130}
2131
2132/** Returns a valid integer log severity level from <b>severity</b> that
2133 * is compatible with Tor's logging functions. Returns <b>-1</b> on
2134 * error. */
2135STATIC int
2136managed_proxy_severity_parse(const char *severity)
2137{
2138 tor_assert(severity);
2139
2140 /* Slightly different than log.c's parse_log_level :-( */
2141 if (! strcmp(severity, "debug"))
2142 return LOG_DEBUG;
2143
2144 if (! strcmp(severity, "info"))
2145 return LOG_INFO;
2146
2147 if (! strcmp(severity, "notice"))
2148 return LOG_NOTICE;
2149
2150 if (! strcmp(severity, "warning"))
2151 return LOG_WARN;
2152
2153 if (! strcmp(severity, "error"))
2154 return LOG_ERR;
2155
2156 return -1;
2157}
2158
2159/** Return the outbound address from the given <b>family</b>. Returns NULL if
2160 * the user haven't specified a specific outbound address in either
2161 * OutboundBindAddress or OutboundBindAddressPT. */
2162STATIC const tor_addr_t *
2164{
2165 tor_assert(options);
2166
2167 const tor_addr_t *address = NULL;
2168 int family_index;
2169
2170 switch (family) {
2171 case AF_INET:
2172 family_index = 0;
2173 break;
2174 case AF_INET6:
2175 family_index = 1;
2176 break;
2177 default:
2178 /* LCOV_EXCL_START */
2179 tor_assert_unreached();
2180 return NULL;
2181 /* LCOV_EXCL_STOP */
2182 }
2183
2184 /* We start by checking if the user specified an address in
2185 * OutboundBindAddressPT. */
2186 address = &options->OutboundBindAddresses[OUTBOUND_ADDR_PT][family_index];
2187
2188 if (! tor_addr_is_null(address))
2189 return address;
2190
2191 /* We fallback to check if the user specified an address in
2192 * OutboundBindAddress. */
2193 address = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY][family_index];
2194
2195 if (! tor_addr_is_null(address))
2196 return address;
2197
2198 /* The user have not specified a preference for outgoing connections. */
2199 return NULL;
2200}
2201
2202STATIC const char *
2203managed_proxy_state_to_string(enum pt_proto_state state)
2204{
2205 switch (state) {
2206 case PT_PROTO_INFANT:
2207 return "Infant";
2208 case PT_PROTO_LAUNCHED:
2209 return "Launched";
2210 case PT_PROTO_ACCEPTING_METHODS:
2211 return "Accepting methods";
2212 case PT_PROTO_CONFIGURED:
2213 return "Configured";
2214 case PT_PROTO_COMPLETED:
2215 return "Completed";
2216 case PT_PROTO_BROKEN:
2217 return "Broken";
2218 case PT_PROTO_FAILED_LAUNCH:
2219 return "Failed to launch";
2220 }
2221
2222 /* LCOV_EXCL_START */
2223 tor_assert_unreached();
2224 return NULL;
2225 /* LCOV_EXCL_STOP */
2226}
2227
2228/** Set the internal state of the given <b>mp</b> to the given <b>new_state</b>
2229 * value. */
2230STATIC void
2231managed_proxy_set_state(managed_proxy_t *mp, enum pt_proto_state new_state)
2232{
2233 if (mp->conf_state == new_state)
2234 return;
2235
2236 tor_log(LOG_INFO, LD_PT, "Managed proxy \"%s\" changed state: %s -> %s",
2237 mp->argv[0],
2238 managed_proxy_state_to_string(mp->conf_state),
2239 managed_proxy_state_to_string(new_state));
2240
2241 mp->conf_state = new_state;
2242}
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:243
#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:6750
const char * name
Definition config.c:2472
const or_options_t * get_options(void)
Definition config.c:948
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.
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_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: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)
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)
static void register_client_proxy(const managed_proxy_t *mp)
Definition transports.c:685
static void handle_methods_done(const managed_proxy_t *mp)
Definition transports.c:855
static void register_proxy(const managed_proxy_t *mp)
Definition transports.c:714
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)
static int unconfigured_proxies_n
Definition transports.c:368
STATIC char * get_pt_proxy_uri(void)
Definition transports.c:766
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:150
void pt_configure_remaining_proxies(void)
Definition transports.c:594
STATIC void parse_proxy_error(const char *line)
STATIC void managed_proxy_destroy(managed_proxy_t *mp, int also_terminate_process)
Definition transports.c:724
void sweep_proxy_list(void)
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)
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:181
static int proxy_needs_restart(const managed_proxy_t *mp)
Definition transports.c:473
#define PROTO_ENV_ERROR
Definition transports.c:125
void pt_update_bridge_lines(void)
static void proxy_prepare_for_restart(managed_proxy_t *mp)
Definition transports.c:516
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:806
static int transport_add(transport_t *t)
Definition transports.c:317
STATIC void parse_status_line(const char *line, managed_proxy_t *mp)
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)
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)
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:192
static void assert_unconfigured_count_ok(void)
Definition transports.c:405
static char * get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
void transport_free_(transport_t *transport)
Definition transports.c:168
STATIC void parse_env_error(const char *line)
Definition transports.c:992
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:370
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:258
STATIC int configure_proxy(managed_proxy_t *mp)
Definition transports.c:651
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:846
char * pt_get_extra_info_descriptor_string(void)
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:872
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)