1 /* Copyright (c) 2011-2013, 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 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
54 * <b>In even more detail, this is what happens when a config read
55 * (like a SIGHUP or a SETCONF) occurs:</b>
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.).
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
72 * We then start parsing torrc again.
74 * Everytime 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.
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.
95 #include "circuitbuild.h"
96 #include "transports.h"
99 #include "statefile.h"
100 #include "entrynodes.h"
101 #include "connection_or.h"
102 #include "ext_orport.h"
105 static process_environment_t
*
106 create_managed_proxy_environment(const managed_proxy_t
*mp
);
108 static INLINE
int proxy_configuration_finished(const managed_proxy_t
*mp
);
110 static void handle_finished_proxy(managed_proxy_t
*mp
);
111 static void parse_method_error(const char *line
, int is_server_method
);
112 #define parse_server_method_error(l) parse_method_error(l, 1)
113 #define parse_client_method_error(l) parse_method_error(l, 0)
115 static INLINE
void free_execve_args(char **arg
);
117 /** Managed proxy protocol strings */
118 #define PROTO_ENV_ERROR "ENV-ERROR"
119 #define PROTO_NEG_SUCCESS "VERSION"
120 #define PROTO_NEG_FAIL "VERSION-ERROR no-version"
121 #define PROTO_CMETHOD "CMETHOD"
122 #define PROTO_SMETHOD "SMETHOD"
123 #define PROTO_CMETHOD_ERROR "CMETHOD-ERROR"
124 #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
125 #define PROTO_CMETHODS_DONE "CMETHODS DONE"
126 #define PROTO_SMETHODS_DONE "SMETHODS DONE"
128 /** The first and only supported - at the moment - configuration
130 #define PROTO_VERSION_ONE 1
132 /** A list of pluggable transports found in torrc. */
133 static smartlist_t
*transport_list
= NULL
;
135 /** Returns a transport_t struct for a transport proxy supporting the
136 protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
137 SOCKS version <b>socks_ver</b>. */
139 transport_new(const tor_addr_t
*addr
, uint16_t port
,
140 const char *name
, int socks_ver
,
141 const char *extra_info_args
)
143 transport_t
*t
= tor_malloc_zero(sizeof(transport_t
));
145 tor_addr_copy(&t
->addr
, addr
);
147 t
->name
= tor_strdup(name
);
148 t
->socks_version
= socks_ver
;
150 t
->extra_info_args
= tor_strdup(extra_info_args
);
155 /** Free the pluggable transport struct <b>transport</b>. */
157 transport_free(transport_t
*transport
)
162 tor_free(transport
->name
);
163 tor_free(transport
->extra_info_args
);
167 /** Mark every entry of the transport list to be removed on our next call to
168 * sweep_transport_list unless it has first been un-marked. */
170 mark_transport_list(void)
173 transport_list
= smartlist_new();
174 SMARTLIST_FOREACH(transport_list
, transport_t
*, t
,
175 t
->marked_for_removal
= 1);
178 /** Remove every entry of the transport list that was marked with
179 * mark_transport_list if it has not subsequently been un-marked. */
181 sweep_transport_list(void)
184 transport_list
= smartlist_new();
185 SMARTLIST_FOREACH_BEGIN(transport_list
, transport_t
*, t
) {
186 if (t
->marked_for_removal
) {
187 SMARTLIST_DEL_CURRENT(transport_list
, t
);
190 } SMARTLIST_FOREACH_END(t
);
193 /** Initialize the pluggable transports list to empty, creating it if
196 clear_transport_list(void)
199 transport_list
= smartlist_new();
200 SMARTLIST_FOREACH(transport_list
, transport_t
*, t
, transport_free(t
));
201 smartlist_clear(transport_list
);
204 /** Return a deep copy of <b>transport</b>. */
206 transport_copy(const transport_t
*transport
)
208 transport_t
*new_transport
= NULL
;
210 tor_assert(transport
);
212 new_transport
= tor_malloc_zero(sizeof(transport_t
));
214 new_transport
->socks_version
= transport
->socks_version
;
215 new_transport
->name
= tor_strdup(transport
->name
);
216 tor_addr_copy(&new_transport
->addr
, &transport
->addr
);
217 new_transport
->port
= transport
->port
;
218 new_transport
->marked_for_removal
= transport
->marked_for_removal
;
220 return new_transport
;
223 /** Returns the transport in our transport list that has the name <b>name</b>.
224 * Else returns NULL. */
226 transport_get_by_name(const char *name
)
233 SMARTLIST_FOREACH_BEGIN(transport_list
, transport_t
*, transport
) {
234 if (!strcmp(transport
->name
, name
))
236 } SMARTLIST_FOREACH_END(transport
);
241 /** Resolve any conflicts that the insertion of transport <b>t</b>
243 * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
244 * a transport identical to <b>t</b> already registered and -1 if
245 * <b>t</b> cannot be added due to conflicts. */
247 transport_resolve_conflicts(const transport_t
*t
)
249 /* This is how we resolve transport conflicts:
251 If there is already a transport with the same name and addrport,
252 we either have duplicate torrc lines OR we are here post-HUP and
253 this transport was here pre-HUP as well. In any case, mark the
254 old transport so that it doesn't get removed and ignore the new
255 one. Our caller has to free the new transport so we return '1' to
258 If there is already a transport with the same name but different
260 * if it's marked for removal, it means that it either has a lower
261 priority than 't' in torrc (otherwise the mark would have been
262 cleared by the paragraph above), or it doesn't exist at all in
263 the post-HUP torrc. We destroy the old transport and register 't'.
264 * if it's *not* marked for removal, it means that it was newly
265 added in the post-HUP torrc or that it's of higher priority, in
266 this case we ignore 't'. */
267 transport_t
*t_tmp
= transport_get_by_name(t
->name
);
268 if (t_tmp
) { /* same name */
269 if (tor_addr_eq(&t
->addr
, &t_tmp
->addr
) && (t
->port
== t_tmp
->port
)) {
270 /* same name *and* addrport */
271 t_tmp
->marked_for_removal
= 0;
273 } else { /* same name but different addrport */
274 char *new_transport_addrport
=
275 tor_strdup(fmt_addrport(&t
->addr
, t
->port
));
276 if (t_tmp
->marked_for_removal
) { /* marked for removal */
277 log_notice(LD_GENERAL
, "You tried to add transport '%s' at '%s' "
278 "but there was already a transport marked for deletion at "
279 "'%s'. We deleted the old transport and registered the "
280 "new one.", t
->name
, new_transport_addrport
,
281 fmt_addrport(&t_tmp
->addr
, t_tmp
->port
));
282 smartlist_remove(transport_list
, t_tmp
);
283 transport_free(t_tmp
);
284 tor_free(new_transport_addrport
);
285 } else { /* *not* marked for removal */
286 log_notice(LD_GENERAL
, "You tried to add transport '%s' at '%s' "
287 "but the same transport already exists at '%s'. "
288 "Skipping.", t
->name
, new_transport_addrport
,
289 fmt_addrport(&t_tmp
->addr
, t_tmp
->port
));
290 tor_free(new_transport_addrport
);
293 tor_free(new_transport_addrport
);
300 /** Add transport <b>t</b> to the internal list of pluggable
302 * Returns 0 if the transport was added correctly, 1 if the same
303 * transport was already registered (in this case the caller must
304 * free the transport) and -1 if there was an error. */
306 transport_add(transport_t
*t
)
311 r
= transport_resolve_conflicts(t
);
314 case 0: /* should register transport */
316 transport_list
= smartlist_new();
317 smartlist_add(transport_list
, t
);
319 default: /* let our caller know the return code */
324 /** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
325 * <b>name</b> is set to the name of the protocol this proxy uses.
326 * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
328 transport_add_from_config(const tor_addr_t
*addr
, uint16_t port
,
329 const char *name
, int socks_ver
)
331 transport_t
*t
= transport_new(addr
, port
, name
, socks_ver
, NULL
);
333 int r
= transport_add(t
);
338 log_notice(LD_GENERAL
, "Could not add transport %s at %s. Skipping.",
339 t
->name
, fmt_addrport(&t
->addr
, t
->port
));
343 log_info(LD_GENERAL
, "Successfully registered transport %s at %s.",
344 t
->name
, fmt_addrport(&t
->addr
, t
->port
));
345 transport_free(t
); /* falling */
348 log_info(LD_GENERAL
, "Successfully registered transport %s at %s.",
349 t
->name
, fmt_addrport(&t
->addr
, t
->port
));
354 /** List of unconfigured managed proxies. */
355 static smartlist_t
*managed_proxy_list
= NULL
;
356 /** Number of still unconfigured proxies. */
357 static int unconfigured_proxies_n
= 0;
358 /** Boolean: True iff we might need to restart some proxies. */
359 static int check_if_restarts_needed
= 0;
361 /** Return true if there are still unconfigured managed proxies, or proxies
362 * that need restarting. */
364 pt_proxies_configuration_pending(void)
366 return unconfigured_proxies_n
|| check_if_restarts_needed
;
369 /** Assert that the unconfigured_proxies_n value correctly matches the number
370 * of proxies in a state other than PT_PROTO_COMPLETE. */
372 assert_unconfigured_count_ok(void)
375 if (!managed_proxy_list
) {
376 tor_assert(unconfigured_proxies_n
== 0);
380 SMARTLIST_FOREACH(managed_proxy_list
, managed_proxy_t
*, mp
, {
381 if (mp
->conf_state
== PT_PROTO_COMPLETED
)
385 tor_assert(n_completed
+ unconfigured_proxies_n
==
386 smartlist_len(managed_proxy_list
));
389 /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
391 managed_proxy_has_argv(const managed_proxy_t
*mp
, char **proxy_argv
)
393 char **tmp1
=proxy_argv
;
394 char **tmp2
=mp
->argv
;
399 while (*tmp1
&& *tmp2
) {
400 if (strcmp(*tmp1
++, *tmp2
++))
404 if (!*tmp1
&& !*tmp2
)
410 /** Return a managed proxy with the same argv as <b>proxy_argv</b>.
411 * If no such managed proxy exists, return NULL. */
412 static managed_proxy_t
*
413 get_managed_proxy_by_argv_and_type(char **proxy_argv
, int is_server
)
415 if (!managed_proxy_list
)
418 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, managed_proxy_t
*, mp
) {
419 if (managed_proxy_has_argv(mp
, proxy_argv
) &&
420 mp
->is_server
== is_server
)
422 } SMARTLIST_FOREACH_END(mp
);
427 /** Add <b>transport</b> to managed proxy <b>mp</b>. */
429 add_transport_to_proxy(const char *transport
, managed_proxy_t
*mp
)
431 tor_assert(mp
->transports_to_launch
);
432 if (!smartlist_contains_string(mp
->transports_to_launch
, transport
))
433 smartlist_add(mp
->transports_to_launch
, tor_strdup(transport
));
436 /** Called when a SIGHUP occurs. Returns true if managed proxy
437 * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
440 proxy_needs_restart(const managed_proxy_t
*mp
)
442 /* mp->transport_to_launch is populated with the names of the
443 transports that must be launched *after* the SIGHUP.
444 mp->transports is populated with the transports that were
445 launched *before* the SIGHUP.
447 Check if all the transports that need to be launched are already
450 tor_assert(smartlist_len(mp
->transports_to_launch
) > 0);
451 tor_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
453 if (smartlist_len(mp
->transports_to_launch
) != smartlist_len(mp
->transports
))
456 SMARTLIST_FOREACH_BEGIN(mp
->transports
, const transport_t
*, t
) {
457 if (!smartlist_contains_string(mp
->transports_to_launch
, t
->name
))
460 } SMARTLIST_FOREACH_END(t
);
468 /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
469 * preparations and then flag its state so that it will be relaunched
470 * in the next tick. */
473 proxy_prepare_for_restart(managed_proxy_t
*mp
)
475 transport_t
*t_tmp
= NULL
;
477 tor_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
479 /* destroy the process handle and terminate the process. */
480 tor_process_handle_destroy(mp
->process_handle
, 1);
481 mp
->process_handle
= NULL
;
483 /* destroy all its registered transports, since we will no longer
485 SMARTLIST_FOREACH_BEGIN(mp
->transports
, const transport_t
*, t
) {
486 t_tmp
= transport_get_by_name(t
->name
);
488 t_tmp
->marked_for_removal
= 1;
489 } SMARTLIST_FOREACH_END(t
);
490 sweep_transport_list();
492 /* free the transport in mp->transports */
493 SMARTLIST_FOREACH(mp
->transports
, transport_t
*, t
, transport_free(t
));
494 smartlist_clear(mp
->transports
);
496 /* flag it as an infant proxy so that it gets launched on next tick */
497 mp
->conf_state
= PT_PROTO_INFANT
;
498 unconfigured_proxies_n
++;
501 /** Launch managed proxy <b>mp</b>. */
503 launch_managed_proxy(managed_proxy_t
*mp
)
507 process_environment_t
*env
= create_managed_proxy_environment(mp
);
510 /* Passing NULL as lpApplicationName makes Windows search for the .exe */
511 retval
= tor_spawn_background(NULL
,
512 (const char **)mp
->argv
,
514 &mp
->process_handle
);
516 retval
= tor_spawn_background(mp
->argv
[0],
517 (const char **)mp
->argv
,
519 &mp
->process_handle
);
522 process_environment_free(env
);
524 if (retval
== PROCESS_STATUS_ERROR
) {
525 log_warn(LD_GENERAL
, "Managed proxy at '%s' failed at launch.",
530 log_info(LD_CONFIG
, "Managed proxy at '%s' has spawned with PID '%d'.",
531 mp
->argv
[0], tor_process_get_pid(mp
->process_handle
));
533 mp
->conf_state
= PT_PROTO_LAUNCHED
;
538 /** Check if any of the managed proxies we are currently trying to
539 * configure has anything new to say. */
541 pt_configure_remaining_proxies(void)
543 int at_least_a_proxy_config_finished
= 0;
544 smartlist_t
*tmp
= smartlist_new();
546 log_debug(LD_CONFIG
, "Configuring remaining managed proxies (%d)!",
547 unconfigured_proxies_n
);
549 /* Iterate over tmp, not managed_proxy_list, since configure_proxy can
550 * remove elements from managed_proxy_list. */
551 smartlist_add_all(tmp
, managed_proxy_list
);
553 assert_unconfigured_count_ok();
555 SMARTLIST_FOREACH_BEGIN(tmp
, managed_proxy_t
*, mp
) {
556 tor_assert(mp
->conf_state
!= PT_PROTO_BROKEN
&&
557 mp
->conf_state
!= PT_PROTO_FAILED_LAUNCH
);
559 if (mp
->was_around_before_config_read
) {
560 /* This proxy is marked by a config read. Check whether we need
563 mp
->was_around_before_config_read
= 0;
565 if (proxy_needs_restart(mp
)) {
566 log_info(LD_GENERAL
, "Preparing managed proxy '%s' for restart.",
568 proxy_prepare_for_restart(mp
);
569 } else { /* it doesn't need to be restarted. */
570 log_info(LD_GENERAL
, "Nothing changed for managed proxy '%s' after "
571 "HUP: not restarting.", mp
->argv
[0]);
577 /* If the proxy is not fully configured, try to configure it
579 if (!proxy_configuration_finished(mp
))
580 if (configure_proxy(mp
) == 1)
581 at_least_a_proxy_config_finished
= 1;
583 } SMARTLIST_FOREACH_END(mp
);
586 check_if_restarts_needed
= 0;
587 assert_unconfigured_count_ok();
589 if (at_least_a_proxy_config_finished
)
590 mark_my_descriptor_dirty("configured managed proxies");
593 /** Attempt to continue configuring managed proxy <b>mp</b>.
594 * Return 1 if the transport configuration finished, and return 0
595 * otherwise (if we still have more configuring to do for this
598 configure_proxy(managed_proxy_t
*mp
)
600 int configuration_finished
= 0;
601 smartlist_t
*proxy_output
= NULL
;
602 enum stream_status stream_status
= 0;
604 /* if we haven't launched the proxy yet, do it now */
605 if (mp
->conf_state
== PT_PROTO_INFANT
) {
606 if (launch_managed_proxy(mp
) < 0) { /* launch fail */
607 mp
->conf_state
= PT_PROTO_FAILED_LAUNCH
;
608 handle_finished_proxy(mp
);
613 tor_assert(mp
->conf_state
!= PT_PROTO_INFANT
);
614 tor_assert(mp
->process_handle
);
617 tor_get_lines_from_handle(tor_process_get_stdout_pipe(mp
->process_handle
),
619 if (!proxy_output
) { /* failed to get input from proxy */
620 if (stream_status
!= IO_STREAM_EAGAIN
) { /* bad stream status! */
621 mp
->conf_state
= PT_PROTO_BROKEN
;
622 log_warn(LD_GENERAL
, "The communication stream of managed proxy '%s' "
623 "is '%s'. Most probably the managed proxy stopped running. "
624 "This might be a bug of the managed proxy, a bug of Tor, or "
625 "a misconfiguration. Please enable logging on your managed "
626 "proxy and check the logs for errors.",
627 mp
->argv
[0], stream_status_to_string(stream_status
));
634 SMARTLIST_FOREACH_BEGIN(proxy_output
, const char *, line
) {
635 handle_proxy_line(line
, mp
);
636 if (proxy_configuration_finished(mp
))
638 } SMARTLIST_FOREACH_END(line
);
641 /* if the proxy finished configuring, exit the loop. */
642 if (proxy_configuration_finished(mp
)) {
643 handle_finished_proxy(mp
);
644 configuration_finished
= 1;
648 SMARTLIST_FOREACH(proxy_output
, char *, cp
, tor_free(cp
));
649 smartlist_free(proxy_output
);
652 return configuration_finished
;
655 /** Register server managed proxy <b>mp</b> transports to state */
657 register_server_proxy(const managed_proxy_t
*mp
)
659 tor_assert(mp
->conf_state
!= PT_PROTO_COMPLETED
);
661 SMARTLIST_FOREACH_BEGIN(mp
->transports
, transport_t
*, t
) {
662 save_transport_to_state(t
->name
, &t
->addr
, t
->port
);
663 log_notice(LD_GENERAL
, "Registered server transport '%s' at '%s'",
664 t
->name
, fmt_addrport(&t
->addr
, t
->port
));
665 control_event_transport_launched("server", t
->name
, &t
->addr
, t
->port
);
666 } SMARTLIST_FOREACH_END(t
);
669 /** Register all the transports supported by client managed proxy
670 * <b>mp</b> to the bridge subsystem. */
672 register_client_proxy(const managed_proxy_t
*mp
)
676 tor_assert(mp
->conf_state
!= PT_PROTO_COMPLETED
);
678 SMARTLIST_FOREACH_BEGIN(mp
->transports
, transport_t
*, t
) {
679 transport_t
*transport_tmp
= transport_copy(t
);
680 r
= transport_add(transport_tmp
);
683 log_notice(LD_GENERAL
, "Could not add transport %s. Skipping.", t
->name
);
684 transport_free(transport_tmp
);
687 log_info(LD_GENERAL
, "Successfully registered transport %s", t
->name
);
688 control_event_transport_launched("client", t
->name
, &t
->addr
, t
->port
);
691 log_info(LD_GENERAL
, "Successfully registered transport %s", t
->name
);
692 control_event_transport_launched("client", t
->name
, &t
->addr
, t
->port
);
693 transport_free(transport_tmp
);
696 } SMARTLIST_FOREACH_END(t
);
699 /** Register the transports of managed proxy <b>mp</b>. */
701 register_proxy(const managed_proxy_t
*mp
)
704 register_server_proxy(mp
);
706 register_client_proxy(mp
);
709 /** Free memory allocated by managed proxy <b>mp</b>. */
711 managed_proxy_destroy(managed_proxy_t
*mp
,
712 int also_terminate_process
)
714 SMARTLIST_FOREACH(mp
->transports
, transport_t
*, t
, transport_free(t
));
716 /* free the transports smartlist */
717 smartlist_free(mp
->transports
);
719 /* free the transports_to_launch smartlist */
720 SMARTLIST_FOREACH(mp
->transports_to_launch
, char *, t
, tor_free(t
));
721 smartlist_free(mp
->transports_to_launch
);
723 /* remove it from the list of managed proxies */
724 if (managed_proxy_list
)
725 smartlist_remove(managed_proxy_list
, mp
);
728 free_execve_args(mp
->argv
);
730 tor_process_handle_destroy(mp
->process_handle
, also_terminate_process
);
731 mp
->process_handle
= NULL
;
736 /** Handle a configured or broken managed proxy <b>mp</b>. */
738 handle_finished_proxy(managed_proxy_t
*mp
)
740 switch (mp
->conf_state
) {
741 case PT_PROTO_BROKEN
: /* if broken: */
742 managed_proxy_destroy(mp
, 1); /* annihilate it. */
744 case PT_PROTO_FAILED_LAUNCH
: /* if it failed before launching: */
745 managed_proxy_destroy(mp
, 0); /* destroy it but don't terminate */
747 case PT_PROTO_CONFIGURED
: /* if configured correctly: */
748 register_proxy(mp
); /* register its transports */
749 mp
->conf_state
= PT_PROTO_COMPLETED
; /* and mark it as completed. */
751 case PT_PROTO_INFANT
:
752 case PT_PROTO_LAUNCHED
:
753 case PT_PROTO_ACCEPTING_METHODS
:
754 case PT_PROTO_COMPLETED
:
756 log_warn(LD_CONFIG
, "Unexpected state '%d' of managed proxy '%s'.",
757 (int)mp
->conf_state
, mp
->argv
[0]);
761 unconfigured_proxies_n
--;
764 /** Return true if the configuration of the managed proxy <b>mp</b> is
767 proxy_configuration_finished(const managed_proxy_t
*mp
)
769 return (mp
->conf_state
== PT_PROTO_CONFIGURED
||
770 mp
->conf_state
== PT_PROTO_BROKEN
||
771 mp
->conf_state
== PT_PROTO_FAILED_LAUNCH
);
774 /** This function is called when a proxy sends an {S,C}METHODS DONE message. */
776 handle_methods_done(const managed_proxy_t
*mp
)
778 tor_assert(mp
->transports
);
780 if (smartlist_len(mp
->transports
) == 0)
781 log_notice(LD_GENERAL
, "Managed proxy '%s' was spawned successfully, "
782 "but it didn't launch any pluggable transport listeners!",
785 log_info(LD_CONFIG
, "%s managed proxy '%s' configuration completed!",
786 mp
->is_server
? "Server" : "Client",
790 /** Handle a configuration protocol <b>line</b> received from a
791 * managed proxy <b>mp</b>. */
793 handle_proxy_line(const char *line
, managed_proxy_t
*mp
)
795 log_info(LD_GENERAL
, "Got a line from managed proxy '%s': (%s)",
798 if (!strcmpstart(line
, PROTO_ENV_ERROR
)) {
799 if (mp
->conf_state
!= PT_PROTO_LAUNCHED
)
802 parse_env_error(line
);
804 } else if (!strcmpstart(line
, PROTO_NEG_FAIL
)) {
805 if (mp
->conf_state
!= PT_PROTO_LAUNCHED
)
808 log_warn(LD_CONFIG
, "Managed proxy could not pick a "
809 "configuration protocol version.");
811 } else if (!strcmpstart(line
, PROTO_NEG_SUCCESS
)) {
812 if (mp
->conf_state
!= PT_PROTO_LAUNCHED
)
815 if (parse_version(line
,mp
) < 0)
818 tor_assert(mp
->conf_protocol
!= 0);
819 mp
->conf_state
= PT_PROTO_ACCEPTING_METHODS
;
821 } else if (!strcmpstart(line
, PROTO_CMETHODS_DONE
)) {
822 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
825 handle_methods_done(mp
);
827 mp
->conf_state
= PT_PROTO_CONFIGURED
;
829 } else if (!strcmpstart(line
, PROTO_SMETHODS_DONE
)) {
830 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
833 handle_methods_done(mp
);
835 mp
->conf_state
= PT_PROTO_CONFIGURED
;
837 } else if (!strcmpstart(line
, PROTO_CMETHOD_ERROR
)) {
838 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
841 parse_client_method_error(line
);
843 } else if (!strcmpstart(line
, PROTO_SMETHOD_ERROR
)) {
844 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
847 parse_server_method_error(line
);
849 } else if (!strcmpstart(line
, PROTO_CMETHOD
)) {
850 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
853 if (parse_cmethod_line(line
, mp
) < 0)
857 } else if (!strcmpstart(line
, PROTO_SMETHOD
)) {
858 if (mp
->conf_state
!= PT_PROTO_ACCEPTING_METHODS
)
861 if (parse_smethod_line(line
, mp
) < 0)
865 } else if (!strcmpstart(line
, SPAWN_ERROR_MESSAGE
)) {
866 /* managed proxy launch failed: parse error message to learn why. */
867 int retval
, child_state
, saved_errno
;
868 retval
= tor_sscanf(line
, SPAWN_ERROR_MESSAGE
"%x/%x",
869 &child_state
, &saved_errno
);
872 "Could not launch managed proxy executable at '%s' ('%s').",
873 mp
->argv
[0], strerror(saved_errno
));
874 } else { /* failed to parse error message */
875 log_warn(LD_GENERAL
,"Could not launch managed proxy executable at '%s'.",
879 mp
->conf_state
= PT_PROTO_FAILED_LAUNCH
;
883 log_notice(LD_GENERAL
, "Unknown line received by managed proxy (%s).", line
);
887 mp
->conf_state
= PT_PROTO_BROKEN
;
888 log_warn(LD_CONFIG
, "Managed proxy at '%s' failed the configuration protocol"
889 " and will be destroyed.", mp
->argv
[0]);
892 /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
894 parse_env_error(const char *line
)
896 /* (Length of the protocol string) plus (a space) and (the first char of
897 the error message) */
898 if (strlen(line
) < (strlen(PROTO_ENV_ERROR
) + 2))
899 log_notice(LD_CONFIG
, "Managed proxy sent us an %s without an error "
900 "message.", PROTO_ENV_ERROR
);
902 log_warn(LD_CONFIG
, "Managed proxy couldn't understand the "
903 "pluggable transport environment variables. (%s)",
904 line
+strlen(PROTO_ENV_ERROR
)+1);
907 /** Handles a VERSION <b>line</b>. Updates the configuration protocol
908 * version in <b>mp</b>. */
910 parse_version(const char *line
, managed_proxy_t
*mp
)
912 if (strlen(line
) < (strlen(PROTO_NEG_SUCCESS
) + 2)) {
913 log_warn(LD_CONFIG
, "Managed proxy sent us malformed %s line.",
918 if (strcmp("1", line
+strlen(PROTO_NEG_SUCCESS
)+1)) { /* hardcoded temp */
919 log_warn(LD_CONFIG
, "Managed proxy tried to negotiate on version '%s'. "
920 "We only support version '1'", line
+strlen(PROTO_NEG_SUCCESS
)+1);
924 mp
->conf_protocol
= PROTO_VERSION_ONE
; /* temp. till more versions appear */
928 /** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
929 * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
930 * otherwise it is a CMETHOD-ERROR. */
932 parse_method_error(const char *line
, int is_server
)
934 const char* error
= is_server
?
935 PROTO_SMETHOD_ERROR
: PROTO_CMETHOD_ERROR
;
937 /* (Length of the protocol string) plus (a space) and (the first char of
938 the error message) */
939 if (strlen(line
) < (strlen(error
) + 2))
940 log_warn(LD_CONFIG
, "Managed proxy sent us an %s without an error "
943 log_warn(LD_CONFIG
, "%s managed proxy encountered a method error. (%s)",
944 is_server
? "Server" : "Client",
945 line
+strlen(error
)+1);
948 /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
949 * new transport in <b>mp</b>. */
951 parse_smethod_line(const char *line
, managed_proxy_t
*mp
)
954 smartlist_t
*items
= NULL
;
956 char *method_name
=NULL
;
957 char *args_string
=NULL
;
963 transport_t
*transport
=NULL
;
965 items
= smartlist_new();
966 smartlist_split_string(items
, line
, NULL
,
967 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
968 if (smartlist_len(items
) < 3) {
969 log_warn(LD_CONFIG
, "Server managed proxy sent us a SMETHOD line "
970 "with too few arguments.");
974 /* Example of legit SMETHOD line:
975 SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
977 tor_assert(!strcmp(smartlist_get(items
,0),PROTO_SMETHOD
));
979 method_name
= smartlist_get(items
,1);
980 if (!string_is_C_identifier(method_name
)) {
981 log_warn(LD_CONFIG
, "Transport name is not a C identifier (%s).",
986 addrport
= smartlist_get(items
, 2);
987 if (tor_addr_port_split(LOG_WARN
, addrport
, &address
, &port
)<0) {
988 log_warn(LD_CONFIG
, "Error parsing transport "
989 "address '%s'", addrport
);
995 "Transport address '%s' has no port.", addrport
);
999 if (tor_addr_parse(&tor_addr
, address
) < 0) {
1000 log_warn(LD_CONFIG
, "Error parsing transport address '%s'", address
);
1004 if (smartlist_len(items
) > 3) {
1005 /* Seems like there are also some [options] in the SMETHOD line.
1006 Let's see if we can parse them. */
1007 char *options_string
= smartlist_get(items
, 3);
1008 log_debug(LD_CONFIG
, "Got options_string: %s", options_string
);
1009 if (!strcmpstart(options_string
, "ARGS:")) {
1010 args_string
= options_string
+strlen("ARGS:");
1011 log_debug(LD_CONFIG
, "Got ARGS: %s", args_string
);
1015 transport
= transport_new(&tor_addr
, port
, method_name
,
1016 PROXY_NONE
, args_string
);
1020 smartlist_add(mp
->transports
, transport
);
1022 /* For now, notify the user so that he knows where the server
1023 transport is listening. */
1024 log_info(LD_CONFIG
, "Server transport %s at %s:%d.",
1025 method_name
, address
, (int)port
);
1034 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
1035 smartlist_free(items
);
1040 /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
1041 * the new transport in <b>mp</b>. */
1043 parse_cmethod_line(const char *line
, managed_proxy_t
*mp
)
1046 smartlist_t
*items
= NULL
;
1048 char *method_name
=NULL
;
1050 char *socks_ver_str
=NULL
;
1051 int socks_ver
=PROXY_NONE
;
1053 char *addrport
=NULL
;
1054 tor_addr_t tor_addr
;
1058 transport_t
*transport
=NULL
;
1060 items
= smartlist_new();
1061 smartlist_split_string(items
, line
, NULL
,
1062 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
1063 if (smartlist_len(items
) < 4) {
1064 log_warn(LD_CONFIG
, "Client managed proxy sent us a CMETHOD line "
1065 "with too few arguments.");
1069 tor_assert(!strcmp(smartlist_get(items
,0),PROTO_CMETHOD
));
1071 method_name
= smartlist_get(items
,1);
1072 if (!string_is_C_identifier(method_name
)) {
1073 log_warn(LD_CONFIG
, "Transport name is not a C identifier (%s).",
1078 socks_ver_str
= smartlist_get(items
,2);
1080 if (!strcmp(socks_ver_str
,"socks4")) {
1081 socks_ver
= PROXY_SOCKS4
;
1082 } else if (!strcmp(socks_ver_str
,"socks5")) {
1083 socks_ver
= PROXY_SOCKS5
;
1085 log_warn(LD_CONFIG
, "Client managed proxy sent us a proxy protocol "
1086 "we don't recognize. (%s)", socks_ver_str
);
1090 addrport
= smartlist_get(items
, 3);
1091 if (tor_addr_port_split(LOG_WARN
, addrport
, &address
, &port
)<0) {
1092 log_warn(LD_CONFIG
, "Error parsing transport "
1093 "address '%s'", addrport
);
1099 "Transport address '%s' has no port.", addrport
);
1103 if (tor_addr_parse(&tor_addr
, address
) < 0) {
1104 log_warn(LD_CONFIG
, "Error parsing transport address '%s'", address
);
1108 transport
= transport_new(&tor_addr
, port
, method_name
, socks_ver
, NULL
);
1112 smartlist_add(mp
->transports
, transport
);
1114 log_info(LD_CONFIG
, "Transport %s at %s:%d with SOCKS %d. "
1115 "Attached to managed proxy.",
1116 method_name
, address
, (int)port
, socks_ver
);
1125 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
1126 smartlist_free(items
);
1131 /** Return a newly allocated string that tor should place in
1132 * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
1133 * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
1135 get_transport_options_for_server_proxy(const managed_proxy_t
*mp
)
1137 char *options_string
= NULL
;
1138 smartlist_t
*string_sl
= smartlist_new();
1140 tor_assert(mp
->is_server
);
1142 /** Loop over the transports of the proxy. If we have options for
1143 any of them, format them appropriately and place them in our
1144 smartlist. Finally, join our smartlist to get the final
1146 SMARTLIST_FOREACH_BEGIN(mp
->transports_to_launch
, const char *, transport
) {
1147 smartlist_t
*options_tmp_sl
= NULL
;
1148 options_tmp_sl
= get_options_for_server_transport(transport
);
1149 if (!options_tmp_sl
)
1152 /** Loop over the options of this transport, escape them, and
1153 place them in the smartlist. */
1154 SMARTLIST_FOREACH_BEGIN(options_tmp_sl
, const char *, options
) {
1155 char *escaped_opts
= tor_escape_str_for_pt_args(options
, ":;\\");
1156 smartlist_add_asprintf(string_sl
, "%s:%s",
1157 transport
, escaped_opts
);
1158 tor_free(escaped_opts
);
1159 } SMARTLIST_FOREACH_END(options
);
1161 SMARTLIST_FOREACH(options_tmp_sl
, char *, c
, tor_free(c
));
1162 smartlist_free(options_tmp_sl
);
1163 } SMARTLIST_FOREACH_END(transport
);
1165 if (smartlist_len(string_sl
)) {
1166 options_string
= smartlist_join_strings(string_sl
, ";", 0, NULL
);
1169 SMARTLIST_FOREACH(string_sl
, char *, t
, tor_free(t
));
1170 smartlist_free(string_sl
);
1172 return options_string
;
1175 /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
1176 * while configuring the server managed proxy in <b>mp</b>. The
1177 * string is stored in the heap, and it's the the responsibility of
1178 * the caller to deallocate it after its use. */
1180 get_bindaddr_for_server_proxy(const managed_proxy_t
*mp
)
1182 char *bindaddr_result
= NULL
;
1183 char *bindaddr_tmp
= NULL
;
1184 smartlist_t
*string_tmp
= smartlist_new();
1186 tor_assert(mp
->is_server
);
1188 SMARTLIST_FOREACH_BEGIN(mp
->transports_to_launch
, char *, t
) {
1189 bindaddr_tmp
= get_stored_bindaddr_for_server_transport(t
);
1191 smartlist_add_asprintf(string_tmp
, "%s-%s", t
, bindaddr_tmp
);
1193 tor_free(bindaddr_tmp
);
1194 } SMARTLIST_FOREACH_END(t
);
1196 bindaddr_result
= smartlist_join_strings(string_tmp
, ",", 0, NULL
);
1198 SMARTLIST_FOREACH(string_tmp
, char *, t
, tor_free(t
));
1199 smartlist_free(string_tmp
);
1201 return bindaddr_result
;
1204 /** Return a newly allocated process_environment_t * for <b>mp</b>'s
1206 static process_environment_t
*
1207 create_managed_proxy_environment(const managed_proxy_t
*mp
)
1209 const or_options_t
*options
= get_options();
1211 /* Environment variables to be added to or set in mp's environment. */
1212 smartlist_t
*envs
= smartlist_new();
1213 /* XXXX The next time someone touches this code, shorten the name of
1214 * set_environment_variable_in_smartlist, add a
1215 * set_env_var_in_smartlist_asprintf function, and get rid of the
1216 * silly extra envs smartlist. */
1218 /* The final environment to be passed to mp. */
1219 smartlist_t
*merged_env_vars
= get_current_process_environment_variables();
1221 process_environment_t
*env
;
1224 char *state_tmp
= get_datadir_fname("pt_state/"); /* XXX temp */
1225 smartlist_add_asprintf(envs
, "TOR_PT_STATE_LOCATION=%s", state_tmp
);
1226 tor_free(state_tmp
);
1229 smartlist_add(envs
, tor_strdup("TOR_PT_MANAGED_TRANSPORT_VER=1"));
1232 char *transports_to_launch
=
1233 smartlist_join_strings(mp
->transports_to_launch
, ",", 0, NULL
);
1235 smartlist_add_asprintf(envs
,
1237 "TOR_PT_SERVER_TRANSPORTS=%s" :
1238 "TOR_PT_CLIENT_TRANSPORTS=%s",
1239 transports_to_launch
);
1241 tor_free(transports_to_launch
);
1244 if (mp
->is_server
) {
1247 get_first_listener_addrport_string(CONN_TYPE_OR_LISTENER
);
1249 smartlist_add_asprintf(envs
, "TOR_PT_ORPORT=%s", orport_tmp
);
1250 tor_free(orport_tmp
);
1255 char *bindaddr_tmp
= get_bindaddr_for_server_proxy(mp
);
1256 smartlist_add_asprintf(envs
, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp
);
1257 tor_free(bindaddr_tmp
);
1261 char *server_transport_options
=
1262 get_transport_options_for_server_proxy(mp
);
1263 if (server_transport_options
) {
1264 smartlist_add_asprintf(envs
, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1265 server_transport_options
);
1266 tor_free(server_transport_options
);
1270 /* XXX024 Remove the '=' here once versions of obfsproxy which
1271 * assert that this env var exists are sufficiently dead.
1273 * (If we remove this line entirely, some joker will stick this
1274 * variable in Tor's environment and crash PTs that try to parse
1275 * it even when not run in server mode.) */
1277 if (options
->ExtORPort_lines
) {
1278 char *ext_or_addrport_tmp
=
1279 get_first_listener_addrport_string(CONN_TYPE_EXT_OR_LISTENER
);
1280 char *cookie_file_loc
= get_ext_or_auth_cookie_file_name();
1282 if (ext_or_addrport_tmp
) {
1283 smartlist_add_asprintf(envs
, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1284 ext_or_addrport_tmp
);
1286 smartlist_add_asprintf(envs
, "TOR_PT_AUTH_COOKIE_FILE=%s",
1289 tor_free(ext_or_addrport_tmp
);
1290 tor_free(cookie_file_loc
);
1293 smartlist_add_asprintf(envs
, "TOR_PT_EXTENDED_SERVER_PORT=");
1297 SMARTLIST_FOREACH_BEGIN(envs
, const char *, env_var
) {
1298 set_environment_variable_in_smartlist(merged_env_vars
, env_var
,
1300 } SMARTLIST_FOREACH_END(env_var
);
1302 env
= process_environment_make(merged_env_vars
);
1304 smartlist_free(envs
);
1306 SMARTLIST_FOREACH(merged_env_vars
, void *, x
, tor_free(x
));
1307 smartlist_free(merged_env_vars
);
1312 /** Create and return a new managed proxy for <b>transport</b> using
1313 * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
1314 * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
1315 * <b>proxy_argv</b>.
1317 * Requires that proxy_argv have at least one element. */
1318 STATIC managed_proxy_t
*
1319 managed_proxy_create(const smartlist_t
*transport_list
,
1320 char **proxy_argv
, int is_server
)
1322 managed_proxy_t
*mp
= tor_malloc_zero(sizeof(managed_proxy_t
));
1323 mp
->conf_state
= PT_PROTO_INFANT
;
1324 mp
->is_server
= is_server
;
1325 mp
->argv
= proxy_argv
;
1326 mp
->transports
= smartlist_new();
1328 mp
->transports_to_launch
= smartlist_new();
1329 SMARTLIST_FOREACH(transport_list
, const char *, transport
,
1330 add_transport_to_proxy(transport
, mp
));
1332 /* register the managed proxy */
1333 if (!managed_proxy_list
)
1334 managed_proxy_list
= smartlist_new();
1335 smartlist_add(managed_proxy_list
, mp
);
1336 unconfigured_proxies_n
++;
1338 assert_unconfigured_count_ok();
1343 /** Register proxy with <b>proxy_argv</b>, supporting transports in
1344 * <b>transport_list</b>, to the managed proxy subsystem.
1345 * If <b>is_server</b> is true, then the proxy is a server proxy.
1347 * Takes ownership of proxy_argv.
1349 * Requires that proxy_argv be a NULL-terminated array of command-line
1350 * elements, containing at least one element.
1353 pt_kickstart_proxy(const smartlist_t
*transport_list
,
1354 char **proxy_argv
, int is_server
)
1356 managed_proxy_t
*mp
=NULL
;
1357 transport_t
*old_transport
= NULL
;
1359 if (!proxy_argv
|| !proxy_argv
[0]) {
1363 mp
= get_managed_proxy_by_argv_and_type(proxy_argv
, is_server
);
1365 if (!mp
) { /* we haven't seen this proxy before */
1366 managed_proxy_create(transport_list
, proxy_argv
, is_server
);
1368 } else { /* known proxy. add its transport to its transport list */
1369 if (mp
->was_around_before_config_read
) {
1370 /* If this managed proxy was around even before we read the
1371 config this time, it means that it was already enabled before
1372 and is not useless and should be kept. If it's marked for
1373 removal, unmark it and make sure that we check whether it
1374 needs to be restarted. */
1375 if (mp
->marked_for_removal
) {
1376 mp
->marked_for_removal
= 0;
1377 check_if_restarts_needed
= 1;
1380 /* For each new transport, check if the managed proxy used to
1381 support it before the SIGHUP. If that was the case, make sure
1382 it doesn't get removed because we might reuse it. */
1383 SMARTLIST_FOREACH_BEGIN(transport_list
, const char *, transport
) {
1384 old_transport
= transport_get_by_name(transport
);
1386 old_transport
->marked_for_removal
= 0;
1387 } SMARTLIST_FOREACH_END(transport
);
1390 SMARTLIST_FOREACH(transport_list
, const char *, transport
,
1391 add_transport_to_proxy(transport
, mp
));
1392 free_execve_args(proxy_argv
);
1396 /** Frees the array of pointers in <b>arg</b> used as arguments to
1399 free_execve_args(char **arg
)
1402 while (*tmp
) /* use the fact that the last element of the array is a
1403 NULL pointer to know when to stop freeing */
1409 /** Tor will read its config.
1410 * Prepare the managed proxy list so that proxies not used in the new
1411 * config will shutdown, and proxies that need to spawn different
1412 * transports will do so. */
1414 pt_prepare_proxy_list_for_config_read(void)
1416 if (!managed_proxy_list
)
1419 assert_unconfigured_count_ok();
1420 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, managed_proxy_t
*, mp
) {
1421 /* Destroy unconfigured proxies. */
1422 if (mp
->conf_state
!= PT_PROTO_COMPLETED
) {
1423 SMARTLIST_DEL_CURRENT(managed_proxy_list
, mp
);
1424 managed_proxy_destroy(mp
, 1);
1425 unconfigured_proxies_n
--;
1429 tor_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
1431 /* Mark all proxies for removal, and also note that they have been
1432 here before the config read. */
1433 mp
->marked_for_removal
= 1;
1434 mp
->was_around_before_config_read
= 1;
1435 SMARTLIST_FOREACH(mp
->transports_to_launch
, char *, t
, tor_free(t
));
1436 smartlist_clear(mp
->transports_to_launch
);
1437 } SMARTLIST_FOREACH_END(mp
);
1439 assert_unconfigured_count_ok();
1441 tor_assert(unconfigured_proxies_n
== 0);
1444 /** Return a smartlist containing the ports where our pluggable
1445 * transports are listening. */
1447 get_transport_proxy_ports(void)
1449 smartlist_t
*sl
= NULL
;
1451 if (!managed_proxy_list
)
1454 /** XXX assume that external proxy ports have been forwarded
1456 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, const managed_proxy_t
*, mp
) {
1457 if (!mp
->is_server
|| mp
->conf_state
!= PT_PROTO_COMPLETED
)
1460 if (!sl
) sl
= smartlist_new();
1462 tor_assert(mp
->transports
);
1463 SMARTLIST_FOREACH(mp
->transports
, const transport_t
*, t
,
1464 smartlist_add_asprintf(sl
, "%u:%u", t
->port
, t
->port
));
1466 } SMARTLIST_FOREACH_END(mp
);
1471 /** Return the pluggable transport string that we should display in
1472 * our extra-info descriptor. If we shouldn't display such a string,
1473 * or we have nothing to display, return NULL. The string is
1474 * allocated on the heap and it's the responsibility of the caller to
1477 pt_get_extra_info_descriptor_string(void)
1479 char *the_string
= NULL
;
1480 smartlist_t
*string_chunks
= NULL
;
1482 if (!managed_proxy_list
)
1485 string_chunks
= smartlist_new();
1487 /* For each managed proxy, add its transports to the chunks list. */
1488 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, const managed_proxy_t
*, mp
) {
1489 if ((!mp
->is_server
) || (mp
->conf_state
!= PT_PROTO_COMPLETED
))
1492 tor_assert(mp
->transports
);
1494 SMARTLIST_FOREACH_BEGIN(mp
->transports
, const transport_t
*, t
) {
1495 char *transport_args
= NULL
;
1497 /* If the transport proxy returned "0.0.0.0" as its address, and
1498 * we know our external IP address, use it. Otherwise, use the
1499 * returned address. */
1500 const char *addrport
= NULL
;
1501 uint32_t external_ip_address
= 0;
1502 if (tor_addr_is_null(&t
->addr
) &&
1503 router_pick_published_address(get_options(),
1504 &external_ip_address
) >= 0) {
1506 tor_addr_from_ipv4h(&addr
, external_ip_address
);
1507 addrport
= fmt_addrport(&addr
, t
->port
);
1509 addrport
= fmt_addrport(&t
->addr
, t
->port
);
1512 /* If this transport has any arguments with it, prepend a space
1513 to them so that we can add them to the transport line. */
1514 if (t
->extra_info_args
)
1515 tor_asprintf(&transport_args
, " %s", t
->extra_info_args
);
1517 smartlist_add_asprintf(string_chunks
,
1518 "transport %s %s%s",
1520 transport_args
? transport_args
: "");
1521 tor_free(transport_args
);
1522 } SMARTLIST_FOREACH_END(t
);
1524 } SMARTLIST_FOREACH_END(mp
);
1526 if (smartlist_len(string_chunks
) == 0) {
1527 smartlist_free(string_chunks
);
1531 /* Join all the chunks into the final string. */
1532 the_string
= smartlist_join_strings(string_chunks
, "\n", 1, NULL
);
1534 SMARTLIST_FOREACH(string_chunks
, char *, s
, tor_free(s
));
1535 smartlist_free(string_chunks
);
1540 /** Stringify the SOCKS arguments in <b>socks_args</b> according to
1541 * 180_pluggable_transport.txt. The string is allocated on the heap
1542 * and it's the responsibility of the caller to free it after use. */
1544 pt_stringify_socks_args(const smartlist_t
*socks_args
)
1546 /* tmp place to store escaped socks arguments, so that we can
1547 concatenate them up afterwards */
1548 smartlist_t
*sl_tmp
= NULL
;
1549 char *escaped_string
= NULL
;
1550 char *new_string
= NULL
;
1552 tor_assert(socks_args
);
1553 tor_assert(smartlist_len(socks_args
) > 0);
1555 sl_tmp
= smartlist_new();
1557 SMARTLIST_FOREACH_BEGIN(socks_args
, const char *, s
) {
1558 /* Escape ';' and '\'. */
1559 escaped_string
= tor_escape_str_for_pt_args(s
, ";\\");
1560 if (!escaped_string
)
1563 smartlist_add(sl_tmp
, escaped_string
);
1564 } SMARTLIST_FOREACH_END(s
);
1566 new_string
= smartlist_join_strings(sl_tmp
, ";", 0, NULL
);
1569 SMARTLIST_FOREACH(sl_tmp
, char *, s
, tor_free(s
));
1570 smartlist_free(sl_tmp
);
1575 /** Return a string of the SOCKS arguments that we should pass to the
1576 * pluggable transports proxy in <b>addr</b>:<b>port</b> according to
1577 * 180_pluggable_transport.txt. The string is allocated on the heap
1578 * and it's the responsibility of the caller to free it after use. */
1580 pt_get_socks_args_for_proxy_addrport(const tor_addr_t
*addr
, uint16_t port
)
1582 const smartlist_t
*socks_args
= NULL
;
1584 socks_args
= get_socks_args_by_bridge_addrport(addr
, port
);
1588 return pt_stringify_socks_args(socks_args
);
1591 /** The tor config was read.
1592 * Destroy all managed proxies that were marked by a previous call to
1593 * prepare_proxy_list_for_config_read() and are not used by the new
1596 sweep_proxy_list(void)
1598 if (!managed_proxy_list
)
1600 assert_unconfigured_count_ok();
1601 SMARTLIST_FOREACH_BEGIN(managed_proxy_list
, managed_proxy_t
*, mp
) {
1602 if (mp
->marked_for_removal
) {
1603 SMARTLIST_DEL_CURRENT(managed_proxy_list
, mp
);
1604 managed_proxy_destroy(mp
, 1);
1606 } SMARTLIST_FOREACH_END(mp
);
1607 assert_unconfigured_count_ok();
1610 /** Release all storage held by the pluggable transports subsystem. */
1614 if (transport_list
) {
1615 clear_transport_list();
1616 smartlist_free(transport_list
);
1617 transport_list
= NULL
;
1620 if (managed_proxy_list
) {
1621 /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1622 transports and it's the duty of the circuitbuild.c subsystem to
1623 free them. Otherwise, it hasn't registered its transports yet
1624 and we should free them here. */
1625 SMARTLIST_FOREACH(managed_proxy_list
, managed_proxy_t
*, mp
, {
1626 SMARTLIST_DEL_CURRENT(managed_proxy_list
, mp
);
1627 managed_proxy_destroy(mp
, 1);
1630 smartlist_free(managed_proxy_list
);
1631 managed_proxy_list
=NULL
;