Tor  0.4.4.0-alpha-dev
transports.c
Go to the documentation of this file.
1 /* Copyright (c) 2011-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * \file transports.c
6  * \brief Pluggable Transports related code.
7  *
8  * \details
9  * Each managed proxy is represented by a <b>managed_proxy_t</b>.
10  * Each managed proxy can support multiple transports.
11  * Each managed proxy gets configured through a multistep process.
12  *
13  * ::managed_proxy_list contains all the managed proxies this tor
14  * instance is supporting.
15  * In the ::managed_proxy_list there are ::unconfigured_proxies_n
16  * managed proxies that are still unconfigured.
17  *
18  * In every run_scheduled_event() tick, we attempt to launch and then
19  * configure the 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.
22  *
23  * When a managed proxy is fully configured, we register all its
24  * transports to the circuitbuild.c subsystem. At that point the
25  * transports are owned by the circuitbuild.c subsystem.
26  *
27  * When a managed proxy fails to follow the 180 configuration
28  * protocol, it gets marked as broken and gets destroyed.
29  *
30  * <b>In a little more detail:</b>
31  *
32  * While we are serially parsing torrc, we store all the transports
33  * that a proxy should spawn in its <em>transports_to_launch</em>
34  * element.
35  *
36  * When we finish reading the torrc, we spawn the managed proxy and
37  * expect {S,C}METHOD lines from its output. We add transports
38  * described by METHOD lines to its <em>transports</em> element, as
39  * transport_t structs.
40  *
41  * When the managed proxy stops spitting METHOD lines (signified by a
42  * '{S,C}METHODS DONE' message) we pass copies of its transports to
43  * the bridge subsystem. We keep copies of the 'transport_t's on the
44  * managed proxy to be able to associate the proxy with its
45  * transports, and we pass copies to the bridge subsystem so that
46  * transports can be associated with bridges.
47  * [ XXX We should try see whether the two copies are really needed
48  * and maybe cut it into a single copy of the 'transport_t' shared
49  * between the managed proxy and the bridge subsystem. Preliminary
50  * analysis shows that both copies are needed with the current code
51  * logic, because of race conditions that can cause dangling
52  * pointers. ]
53  *
54  * <b>In even more detail, this is what happens when a config read
55  * (like a SIGHUP or a SETCONF) occurs:</b>
56  *
57  * We immediately destroy all unconfigured proxies (We shouldn't have
58  * unconfigured proxies in the first place, except when the config
59  * read happens immediately after tor is launched.).
60  *
61  * We mark all managed proxies and transports to signify that they
62  * must be removed if they don't contribute by the new torrc
63  * (we mark using the <b>marked_for_removal</b> element).
64  * We also mark all managed proxies to signify that they might need to
65  * be restarted so that they end up supporting all the transports the
66  * new torrc wants them to support
67  * (we mark using the <b>was_around_before_config_read</b> element).
68  * We also clear their <b>transports_to_launch</b> list so that we can
69  * put there the transports we need to launch according to the new
70  * torrc.
71  *
72  * We then start parsing torrc again.
73  *
74  * 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.
83  *
84  * During the post-config-read torrc parsing, we unmark all transports
85  * spawned by managed proxies that we find in our torrc.
86  * We do that so that if we don't need to restart a managed proxy, we
87  * can continue using its old transports normally.
88  * If we end up restarting the proxy, we destroy and unregister all
89  * old transports from the circuitbuild.c subsystem.
90  **/
91 
92 #define PT_PRIVATE
93 #include "core/or/or.h"
94 #include "feature/client/bridges.h"
95 #include "app/config/config.h"
97 #include "core/or/circuitbuild.h"
99 #include "feature/relay/router.h"
101 /* 31851: split the server transport code out of the client module */
103 #include "app/config/statefile.h"
104 #include "core/or/connection_or.h"
107 #include "lib/encoding/confline.h"
108 #include "lib/encoding/kvline.h"
109 
110 #include "lib/process/process.h"
111 #include "lib/process/env.h"
112 
113 static smartlist_t *
114 create_managed_proxy_environment(const managed_proxy_t *mp);
115 
116 static inline int proxy_configuration_finished(const managed_proxy_t *mp);
117 
118 static void handle_finished_proxy(managed_proxy_t *mp);
119 static void parse_method_error(const char *line, int is_server_method);
120 #define parse_server_method_error(l) parse_method_error(l, 1)
121 #define parse_client_method_error(l) parse_method_error(l, 0)
122 
123 /** Managed proxy protocol strings */
124 #define PROTO_ENV_ERROR "ENV-ERROR"
125 #define PROTO_NEG_SUCCESS "VERSION"
126 #define PROTO_NEG_FAIL "VERSION-ERROR no-version"
127 #define PROTO_CMETHOD "CMETHOD"
128 #define PROTO_SMETHOD "SMETHOD"
129 #define PROTO_CMETHOD_ERROR "CMETHOD-ERROR"
130 #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
131 #define PROTO_CMETHODS_DONE "CMETHODS DONE"
132 #define PROTO_SMETHODS_DONE "SMETHODS DONE"
133 #define PROTO_PROXY_DONE "PROXY DONE"
134 #define PROTO_PROXY_ERROR "PROXY-ERROR"
135 #define PROTO_LOG "LOG"
136 #define PROTO_STATUS "STATUS"
137 
138 /** The first and only supported - at the moment - configuration
139  protocol version. */
140 #define PROTO_VERSION_ONE 1
141 
142 /** A list of pluggable transports found in torrc. */
144 
145 /** Returns a transport_t struct for a transport proxy supporting the
146  protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
147  SOCKS version <b>socks_ver</b>. */
149 transport_new(const tor_addr_t *addr, uint16_t port,
150  const char *name, int socks_ver,
151  const char *extra_info_args)
152 {
153  transport_t *t = tor_malloc_zero(sizeof(transport_t));
154 
155  tor_addr_copy(&t->addr, addr);
156  t->port = port;
157  t->name = tor_strdup(name);
158  t->socks_version = socks_ver;
159  if (extra_info_args)
160  t->extra_info_args = tor_strdup(extra_info_args);
161 
162  return t;
163 }
164 
165 /** Free the pluggable transport struct <b>transport</b>. */
166 void
168 {
169  if (!transport)
170  return;
171 
172  tor_free(transport->name);
173  tor_free(transport->extra_info_args);
174  tor_free(transport);
175 }
176 
177 /** Mark every entry of the transport list to be removed on our next call to
178  * sweep_transport_list unless it has first been un-marked. */
179 void
181 {
182  if (!transport_list)
185  t->marked_for_removal = 1);
186 }
187 
188 /** Remove every entry of the transport list that was marked with
189  * mark_transport_list if it has not subsequently been un-marked. */
190 void
192 {
193  if (!transport_list)
196  if (t->marked_for_removal) {
198  transport_free(t);
199  }
200  } SMARTLIST_FOREACH_END(t);
201 }
202 
203 /** Initialize the pluggable transports list to empty, creating it if
204  * needed. */
205 static void
207 {
208  if (!transport_list)
210  SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
212 }
213 
214 /** Return a deep copy of <b>transport</b>. */
215 static transport_t *
216 transport_copy(const transport_t *transport)
217 {
218  transport_t *new_transport = NULL;
219 
220  tor_assert(transport);
221 
222  new_transport = tor_malloc_zero(sizeof(transport_t));
223 
224  new_transport->socks_version = transport->socks_version;
225  new_transport->name = tor_strdup(transport->name);
226  tor_addr_copy(&new_transport->addr, &transport->addr);
227  new_transport->port = transport->port;
228  new_transport->marked_for_removal = transport->marked_for_removal;
229 
230  return new_transport;
231 }
232 
233 /** Returns the transport in our transport list that has the name <b>name</b>.
234  * Else returns NULL. */
237 {
238  tor_assert(name);
239 
240  if (!transport_list)
241  return NULL;
242 
244  if (!strcmp(transport->name, name))
245  return transport;
246  } SMARTLIST_FOREACH_END(transport);
247 
248  return NULL;
249 }
250 
251 /** Resolve any conflicts that the insertion of transport <b>t</b>
252  * might cause.
253  * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
254  * a transport identical to <b>t</b> already registered and -1 if
255  * <b>t</b> cannot be added due to conflicts. */
256 static int
258 {
259  /* This is how we resolve transport conflicts:
260 
261  If there is already a transport with the same name and addrport,
262  we either have duplicate torrc lines OR we are here post-HUP and
263  this transport was here pre-HUP as well. In any case, mark the
264  old transport so that it doesn't get removed and ignore the new
265  one. Our caller has to free the new transport so we return '1' to
266  signify this.
267 
268  If there is already a transport with the same name but different
269  addrport:
270  * if it's marked for removal, it means that it either has a lower
271  priority than 't' in torrc (otherwise the mark would have been
272  cleared by the paragraph above), or it doesn't exist at all in
273  the post-HUP torrc. We destroy the old transport and register 't'.
274  * if it's *not* marked for removal, it means that it was newly
275  added in the post-HUP torrc or that it's of higher priority, in
276  this case we ignore 't'. */
278  if (t_tmp) { /* same name */
279  if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
280  /* same name *and* addrport */
281  t_tmp->marked_for_removal = 0;
282  return 1;
283  } else { /* same name but different addrport */
284  char *new_transport_addrport =
285  tor_strdup(fmt_addrport(&t->addr, t->port));
286  if (t_tmp->marked_for_removal) { /* marked for removal */
287  log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s' "
288  "but there was already a transport marked for deletion at "
289  "'%s'. We deleted the old transport and registered the "
290  "new one.", t->name, new_transport_addrport,
291  fmt_addrport(&t_tmp->addr, t_tmp->port));
293  transport_free(t_tmp);
294  tor_free(new_transport_addrport);
295  } else { /* *not* marked for removal */
296  log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s' "
297  "but the same transport already exists at '%s'. "
298  "Skipping.", t->name, new_transport_addrport,
299  fmt_addrport(&t_tmp->addr, t_tmp->port));
300  tor_free(new_transport_addrport);
301  return -1;
302  }
303  tor_free(new_transport_addrport);
304  }
305  }
306 
307  return 0;
308 }
309 
310 /** Add transport <b>t</b> to the internal list of pluggable
311  * transports.
312  * Returns 0 if the transport was added correctly, 1 if the same
313  * transport was already registered (in this case the caller must
314  * free the transport) and -1 if there was an error. */
315 static int
317 {
318  int r;
319  tor_assert(t);
320 
322 
323  switch (r) {
324  case 0: /* should register transport */
325  if (!transport_list)
328  return 0;
329  default: /* let our caller know the return code */
330  return r;
331  }
332 }
333 
334 /** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
335  * <b>name</b> is set to the name of the protocol this proxy uses.
336  * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
337 MOCK_IMPL(int,
338 transport_add_from_config, (const tor_addr_t *addr, uint16_t port,
339  const char *name, int socks_ver))
340 {
341  transport_t *t = transport_new(addr, port, name, socks_ver, NULL);
342 
343  int r = transport_add(t);
344 
345  switch (r) {
346  case -1:
347  default:
348  log_notice(LD_GENERAL, "Could not add transport %s at %s. Skipping.",
349  t->name, fmt_addrport(&t->addr, t->port));
350  transport_free(t);
351  return -1;
352  case 1:
353  log_info(LD_GENERAL, "Successfully registered transport %s at %s.",
354  t->name, fmt_addrport(&t->addr, t->port));
355  transport_free(t); /* falling */
356  return 0;
357  case 0:
358  log_info(LD_GENERAL, "Successfully registered transport %s at %s.",
359  t->name, fmt_addrport(&t->addr, t->port));
360  return 0;
361  }
362 }
363 
364 /** List of unconfigured managed proxies. */
366 /** Number of still unconfigured proxies. */
367 static int unconfigured_proxies_n = 0;
368 /** Boolean: True iff we might need to restart some proxies. */
370 
371 /** Return true if there are still unconfigured managed proxies, or proxies
372  * that need restarting. */
373 int
375 {
377 }
378 
379 /** Assert that the unconfigured_proxies_n value correctly matches the number
380  * of proxies in a state other than PT_PROTO_COMPLETE. */
381 static void
383 {
384  int n_completed = 0;
385  if (!managed_proxy_list) {
387  return;
388  }
389 
390  SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
391  if (mp->conf_state == PT_PROTO_COMPLETED)
392  ++n_completed;
393  });
394 
395  tor_assert(n_completed + unconfigured_proxies_n ==
396  smartlist_len(managed_proxy_list));
397 }
398 
399 /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
400 static int
401 managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
402 {
403  char **tmp1=proxy_argv;
404  char **tmp2=mp->argv;
405 
406  tor_assert(tmp1);
407  tor_assert(tmp2);
408 
409  while (*tmp1 && *tmp2) {
410  if (strcmp(*tmp1++, *tmp2++))
411  return 0;
412  }
413 
414  if (!*tmp1 && !*tmp2)
415  return 1;
416 
417  return 0;
418 }
419 
420 /** Return a managed proxy with the same argv as <b>proxy_argv</b>.
421  * If no such managed proxy exists, return NULL. */
422 static managed_proxy_t *
423 get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server)
424 {
425  if (!managed_proxy_list)
426  return NULL;
427 
428  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
429  if (managed_proxy_has_argv(mp, proxy_argv) &&
430  mp->is_server == is_server)
431  return mp;
432  } SMARTLIST_FOREACH_END(mp);
433 
434  return NULL;
435 }
436 
437 /** Add <b>transport</b> to managed proxy <b>mp</b>. */
438 static void
439 add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
440 {
441  tor_assert(mp->transports_to_launch);
442  if (!smartlist_contains_string(mp->transports_to_launch, transport))
443  smartlist_add_strdup(mp->transports_to_launch, transport);
444 }
445 
446 /** Called when a SIGHUP occurs. Returns true if managed proxy
447  * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
448  * torrc. */
449 static int
450 proxy_needs_restart(const managed_proxy_t *mp)
451 {
452  int ret = 1;
453  char* proxy_uri;
454 
455  /* If the PT proxy config has changed, then all existing pluggable transports
456  * should be restarted.
457  */
458 
459  proxy_uri = get_pt_proxy_uri();
460  if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
461  goto needs_restart;
462 
463  /* mp->transport_to_launch is populated with the names of the
464  transports that must be launched *after* the SIGHUP.
465  mp->transports is populated with the transports that were
466  launched *before* the SIGHUP.
467 
468  Check if all the transports that need to be launched are already
469  launched: */
470 
471  tor_assert(smartlist_len(mp->transports_to_launch) > 0);
472  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
473 
474  if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
475  goto needs_restart;
476 
477  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
478  if (!smartlist_contains_string(mp->transports_to_launch, t->name))
479  goto needs_restart;
480 
481  } SMARTLIST_FOREACH_END(t);
482 
483  ret = 0;
484  needs_restart:
485  tor_free(proxy_uri);
486  return ret;
487 }
488 
489 /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
490  * preparations and then flag its state so that it will be relaunched
491  * in the next tick. */
492 static void
493 proxy_prepare_for_restart(managed_proxy_t *mp)
494 {
495  transport_t *t_tmp = NULL;
496 
497  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
498 
499  /* destroy the process handle and terminate the process. */
500  process_set_data(mp->process, NULL);
501  process_terminate(mp->process);
502 
503  /* destroy all its registered transports, since we will no longer
504  use them. */
505  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
506  t_tmp = transport_get_by_name(t->name);
507  if (t_tmp)
508  t_tmp->marked_for_removal = 1;
509  } SMARTLIST_FOREACH_END(t);
511 
512  /* free the transport in mp->transports */
513  SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
514  smartlist_clear(mp->transports);
515 
516  /* Reset the proxy's HTTPS/SOCKS proxy */
517  tor_free(mp->proxy_uri);
518  mp->proxy_uri = get_pt_proxy_uri();
519  mp->proxy_supported = 0;
520 
521  /* flag it as an infant proxy so that it gets launched on next tick */
522  mp->conf_state = PT_PROTO_INFANT;
524 }
525 
526 /** Launch managed proxy <b>mp</b>. */
527 static int
528 launch_managed_proxy(managed_proxy_t *mp)
529 {
530  tor_assert(mp);
531 
533 
534  /* Configure our process. */
535  process_set_data(mp->process, mp);
539  process_set_protocol(mp->process, PROCESS_PROTOCOL_LINE);
540  process_reset_environment(mp->process, env);
541 
542  /* Cleanup our env. */
543  SMARTLIST_FOREACH(env, char *, x, tor_free(x));
544  smartlist_free(env);
545 
546  /* Skip the argv[0] as we get that from process_new(argv[0]). */
547  for (int i = 1; mp->argv[i] != NULL; ++i)
548  process_append_argument(mp->process, mp->argv[i]);
549 
550  if (process_exec(mp->process) != PROCESS_STATUS_RUNNING) {
551  log_warn(LD_CONFIG, "Managed proxy at '%s' failed at launch.",
552  mp->argv[0]);
553  return -1;
554  }
555 
556  log_info(LD_CONFIG,
557  "Managed proxy at '%s' has spawned with PID '%" PRIu64 "'.",
558  mp->argv[0], process_get_pid(mp->process));
559  mp->conf_state = PT_PROTO_LAUNCHED;
560 
561  return 0;
562 }
563 
564 /** Check if any of the managed proxies we are currently trying to
565  * configure has anything new to say. */
566 void
568 {
569  int at_least_a_proxy_config_finished = 0;
570  smartlist_t *tmp = smartlist_new();
571 
572  log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
574 
575  /* Iterate over tmp, not managed_proxy_list, since configure_proxy can
576  * remove elements from managed_proxy_list. */
578 
580 
581  SMARTLIST_FOREACH_BEGIN(tmp, managed_proxy_t *, mp) {
582  tor_assert(mp->conf_state != PT_PROTO_BROKEN &&
583  mp->conf_state != PT_PROTO_FAILED_LAUNCH);
584 
585  if (mp->was_around_before_config_read) {
586  /* This proxy is marked by a config read. Check whether we need
587  to restart it. */
588 
589  mp->was_around_before_config_read = 0;
590 
591  if (proxy_needs_restart(mp)) {
592  log_info(LD_GENERAL, "Preparing managed proxy '%s' for restart.",
593  mp->argv[0]);
595  } else { /* it doesn't need to be restarted. */
596  log_info(LD_GENERAL, "Nothing changed for managed proxy '%s' after "
597  "HUP: not restarting.", mp->argv[0]);
598  }
599 
600  continue;
601  }
602 
603  /* If the proxy is not fully configured, try to configure it
604  further. */
606  if (configure_proxy(mp) == 1)
607  at_least_a_proxy_config_finished = 1;
608 
609  } SMARTLIST_FOREACH_END(mp);
610 
611  smartlist_free(tmp);
614 
615  if (at_least_a_proxy_config_finished)
616  mark_my_descriptor_dirty("configured managed proxies");
617 }
618 
619 /** Attempt to continue configuring managed proxy <b>mp</b>.
620  * Return 1 if the transport configuration finished, and return 0
621  * otherwise (if we still have more configuring to do for this
622  * proxy). */
623 STATIC int
624 configure_proxy(managed_proxy_t *mp)
625 {
626  /* if we haven't launched the proxy yet, do it now */
627  if (mp->conf_state == PT_PROTO_INFANT) {
628  if (launch_managed_proxy(mp) < 0) { /* launch fail */
629  mp->conf_state = PT_PROTO_FAILED_LAUNCH;
631  }
632  return 0;
633  }
634 
635  tor_assert(mp->conf_state != PT_PROTO_INFANT);
636  tor_assert(mp->process);
637  return mp->conf_state == PT_PROTO_COMPLETED;
638 }
639 
640 /** Register server managed proxy <b>mp</b> transports to state */
641 static void
642 register_server_proxy(const managed_proxy_t *mp)
643 {
644  tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
645 
646  SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
647  save_transport_to_state(t->name, &t->addr, t->port);
648  log_notice(LD_GENERAL, "Registered server transport '%s' at '%s'",
649  t->name, fmt_addrport(&t->addr, t->port));
650  control_event_transport_launched("server", t->name, &t->addr, t->port);
651  } SMARTLIST_FOREACH_END(t);
652 }
653 
654 /** Register all the transports supported by client managed proxy
655  * <b>mp</b> to the bridge subsystem. */
656 static void
657 register_client_proxy(const managed_proxy_t *mp)
658 {
659  int r;
660 
661  tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
662 
663  SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
664  transport_t *transport_tmp = transport_copy(t);
665  r = transport_add(transport_tmp);
666  switch (r) {
667  case -1:
668  log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
669  transport_free(transport_tmp);
670  break;
671  case 0:
672  log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
673  control_event_transport_launched("client", t->name, &t->addr, t->port);
674  break;
675  case 1:
676  log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
677  control_event_transport_launched("client", t->name, &t->addr, t->port);
678  transport_free(transport_tmp);
679  break;
680  }
681  } SMARTLIST_FOREACH_END(t);
682 }
683 
684 /** Register the transports of managed proxy <b>mp</b>. */
685 static inline void
686 register_proxy(const managed_proxy_t *mp)
687 {
688  if (mp->is_server)
690  else
692 }
693 
694 /** Free memory allocated by managed proxy <b>mp</b>. */
695 STATIC void
696 managed_proxy_destroy(managed_proxy_t *mp,
697  int also_terminate_process)
698 {
699  SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
700 
701  /* free the transports smartlist */
702  smartlist_free(mp->transports);
703 
704  /* free the transports_to_launch smartlist */
705  SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
706  smartlist_free(mp->transports_to_launch);
707 
708  /* remove it from the list of managed proxies */
709  if (managed_proxy_list)
711 
712  /* free the argv */
713  free_execve_args(mp->argv);
714 
715  /* free the outgoing proxy URI */
716  tor_free(mp->proxy_uri);
717 
718  /* do we want to terminate our process if it's still running? */
719  if (also_terminate_process && mp->process) {
720  /* Note that we do not call process_free(mp->process) here because we let
721  * the exit handler in managed_proxy_exit_callback() return `true` which
722  * makes the process subsystem deallocate the process_t. */
723  process_set_data(mp->process, NULL);
724  process_terminate(mp->process);
725  }
726 
727  tor_free(mp);
728 }
729 
730 /** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY.
731  * Return a newly allocated string containing the URI, or NULL if no
732  * proxy is set. */
733 STATIC char *
735 {
736  const or_options_t *options = get_options();
737  char *uri = NULL;
738 
739  /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
740  * there isn't a standard URI scheme for some proxy protocols, such as
741  * haproxy. */
742  if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
743  char addr[TOR_ADDR_BUF_LEN+1];
744 
745  if (options->Socks4Proxy) {
746  tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
747  tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
748  } else if (options->Socks5Proxy) {
749  tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
750  if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
751  tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
752  } else {
753  tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
754  options->Socks5ProxyUsername,
755  options->Socks5ProxyPassword,
756  addr, options->Socks5ProxyPort);
757  }
758  } else if (options->HTTPSProxy) {
759  tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
760  if (!options->HTTPSProxyAuthenticator) {
761  tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
762  } else {
763  tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
764  addr, options->HTTPSProxyPort);
765  }
766  }
767  }
768 
769  return uri;
770 }
771 
772 /** Handle a configured or broken managed proxy <b>mp</b>. */
773 static void
774 handle_finished_proxy(managed_proxy_t *mp)
775 {
776  switch (mp->conf_state) {
777  case PT_PROTO_BROKEN: /* if broken: */
778  managed_proxy_destroy(mp, 1); /* annihilate it. */
779  break;
780  case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
781  managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
782  break;
783  case PT_PROTO_CONFIGURED: /* if configured correctly: */
784  if (mp->proxy_uri && !mp->proxy_supported) {
785  log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
786  "specified outgoing proxy and will be terminated.",
787  mp->argv[0]);
788  managed_proxy_destroy(mp, 1); /* annihilate it. */
789  break;
790  }
791  register_proxy(mp); /* register its transports */
792  mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
793  break;
794  case PT_PROTO_INFANT:
795  case PT_PROTO_LAUNCHED:
796  case PT_PROTO_ACCEPTING_METHODS:
797  case PT_PROTO_COMPLETED:
798  default:
799  log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
800  (int)mp->conf_state, mp->argv[0]);
801  tor_assert(0);
802  }
803 
805 }
806 
807 /** Return true if the configuration of the managed proxy <b>mp</b> is
808  finished. */
809 static inline int
810 proxy_configuration_finished(const managed_proxy_t *mp)
811 {
812  return (mp->conf_state == PT_PROTO_CONFIGURED ||
813  mp->conf_state == PT_PROTO_BROKEN ||
814  mp->conf_state == PT_PROTO_FAILED_LAUNCH);
815 }
816 
817 /** This function is called when a proxy sends an {S,C}METHODS DONE message. */
818 static void
819 handle_methods_done(const managed_proxy_t *mp)
820 {
821  tor_assert(mp->transports);
822 
823  if (smartlist_len(mp->transports) == 0)
824  log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
825  "but it didn't launch any pluggable transport listeners!",
826  mp->argv[0]);
827 
828  log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
829  mp->is_server ? "Server" : "Client",
830  mp->argv[0]);
831 }
832 
833 /** Handle a configuration protocol <b>line</b> received from a
834  * managed proxy <b>mp</b>. */
835 STATIC void
836 handle_proxy_line(const char *line, managed_proxy_t *mp)
837 {
838  log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
839  mp->argv[0], line);
840 
841  if (!strcmpstart(line, PROTO_ENV_ERROR)) {
842  if (mp->conf_state != PT_PROTO_LAUNCHED)
843  goto err;
844 
845  parse_env_error(line);
846  goto err;
847  } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
848  if (mp->conf_state != PT_PROTO_LAUNCHED)
849  goto err;
850 
851  log_warn(LD_CONFIG, "Managed proxy could not pick a "
852  "configuration protocol version.");
853  goto err;
854  } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
855  if (mp->conf_state != PT_PROTO_LAUNCHED)
856  goto err;
857 
858  if (parse_version(line,mp) < 0)
859  goto err;
860 
861  tor_assert(mp->conf_protocol != 0);
862  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
863  return;
864  } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
865  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
866  goto err;
867 
869 
870  mp->conf_state = PT_PROTO_CONFIGURED;
871  return;
872  } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
873  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
874  goto err;
875 
877 
878  mp->conf_state = PT_PROTO_CONFIGURED;
879  return;
880  } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
881  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
882  goto err;
883 
884  parse_client_method_error(line);
885  goto err;
886  } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
887  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
888  goto err;
889 
890  parse_server_method_error(line);
891  goto err;
892  } else if (!strcmpstart(line, PROTO_CMETHOD)) {
893  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
894  goto err;
895 
896  if (parse_cmethod_line(line, mp) < 0)
897  goto err;
898 
899  return;
900  } else if (!strcmpstart(line, PROTO_SMETHOD)) {
901  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
902  goto err;
903 
904  if (parse_smethod_line(line, mp) < 0)
905  goto err;
906 
907  return;
908  } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
909  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
910  goto err;
911 
912  if (mp->proxy_uri) {
913  mp->proxy_supported = 1;
914  return;
915  }
916 
917  /* No proxy was configured, this should log */
918  } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
919  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
920  goto err;
921 
922  parse_proxy_error(line);
923  goto err;
924 
925  /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
926  * string to make sure we can later extend this big if/else-if table with
927  * something that begins with "LOG" without having to get the order right.
928  * */
929  } else if (!strcmpstart(line, PROTO_LOG " ")) {
930  parse_log_line(line, mp);
931  return;
932  } else if (!strcmpstart(line, PROTO_STATUS " ")) {
933  parse_status_line(line, mp);
934  return;
935  }
936 
937  log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
938  return;
939 
940  err:
941  mp->conf_state = PT_PROTO_BROKEN;
942  log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
943  " and will be destroyed.", mp->argv[0]);
944 }
945 
946 /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
947 STATIC void
948 parse_env_error(const char *line)
949 {
950  /* (Length of the protocol string) plus (a space) and (the first char of
951  the error message) */
952  if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
953  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
954  "message.", PROTO_ENV_ERROR);
955 
956  log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
957  "pluggable transport environment variables. (%s)",
958  line+strlen(PROTO_ENV_ERROR)+1);
959 }
960 
961 /** Handles a VERSION <b>line</b>. Updates the configuration protocol
962  * version in <b>mp</b>. */
963 STATIC int
964 parse_version(const char *line, managed_proxy_t *mp)
965 {
966  if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
967  log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
968  PROTO_NEG_SUCCESS);
969  return -1;
970  }
971 
972  if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
973  log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
974  "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
975  return -1;
976  }
977 
978  mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
979  return 0;
980 }
981 
982 /** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
983  * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
984  * otherwise it is a CMETHOD-ERROR. */
985 static void
986 parse_method_error(const char *line, int is_server)
987 {
988  const char* error = is_server ?
989  PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
990 
991  /* (Length of the protocol string) plus (a space) and (the first char of
992  the error message) */
993  if (strlen(line) < (strlen(error) + 2))
994  log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
995  "message.", error);
996 
997  log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
998  is_server ? "Server" : "Client",
999  line+strlen(error)+1);
1000 }
1001 
1002 /** A helper for parse_{c,s}method_line(), bootstraps its
1003  * functionalities. If <b>is_smethod</b> is true then the
1004  * the line to parse is a SMETHOD line otherwise it is a
1005  * CMETHOD line*/
1006 static int
1007 parse_method_line_helper(const char *line,
1008  managed_proxy_t *mp,
1009  int is_smethod)
1010 {
1011  int item_index = 0;
1012  int r;
1013 
1014  char *transport_name=NULL;
1015  char *args_string=NULL;
1016  char *addrport=NULL;
1017  int socks_ver=PROXY_NONE;
1018  char *address=NULL;
1019  uint16_t port = 0;
1020 
1021  const char *method_str = is_smethod ? PROTO_SMETHOD : PROTO_CMETHOD;
1022  const int min_args_count = is_smethod ? 3 : 4;
1023 
1024  tor_addr_t tor_addr;
1025  transport_t *transport=NULL;
1026  smartlist_t *items= smartlist_new();
1027 
1028  smartlist_split_string(items, line, NULL,
1029  SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1030  if (smartlist_len(items) < min_args_count) {
1031  log_warn(LD_CONFIG, "Managed proxy sent us a %s line "
1032  "with too few arguments.", method_str);
1033  goto err;
1034  }
1035 
1036  tor_assert(!strcmp(smartlist_get(items, item_index),method_str));
1037  ++item_index;
1038 
1039  transport_name = smartlist_get(items,item_index);
1040  ++item_index;
1041  if (!string_is_C_identifier(transport_name)) {
1042  log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
1043  transport_name);
1044  goto err;
1045  }
1046 
1047  /** Check for the proxy method sent to us in CMETHOD line. */
1048  if (!is_smethod) {
1049  const char *socks_ver_str = smartlist_get(items,item_index);
1050  ++item_index;
1051 
1052  if (!strcmp(socks_ver_str,"socks4")) {
1053  socks_ver = PROXY_SOCKS4;
1054  } else if (!strcmp(socks_ver_str,"socks5")) {
1055  socks_ver = PROXY_SOCKS5;
1056  } else {
1057  log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
1058  "we don't recognize. (%s)", socks_ver_str);
1059  goto err;
1060  }
1061  }
1062 
1063  addrport = smartlist_get(items, item_index);
1064  ++item_index;
1065  if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) {
1066  log_warn(LD_CONFIG, "Error parsing transport address '%s'", addrport);
1067  goto err;
1068  }
1069 
1070  if (!port) {
1071  log_warn(LD_CONFIG,
1072  "Transport address '%s' has no port.", addrport);
1073  goto err;
1074  }
1075 
1076  if (tor_addr_parse(&tor_addr, address) < 0) {
1077  log_warn(LD_CONFIG, "Error parsing transport address '%s'", address);
1078  goto err;
1079  }
1080 
1081  /** Check for options in the SMETHOD line. */
1082  if (is_smethod && smartlist_len(items) > min_args_count) {
1083  /* Seems like there are also some [options] in the SMETHOD line.
1084  Let's see if we can parse them. */
1085  char *options_string = smartlist_get(items, item_index);
1086  log_debug(LD_CONFIG, "Got options_string: %s", options_string);
1087  if (!strcmpstart(options_string, "ARGS:")) {
1088  args_string = options_string+strlen("ARGS:");
1089  log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
1090  }
1091  }
1092 
1093  transport = transport_new(&tor_addr, port, transport_name,
1094  socks_ver, args_string);
1095 
1096  smartlist_add(mp->transports, transport);
1097 
1098  /** Logs info about line parsing success for client or server */
1099  if (is_smethod) {
1100  log_info(LD_CONFIG, "Server transport %s at %s:%d.",
1101  transport_name, address, (int)port);
1102  } else {
1103  log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
1104  "Attached to managed proxy.",
1105  transport_name, address, (int)port, socks_ver);
1106  }
1107 
1108  r=0;
1109  goto done;
1110 
1111  err:
1112  r = -1;
1113 
1114  done:
1115  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
1116  smartlist_free(items);
1117  tor_free(address);
1118  return r;
1119 }
1120 
1121 /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
1122  * new transport in <b>mp</b>. */
1123 STATIC int
1124 parse_smethod_line(const char *line, managed_proxy_t *mp)
1125 {
1126  /* Example of legit SMETHOD line:
1127  SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
1128  return parse_method_line_helper(line, mp, 1);
1129 }
1130 
1131 /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
1132  * the new transport in <b>mp</b>. */
1133 STATIC int
1134 parse_cmethod_line(const char *line, managed_proxy_t *mp)
1135 {
1136  /* Example of legit CMETHOD line:
1137  CMETHOD obfs2 socks5 127.0.0.1:35713 */
1138  return parse_method_line_helper(line, mp, 0);
1139 }
1140 
1141 /** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
1142 STATIC void
1143 parse_proxy_error(const char *line)
1144 {
1145  /* (Length of the protocol string) plus (a space) and (the first char of
1146  the error message) */
1147  if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
1148  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
1149  "message.", PROTO_PROXY_ERROR);
1150 
1151  log_warn(LD_CONFIG, "Managed proxy failed to configure the "
1152  "pluggable transport's outgoing proxy. (%s)",
1153  line+strlen(PROTO_PROXY_ERROR)+1);
1154 }
1155 
1156 /** Parses a LOG <b>line</b> and emit log events accordingly. */
1157 STATIC void
1158 parse_log_line(const char *line, managed_proxy_t *mp)
1159 {
1160  tor_assert(line);
1161  tor_assert(mp);
1162 
1163  config_line_t *values = NULL;
1164  char *log_message = NULL;
1165 
1166  if (strlen(line) < (strlen(PROTO_LOG) + 1)) {
1167  log_warn(LD_PT, "Managed proxy sent us a %s line "
1168  "with missing argument.", PROTO_LOG);
1169  goto done;
1170  }
1171 
1172  const char *data = line + strlen(PROTO_LOG) + 1;
1173  values = kvline_parse(data, KV_QUOTED);
1174 
1175  if (! values) {
1176  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid LOG message: %s",
1177  mp->argv[0], data);
1178  goto done;
1179  }
1180 
1181  const config_line_t *severity = config_line_find(values, "SEVERITY");
1182  const config_line_t *message = config_line_find(values, "MESSAGE");
1183 
1184  /* Check if we got a message. */
1185  if (! message) {
1186  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1187  "MESSAGE: %s", mp->argv[0], escaped(data));
1188  goto done;
1189  }
1190 
1191  /* Check if severity is there and whether it's valid. */
1192  if (! severity) {
1193  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1194  "SEVERITY: %s", mp->argv[0], escaped(data));
1195  goto done;
1196  }
1197 
1198  int log_severity = managed_proxy_severity_parse(severity->value);
1199 
1200  if (log_severity == -1) {
1201  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line with an "
1202  "invalid severity level: %s",
1203  mp->argv[0], severity->value);
1204  goto done;
1205  }
1206 
1207  tor_log(log_severity, LD_PT, "Managed proxy \"%s\": %s",
1208  mp->argv[0], message->value);
1209 
1210  /* Prepend the PT name. */
1211  config_line_prepend(&values, "PT", mp->argv[0]);
1212  log_message = kvline_encode(values, KV_QUOTED);
1213 
1214  /* Emit control port event. */
1215  control_event_pt_log(log_message);
1216 
1217  done:
1218  config_free_lines(values);
1219  tor_free(log_message);
1220 }
1221 
1222 /** Parses a STATUS <b>line</b> and emit control events accordingly. */
1223 STATIC void
1224 parse_status_line(const char *line, managed_proxy_t *mp)
1225 {
1226  tor_assert(line);
1227  tor_assert(mp);
1228 
1229  config_line_t *values = NULL;
1230  char *status_message = NULL;
1231 
1232  if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
1233  log_warn(LD_PT, "Managed proxy sent us a %s line "
1234  "with missing argument.", PROTO_STATUS);
1235  goto done;
1236  }
1237 
1238  const char *data = line + strlen(PROTO_STATUS) + 1;
1239 
1240  values = kvline_parse(data, KV_QUOTED);
1241 
1242  if (! values) {
1243  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
1244  "STATUS message: %s", mp->argv[0], escaped(data));
1245  goto done;
1246  }
1247 
1248  /* We check if we received the TRANSPORT parameter, which is the only
1249  * *required* value. */
1250  const config_line_t *type = config_line_find(values, "TRANSPORT");
1251 
1252  if (! type) {
1253  log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
1254  "TRANSPORT: %s", mp->argv[0], escaped(data));
1255  goto done;
1256  }
1257 
1258  /* Prepend the PT name. */
1259  config_line_prepend(&values, "PT", mp->argv[0]);
1260  status_message = kvline_encode(values, KV_QUOTED);
1261 
1262  /* We have checked that TRANSPORT is there, we can now emit the STATUS event
1263  * via the control port. */
1264  control_event_pt_status(status_message);
1265 
1266  done:
1267  config_free_lines(values);
1268  tor_free(status_message);
1269 }
1270 
1271 /** Return a newly allocated string that tor should place in
1272  * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
1273  * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
1274 STATIC char *
1275 get_transport_options_for_server_proxy(const managed_proxy_t *mp)
1276 {
1277  char *options_string = NULL;
1278  smartlist_t *string_sl = smartlist_new();
1279 
1280  tor_assert(mp->is_server);
1281 
1282  /** Loop over the transports of the proxy. If we have options for
1283  any of them, format them appropriately and place them in our
1284  smartlist. Finally, join our smartlist to get the final
1285  string. */
1286  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
1287  smartlist_t *options_tmp_sl = NULL;
1288  options_tmp_sl = pt_get_options_for_server_transport(transport);
1289  if (!options_tmp_sl)
1290  continue;
1291 
1292  /** Loop over the options of this transport, escape them, and
1293  place them in the smartlist. */
1294  SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
1295  char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
1296  smartlist_add_asprintf(string_sl, "%s:%s",
1297  transport, escaped_opts);
1298  tor_free(escaped_opts);
1299  } SMARTLIST_FOREACH_END(options);
1300 
1301  SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
1302  smartlist_free(options_tmp_sl);
1303  } SMARTLIST_FOREACH_END(transport);
1304 
1305  if (smartlist_len(string_sl)) {
1306  options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
1307  }
1308 
1309  SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
1310  smartlist_free(string_sl);
1311 
1312  return options_string;
1313 }
1314 
1315 /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
1316  * while configuring the server managed proxy in <b>mp</b>. The
1317  * string is stored in the heap, and it's the responsibility of
1318  * the caller to deallocate it after its use. */
1319 static char *
1320 get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
1321 {
1322  char *bindaddr_result = NULL;
1323  char *bindaddr_tmp = NULL;
1324  smartlist_t *string_tmp = smartlist_new();
1325 
1326  tor_assert(mp->is_server);
1327 
1328  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
1329  bindaddr_tmp = get_stored_bindaddr_for_server_transport(t);
1330 
1331  smartlist_add_asprintf(string_tmp, "%s-%s", t, bindaddr_tmp);
1332 
1333  tor_free(bindaddr_tmp);
1334  } SMARTLIST_FOREACH_END(t);
1335 
1336  bindaddr_result = smartlist_join_strings(string_tmp, ",", 0, NULL);
1337 
1338  SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
1339  smartlist_free(string_tmp);
1340 
1341  return bindaddr_result;
1342 }
1343 
1344 /** Return a newly allocated process_environment_t * for <b>mp</b>'s
1345  * process. */
1346 static smartlist_t *
1347 create_managed_proxy_environment(const managed_proxy_t *mp)
1348 {
1349  const or_options_t *options = get_options();
1350 
1351  /* Environment variables to be added to or set in mp's environment. */
1352  smartlist_t *envs = smartlist_new();
1353  /* XXXX The next time someone touches this code, shorten the name of
1354  * set_environment_variable_in_smartlist, add a
1355  * set_env_var_in_smartlist_asprintf function, and get rid of the
1356  * silly extra envs smartlist. */
1357 
1358  /* The final environment to be passed to mp. */
1360 
1361  {
1362  char *state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
1363  smartlist_add_asprintf(envs, "TOR_PT_STATE_LOCATION=%s", state_tmp);
1364  tor_free(state_tmp);
1365  }
1366 
1367  smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
1368 
1369  {
1370  char *transports_to_launch =
1371  smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
1372 
1374  mp->is_server ?
1375  "TOR_PT_SERVER_TRANSPORTS=%s" :
1376  "TOR_PT_CLIENT_TRANSPORTS=%s",
1377  transports_to_launch);
1378 
1379  tor_free(transports_to_launch);
1380  }
1381 
1382  if (mp->is_server) {
1383  {
1384  char *orport_tmp =
1386  if (orport_tmp) {
1387  smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
1388  tor_free(orport_tmp);
1389  }
1390  }
1391 
1392  {
1393  char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
1394  smartlist_add_asprintf(envs, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
1395  tor_free(bindaddr_tmp);
1396  }
1397 
1398  {
1399  char *server_transport_options =
1401  if (server_transport_options) {
1402  smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1403  server_transport_options);
1404  tor_free(server_transport_options);
1405  }
1406  }
1407 
1408  /* XXXX Remove the '=' here once versions of obfsproxy which
1409  * assert that this env var exists are sufficiently dead.
1410  *
1411  * (If we remove this line entirely, some joker will stick this
1412  * variable in Tor's environment and crash PTs that try to parse
1413  * it even when not run in server mode.) */
1414 
1415  if (options->ExtORPort_lines) {
1416  char *ext_or_addrport_tmp =
1418  char *cookie_file_loc = get_ext_or_auth_cookie_file_name();
1419 
1420  if (ext_or_addrport_tmp) {
1421  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1422  ext_or_addrport_tmp);
1423  }
1424  if (cookie_file_loc) {
1425  smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s",
1426  cookie_file_loc);
1427  }
1428 
1429  tor_free(ext_or_addrport_tmp);
1430  tor_free(cookie_file_loc);
1431 
1432  } else {
1433  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
1434  }
1435  } else {
1436  /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
1437  * TOR_PT_PROXY line.
1438  */
1439 
1440  if (mp->proxy_uri) {
1441  smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
1442  }
1443  }
1444 
1445  /* All new versions of tor will keep stdin open, so PTs can use it
1446  * as a reliable termination detection mechanism.
1447  */
1448  smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
1449 
1450  SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
1451  set_environment_variable_in_smartlist(merged_env_vars, env_var,
1452  tor_free_, 1);
1453  } SMARTLIST_FOREACH_END(env_var);
1454 
1455  smartlist_free(envs);
1456 
1457  return merged_env_vars;
1458 }
1459 
1460 /** Create and return a new managed proxy for <b>transport</b> using
1461  * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
1462  * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
1463  * <b>proxy_argv</b>.
1464  *
1465  * Requires that proxy_argv have at least one element. */
1466 STATIC managed_proxy_t *
1467 managed_proxy_create(const smartlist_t *with_transport_list,
1468  char **proxy_argv, int is_server)
1469 {
1470  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
1471  mp->conf_state = PT_PROTO_INFANT;
1472  mp->is_server = is_server;
1473  mp->argv = proxy_argv;
1474  mp->transports = smartlist_new();
1475  mp->proxy_uri = get_pt_proxy_uri();
1476  mp->process = process_new(proxy_argv[0]);
1477 
1478  mp->transports_to_launch = smartlist_new();
1479  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1480  add_transport_to_proxy(transport, mp));
1481 
1482  /* register the managed proxy */
1483  if (!managed_proxy_list)
1487 
1489 
1490  return mp;
1491 }
1492 
1493 /** Register proxy with <b>proxy_argv</b>, supporting transports in
1494  * <b>transport_list</b>, to the managed proxy subsystem.
1495  * If <b>is_server</b> is true, then the proxy is a server proxy.
1496  *
1497  * Takes ownership of proxy_argv.
1498  *
1499  * Requires that proxy_argv be a NULL-terminated array of command-line
1500  * elements, containing at least one element.
1501  **/
1502 MOCK_IMPL(void,
1503 pt_kickstart_proxy, (const smartlist_t *with_transport_list,
1504  char **proxy_argv, int is_server))
1505 {
1506  managed_proxy_t *mp=NULL;
1507  transport_t *old_transport = NULL;
1508 
1509  if (!proxy_argv || !proxy_argv[0]) {
1510  return;
1511  }
1512 
1513  mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
1514 
1515  if (!mp) { /* we haven't seen this proxy before */
1516  managed_proxy_create(with_transport_list, proxy_argv, is_server);
1517 
1518  } else { /* known proxy. add its transport to its transport list */
1519  if (mp->was_around_before_config_read) {
1520  /* If this managed proxy was around even before we read the
1521  config this time, it means that it was already enabled before
1522  and is not useless and should be kept. If it's marked for
1523  removal, unmark it and make sure that we check whether it
1524  needs to be restarted. */
1525  if (mp->marked_for_removal) {
1526  mp->marked_for_removal = 0;
1528  }
1529 
1530  /* For each new transport, check if the managed proxy used to
1531  support it before the SIGHUP. If that was the case, make sure
1532  it doesn't get removed because we might reuse it. */
1533  SMARTLIST_FOREACH_BEGIN(with_transport_list, const char *, transport) {
1534  old_transport = transport_get_by_name(transport);
1535  if (old_transport)
1536  old_transport->marked_for_removal = 0;
1537  } SMARTLIST_FOREACH_END(transport);
1538  }
1539 
1540  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1541  add_transport_to_proxy(transport, mp));
1542  free_execve_args(proxy_argv);
1543  }
1544 }
1545 
1546 /** Frees the array of pointers in <b>arg</b> used as arguments to
1547  execve(2). */
1548 STATIC void
1549 free_execve_args(char **arg)
1550 {
1551  char **tmp = arg;
1552  while (*tmp) /* use the fact that the last element of the array is a
1553  NULL pointer to know when to stop freeing */
1554  tor_free_(*tmp++);
1555 
1556  tor_free(arg);
1557 }
1558 
1559 /** Tor will read its config.
1560  * Prepare the managed proxy list so that proxies not used in the new
1561  * config will shutdown, and proxies that need to spawn different
1562  * transports will do so. */
1563 void
1565 {
1566  if (!managed_proxy_list)
1567  return;
1568 
1570  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1571  /* Destroy unconfigured proxies. */
1572  if (mp->conf_state != PT_PROTO_COMPLETED) {
1574  managed_proxy_destroy(mp, 1);
1576  continue;
1577  }
1578 
1579  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1580 
1581  /* Mark all proxies for removal, and also note that they have been
1582  here before the config read. */
1583  mp->marked_for_removal = 1;
1584  mp->was_around_before_config_read = 1;
1585  SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
1586  smartlist_clear(mp->transports_to_launch);
1587  } SMARTLIST_FOREACH_END(mp);
1588 
1590 
1592 }
1593 
1594 /** Return a smartlist containing the ports where our pluggable
1595  * transports are listening. */
1596 smartlist_t *
1598 {
1599  smartlist_t *sl = NULL;
1600 
1601  if (!managed_proxy_list)
1602  return NULL;
1603 
1604  /** XXX assume that external proxy ports have been forwarded
1605  manually */
1606  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1607  if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED)
1608  continue;
1609 
1610  if (!sl) sl = smartlist_new();
1611 
1612  tor_assert(mp->transports);
1613  SMARTLIST_FOREACH(mp->transports, const transport_t *, t,
1614  smartlist_add_asprintf(sl, "%u:%u", t->port, t->port));
1615 
1616  } SMARTLIST_FOREACH_END(mp);
1617 
1618  return sl;
1619 }
1620 
1621 /** Return the pluggable transport string that we should display in
1622  * our extra-info descriptor. If we shouldn't display such a string,
1623  * or we have nothing to display, return NULL. The string is
1624  * allocated on the heap and it's the responsibility of the caller to
1625  * free it. */
1626 char *
1628 {
1629  char *the_string = NULL;
1630  smartlist_t *string_chunks = NULL;
1631 
1632  if (!managed_proxy_list)
1633  return NULL;
1634 
1635  string_chunks = smartlist_new();
1636 
1637  /* For each managed proxy, add its transports to the chunks list. */
1638  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1639  if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
1640  continue;
1641 
1642  tor_assert(mp->transports);
1643 
1644  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1645  char *transport_args = NULL;
1646 
1647  /* If the transport proxy returned "0.0.0.0" as its address, and
1648  * we know our external IP address, use it. Otherwise, use the
1649  * returned address. */
1650  const char *addrport = NULL;
1651  uint32_t external_ip_address = 0;
1652  if (tor_addr_is_null(&t->addr) &&
1654  &external_ip_address, 0) >= 0) {
1655  tor_addr_t addr;
1656  tor_addr_from_ipv4h(&addr, external_ip_address);
1657  addrport = fmt_addrport(&addr, t->port);
1658  } else {
1659  addrport = fmt_addrport(&t->addr, t->port);
1660  }
1661 
1662  /* If this transport has any arguments with it, prepend a space
1663  to them so that we can add them to the transport line. */
1664  if (t->extra_info_args)
1665  tor_asprintf(&transport_args, " %s", t->extra_info_args);
1666 
1667  smartlist_add_asprintf(string_chunks,
1668  "transport %s %s%s",
1669  t->name, addrport,
1670  transport_args ? transport_args : "");
1671  tor_free(transport_args);
1672  } SMARTLIST_FOREACH_END(t);
1673 
1674  } SMARTLIST_FOREACH_END(mp);
1675 
1676  if (smartlist_len(string_chunks) == 0) {
1677  smartlist_free(string_chunks);
1678  return NULL;
1679  }
1680 
1681  /* Join all the chunks into the final string. */
1682  the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1683 
1684  SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1685  smartlist_free(string_chunks);
1686 
1687  return the_string;
1688 }
1689 
1690 /** Stringify the SOCKS arguments in <b>socks_args</b> according to
1691  * 180_pluggable_transport.txt. The string is allocated on the heap
1692  * and it's the responsibility of the caller to free it after use. */
1693 char *
1695 {
1696  /* tmp place to store escaped socks arguments, so that we can
1697  concatenate them up afterwards */
1698  smartlist_t *sl_tmp = NULL;
1699  char *escaped_string = NULL;
1700  char *new_string = NULL;
1701 
1702  tor_assert(socks_args);
1703  tor_assert(smartlist_len(socks_args) > 0);
1704 
1705  sl_tmp = smartlist_new();
1706 
1707  SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
1708  /* Escape ';' and '\'. */
1709  escaped_string = tor_escape_str_for_pt_args(s, ";\\");
1710  if (!escaped_string)
1711  goto done;
1712 
1713  smartlist_add(sl_tmp, escaped_string);
1714  } SMARTLIST_FOREACH_END(s);
1715 
1716  new_string = smartlist_join_strings(sl_tmp, ";", 0, NULL);
1717 
1718  done:
1719  SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
1720  smartlist_free(sl_tmp);
1721 
1722  return new_string;
1723 }
1724 
1725 /** Return a string of the SOCKS arguments that we should pass to the
1726  * pluggable transports proxy in <b>addr</b>:<b>port</b> according to
1727  * 180_pluggable_transport.txt. The string is allocated on the heap
1728  * and it's the responsibility of the caller to free it after use. */
1729 char *
1731 {
1732  const smartlist_t *socks_args = NULL;
1733 
1734  socks_args = get_socks_args_by_bridge_addrport(addr, port);
1735  if (!socks_args)
1736  return NULL;
1737 
1738  return pt_stringify_socks_args(socks_args);
1739 }
1740 
1741 /** The tor config was read.
1742  * Destroy all managed proxies that were marked by a previous call to
1743  * prepare_proxy_list_for_config_read() and are not used by the new
1744  * config. */
1745 void
1747 {
1748  if (!managed_proxy_list)
1749  return;
1751  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1752  if (mp->marked_for_removal) {
1754  managed_proxy_destroy(mp, 1);
1755  }
1756  } SMARTLIST_FOREACH_END(mp);
1758 }
1759 
1760 /** Release all storage held by the pluggable transports subsystem. */
1761 void
1763 {
1764  if (transport_list) {
1766  smartlist_free(transport_list);
1767  transport_list = NULL;
1768  }
1769 
1770  if (managed_proxy_list) {
1771  /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1772  transports and it's the duty of the circuitbuild.c subsystem to
1773  free them. Otherwise, it hasn't registered its transports yet
1774  and we should free them here. */
1775  SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
1777  managed_proxy_destroy(mp, 1);
1778  });
1779 
1780  smartlist_free(managed_proxy_list);
1781  managed_proxy_list=NULL;
1782  }
1783 }
1784 
1785 /** Return a newly allocated string equal to <b>string</b>, except that every
1786  * character in <b>chars_to_escape</b> is preceded by a backslash. */
1787 char *
1788 tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
1789 {
1790  char *new_string = NULL;
1791  char *new_cp = NULL;
1792  size_t length, new_length;
1793 
1794  tor_assert(string);
1795 
1796  length = strlen(string);
1797 
1798  if (!length) /* If we were given the empty string, return the same. */
1799  return tor_strdup("");
1800  /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
1801  (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
1802  if (length > (SIZE_MAX - 1)/2) /* check for overflow */
1803  return NULL;
1804 
1805  /* this should be enough even if all characters must be escaped */
1806  new_length = (length * 2) + 1;
1807 
1808  new_string = new_cp = tor_malloc(new_length);
1809 
1810  while (*string) {
1811  if (strchr(chars_to_escape, *string))
1812  *new_cp++ = '\\';
1813 
1814  *new_cp++ = *string++;
1815  }
1816 
1817  *new_cp = '\0'; /* NUL-terminate the new string */
1818 
1819  return new_string;
1820 }
1821 
1822 /** Callback function that is called when our PT process have data on its
1823  * stdout. Our process can be found in <b>process</b>, the data can be found in
1824  * <b>line</b> and the length of our line is given in <b>size</b>. */
1825 STATIC void
1827  const char *line,
1828  size_t size)
1829 {
1830  tor_assert(process);
1831  tor_assert(line);
1832 
1833  (void)size;
1834 
1835  managed_proxy_t *mp = process_get_data(process);
1836 
1837  if (mp == NULL)
1838  return;
1839 
1840  handle_proxy_line(line, mp);
1841 
1844 }
1845 
1846 /** Callback function that is called when our PT process have data on its
1847  * stderr. Our process can be found in <b>process</b>, the data can be found in
1848  * <b>line</b> and the length of our line is given in <b>size</b>. */
1849 STATIC void
1851  const char *line,
1852  size_t size)
1853 {
1854  tor_assert(process);
1855  tor_assert(line);
1856 
1857  (void)size;
1858 
1859  managed_proxy_t *mp = process_get_data(process);
1860 
1861  if (BUG(mp == NULL))
1862  return;
1863 
1864  log_info(LD_PT,
1865  "Managed proxy at '%s' reported via standard error: %s",
1866  mp->argv[0], line);
1867 }
1868 
1869 /** Callback function that is called when our PT process terminates. The
1870  * process exit code can be found in <b>exit_code</b> and our process can be
1871  * found in <b>process</b>. Returns true iff we want the process subsystem to
1872  * free our process_t handle for us. */
1873 STATIC bool
1874 managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
1875 {
1876  tor_assert(process);
1877 
1878  log_warn(LD_PT,
1879  "Pluggable Transport process terminated with status code %" PRIu64,
1880  exit_code);
1881 
1882  /* Returning true here means that the process subsystem will take care of
1883  * calling process_free() on our process_t. */
1884  return true;
1885 }
1886 
1887 /** Returns a valid integer log severity level from <b>severity</b> that
1888  * is compatible with Tor's logging functions. Returns <b>-1</b> on
1889  * error. */
1890 STATIC int
1891 managed_proxy_severity_parse(const char *severity)
1892 {
1893  tor_assert(severity);
1894 
1895  /* Slightly different than log.c's parse_log_level :-( */
1896  if (! strcmp(severity, "debug"))
1897  return LOG_DEBUG;
1898 
1899  if (! strcmp(severity, "info"))
1900  return LOG_INFO;
1901 
1902  if (! strcmp(severity, "notice"))
1903  return LOG_NOTICE;
1904 
1905  if (! strcmp(severity, "warning"))
1906  return LOG_WARN;
1907 
1908  if (! strcmp(severity, "error"))
1909  return LOG_ERR;
1910 
1911  return -1;
1912 }
process_reset_environment
void process_reset_environment(process_t *process, const smartlist_t *env)
Definition: process.c:470
transport_t::name
char * name
Definition: transports.h:21
tor_free
#define tor_free(p)
Definition: malloc.h:52
router_pick_published_address
int router_pick_published_address(const or_options_t *options, uint32_t *addr, int cache_only)
Definition: relay_find_addr.c:112
transport_copy
static transport_t * transport_copy(const transport_t *transport)
Definition: transports.c:216
pt_get_options_for_server_transport
smartlist_t * pt_get_options_for_server_transport(const char *transport)
Definition: transport_config.c:171
LOG_DEBUG
#define LOG_DEBUG
Definition: log.h:42
transport_resolve_conflicts
static int transport_resolve_conflicts(const transport_t *t)
Definition: transports.c:257
tor_free_
void tor_free_(void *mem)
Definition: malloc.c:227
smartlist_split_string
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
Definition: smartlist_split.c:37
name
const char * name
Definition: config.c:2440
transport_free_
void transport_free_(transport_t *transport)
Definition: transports.c:167
or_options_t::Socks5Proxy
char * Socks5Proxy
Definition: or_options_st.h:414
transport_t::extra_info_args
char * extra_info_args
Definition: transports.h:32
transport_t
Definition: transports.h:17
tor_addr_t
Definition: address.h:68
managed_proxy_has_argv
static int managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
Definition: transports.c:401
pt_prepare_proxy_list_for_config_read
void pt_prepare_proxy_list_for_config_read(void)
Definition: transports.c:1564
smartlist_add_strdup
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
Definition: smartlist_core.c:137
LOG_NOTICE
#define LOG_NOTICE
Definition: log.h:50
MOCK_IMPL
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
tor_addr_to_str
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
Definition: address.c:328
transport_config.h
Header for feature/relay/transport_config.c.
or_options_t::HTTPSProxyAuthenticator
char * HTTPSProxyAuthenticator
Definition: or_options_st.h:408
transport_t::port
uint16_t port
Definition: transports.h:26
transport_get_by_name
transport_t * transport_get_by_name(const char *name)
Definition: transports.c:236
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
process_set_stdout_read_callback
void process_set_stdout_read_callback(process_t *process, process_read_callback_t callback)
Definition: process.c:321
relay_find_addr.h
Header file for relay_find_addr.c.
router.h
Header file for router.c.
managed_proxy_severity_parse
STATIC int managed_proxy_severity_parse(const char *severity)
Definition: transports.c:1891
kvline_encode
char * kvline_encode(const config_line_t *line, unsigned flags)
Definition: kvline.c:126
clear_transport_list
static void clear_transport_list(void)
Definition: transports.c:206
LD_GENERAL
#define LD_GENERAL
Definition: log.h:62
mark_transport_list
void mark_transport_list(void)
Definition: transports.c:180
parse_proxy_error
STATIC void parse_proxy_error(const char *line)
Definition: transports.c:1143
or_options_t::Socks5ProxyPort
uint16_t Socks5ProxyPort
Definition: or_options_st.h:416
string_is_C_identifier
int string_is_C_identifier(const char *string)
Definition: util_string.c:414
get_transport_options_for_server_proxy
STATIC char * get_transport_options_for_server_proxy(const managed_proxy_t *mp)
Definition: transports.c:1275
pt_kickstart_proxy
void pt_kickstart_proxy(const smartlist_t *with_transport_list, char **proxy_argv, int is_server)
Definition: transports.c:1504
PROCESS_PROTOCOL_LINE
@ PROCESS_PROTOCOL_LINE
Definition: process.h:42
smartlist_add_all
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
Definition: smartlist_core.c:125
control_event_pt_log
void control_event_pt_log(const char *log)
Definition: control_events.c:1818
process_get_pid
process_pid_t process_get_pid(process_t *process)
Definition: process.c:303
smartlist_add
void smartlist_add(smartlist_t *sl, void *element)
Definition: smartlist_core.c:117
register_server_proxy
static void register_server_proxy(const managed_proxy_t *mp)
Definition: transports.c:642
transport_t::socks_version
int socks_version
Definition: transports.h:19
config_line_prepend
void config_line_prepend(config_line_t **lst, const char *key, const char *val)
Definition: confline.c:53
unconfigured_proxies_n
static int unconfigured_proxies_n
Definition: transports.c:367
env.h
Header for env.c.
parse_method_error
static void parse_method_error(const char *line, int is_server_method)
Definition: transports.c:986
TOR_ADDR_BUF_LEN
#define TOR_ADDR_BUF_LEN
Definition: address.h:214
parse_version
STATIC int parse_version(const char *line, managed_proxy_t *mp)
Definition: transports.c:964
get_current_process_environment_variables
struct smartlist_t * get_current_process_environment_variables(void)
Definition: env.c:189
smartlist_new
smartlist_t * smartlist_new(void)
Definition: smartlist_core.c:26
register_client_proxy
static void register_client_proxy(const managed_proxy_t *mp)
Definition: transports.c:657
statefile.h
Header for statefile.c.
SMARTLIST_FOREACH
#define SMARTLIST_FOREACH(sl, type, var, cmd)
Definition: smartlist_foreach.h:112
CONN_TYPE_EXT_OR_LISTENER
#define CONN_TYPE_EXT_OR_LISTENER
Definition: connection.h:71
or_options_t::Socks5ProxyUsername
char * Socks5ProxyUsername
Definition: or_options_st.h:417
CONN_TYPE_OR_LISTENER
#define CONN_TYPE_OR_LISTENER
Definition: connection.h:39
handle_proxy_line
STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:836
transport_t::addr
tor_addr_t addr
Definition: transports.h:24
handle_methods_done
static void handle_methods_done(const managed_proxy_t *mp)
Definition: transports.c:819
get_transport_proxy_ports
smartlist_t * get_transport_proxy_ports(void)
Definition: transports.c:1597
sweep_proxy_list
void sweep_proxy_list(void)
Definition: transports.c:1746
LD_PT
#define LD_PT
Definition: log.h:117
strcmp_opt
int strcmp_opt(const char *s1, const char *s2)
Definition: util_string.c:188
transport_add
static int transport_add(transport_t *t)
Definition: transports.c:316
handle_finished_proxy
static void handle_finished_proxy(managed_proxy_t *mp)
Definition: transports.c:774
bridges.h
Header file for circuitbuild.c.
process.h
Header for process.c.
tor_escape_str_for_pt_args
char * tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
Definition: transports.c:1788
control_event_transport_launched
void control_event_transport_launched(const char *mode, const char *transport_name, tor_addr_t *addr, uint16_t port)
Definition: control_events.c:1807
tor_addr_from_ipv4h
#define tor_addr_from_ipv4h(dest, v4addr)
Definition: address.h:314
pt_proxies_configuration_pending
int pt_proxies_configuration_pending(void)
Definition: transports.c:374
pt_stringify_socks_args
char * pt_stringify_socks_args(const smartlist_t *socks_args)
Definition: transports.c:1694
or_options_t::Socks4ProxyAddr
tor_addr_t Socks4ProxyAddr
Definition: or_options_st.h:411
get_managed_proxy_by_argv_and_type
static managed_proxy_t * get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server)
Definition: transports.c:423
process_terminate
bool process_terminate(process_t *process)
Definition: process.c:284
managed_proxy_stderr_callback
STATIC void managed_proxy_stderr_callback(process_t *process, const char *line, size_t size)
Definition: transports.c:1850
process_t
Definition: process.c:36
get_socks_args_by_bridge_addrport
const smartlist_t * get_socks_args_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
Definition: bridges.c:644
or_options_t::Socks4ProxyPort
uint16_t Socks4ProxyPort
Definition: or_options_st.h:412
or_options_t::HTTPSProxy
char * HTTPSProxy
Definition: or_options_st.h:405
process_append_argument
void process_append_argument(process_t *process, const char *argument)
Definition: process.c:419
transport_t::marked_for_removal
unsigned marked_for_removal
Definition: transports.h:29
or_options_t::HTTPSProxyAddr
tor_addr_t HTTPSProxyAddr
Definition: or_options_st.h:406
or_options_t::Socks5ProxyAddr
tor_addr_t Socks5ProxyAddr
Definition: or_options_st.h:415
transport_new
STATIC transport_t * transport_new(const tor_addr_t *addr, uint16_t port, const char *name, int socks_ver, const char *extra_info_args)
Definition: transports.c:149
proxy_needs_restart
static int proxy_needs_restart(const managed_proxy_t *mp)
Definition: transports.c:450
configure_proxy
STATIC int configure_proxy(managed_proxy_t *mp)
Definition: transports.c:624
parse_log_line
STATIC void parse_log_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1158
escaped
const char * escaped(const char *s)
Definition: escape.c:126
transport_add_from_config
int transport_add_from_config(const tor_addr_t *addr, uint16_t port, const char *name, int socks_ver)
Definition: transports.c:339
strcmpstart
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:206
config_line_find
const config_line_t * config_line_find(const config_line_t *lines, const char *key)
Definition: confline.c:74
proxy_prepare_for_restart
static void proxy_prepare_for_restart(managed_proxy_t *mp)
Definition: transports.c:493
smartlist_contains_string
int smartlist_contains_string(const smartlist_t *sl, const char *element)
Definition: smartlist.c:93
LD_CONFIG
#define LD_CONFIG
Definition: log.h:68
launch_managed_proxy
static int launch_managed_proxy(managed_proxy_t *mp)
Definition: transports.c:528
pt_get_socks_args_for_proxy_addrport
char * pt_get_socks_args_for_proxy_addrport(const tor_addr_t *addr, uint16_t port)
Definition: transports.c:1730
get_stored_bindaddr_for_server_transport
char * get_stored_bindaddr_for_server_transport(const char *transport)
Definition: statefile.c:638
pt_free_all
void pt_free_all(void)
Definition: transports.c:1762
transports.h
Headers for transports.c.
tor_addr_parse
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1308
ext_orport.h
Header for ext_orport.c.
or_options_t::ExtORPort_lines
struct config_line_t * ExtORPort_lines
Definition: or_options_st.h:133
LOG_INFO
#define LOG_INFO
Definition: log.h:45
process_exec
process_status_t process_exec(process_t *process)
Definition: process.c:253
control_events.h
Header file for control_events.c.
get_options
const or_options_t * get_options(void)
Definition: config.c:925
save_transport_to_state
void save_transport_to_state(const char *transport, const tor_addr_t *addr, uint16_t port)
Definition: statefile.c:671
circuitbuild.h
Header file for circuitbuild.c.
fmt_addrport
const char * fmt_addrport(const tor_addr_t *addr, uint16_t port)
Definition: address.c:1190
free_execve_args
STATIC void free_execve_args(char **arg)
Definition: transports.c:1549
get_pt_proxy_uri
STATIC char * get_pt_proxy_uri(void)
Definition: transports.c:734
smartlist_clear
void smartlist_clear(smartlist_t *sl)
Definition: smartlist_core.c:50
parse_cmethod_line
STATIC int parse_cmethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1134
process_set_data
void process_set_data(process_t *process, void *data)
Definition: process.c:385
connection.h
Header file for connection.c.
process_set_stderr_read_callback
void process_set_stderr_read_callback(process_t *process, process_read_callback_t callback)
Definition: process.c:336
kvline_parse
config_line_t * kvline_parse(const char *line, unsigned flags)
Definition: kvline.c:199
confline.h
Header for confline.c.
managed_proxy_create
STATIC managed_proxy_t * managed_proxy_create(const smartlist_t *with_transport_list, char **proxy_argv, int is_server)
Definition: transports.c:1467
pt_configure_remaining_proxies
void pt_configure_remaining_proxies(void)
Definition: transports.c:567
managed_proxy_stdout_callback
STATIC void managed_proxy_stdout_callback(process_t *process, const char *line, size_t size)
Definition: transports.c:1826
register_proxy
static void register_proxy(const managed_proxy_t *mp)
Definition: transports.c:686
tor_addr_is_null
int tor_addr_is_null(const tor_addr_t *addr)
Definition: address.c:771
or_options_t::HTTPSProxyPort
uint16_t HTTPSProxyPort
Definition: or_options_st.h:407
tor_asprintf
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
get_ext_or_auth_cookie_file_name
char * get_ext_or_auth_cookie_file_name(void)
Definition: ext_orport.c:127
kvline.h
Header for kvline.c.
SMARTLIST_FOREACH_BEGIN
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
Definition: smartlist_foreach.h:78
process_get_data
void * process_get_data(const process_t *process)
Definition: process.c:395
SMARTLIST_DEL_CURRENT
#define SMARTLIST_DEL_CURRENT(sl, var)
Definition: smartlist_foreach.h:120
create_managed_proxy_environment
static smartlist_t * create_managed_proxy_environment(const managed_proxy_t *mp)
Definition: transports.c:1347
managed_proxy_destroy
STATIC void managed_proxy_destroy(managed_proxy_t *mp, int also_terminate_process)
Definition: transports.c:696
LOG_WARN
#define LOG_WARN
Definition: log.h:53
assert_unconfigured_count_ok
static void assert_unconfigured_count_ok(void)
Definition: transports.c:382
LOG_ERR
#define LOG_ERR
Definition: log.h:56
transport_list
static smartlist_t * transport_list
Definition: transports.c:143
control_event_pt_status
void control_event_pt_status(const char *status)
Definition: control_events.c:1828
process_new
process_t * process_new(const char *command)
Definition: process.c:180
add_transport_to_proxy
static void add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
Definition: transports.c:439
config_line_t
Definition: confline.h:29
config.h
Header file for config.c.
sweep_transport_list
void sweep_transport_list(void)
Definition: transports.c:191
smartlist_add_asprintf
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
Definition: smartlist.c:36
PROCESS_STATUS_RUNNING
@ PROCESS_STATUS_RUNNING
Definition: process.h:31
managed_proxy_list
static smartlist_t * managed_proxy_list
Definition: transports.c:365
tor_log
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:628
get_first_listener_addrport_string
char * get_first_listener_addrport_string(int listener_type)
Definition: config.c:6448
or_options_t
Definition: or_options_st.h:39
or_options_t::Socks4Proxy
char * Socks4Proxy
Definition: or_options_st.h:410
parse_smethod_line
STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1124
set_environment_variable_in_smartlist
void set_environment_variable_in_smartlist(struct smartlist_t *env_vars, const char *new_var, void(*free_old)(void *), int free_p)
Definition: env.c:206
parse_env_error
STATIC void parse_env_error(const char *line)
Definition: transports.c:948
STATIC
#define STATIC
Definition: testsupport.h:32
proxy_configuration_finished
static int proxy_configuration_finished(const managed_proxy_t *mp)
Definition: transports.c:810
process_set_exit_callback
void process_set_exit_callback(process_t *process, process_exit_callback_t callback)
Definition: process.c:347
or_options_t::Socks5ProxyPassword
char * Socks5ProxyPassword
Definition: or_options_st.h:418
PROTO_ENV_ERROR
#define PROTO_ENV_ERROR
Definition: transports.c:124
PROTO_VERSION_ONE
#define PROTO_VERSION_ONE
Definition: transports.c:140
smartlist_t
Definition: smartlist_core.h:26
smartlist_remove
void smartlist_remove(smartlist_t *sl, const void *element)
Definition: smartlist_core.c:151
smartlist_join_strings
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition: smartlist.c:279
parse_method_line_helper
static int parse_method_line_helper(const char *line, managed_proxy_t *mp, int is_smethod)
Definition: transports.c:1007
tor_addr_port_split
int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out)
Definition: address.c:1871
tor_addr_eq
#define tor_addr_eq(a, b)
Definition: address.h:268
get_bindaddr_for_server_proxy
static char * get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
Definition: transports.c:1320
mark_my_descriptor_dirty
void mark_my_descriptor_dirty(const char *reason)
Definition: router.c:2428
connection_or.h
Header file for connection_or.c.
tor_addr_copy
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:924
managed_proxy_exit_callback
STATIC bool managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
Definition: transports.c:1874
pt_get_extra_info_descriptor_string
char * pt_get_extra_info_descriptor_string(void)
Definition: transports.c:1627
check_if_restarts_needed
static int check_if_restarts_needed
Definition: transports.c:369
or.h
Master header file for Tor-specific functionality.
parse_status_line
STATIC void parse_status_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1224