1 /* Copyright (c) 2011, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Pluggable Transports related code.
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.
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.
18 * In every run_scheduled_event() tick, we attempt to launch and then
19 * configure the unconfiged 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.
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.
27 * When a managed proxy fails to follow the 180 configuration
28 * protocol, it gets marked as broken and gets destroyed.
30 * <b>In a little more detail:</b>
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>
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.
41 * When the managed proxy stops spitting METHOD lines (signified by a
42 * '{S,C}METHODS DONE' message) we register all the transports
43 * collected to the circuitbuild.c subsystem. At this point, the
44 * pointers to transport_t can be transformed into dangling pointers
45 * at any point by the circuitbuild.c subsystem, and so we replace all
46 * transport_t pointers with strings describing the transport names.
47 * We can still go from a transport name to a transport_t using the
48 * fact that each transport name uniquely identifies a transport_t.
50 * <b>In even more detail, this is what happens when a SIGHUP
53 * We immediately destroy all unconfigured proxies (We shouldn't have
54 * unconfigured proxies in the first place, except when SIGHUP rings
55 * immediately after tor is launched.).
57 * We mark all managed proxies and transports to signify that they
58 * must be removed if they don't contribute by the new torrc
59 * (we mark using the <b>marked_for_removal</b> element).
60 * We also mark all managed proxies to signify that they might need to
61 * be restarted so that they end up supporting all the transports the
62 * new torrc wants them to support (using the <b>got_hup</b> element).
63 * We also clear their <b>transports_to_launch</b> list so that we can
64 * put there the transports we need to launch according to the new
67 * We then start parsing torrc again.
69 * Everytime we encounter a transport line using a known pre-SIGHUP
70 * managed proxy, we cleanse that proxy from the removal mark.
71 * We also mark it as unconfigured so that on the next scheduled
72 * events tick, we investigate whether we need to restart the proxy
73 * so that it also spawns the new transports.
74 * If the post-SIGHUP <b>transports_to_launch</b> list is identical to
75 * the pre-SIGHUP one, it means that no changes were introduced to
76 * this proxy during the SIGHUP and no restart has to take place.
78 * During the post-SIGHUP torrc parsing, we unmark all transports
79 * spawned by managed proxies that we find in our torrc.
80 * We do that so that if we don't need to restart a managed proxy, we
81 * can continue using its old transports normally.
82 * If we end up restarting the proxy, we destroy and unregister all
83 * old transports from the circuitbuild.c subsystem.
89 #include "circuitbuild.h"
90 #include "transports.h"
94 static process_environment_t
*
95 create_managed_proxy_environment(const managed_proxy_t
*mp
);
97 static INLINE
int proxy_configuration_finished(const managed_proxy_t
*mp
);
99 static void managed_proxy_destroy(managed_proxy_t
*mp
,
100 int also_terminate_process
);
102 static void handle_finished_proxy(managed_proxy_t
*mp
);
103 static void configure_proxy(managed_proxy_t
*mp
);
105 static void parse_method_error(const char *line
, int is_server_method
);
106 #define parse_server_method_error(l) parse_method_error(l, 1)
107 #define parse_client_method_error(l) parse_method_error(l, 0)
109 static INLINE
void free_execve_args(char **arg
);
111 /** Managed proxy protocol strings */
112 #define PROTO_ENV_ERROR "ENV-ERROR"
113 #define PROTO_NEG_SUCCESS "VERSION"
114 #define PROTO_NEG_FAIL "VERSION-ERROR no-version"
115 #define PROTO_CMETHOD "CMETHOD"
116 #define PROTO_SMETHOD "SMETHOD"
117 #define PROTO_CMETHOD_ERROR "CMETHOD-ERROR"
118 #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
119 #define PROTO_CMETHODS_DONE "CMETHODS DONE"
120 #define PROTO_SMETHODS_DONE "SMETHODS DONE"
122 /* The smallest valid managed proxy protocol line that can
123 appear. It's the size of "VERSION 1" */
124 #define SMALLEST_MANAGED_LINE_SIZE 9
126 /** Number of environment variables for managed proxy clients/servers. */
127 #define ENVIRON_SIZE_CLIENT 3
128 #define ENVIRON_SIZE_SERVER 7 /* XXX known to be too high, but that's ok */
130 /** The first and only supported - at the moment - configuration
132 #define PROTO_VERSION_ONE 1
134 /** List of unconfigured managed proxies. */
135 static smartlist_t
*managed_proxy_list
= NULL
;
136 /** Number of still unconfigured proxies. */
137 static int unconfigured_proxies_n
= 0;
138 /** Boolean: True iff we might need to restart some proxies. */
139 static int check_if_restarts_needed
= 0;
141 /** Return true if there are still unconfigured managed proxies, or proxies
142 * that need restarting. */
144 pt_proxies_configuration_pending(void)
146 return unconfigured_proxies_n
|| check_if_restarts_needed
;
149 /** Assert that the unconfigured_proxies_n value correctly matches the number
150 * of proxies in a state other than PT_PROTO_COMPLETE. */
152 assert_unconfigured_count_ok(void)
155 if (!managed_proxy_list
) {
156 tor_assert(unconfigured_proxies_n
== 0);
160 SMARTLIST_FOREACH(managed_proxy_list
, managed_proxy_t
*, mp
, {
161 if (mp
->conf_state
== PT_PROTO_COMPLETED
)
165 tor_assert(n_completed
+ unconfigured_proxies_n
==
166 smartlist_len(managed_proxy_list
));
169 /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
171 managed_proxy_has_argv(const managed_proxy_t
*mp
, char **proxy_argv
)
173 char **tmp1
=proxy_argv
;
174 char **tmp2
=mp
->argv
;
179 while (*tmp1
&& *tmp2
) {
180 if (strcmp(*tmp1
++, *tmp2
++))
184 if (!*tmp1
&& !*tmp2
)
190 /** Return a managed proxy with the same argv as <b>proxy_argv</b>.
191 * If no such managed proxy exists, return NULL. */
192 static managed_proxy_t
*
193 get_managed_proxy_by_argv_and_type(char **proxy_argv
, int is_server
)
195 if (!managed_proxy_list
)
198 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, managed_proxy_t
*, mp
) {
199 if (managed_proxy_has_argv(mp
, proxy_argv
) &&
200 mp
->is_server
== is_server
)
202 } SMARTLIST_FOREACH_END(mp
);
207 /** Add <b>transport</b> to managed proxy <b>mp</b>. */
209 add_transport_to_proxy(const char *transport
, managed_proxy_t
*mp
)
211 tor_assert(mp
->transports_to_launch
);
212 if (!smartlist_string_isin(mp
->transports_to_launch
, transport
))
213 smartlist_add(mp
->transports_to_launch
, tor_strdup(transport
));
216 /** Called when a SIGHUP occurs. Returns true if managed proxy
217 * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
220 proxy_needs_restart(const managed_proxy_t
*mp
)
222 /* mp->transport_to_launch is populated with the names of the
223 transports that must be launched *after* the SIGHUP.
224 mp->transports is populated with the names of the transports that
225 were launched *before* the SIGHUP.
227 If the two lists contain the same strings, we don't need to
228 restart the proxy, since it already does what we want. */
230 tor_assert(smartlist_len(mp
->transports_to_launch
) > 0);
231 tor_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
233 if (smartlist_len(mp
->transports_to_launch
) != smartlist_len(mp
->transports
))
236 SMARTLIST_FOREACH_BEGIN(mp
->transports_to_launch
, char *, t_t_l
) {
237 if (!smartlist_string_isin(mp
->transports
, t_t_l
))
240 } SMARTLIST_FOREACH_END(t_t_l
);
248 /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
249 * preparations and then flag its state so that it will be relaunched
250 * in the next tick. */
252 proxy_prepare_for_restart(managed_proxy_t
*mp
)
254 transport_t
*t_tmp
= NULL
;
256 tor_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
258 /* destroy the process handle and terminate the process. */
259 tor_process_handle_destroy(mp
->process_handle
, 1);
260 mp
->process_handle
= NULL
;
262 /* destroy all its old transports. we no longer use them. */
263 SMARTLIST_FOREACH_BEGIN(mp
->transports
, const char *, t_name
) {
264 t_tmp
= transport_get_by_name(t_name
);
266 t_tmp
->marked_for_removal
= 1;
267 } SMARTLIST_FOREACH_END(t_name
);
268 sweep_transport_list();
270 /* free the transport names in mp->transports */
271 SMARTLIST_FOREACH(mp
->transports
, char *, t_name
, tor_free(t_name
));
272 smartlist_clear(mp
->transports
);
274 /* flag it as an infant proxy so that it gets launched on next tick */
275 mp
->conf_state
= PT_PROTO_INFANT
;
276 unconfigured_proxies_n
++;
279 /** Launch managed proxy <b>mp</b>. */
281 launch_managed_proxy(managed_proxy_t
*mp
)
285 process_environment_t
*env
= create_managed_proxy_environment(mp
);
288 /* Passing NULL as lpApplicationName makes Windows search for the .exe */
289 retval
= tor_spawn_background(NULL
,
290 (const char **)mp
->argv
,
292 &mp
->process_handle
);
294 retval
= tor_spawn_background(mp
->argv
[0],
295 (const char **)mp
->argv
,
297 &mp
->process_handle
);
300 process_environment_free(env
);
302 if (retval
== PROCESS_STATUS_ERROR
) {
303 log_warn(LD_GENERAL
, "Managed proxy at '%s' failed at launch.",
308 log_info(LD_CONFIG
, "Managed proxy at '%s' has spawned with PID '%d'.",
309 mp
->argv
[0], tor_process_get_pid(mp
->process_handle
));
311 mp
->conf_state
= PT_PROTO_LAUNCHED
;
316 /** Check if any of the managed proxies we are currently trying to
317 * configure have anything new to say. This is called from
318 * run_scheduled_events(). */
320 pt_configure_remaining_proxies(void)
322 smartlist_t
*tmp
= smartlist_new();
324 log_debug(LD_CONFIG
, "Configuring remaining managed proxies (%d)!",
325 unconfigured_proxies_n
);
327 /* Iterate over tmp, not managed_proxy_list, since configure_proxy can
328 * remove elements from managed_proxy_list. */
329 smartlist_add_all(tmp
, managed_proxy_list
);
331 assert_unconfigured_count_ok();
333 SMARTLIST_FOREACH_BEGIN(tmp
, managed_proxy_t
*, mp
) {
334 tor_assert(mp
->conf_state
!= PT_PROTO_BROKEN
||
335 mp
->conf_state
!= PT_PROTO_FAILED_LAUNCH
);
340 /* This proxy is marked by a SIGHUP. Check whether we need to
342 if (proxy_needs_restart(mp
)) {
343 log_info(LD_GENERAL
, "Preparing managed proxy '%s' for restart.",
345 proxy_prepare_for_restart(mp
);
346 } else { /* it doesn't need to be restarted. */
347 log_info(LD_GENERAL
, "Nothing changed for managed proxy '%s' after HUP: "
348 "not restarting.", mp
->argv
[0]);
354 /* If the proxy is not fully configured, try to configure it
356 if (!proxy_configuration_finished(mp
))
359 } SMARTLIST_FOREACH_END(mp
);
362 check_if_restarts_needed
= 0;
363 assert_unconfigured_count_ok();
368 /** Attempt to continue configuring managed proxy <b>mp</b>. */
370 configure_proxy(managed_proxy_t
*mp
)
373 char stdout_buf
[200];
374 smartlist_t
*lines
= NULL
;
376 /* if we haven't launched the proxy yet, do it now */
377 if (mp
->conf_state
== PT_PROTO_INFANT
) {
378 if (launch_managed_proxy(mp
) < 0) { /* launch fail */
379 mp
->conf_state
= PT_PROTO_FAILED_LAUNCH
;
380 handle_finished_proxy(mp
);
385 tor_assert(mp
->conf_state
!= PT_PROTO_INFANT
);
386 tor_assert(mp
->process_handle
);
388 pos
= tor_read_all_handle(tor_process_get_stdout_pipe(mp
->process_handle
),
389 stdout_buf
, sizeof(stdout_buf
) - 1, NULL
);
391 log_notice(LD_GENERAL
, "Failed to read data from managed proxy '%s'.",
393 mp
->conf_state
= PT_PROTO_BROKEN
;
397 if (pos
== 0) /* proxy has nothing interesting to say. */
400 /* End with a null even if there isn't a \r\n at the end */
401 /* TODO: What if this is a partial line? */
402 stdout_buf
[pos
] = '\0';
404 /* Split up the buffer */
405 lines
= smartlist_new();
406 tor_split_lines(lines
, stdout_buf
, pos
);
409 SMARTLIST_FOREACH_BEGIN(lines
, const char *, line
) {
410 handle_proxy_line(line
, mp
);
411 if (proxy_configuration_finished(mp
))
413 } SMARTLIST_FOREACH_END(line
);
416 /* if the proxy finished configuring, exit the loop. */
417 if (proxy_configuration_finished(mp
))
418 handle_finished_proxy(mp
);
421 smartlist_free(lines
);
426 /** Attempt to continue configuring managed proxy <b>mp</b>. */
428 configure_proxy(managed_proxy_t
*mp
)
430 enum stream_status r
;
431 char stdout_buf
[200];
433 /* if we haven't launched the proxy yet, do it now */
434 if (mp
->conf_state
== PT_PROTO_INFANT
) {
435 if (launch_managed_proxy(mp
) < 0) { /* launch fail */
436 mp
->conf_state
= PT_PROTO_FAILED_LAUNCH
;
437 handle_finished_proxy(mp
);
442 tor_assert(mp
->conf_state
!= PT_PROTO_INFANT
);
443 tor_assert(mp
->process_handle
);
446 r
= get_string_from_pipe(tor_process_get_stdout_pipe(mp
->process_handle
),
447 stdout_buf
, sizeof(stdout_buf
) - 1);
449 if (r
== IO_STREAM_OKAY
) { /* got a line; handle it! */
450 handle_proxy_line((const char *)stdout_buf
, mp
);
451 } else if (r
== IO_STREAM_EAGAIN
) { /* check back later */
453 } else if (r
== IO_STREAM_CLOSED
|| r
== IO_STREAM_TERM
) { /* snap! */
454 log_warn(LD_GENERAL
, "Our communication channel with the managed proxy "
455 "'%s' closed. Most probably application stopped running.",
457 mp
->conf_state
= PT_PROTO_BROKEN
;
458 } else { /* unknown stream status */
459 log_warn(LD_BUG
, "Unknown stream status '%d' while configuring managed "
460 "proxy '%s'.", r
, mp
->argv
[0]);
463 /* if the proxy finished configuring, exit the loop. */
464 if (proxy_configuration_finished(mp
)) {
465 handle_finished_proxy(mp
);
473 /** Register server managed proxy <b>mp</b> transports to state */
475 register_server_proxy(managed_proxy_t
*mp
)
477 /* After we register this proxy's transports, we switch its
478 mp->transports to a list containing strings of its transport
479 names. (See transports.h) */
480 smartlist_t
*sm_tmp
= smartlist_new();
482 tor_assert(mp
->conf_state
!= PT_PROTO_COMPLETED
);
483 SMARTLIST_FOREACH_BEGIN(mp
->transports
, transport_t
*, t
) {
484 save_transport_to_state(t
->name
, &t
->addr
, t
->port
);
485 log_notice(LD_GENERAL
, "Registered server transport '%s' at '%s:%d'",
486 t
->name
, fmt_addr(&t
->addr
), (int)t
->port
);
487 smartlist_add(sm_tmp
, tor_strdup(t
->name
));
488 } SMARTLIST_FOREACH_END(t
);
490 /* Since server proxies don't register their transports in the
491 circuitbuild.c subsystem, it's our duty to free them when we
492 switch mp->transports to strings. */
493 SMARTLIST_FOREACH(mp
->transports
, transport_t
*, t
, transport_free(t
));
494 smartlist_free(mp
->transports
);
496 mp
->transports
= sm_tmp
;
499 /** Register all the transports supported by client managed proxy
500 * <b>mp</b> to the bridge subsystem. */
502 register_client_proxy(managed_proxy_t
*mp
)
505 /* After we register this proxy's transports, we switch its
506 mp->transports to a list containing strings of its transport
507 names. (See transports.h) */
508 smartlist_t
*sm_tmp
= smartlist_new();
510 tor_assert(mp
->conf_state
!= PT_PROTO_COMPLETED
);
511 SMARTLIST_FOREACH_BEGIN(mp
->transports
, transport_t
*, t
) {
512 r
= transport_add(t
);
515 log_notice(LD_GENERAL
, "Could not add transport %s. Skipping.", t
->name
);
519 log_info(LD_GENERAL
, "Succesfully registered transport %s", t
->name
);
520 smartlist_add(sm_tmp
, tor_strdup(t
->name
));
523 log_info(LD_GENERAL
, "Succesfully registered transport %s", t
->name
);
524 smartlist_add(sm_tmp
, tor_strdup(t
->name
));
528 } SMARTLIST_FOREACH_END(t
);
530 smartlist_free(mp
->transports
);
531 mp
->transports
= sm_tmp
;
534 /** Register the transports of managed proxy <b>mp</b>. */
536 register_proxy(managed_proxy_t
*mp
)
539 register_server_proxy(mp
);
541 register_client_proxy(mp
);
544 /** Free memory allocated by managed proxy <b>mp</b>. */
546 managed_proxy_destroy(managed_proxy_t
*mp
,
547 int also_terminate_process
)
549 if (mp
->conf_state
!= PT_PROTO_COMPLETED
)
550 SMARTLIST_FOREACH(mp
->transports
, transport_t
*, t
, transport_free(t
));
552 SMARTLIST_FOREACH(mp
->transports
, char *, t_name
, tor_free(t_name
));
554 /* free the transports smartlist */
555 smartlist_free(mp
->transports
);
557 /* free the transports_to_launch smartlist */
558 SMARTLIST_FOREACH(mp
->transports_to_launch
, char *, t
, tor_free(t
));
559 smartlist_free(mp
->transports_to_launch
);
561 /* remove it from the list of managed proxies */
562 smartlist_remove(managed_proxy_list
, mp
);
565 free_execve_args(mp
->argv
);
567 tor_process_handle_destroy(mp
->process_handle
, also_terminate_process
);
568 mp
->process_handle
= NULL
;
573 /** Handle a configured or broken managed proxy <b>mp</b>. */
575 handle_finished_proxy(managed_proxy_t
*mp
)
577 switch (mp
->conf_state
) {
578 case PT_PROTO_BROKEN
: /* if broken: */
579 managed_proxy_destroy(mp
, 1); /* annihilate it. */
581 case PT_PROTO_FAILED_LAUNCH
: /* if it failed before launching: */
582 managed_proxy_destroy(mp
, 0); /* destroy it but don't terminate */
584 case PT_PROTO_CONFIGURED
: /* if configured correctly: */
585 register_proxy(mp
); /* register its transports */
586 mp
->conf_state
= PT_PROTO_COMPLETED
; /* and mark it as completed. */
588 case PT_PROTO_INFANT
:
589 case PT_PROTO_LAUNCHED
:
590 case PT_PROTO_ACCEPTING_METHODS
:
591 case PT_PROTO_COMPLETED
:
593 log_warn(LD_CONFIG
, "Unexpected state '%d' of managed proxy '%s'.",
594 mp
->conf_state
, mp
->argv
[0]);
598 unconfigured_proxies_n
--;
599 tor_assert(unconfigured_proxies_n
>= 0);
602 /** Return true if the configuration of the managed proxy <b>mp</b> is
605 proxy_configuration_finished(const managed_proxy_t
*mp
)
607 return (mp
->conf_state
== PT_PROTO_CONFIGURED
||
608 mp
->conf_state
== PT_PROTO_BROKEN
||
609 mp
->conf_state
== PT_PROTO_FAILED_LAUNCH
);
612 /** This function is called when a proxy sends an {S,C}METHODS DONE message. */
614 handle_methods_done(const managed_proxy_t
*mp
)
616 tor_assert(mp
->transports
);
618 if (smartlist_len(mp
->transports
) == 0)
619 log_notice(LD_GENERAL
, "Managed proxy '%s' was spawned successfully, "
620 "but it didn't launch any pluggable transport listeners!",
623 log_info(LD_CONFIG
, "%s managed proxy '%s' configuration completed!",
624 mp
->is_server
? "Server" : "Client",
628 /** Handle a configuration protocol <b>line</b> received from a
629 * managed proxy <b>mp</b>. */
631 handle_proxy_line(const char *line
, managed_proxy_t
*mp
)
633 log_info(LD_GENERAL
, "Got a line from managed proxy '%s': (%s)",
636 if (strlen(line
) < SMALLEST_MANAGED_LINE_SIZE
) {
637 log_warn(LD_GENERAL
, "Managed proxy configuration line is too small. "
642 if (!strcmpstart(line
, PROTO_ENV_ERROR
)) {
643 if (mp
->conf_state
!= PT_PROTO_LAUNCHED
)
646 parse_env_error(line
);
648 } else if (!strcmpstart(line
, PROTO_NEG_FAIL
)) {
649 if (mp
->conf_state
!= PT_PROTO_LAUNCHED
)
652 log_warn(LD_CONFIG
, "Managed proxy could not pick a "
653 "configuration protocol version.");
655 } else if (!strcmpstart(line
, PROTO_NEG_SUCCESS
)) {
656 if (mp
->conf_state
!= PT_PROTO_LAUNCHED
)
659 if (parse_version(line
,mp
) < 0)
662 tor_assert(mp
->conf_protocol
!= 0);
663 mp
->conf_state
= PT_PROTO_ACCEPTING_METHODS
;
665 } else if (!strcmpstart(line
, PROTO_CMETHODS_DONE
)) {
666 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
669 handle_methods_done(mp
);
671 mp
->conf_state
= PT_PROTO_CONFIGURED
;
673 } else if (!strcmpstart(line
, PROTO_SMETHODS_DONE
)) {
674 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
677 handle_methods_done(mp
);
679 mp
->conf_state
= PT_PROTO_CONFIGURED
;
681 } else if (!strcmpstart(line
, PROTO_CMETHOD_ERROR
)) {
682 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
685 parse_client_method_error(line
);
687 } else if (!strcmpstart(line
, PROTO_SMETHOD_ERROR
)) {
688 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
691 parse_server_method_error(line
);
693 } else if (!strcmpstart(line
, PROTO_CMETHOD
)) {
694 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
697 if (parse_cmethod_line(line
, mp
) < 0)
701 } else if (!strcmpstart(line
, PROTO_SMETHOD
)) {
702 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
705 if (parse_smethod_line(line
, mp
) < 0)
709 } else if (!strcmpstart(line
, SPAWN_ERROR_MESSAGE
)) {
710 log_warn(LD_GENERAL
, "Could not launch managed proxy executable!");
711 mp
->conf_state
= PT_PROTO_FAILED_LAUNCH
;
715 log_warn(LD_CONFIG
, "Unknown line received by managed proxy. (%s)", line
);
718 mp
->conf_state
= PT_PROTO_BROKEN
;
719 log_warn(LD_CONFIG
, "Managed proxy at '%s' failed the configuration protocol"
720 " and will be destroyed.", mp
->argv
[0]);
723 /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
725 parse_env_error(const char *line
)
727 /* (Length of the protocol string) plus (a space) and (the first char of
728 the error message) */
729 if (strlen(line
) < (strlen(PROTO_ENV_ERROR
) + 2))
730 log_notice(LD_CONFIG
, "Managed proxy sent us an %s without an error "
731 "message.", PROTO_ENV_ERROR
);
733 log_warn(LD_CONFIG
, "Managed proxy couldn't understand the "
734 "pluggable transport environment variables. (%s)",
735 line
+strlen(PROTO_ENV_ERROR
)+1);
738 /** Handles a VERSION <b>line</b>. Updates the configuration protocol
739 * version in <b>mp</b>. */
741 parse_version(const char *line
, managed_proxy_t
*mp
)
743 if (strlen(line
) < (strlen(PROTO_NEG_SUCCESS
) + 2)) {
744 log_warn(LD_CONFIG
, "Managed proxy sent us malformed %s line.",
749 if (strcmp("1", line
+strlen(PROTO_NEG_SUCCESS
)+1)) { /* hardcoded temp */
750 log_warn(LD_CONFIG
, "Managed proxy tried to negotiate on version '%s'. "
751 "We only support version '1'", line
+strlen(PROTO_NEG_SUCCESS
)+1);
755 mp
->conf_protocol
= PROTO_VERSION_ONE
; /* temp. till more versions appear */
759 /** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
760 * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
761 * otherwise it is a CMETHOD-ERROR. */
763 parse_method_error(const char *line
, int is_server
)
765 const char* error
= is_server
?
766 PROTO_SMETHOD_ERROR
: PROTO_CMETHOD_ERROR
;
768 /* (Length of the protocol string) plus (a space) and (the first char of
769 the error message) */
770 if (strlen(line
) < (strlen(error
) + 2))
771 log_warn(LD_CONFIG
, "Managed proxy sent us an %s without an error "
774 log_warn(LD_CONFIG
, "%s managed proxy encountered a method error. (%s)",
775 is_server
? "Server" : "Client",
776 line
+strlen(error
)+1);
779 /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
780 * new transport in <b>mp</b>. */
782 parse_smethod_line(const char *line
, managed_proxy_t
*mp
)
785 smartlist_t
*items
= NULL
;
787 char *method_name
=NULL
;
793 transport_t
*transport
=NULL
;
795 items
= smartlist_new();
796 smartlist_split_string(items
, line
, NULL
,
797 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
798 if (smartlist_len(items
) < 3) {
799 log_warn(LD_CONFIG
, "Server managed proxy sent us a SMETHOD line "
800 "with too few arguments.");
804 tor_assert(!strcmp(smartlist_get(items
,0),PROTO_SMETHOD
));
806 method_name
= smartlist_get(items
,1);
807 if (!string_is_C_identifier(method_name
)) {
808 log_warn(LD_CONFIG
, "Transport name is not a C identifier (%s).",
813 addrport
= smartlist_get(items
, 2);
814 if (tor_addr_port_lookup(addrport
, &addr
, &port
)<0) {
815 log_warn(LD_CONFIG
, "Error parsing transport "
816 "address '%s'", addrport
);
822 "Transport address '%s' has no port.", addrport
);
826 transport
= transport_new(&addr
, port
, method_name
, PROXY_NONE
);
830 smartlist_add(mp
->transports
, transport
);
832 /* For now, notify the user so that he knows where the server
833 transport is listening. */
834 log_info(LD_CONFIG
, "Server transport %s at %s:%d.",
835 method_name
, fmt_addr(&addr
), (int)port
);
844 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
845 smartlist_free(items
);
849 /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
850 * the new transport in <b>mp</b>. */
852 parse_cmethod_line(const char *line
, managed_proxy_t
*mp
)
855 smartlist_t
*items
= NULL
;
857 char *method_name
=NULL
;
859 char *socks_ver_str
=NULL
;
860 int socks_ver
=PROXY_NONE
;
866 transport_t
*transport
=NULL
;
868 items
= smartlist_new();
869 smartlist_split_string(items
, line
, NULL
,
870 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
871 if (smartlist_len(items
) < 4) {
872 log_warn(LD_CONFIG
, "Client managed proxy sent us a CMETHOD line "
873 "with too few arguments.");
877 tor_assert(!strcmp(smartlist_get(items
,0),PROTO_CMETHOD
));
879 method_name
= smartlist_get(items
,1);
880 if (!string_is_C_identifier(method_name
)) {
881 log_warn(LD_CONFIG
, "Transport name is not a C identifier (%s).",
886 socks_ver_str
= smartlist_get(items
,2);
888 if (!strcmp(socks_ver_str
,"socks4")) {
889 socks_ver
= PROXY_SOCKS4
;
890 } else if (!strcmp(socks_ver_str
,"socks5")) {
891 socks_ver
= PROXY_SOCKS5
;
893 log_warn(LD_CONFIG
, "Client managed proxy sent us a proxy protocol "
894 "we don't recognize. (%s)", socks_ver_str
);
898 addrport
= smartlist_get(items
, 3);
899 if (tor_addr_port_lookup(addrport
, &addr
, &port
)<0) {
900 log_warn(LD_CONFIG
, "Error parsing transport "
901 "address '%s'", addrport
);
907 "Transport address '%s' has no port.", addrport
);
911 transport
= transport_new(&addr
, port
, method_name
, socks_ver
);
915 smartlist_add(mp
->transports
, transport
);
917 log_info(LD_CONFIG
, "Transport %s at %s:%d with SOCKS %d. "
918 "Attached to managed proxy.",
919 method_name
, fmt_addr(&addr
), (int)port
, socks_ver
);
928 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
929 smartlist_free(items
);
933 /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
934 * while configuring the server managed proxy in <b>mp</b>. The
935 * string is stored in the heap, and it's the the responsibility of
936 * the caller to deallocate it after its use. */
938 get_bindaddr_for_server_proxy(const managed_proxy_t
*mp
)
940 char *bindaddr_result
= NULL
;
941 char *bindaddr_tmp
= NULL
;
942 smartlist_t
*string_tmp
= smartlist_new();
944 tor_assert(mp
->is_server
);
946 SMARTLIST_FOREACH_BEGIN(mp
->transports_to_launch
, char *, t
) {
947 bindaddr_tmp
= get_stored_bindaddr_for_server_transport(t
);
949 smartlist_add_asprintf(string_tmp
, "%s-%s", t
, bindaddr_tmp
);
951 tor_free(bindaddr_tmp
);
952 } SMARTLIST_FOREACH_END(t
);
954 bindaddr_result
= smartlist_join_strings(string_tmp
, ",", 0, NULL
);
956 SMARTLIST_FOREACH(string_tmp
, char *, t
, tor_free(t
));
957 smartlist_free(string_tmp
);
959 return bindaddr_result
;
962 /** Return a newly allocated process_environment_t * for <b>mp</b>'s
964 static process_environment_t
*
965 create_managed_proxy_environment(const managed_proxy_t
*mp
)
967 const or_options_t
*options
= get_options();
969 /* Environment variables to be added to or set in mp's environment. */
970 smartlist_t
*envs
= smartlist_new();
971 /* XXXX The next time someone touches this code, shorten the name of
972 * set_environment_variable_in_smartlist, add a
973 * set_env_var_in_smartlist_asprintf function, and get rid of the
974 * silly extra envs smartlist. */
976 /* The final environment to be passed to mp. */
977 smartlist_t
*merged_env_vars
= get_current_process_environment_variables();
979 process_environment_t
*env
;
982 char *state_tmp
= get_datadir_fname("pt_state/"); /* XXX temp */
983 smartlist_add_asprintf(envs
, "TOR_PT_STATE_LOCATION=%s", state_tmp
);
987 smartlist_add(envs
, tor_strdup("TOR_PT_MANAGED_TRANSPORT_VER=1"));
990 char *transports_to_launch
=
991 smartlist_join_strings(mp
->transports_to_launch
, ",", 0, NULL
);
993 smartlist_add_asprintf(envs
,
995 "TOR_PT_SERVER_TRANSPORTS=%s" :
996 "TOR_PT_CLIENT_TRANSPORTS=%s",
997 transports_to_launch
);
999 tor_free(transports_to_launch
);
1002 if (mp
->is_server
) {
1003 smartlist_add_asprintf(envs
, "TOR_PT_ORPORT=127.0.0.1:%s",
1004 options
->ORPort
->value
);
1007 char *bindaddr_tmp
= get_bindaddr_for_server_proxy(mp
);
1008 smartlist_add_asprintf(envs
, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp
);
1009 tor_free(bindaddr_tmp
);
1012 /* XXX023 Remove the '=' here once versions of obfsproxy which
1013 * assert that this env var exists are sufficiently dead.
1015 * (If we remove this line entirely, some joker will stick this
1016 * variable in Tor's environment and crash PTs that try to parse
1017 * it even when not run in server mode.) */
1018 smartlist_add(envs
, tor_strdup("TOR_PT_EXTENDED_SERVER_PORT="));
1021 SMARTLIST_FOREACH_BEGIN(envs
, const char *, env_var
) {
1022 set_environment_variable_in_smartlist(merged_env_vars
, env_var
,
1024 } SMARTLIST_FOREACH_END(env_var
);
1026 env
= process_environment_make(merged_env_vars
);
1028 smartlist_free(envs
);
1030 SMARTLIST_FOREACH(merged_env_vars
, void *, x
, tor_free(x
));
1031 smartlist_free(merged_env_vars
);
1036 /** Create and return a new managed proxy for <b>transport</b> using
1037 * <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server
1039 static managed_proxy_t
*
1040 managed_proxy_create(const smartlist_t
*transport_list
,
1041 char **proxy_argv
, int is_server
)
1043 managed_proxy_t
*mp
= tor_malloc_zero(sizeof(managed_proxy_t
));
1044 mp
->conf_state
= PT_PROTO_INFANT
;
1045 mp
->is_server
= is_server
;
1046 mp
->argv
= proxy_argv
;
1047 mp
->transports
= smartlist_new();
1049 mp
->transports_to_launch
= smartlist_new();
1050 SMARTLIST_FOREACH(transport_list
, const char *, transport
,
1051 add_transport_to_proxy(transport
, mp
));
1053 /* register the managed proxy */
1054 if (!managed_proxy_list
)
1055 managed_proxy_list
= smartlist_new();
1056 smartlist_add(managed_proxy_list
, mp
);
1057 unconfigured_proxies_n
++;
1059 assert_unconfigured_count_ok();
1064 /** Register proxy with <b>proxy_argv</b>, supporting transports in
1065 * <b>transport_list</b>, to the managed proxy subsystem.
1066 * If <b>is_server</b> is true, then the proxy is a server proxy. */
1068 pt_kickstart_proxy(const smartlist_t
*transport_list
,
1069 char **proxy_argv
, int is_server
)
1071 managed_proxy_t
*mp
=NULL
;
1072 transport_t
*old_transport
= NULL
;
1074 mp
= get_managed_proxy_by_argv_and_type(proxy_argv
, is_server
);
1076 if (!mp
) { /* we haven't seen this proxy before */
1077 managed_proxy_create(transport_list
, proxy_argv
, is_server
);
1079 } else { /* known proxy. add its transport to its transport list */
1081 /* If the managed proxy we found is marked by a SIGHUP, it means
1082 that it's not useless and should be kept. If it's marked for
1083 removal, unmark it and increase the unconfigured proxies so
1084 that we try to restart it if we need to. Afterwards, check if
1085 a transport_t for 'transport' used to exist before the SIGHUP
1086 and make sure it doesn't get deleted because we might reuse
1088 if (mp
->marked_for_removal
) {
1089 mp
->marked_for_removal
= 0;
1090 check_if_restarts_needed
= 1;
1093 SMARTLIST_FOREACH_BEGIN(transport_list
, const char *, transport
) {
1094 old_transport
= transport_get_by_name(transport
);
1096 old_transport
->marked_for_removal
= 0;
1097 } SMARTLIST_FOREACH_END(transport
);
1100 SMARTLIST_FOREACH(transport_list
, const char *, transport
,
1101 add_transport_to_proxy(transport
, mp
));
1102 free_execve_args(proxy_argv
);
1106 /** Frees the array of pointers in <b>arg</b> used as arguments to
1109 free_execve_args(char **arg
)
1112 while (*tmp
) /* use the fact that the last element of the array is a
1113 NULL pointer to know when to stop freeing */
1119 /** Tor will read its config.
1120 * Prepare the managed proxy list so that proxies not used in the new
1121 * config will shutdown, and proxies that need to spawn different
1122 * transports will do so. */
1124 pt_prepare_proxy_list_for_config_read(void)
1126 if (!managed_proxy_list
)
1129 assert_unconfigured_count_ok();
1130 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, managed_proxy_t
*, mp
) {
1131 /* Destroy unconfigured proxies. */
1132 if (mp
->conf_state
!= PT_PROTO_COMPLETED
) {
1133 SMARTLIST_DEL_CURRENT(managed_proxy_list
, mp
);
1134 managed_proxy_destroy(mp
, 1);
1135 unconfigured_proxies_n
--;
1139 tor_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
1141 mp
->marked_for_removal
= 1;
1143 SMARTLIST_FOREACH(mp
->transports_to_launch
, char *, t
, tor_free(t
));
1144 smartlist_clear(mp
->transports_to_launch
);
1145 } SMARTLIST_FOREACH_END(mp
);
1147 assert_unconfigured_count_ok();
1149 tor_assert(unconfigured_proxies_n
== 0);
1152 /** The tor config was read.
1153 * Destroy all managed proxies that were marked by a previous call to
1154 * prepare_proxy_list_for_config_read() and are not used by the new
1157 sweep_proxy_list(void)
1159 if (!managed_proxy_list
)
1161 assert_unconfigured_count_ok();
1162 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, managed_proxy_t
*, mp
) {
1163 if (mp
->marked_for_removal
) {
1164 SMARTLIST_DEL_CURRENT(managed_proxy_list
, mp
);
1165 managed_proxy_destroy(mp
, 1);
1167 } SMARTLIST_FOREACH_END(mp
);
1168 assert_unconfigured_count_ok();
1171 /** Release all storage held by the pluggable transports subsystem. */
1175 if (managed_proxy_list
) {
1176 /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1177 transports and it's the duty of the circuitbuild.c subsystem to
1178 free them. Otherwise, it hasn't registered its transports yet
1179 and we should free them here. */
1180 SMARTLIST_FOREACH(managed_proxy_list
, managed_proxy_t
*, mp
, {
1181 SMARTLIST_DEL_CURRENT(managed_proxy_list
, mp
);
1182 managed_proxy_destroy(mp
, 1);
1185 smartlist_free(managed_proxy_list
);
1186 managed_proxy_list
=NULL
;