Make transports.c logs a bit more helpful.
[tor/neena.git] / src / or / transports.c
blobb8b2331c5ac7331ae787be0e902a09b28898f22b
1 /* Copyright (c) 2011, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file transports.c
6 * \brief Pluggable Transports related code.
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.
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>
34 * element.
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
51 * occurs:</b>
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
65 * torrc.
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.
84 **/
86 #define PT_PRIVATE
87 #include "or.h"
88 #include "config.h"
89 #include "circuitbuild.h"
90 #include "transports.h"
91 #include "util.h"
92 #include "router.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
131 protocol version. */
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. */
151 static void
152 assert_unconfigured_count_ok(void)
154 int n_completed = 0;
155 if (!managed_proxy_list) {
156 tor_assert(unconfigured_proxies_n == 0);
157 return;
160 SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
161 if (mp->conf_state == PT_PROTO_COMPLETED)
162 ++n_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> */
170 static int
171 managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
173 char **tmp1=proxy_argv;
174 char **tmp2=mp->argv;
176 tor_assert(tmp1);
177 tor_assert(tmp2);
179 while (*tmp1 && *tmp2) {
180 if (strcmp(*tmp1++, *tmp2++))
181 return 0;
184 if (!*tmp1 && !*tmp2)
185 return 1;
187 return 0;
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)
196 return NULL;
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)
201 return mp;
202 } SMARTLIST_FOREACH_END(mp);
204 return NULL;
207 /** Add <b>transport</b> to managed proxy <b>mp</b>. */
208 static void
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
218 * torrc. */
219 static int
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))
234 goto needs_restart;
236 SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
237 if (!smartlist_string_isin(mp->transports, t_t_l))
238 goto needs_restart;
240 } SMARTLIST_FOREACH_END(t_t_l);
242 return 0;
244 needs_restart:
245 return 1;
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. */
251 static void
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);
265 if (t_tmp)
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>. */
280 static int
281 launch_managed_proxy(managed_proxy_t *mp)
283 int retval;
285 process_environment_t *env = create_managed_proxy_environment(mp);
287 #ifdef _WIN32
288 /* Passing NULL as lpApplicationName makes Windows search for the .exe */
289 retval = tor_spawn_background(NULL,
290 (const char **)mp->argv,
291 env,
292 &mp->process_handle);
293 #else
294 retval = tor_spawn_background(mp->argv[0],
295 (const char **)mp->argv,
296 env,
297 &mp->process_handle);
298 #endif
300 process_environment_free(env);
302 if (retval == PROCESS_STATUS_ERROR) {
303 log_warn(LD_GENERAL, "Managed proxy at '%s' failed at launch.",
304 mp->argv[0]);
305 return -1;
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;
313 return 0;
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(). */
319 void
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);
337 if (mp->got_hup) {
338 mp->got_hup = 0;
340 /* This proxy is marked by a SIGHUP. Check whether we need to
341 restart it. */
342 if (proxy_needs_restart(mp)) {
343 log_info(LD_GENERAL, "Preparing managed proxy '%s' for restart.",
344 mp->argv[0]);
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]);
351 continue;
354 /* If the proxy is not fully configured, try to configure it
355 futher. */
356 if (!proxy_configuration_finished(mp))
357 configure_proxy(mp);
359 } SMARTLIST_FOREACH_END(mp);
361 smartlist_free(tmp);
362 check_if_restarts_needed = 0;
363 assert_unconfigured_count_ok();
366 #ifdef _WIN32
368 /** Attempt to continue configuring managed proxy <b>mp</b>. */
369 static void
370 configure_proxy(managed_proxy_t *mp)
372 int pos;
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);
382 return;
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);
390 if (pos < 0) {
391 log_notice(LD_GENERAL, "Failed to read data from managed proxy '%s'.",
392 mp->argv[0]);
393 mp->conf_state = PT_PROTO_BROKEN;
394 goto done;
397 if (pos == 0) /* proxy has nothing interesting to say. */
398 return;
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);
408 /* Handle lines. */
409 SMARTLIST_FOREACH_BEGIN(lines, const char *, line) {
410 handle_proxy_line(line, mp);
411 if (proxy_configuration_finished(mp))
412 goto done;
413 } SMARTLIST_FOREACH_END(line);
415 done:
416 /* if the proxy finished configuring, exit the loop. */
417 if (proxy_configuration_finished(mp))
418 handle_finished_proxy(mp);
420 if (lines)
421 smartlist_free(lines);
424 #else /* _WIN32 */
426 /** Attempt to continue configuring managed proxy <b>mp</b>. */
427 static void
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);
439 return;
442 tor_assert(mp->conf_state != PT_PROTO_INFANT);
443 tor_assert(mp->process_handle);
445 while (1) {
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 */
452 return;
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.",
456 mp->argv[0]);
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);
466 return;
471 #endif /* _WIN32 */
473 /** Register server managed proxy <b>mp</b> transports to state */
474 static void
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. */
501 static void
502 register_client_proxy(managed_proxy_t *mp)
504 int r;
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);
513 switch (r) {
514 case -1:
515 log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
516 transport_free(t);
517 break;
518 case 0:
519 log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
520 smartlist_add(sm_tmp, tor_strdup(t->name));
521 break;
522 case 1:
523 log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
524 smartlist_add(sm_tmp, tor_strdup(t->name));
525 transport_free(t);
526 break;
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>. */
535 static INLINE void
536 register_proxy(managed_proxy_t *mp)
538 if (mp->is_server)
539 register_server_proxy(mp);
540 else
541 register_client_proxy(mp);
544 /** Free memory allocated by managed proxy <b>mp</b>. */
545 static void
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));
551 else
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);
564 /* free the argv */
565 free_execve_args(mp->argv);
567 tor_process_handle_destroy(mp->process_handle, also_terminate_process);
568 mp->process_handle = NULL;
570 tor_free(mp);
573 /** Handle a configured or broken managed proxy <b>mp</b>. */
574 static void
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. */
580 break;
581 case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
582 managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
583 break;
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. */
587 break;
588 case PT_PROTO_INFANT:
589 case PT_PROTO_LAUNCHED:
590 case PT_PROTO_ACCEPTING_METHODS:
591 case PT_PROTO_COMPLETED:
592 default:
593 log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
594 mp->conf_state, mp->argv[0]);
595 tor_assert(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
603 finished. */
604 static INLINE int
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. */
613 static void
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!",
621 mp->argv[0]);
623 log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
624 mp->is_server ? "Server" : "Client",
625 mp->argv[0]);
628 /** Handle a configuration protocol <b>line</b> received from a
629 * managed proxy <b>mp</b>. */
630 void
631 handle_proxy_line(const char *line, managed_proxy_t *mp)
633 log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
634 mp->argv[0], line);
636 if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) {
637 log_warn(LD_GENERAL, "Managed proxy configuration line is too small. "
638 "Discarding");
639 goto err;
642 if (!strcmpstart(line, PROTO_ENV_ERROR)) {
643 if (mp->conf_state != PT_PROTO_LAUNCHED)
644 goto err;
646 parse_env_error(line);
647 goto err;
648 } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
649 if (mp->conf_state != PT_PROTO_LAUNCHED)
650 goto err;
652 log_warn(LD_CONFIG, "Managed proxy could not pick a "
653 "configuration protocol version.");
654 goto err;
655 } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
656 if (mp->conf_state != PT_PROTO_LAUNCHED)
657 goto err;
659 if (parse_version(line,mp) < 0)
660 goto err;
662 tor_assert(mp->conf_protocol != 0);
663 mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
664 return;
665 } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
666 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
667 goto err;
669 handle_methods_done(mp);
671 mp->conf_state = PT_PROTO_CONFIGURED;
672 return;
673 } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
674 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
675 goto err;
677 handle_methods_done(mp);
679 mp->conf_state = PT_PROTO_CONFIGURED;
680 return;
681 } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
682 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
683 goto err;
685 parse_client_method_error(line);
686 goto err;
687 } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
688 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
689 goto err;
691 parse_server_method_error(line);
692 goto err;
693 } else if (!strcmpstart(line, PROTO_CMETHOD)) {
694 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
695 goto err;
697 if (parse_cmethod_line(line, mp) < 0)
698 goto err;
700 return;
701 } else if (!strcmpstart(line, PROTO_SMETHOD)) {
702 if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
703 goto err;
705 if (parse_smethod_line(line, mp) < 0)
706 goto err;
708 return;
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;
712 return;
715 log_warn(LD_CONFIG, "Unknown line received by managed proxy. (%s)", line);
717 err:
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. */
724 void
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.",
745 PROTO_NEG_SUCCESS);
746 return -1;
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);
752 return -1;
755 mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
756 return 0;
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. */
762 static void
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 "
772 "message.", 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)
784 int r;
785 smartlist_t *items = NULL;
787 char *method_name=NULL;
789 char *addrport=NULL;
790 tor_addr_t addr;
791 uint16_t port = 0;
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.");
801 goto err;
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).",
809 method_name);
810 goto err;
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);
817 goto err;
820 if (!port) {
821 log_warn(LD_CONFIG,
822 "Transport address '%s' has no port.", addrport);
823 goto err;
826 transport = transport_new(&addr, port, method_name, PROXY_NONE);
827 if (!transport)
828 goto err;
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);
837 r=0;
838 goto done;
840 err:
841 r = -1;
843 done:
844 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
845 smartlist_free(items);
846 return r;
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)
854 int r;
855 smartlist_t *items = NULL;
857 char *method_name=NULL;
859 char *socks_ver_str=NULL;
860 int socks_ver=PROXY_NONE;
862 char *addrport=NULL;
863 tor_addr_t addr;
864 uint16_t port = 0;
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.");
874 goto err;
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).",
882 method_name);
883 goto err;
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;
892 } else {
893 log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
894 "we don't recognize. (%s)", socks_ver_str);
895 goto err;
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);
902 goto err;
905 if (!port) {
906 log_warn(LD_CONFIG,
907 "Transport address '%s' has no port.", addrport);
908 goto err;
911 transport = transport_new(&addr, port, method_name, socks_ver);
912 if (!transport)
913 goto err;
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);
921 r=0;
922 goto done;
924 err:
925 r = -1;
927 done:
928 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
929 smartlist_free(items);
930 return r;
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. */
937 static char *
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
963 * process. */
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);
984 tor_free(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,
994 mp->is_server ?
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,
1023 _tor_free, 1);
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);
1033 return env;
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
1038 * managed proxy. */
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();
1061 return mp;
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. */
1067 void
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 */
1080 if (mp->got_hup) {
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
1087 it. */
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);
1095 if (old_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
1107 execve(2). */
1108 static INLINE void
1109 free_execve_args(char **arg)
1111 char **tmp = 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 */
1114 _tor_free(*tmp++);
1116 tor_free(arg);
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. */
1123 void
1124 pt_prepare_proxy_list_for_config_read(void)
1126 if (!managed_proxy_list)
1127 return;
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--;
1136 continue;
1139 tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1141 mp->marked_for_removal = 1;
1142 mp->got_hup = 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
1155 * config. */
1156 void
1157 sweep_proxy_list(void)
1159 if (!managed_proxy_list)
1160 return;
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. */
1172 void
1173 pt_free_all(void)
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;