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