Tor  0.4.7.0-alpha-dev
transports.c
Go to the documentation of this file.
1 /* Copyright (c) 2011-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * \file transports.c
6  * \brief Pluggable Transports related code.
7  *
8  * \details
9  * Each managed proxy is represented by a <b>managed_proxy_t</b>.
10  * Each managed proxy can support multiple transports.
11  * Each managed proxy gets configured through a multistep process.
12  *
13  * ::managed_proxy_list contains all the managed proxies this tor
14  * instance is supporting.
15  * In the ::managed_proxy_list there are ::unconfigured_proxies_n
16  * managed proxies that are still unconfigured.
17  *
18  * In every run_scheduled_event() tick, we attempt to launch and then
19  * configure the unconfigured managed proxies, using the configuration
20  * protocol defined in the 180_pluggable_transport.txt proposal. A
21  * managed proxy might need several ticks to get fully configured.
22  *
23  * When a managed proxy is fully configured, we register all its
24  * transports to the circuitbuild.c subsystem. At that point the
25  * transports are owned by the circuitbuild.c subsystem.
26  *
27  * When a managed proxy fails to follow the 180 configuration
28  * protocol, it gets marked as broken and gets destroyed.
29  *
30  * <b>In a little more detail:</b>
31  *
32  * While we are serially parsing torrc, we store all the transports
33  * that a proxy should spawn in its <em>transports_to_launch</em>
34  * element.
35  *
36  * When we finish reading the torrc, we spawn the managed proxy and
37  * expect {S,C}METHOD lines from its output. We add transports
38  * described by METHOD lines to its <em>transports</em> element, as
39  * transport_t structs.
40  *
41  * When the managed proxy stops spitting METHOD lines (signified by a
42  * '{S,C}METHODS DONE' message) we pass copies of its transports to
43  * the bridge subsystem. We keep copies of the 'transport_t's on the
44  * managed proxy to be able to associate the proxy with its
45  * transports, and we pass copies to the bridge subsystem so that
46  * transports can be associated with bridges.
47  * [ XXX We should try see whether the two copies are really needed
48  * and maybe cut it into a single copy of the 'transport_t' shared
49  * between the managed proxy and the bridge subsystem. Preliminary
50  * analysis shows that both copies are needed with the current code
51  * logic, because of race conditions that can cause dangling
52  * pointers. ]
53  *
54  * <b>In even more detail, this is what happens when a config read
55  * (like a SIGHUP or a SETCONF) occurs:</b>
56  *
57  * We immediately destroy all unconfigured proxies (We shouldn't have
58  * unconfigured proxies in the first place, except when the config
59  * read happens immediately after tor is launched.).
60  *
61  * We mark all managed proxies and transports to signify that they
62  * must be removed if they don't contribute by the new torrc
63  * (we mark using the <b>marked_for_removal</b> element).
64  * We also mark all managed proxies to signify that they might need to
65  * be restarted so that they end up supporting all the transports the
66  * new torrc wants them to support
67  * (we mark using the <b>was_around_before_config_read</b> element).
68  * We also clear their <b>transports_to_launch</b> list so that we can
69  * put there the transports we need to launch according to the new
70  * torrc.
71  *
72  * We then start parsing torrc again.
73  *
74  * Every time we encounter a transport line using a managed proxy that
75  * was around before the config read, we cleanse that proxy from the
76  * removal mark. We also toggle the <b>check_if_restarts_needed</b>
77  * flag, so that on the next <b>pt_configure_remaining_proxies</b>
78  * tick, we investigate whether we need to restart the proxy so that
79  * it also spawns the new transports. If the post-config-read
80  * <b>transports_to_launch</b> list is identical to the pre-config-read
81  * one, it means that no changes were introduced to this proxy during
82  * the config read and no restart has to take place.
83  *
84  * During the post-config-read torrc parsing, we unmark all transports
85  * spawned by managed proxies that we find in our torrc.
86  * We do that so that if we don't need to restart a managed proxy, we
87  * can continue using its old transports normally.
88  * If we end up restarting the proxy, we destroy and unregister all
89  * old transports from the circuitbuild.c subsystem.
90  **/
91 
92 #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 iff we have a managed_proxy_t in the global list is for the
372  * given transport name. */
373 bool
374 managed_proxy_has_transport(const char *transport_name)
375 {
376  tor_assert(transport_name);
377 
378  if (!managed_proxy_list) {
379  return false;
380  }
381 
382  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
383  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, name) {
384  if (!strcasecmp(name, transport_name)) {
385  return true;
386  }
387  } SMARTLIST_FOREACH_END(name);
388  } SMARTLIST_FOREACH_END(mp);
389 
390  return false;
391 }
392 
393 /** Return true if there are still unconfigured managed proxies, or proxies
394  * that need restarting. */
395 int
397 {
399 }
400 
401 /** Assert that the unconfigured_proxies_n value correctly matches the number
402  * of proxies in a state other than PT_PROTO_COMPLETE. */
403 static void
405 {
406  int n_completed = 0;
407  if (!managed_proxy_list) {
409  return;
410  }
411 
412  SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
413  if (mp->conf_state == PT_PROTO_COMPLETED)
414  ++n_completed;
415  });
416 
417  tor_assert(n_completed + unconfigured_proxies_n ==
418  smartlist_len(managed_proxy_list));
419 }
420 
421 /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
422 static int
423 managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
424 {
425  char **tmp1=proxy_argv;
426  char **tmp2=mp->argv;
427 
428  tor_assert(tmp1);
429  tor_assert(tmp2);
430 
431  while (*tmp1 && *tmp2) {
432  if (strcmp(*tmp1++, *tmp2++))
433  return 0;
434  }
435 
436  if (!*tmp1 && !*tmp2)
437  return 1;
438 
439  return 0;
440 }
441 
442 /** Return a managed proxy with the same argv as <b>proxy_argv</b>.
443  * If no such managed proxy exists, return NULL. */
444 static managed_proxy_t *
445 get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server)
446 {
447  if (!managed_proxy_list)
448  return NULL;
449 
450  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
451  if (managed_proxy_has_argv(mp, proxy_argv) &&
452  mp->is_server == is_server)
453  return mp;
454  } SMARTLIST_FOREACH_END(mp);
455 
456  return NULL;
457 }
458 
459 /** Add <b>transport</b> to managed proxy <b>mp</b>. */
460 static void
461 add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
462 {
463  tor_assert(mp->transports_to_launch);
464  if (!smartlist_contains_string(mp->transports_to_launch, transport))
465  smartlist_add_strdup(mp->transports_to_launch, transport);
466 }
467 
468 /** Called when a SIGHUP occurs. Returns true if managed proxy
469  * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
470  * torrc. */
471 static int
472 proxy_needs_restart(const managed_proxy_t *mp)
473 {
474  int ret = 1;
475  char* proxy_uri;
476 
477  /* If the PT proxy config has changed, then all existing pluggable transports
478  * should be restarted.
479  */
480 
481  proxy_uri = get_pt_proxy_uri();
482  if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
483  goto needs_restart;
484 
485  /* mp->transport_to_launch is populated with the names of the
486  transports that must be launched *after* the SIGHUP.
487  mp->transports is populated with the transports that were
488  launched *before* the SIGHUP.
489 
490  Check if all the transports that need to be launched are already
491  launched: */
492 
493  tor_assert(smartlist_len(mp->transports_to_launch) > 0);
494  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
495 
496  if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
497  goto needs_restart;
498 
499  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
500  if (!smartlist_contains_string(mp->transports_to_launch, t->name))
501  goto needs_restart;
502 
503  } SMARTLIST_FOREACH_END(t);
504 
505  ret = 0;
506  needs_restart:
507  tor_free(proxy_uri);
508  return ret;
509 }
510 
511 /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
512  * preparations and then flag its state so that it will be relaunched
513  * in the next tick. */
514 static void
515 proxy_prepare_for_restart(managed_proxy_t *mp)
516 {
517  transport_t *t_tmp = NULL;
518 
519  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
520 
521  /* destroy the process handle and terminate the process. */
522  process_set_data(mp->process, NULL);
523  process_terminate(mp->process);
524 
525  /* destroy all its registered transports, since we will no longer
526  use them. */
527  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
528  t_tmp = transport_get_by_name(t->name);
529  if (t_tmp)
530  t_tmp->marked_for_removal = 1;
531  } SMARTLIST_FOREACH_END(t);
533 
534  /* free the transport in mp->transports */
535  SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
536  smartlist_clear(mp->transports);
537 
538  /* Reset the proxy's HTTPS/SOCKS proxy */
539  tor_free(mp->proxy_uri);
540  mp->proxy_uri = get_pt_proxy_uri();
541  mp->proxy_supported = 0;
542 
543  /* flag it as an infant proxy so that it gets launched on next tick */
544  mp->conf_state = PT_PROTO_INFANT;
546 }
547 
548 /** Launch managed proxy <b>mp</b>. */
549 static int
550 launch_managed_proxy(managed_proxy_t *mp)
551 {
552  tor_assert(mp);
553 
555 
556  /* Configure our process. */
557  process_set_data(mp->process, mp);
561  process_set_protocol(mp->process, PROCESS_PROTOCOL_LINE);
562  process_reset_environment(mp->process, env);
563 
564  /* Cleanup our env. */
565  SMARTLIST_FOREACH(env, char *, x, tor_free(x));
566  smartlist_free(env);
567 
568  /* Skip the argv[0] as we get that from process_new(argv[0]). */
569  for (int i = 1; mp->argv[i] != NULL; ++i)
570  process_append_argument(mp->process, mp->argv[i]);
571 
572  if (process_exec(mp->process) != PROCESS_STATUS_RUNNING) {
573  log_warn(LD_CONFIG, "Managed proxy at '%s' failed at launch.",
574  mp->argv[0]);
575  return -1;
576  }
577 
578  log_info(LD_CONFIG,
579  "Managed proxy at '%s' has spawned with PID '%" PRIu64 "'.",
580  mp->argv[0], process_get_pid(mp->process));
581  mp->conf_state = PT_PROTO_LAUNCHED;
582 
583  return 0;
584 }
585 
586 /** Check if any of the managed proxies we are currently trying to
587  * configure has anything new to say. */
588 void
590 {
591  int at_least_a_proxy_config_finished = 0;
592  smartlist_t *tmp = smartlist_new();
593 
594  log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
596 
597  /* Iterate over tmp, not managed_proxy_list, since configure_proxy can
598  * remove elements from managed_proxy_list. */
600 
602 
603  SMARTLIST_FOREACH_BEGIN(tmp, managed_proxy_t *, mp) {
604  tor_assert(mp->conf_state != PT_PROTO_BROKEN &&
605  mp->conf_state != PT_PROTO_FAILED_LAUNCH);
606 
607  if (mp->was_around_before_config_read) {
608  /* This proxy is marked by a config read. Check whether we need
609  to restart it. */
610 
611  mp->was_around_before_config_read = 0;
612 
613  if (proxy_needs_restart(mp)) {
614  log_info(LD_GENERAL, "Preparing managed proxy '%s' for restart.",
615  mp->argv[0]);
617  } else { /* it doesn't need to be restarted. */
618  log_info(LD_GENERAL, "Nothing changed for managed proxy '%s' after "
619  "HUP: not restarting.", mp->argv[0]);
620  }
621 
622  continue;
623  }
624 
625  /* If the proxy is not fully configured, try to configure it
626  further. */
628  if (configure_proxy(mp) == 1)
629  at_least_a_proxy_config_finished = 1;
630 
631  } SMARTLIST_FOREACH_END(mp);
632 
633  smartlist_free(tmp);
636 
637  if (at_least_a_proxy_config_finished)
638  mark_my_descriptor_dirty("configured managed proxies");
639 }
640 
641 /** Attempt to continue configuring managed proxy <b>mp</b>.
642  * Return 1 if the transport configuration finished, and return 0
643  * otherwise (if we still have more configuring to do for this
644  * proxy). */
645 STATIC int
646 configure_proxy(managed_proxy_t *mp)
647 {
648  /* if we haven't launched the proxy yet, do it now */
649  if (mp->conf_state == PT_PROTO_INFANT) {
650  if (launch_managed_proxy(mp) < 0) { /* launch fail */
651  mp->conf_state = PT_PROTO_FAILED_LAUNCH;
653  }
654  return 0;
655  }
656 
657  tor_assert(mp->conf_state != PT_PROTO_INFANT);
658  tor_assert(mp->process);
659  return mp->conf_state == PT_PROTO_COMPLETED;
660 }
661 
662 /** Register server managed proxy <b>mp</b> transports to state */
663 static void
664 register_server_proxy(const managed_proxy_t *mp)
665 {
666  tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
667 
668  SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
669  save_transport_to_state(t->name, &t->addr, t->port);
670  log_notice(LD_GENERAL, "Registered server transport '%s' at '%s'",
671  t->name, fmt_addrport(&t->addr, t->port));
672  control_event_transport_launched("server", t->name, &t->addr, t->port);
673  } SMARTLIST_FOREACH_END(t);
674 }
675 
676 /** Register all the transports supported by client managed proxy
677  * <b>mp</b> to the bridge subsystem. */
678 static void
679 register_client_proxy(const managed_proxy_t *mp)
680 {
681  int r;
682 
683  tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
684 
685  SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
686  transport_t *transport_tmp = transport_copy(t);
687  r = transport_add(transport_tmp);
688  switch (r) {
689  case -1:
690  log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
691  transport_free(transport_tmp);
692  break;
693  case 0:
694  log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
695  control_event_transport_launched("client", t->name, &t->addr, t->port);
696  break;
697  case 1:
698  log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
699  control_event_transport_launched("client", t->name, &t->addr, t->port);
700  transport_free(transport_tmp);
701  break;
702  }
703  } SMARTLIST_FOREACH_END(t);
704 }
705 
706 /** Register the transports of managed proxy <b>mp</b>. */
707 static inline void
708 register_proxy(const managed_proxy_t *mp)
709 {
710  if (mp->is_server)
712  else
714 }
715 
716 /** Free memory allocated by managed proxy <b>mp</b>. */
717 STATIC void
718 managed_proxy_destroy(managed_proxy_t *mp,
719  int also_terminate_process)
720 {
721  SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
722 
723  /* free the transports smartlist */
724  smartlist_free(mp->transports);
725 
726  /* free the transports_to_launch smartlist */
727  SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
728  smartlist_free(mp->transports_to_launch);
729 
730  /* remove it from the list of managed proxies */
731  if (managed_proxy_list)
733 
734  /* free the argv */
735  free_execve_args(mp->argv);
736 
737  /* free the outgoing proxy URI */
738  tor_free(mp->proxy_uri);
739 
740  /* do we want to terminate our process if it's still running? */
741  if (also_terminate_process && mp->process) {
742  /* Note that we do not call process_free(mp->process) here because we let
743  * the exit handler in managed_proxy_exit_callback() return `true` which
744  * makes the process subsystem deallocate the process_t. */
745  process_set_data(mp->process, NULL);
746  process_terminate(mp->process);
747  }
748 
749  tor_free(mp);
750 }
751 
752 /** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY.
753  * Return a newly allocated string containing the URI, or NULL if no
754  * proxy is set. */
755 STATIC char *
757 {
758  const or_options_t *options = get_options();
759  char *uri = NULL;
760 
761  /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
762  * there isn't a standard URI scheme for some proxy protocols, such as
763  * haproxy. */
764  if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
765  char addr[TOR_ADDR_BUF_LEN+1];
766 
767  if (options->Socks4Proxy) {
768  tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
769  tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
770  } else if (options->Socks5Proxy) {
771  tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
772  if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
773  tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
774  } else {
775  tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
776  options->Socks5ProxyUsername,
777  options->Socks5ProxyPassword,
778  addr, options->Socks5ProxyPort);
779  }
780  } else if (options->HTTPSProxy) {
781  tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
782  if (!options->HTTPSProxyAuthenticator) {
783  tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
784  } else {
785  tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
786  addr, options->HTTPSProxyPort);
787  }
788  }
789  }
790 
791  return uri;
792 }
793 
794 /** Handle a configured or broken managed proxy <b>mp</b>. */
795 static void
796 handle_finished_proxy(managed_proxy_t *mp)
797 {
798  switch (mp->conf_state) {
799  case PT_PROTO_BROKEN: /* if broken: */
800  managed_proxy_destroy(mp, 1); /* annihilate it. */
801  break;
802  case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
803  managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
804  break;
805  case PT_PROTO_CONFIGURED: /* if configured correctly: */
806  if (mp->proxy_uri && !mp->proxy_supported) {
807  log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
808  "specified outgoing proxy and will be terminated.",
809  mp->argv[0]);
810  managed_proxy_destroy(mp, 1); /* annihilate it. */
811  break;
812  }
813  register_proxy(mp); /* register its transports */
814  mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
815  break;
816  case PT_PROTO_INFANT:
817  case PT_PROTO_LAUNCHED:
818  case PT_PROTO_ACCEPTING_METHODS:
819  case PT_PROTO_COMPLETED:
820  default:
821  log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
822  (int)mp->conf_state, mp->argv[0]);
823  tor_assert(0);
824  }
825 
827 }
828 
829 /** Return true if the configuration of the managed proxy <b>mp</b> is
830  finished. */
831 static inline int
832 proxy_configuration_finished(const managed_proxy_t *mp)
833 {
834  return (mp->conf_state == PT_PROTO_CONFIGURED ||
835  mp->conf_state == PT_PROTO_BROKEN ||
836  mp->conf_state == PT_PROTO_FAILED_LAUNCH);
837 }
838 
839 /** This function is called when a proxy sends an {S,C}METHODS DONE message. */
840 static void
841 handle_methods_done(const managed_proxy_t *mp)
842 {
843  tor_assert(mp->transports);
844 
845  if (smartlist_len(mp->transports) == 0)
846  log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
847  "but it didn't launch any pluggable transport listeners!",
848  mp->argv[0]);
849 
850  log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
851  mp->is_server ? "Server" : "Client",
852  mp->argv[0]);
853 }
854 
855 /** Handle a configuration protocol <b>line</b> received from a
856  * managed proxy <b>mp</b>. */
857 STATIC void
858 handle_proxy_line(const char *line, managed_proxy_t *mp)
859 {
860  log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
861  mp->argv[0], line);
862 
863  if (!strcmpstart(line, PROTO_ENV_ERROR)) {
864  if (mp->conf_state != PT_PROTO_LAUNCHED)
865  goto err;
866 
867  parse_env_error(line);
868  goto err;
869  } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
870  if (mp->conf_state != PT_PROTO_LAUNCHED)
871  goto err;
872 
873  log_warn(LD_CONFIG, "Managed proxy could not pick a "
874  "configuration protocol version.");
875  goto err;
876  } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
877  if (mp->conf_state != PT_PROTO_LAUNCHED)
878  goto err;
879 
880  if (parse_version(line,mp) < 0)
881  goto err;
882 
883  tor_assert(mp->conf_protocol != 0);
884  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
885  return;
886  } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
887  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
888  goto err;
889 
891 
892  mp->conf_state = PT_PROTO_CONFIGURED;
893  return;
894  } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
895  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
896  goto err;
897 
899 
900  mp->conf_state = PT_PROTO_CONFIGURED;
901  return;
902  } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
903  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
904  goto err;
905 
906  parse_client_method_error(line);
907  goto err;
908  } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
909  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
910  goto err;
911 
912  parse_server_method_error(line);
913  goto err;
914  } else if (!strcmpstart(line, PROTO_CMETHOD)) {
915  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
916  goto err;
917 
918  if (parse_cmethod_line(line, mp) < 0)
919  goto err;
920 
921  return;
922  } else if (!strcmpstart(line, PROTO_SMETHOD)) {
923  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
924  goto err;
925 
926  if (parse_smethod_line(line, mp) < 0)
927  goto err;
928 
929  return;
930  } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
931  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
932  goto err;
933 
934  if (mp->proxy_uri) {
935  mp->proxy_supported = 1;
936  return;
937  }
938 
939  /* No proxy was configured, this should log */
940  } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
941  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
942  goto err;
943 
944  parse_proxy_error(line);
945  goto err;
946 
947  /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
948  * string to make sure we can later extend this big if/else-if table with
949  * something that begins with "LOG" without having to get the order right.
950  * */
951  } else if (!strcmpstart(line, PROTO_LOG " ")) {
952  parse_log_line(line, mp);
953  return;
954  } else if (!strcmpstart(line, PROTO_STATUS " ")) {
955  parse_status_line(line, mp);
956  return;
957  }
958 
959  log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
960  return;
961 
962  err:
963  mp->conf_state = PT_PROTO_BROKEN;
964  log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
965  " and will be destroyed.", mp->argv[0]);
966 }
967 
968 /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
969 STATIC void
970 parse_env_error(const char *line)
971 {
972  /* (Length of the protocol string) plus (a space) and (the first char of
973  the error message) */
974  if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
975  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
976  "message.", PROTO_ENV_ERROR);
977 
978  log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
979  "pluggable transport environment variables. (%s)",
980  line+strlen(PROTO_ENV_ERROR)+1);
981 }
982 
983 /** Handles a VERSION <b>line</b>. Updates the configuration protocol
984  * version in <b>mp</b>. */
985 STATIC int
986 parse_version(const char *line, managed_proxy_t *mp)
987 {
988  if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
989  log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
990  PROTO_NEG_SUCCESS);
991  return -1;
992  }
993 
994  if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
995  log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
996  "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
997  return -1;
998  }
999 
1000  mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
1001  return 0;
1002 }
1003 
1004 /** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
1005  * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
1006  * otherwise it is a CMETHOD-ERROR. */
1007 static void
1008 parse_method_error(const char *line, int is_server)
1009 {
1010  const char* error = is_server ?
1011  PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
1012 
1013  /* (Length of the protocol string) plus (a space) and (the first char of
1014  the error message) */
1015  if (strlen(line) < (strlen(error) + 2))
1016  log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
1017  "message.", error);
1018 
1019  log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
1020  is_server ? "Server" : "Client",
1021  line+strlen(error)+1);
1022 }
1023 
1024 /** A helper for parse_{c,s}method_line(), bootstraps its
1025  * functionalities. If <b>is_smethod</b> is true then the
1026  * the line to parse is a SMETHOD line otherwise it is a
1027  * CMETHOD line*/
1028 static int
1029 parse_method_line_helper(const char *line,
1030  managed_proxy_t *mp,
1031  int is_smethod)
1032 {
1033  int item_index = 0;
1034  int r;
1035 
1036  char *transport_name=NULL;
1037  char *args_string=NULL;
1038  char *addrport=NULL;
1039  int socks_ver=PROXY_NONE;
1040  char *address=NULL;
1041  uint16_t port = 0;
1042 
1043  const char *method_str = is_smethod ? PROTO_SMETHOD : PROTO_CMETHOD;
1044  const int min_args_count = is_smethod ? 3 : 4;
1045 
1046  tor_addr_t tor_addr;
1047  transport_t *transport=NULL;
1048  smartlist_t *items= smartlist_new();
1049 
1050  smartlist_split_string(items, line, NULL,
1051  SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1052  if (smartlist_len(items) < min_args_count) {
1053  log_warn(LD_CONFIG, "Managed proxy sent us a %s line "
1054  "with too few arguments.", method_str);
1055  goto err;
1056  }
1057 
1058  tor_assert(!strcmp(smartlist_get(items, item_index),method_str));
1059  ++item_index;
1060 
1061  transport_name = smartlist_get(items,item_index);
1062  ++item_index;
1063  if (!string_is_C_identifier(transport_name)) {
1064  log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
1065  transport_name);
1066  goto err;
1067  }
1068 
1069  /** Check for the proxy method sent to us in CMETHOD line. */
1070  if (!is_smethod) {
1071  const char *socks_ver_str = smartlist_get(items,item_index);
1072  ++item_index;
1073 
1074  if (!strcmp(socks_ver_str,"socks4")) {
1075  socks_ver = PROXY_SOCKS4;
1076  } else if (!strcmp(socks_ver_str,"socks5")) {
1077  socks_ver = PROXY_SOCKS5;
1078  } else {
1079  log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
1080  "we don't recognize. (%s)", socks_ver_str);
1081  goto err;
1082  }
1083  }
1084 
1085  addrport = smartlist_get(items, item_index);
1086  ++item_index;
1087  if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) {
1088  log_warn(LD_CONFIG, "Error parsing transport address '%s'", addrport);
1089  goto err;
1090  }
1091 
1092  if (!port) {
1093  log_warn(LD_CONFIG,
1094  "Transport address '%s' has no port.", addrport);
1095  goto err;
1096  }
1097 
1098  if (tor_addr_parse(&tor_addr, address) < 0) {
1099  log_warn(LD_CONFIG, "Error parsing transport address '%s'", address);
1100  goto err;
1101  }
1102 
1103  /** Check for options in the SMETHOD line. */
1104  if (is_smethod && smartlist_len(items) > min_args_count) {
1105  /* Seems like there are also some [options] in the SMETHOD line.
1106  Let's see if we can parse them. */
1107  char *options_string = smartlist_get(items, item_index);
1108  log_debug(LD_CONFIG, "Got options_string: %s", options_string);
1109  if (!strcmpstart(options_string, "ARGS:")) {
1110  args_string = options_string+strlen("ARGS:");
1111  log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
1112  }
1113  }
1114 
1115  transport = transport_new(&tor_addr, port, transport_name,
1116  socks_ver, args_string);
1117 
1118  smartlist_add(mp->transports, transport);
1119 
1120  /** Logs info about line parsing success for client or server */
1121  if (is_smethod) {
1122  log_info(LD_CONFIG, "Server transport %s at %s:%d.",
1123  transport_name, address, (int)port);
1124  } else {
1125  log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
1126  "Attached to managed proxy.",
1127  transport_name, address, (int)port, socks_ver);
1128  }
1129 
1130  r=0;
1131  goto done;
1132 
1133  err:
1134  r = -1;
1135 
1136  done:
1137  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
1138  smartlist_free(items);
1139  tor_free(address);
1140  return r;
1141 }
1142 
1143 /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
1144  * new transport in <b>mp</b>. */
1145 STATIC int
1146 parse_smethod_line(const char *line, managed_proxy_t *mp)
1147 {
1148  /* Example of legit SMETHOD line:
1149  SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
1150  return parse_method_line_helper(line, mp, 1);
1151 }
1152 
1153 /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
1154  * the new transport in <b>mp</b>. */
1155 STATIC int
1156 parse_cmethod_line(const char *line, managed_proxy_t *mp)
1157 {
1158  /* Example of legit CMETHOD line:
1159  CMETHOD obfs2 socks5 127.0.0.1:35713 */
1160  return parse_method_line_helper(line, mp, 0);
1161 }
1162 
1163 /** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
1164 STATIC void
1165 parse_proxy_error(const char *line)
1166 {
1167  /* (Length of the protocol string) plus (a space) and (the first char of
1168  the error message) */
1169  if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
1170  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
1171  "message.", PROTO_PROXY_ERROR);
1172 
1173  log_warn(LD_CONFIG, "Managed proxy failed to configure the "
1174  "pluggable transport's outgoing proxy. (%s)",
1175  line+strlen(PROTO_PROXY_ERROR)+1);
1176 }
1177 
1178 /** Parses a LOG <b>line</b> and emit log events accordingly. */
1179 STATIC void
1180 parse_log_line(const char *line, managed_proxy_t *mp)
1181 {
1182  tor_assert(line);
1183  tor_assert(mp);
1184 
1185  config_line_t *values = NULL;
1186  char *log_message = NULL;
1187 
1188  if (strlen(line) < (strlen(PROTO_LOG) + 1)) {
1189  log_warn(LD_PT, "Managed proxy sent us a %s line "
1190  "with missing argument.", PROTO_LOG);
1191  goto done;
1192  }
1193 
1194  const char *data = line + strlen(PROTO_LOG) + 1;
1195  values = kvline_parse(data, KV_QUOTED);
1196 
1197  if (! values) {
1198  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid LOG message: %s",
1199  mp->argv[0], data);
1200  goto done;
1201  }
1202 
1203  const config_line_t *severity = config_line_find(values, "SEVERITY");
1204  const config_line_t *message = config_line_find(values, "MESSAGE");
1205 
1206  /* Check if we got a message. */
1207  if (! message) {
1208  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1209  "MESSAGE: %s", mp->argv[0], escaped(data));
1210  goto done;
1211  }
1212 
1213  /* Check if severity is there and whether it's valid. */
1214  if (! severity) {
1215  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1216  "SEVERITY: %s", mp->argv[0], escaped(data));
1217  goto done;
1218  }
1219 
1220  int log_severity = managed_proxy_severity_parse(severity->value);
1221 
1222  if (log_severity == -1) {
1223  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line with an "
1224  "invalid severity level: %s",
1225  mp->argv[0], severity->value);
1226  goto done;
1227  }
1228 
1229  tor_log(log_severity, LD_PT, "Managed proxy \"%s\": %s",
1230  mp->argv[0], message->value);
1231 
1232  /* Prepend the PT name. */
1233  config_line_prepend(&values, "PT", mp->argv[0]);
1234  log_message = kvline_encode(values, KV_QUOTED);
1235 
1236  /* Emit control port event. */
1237  control_event_pt_log(log_message);
1238 
1239  done:
1240  config_free_lines(values);
1241  tor_free(log_message);
1242 }
1243 
1244 /** Parses a STATUS <b>line</b> and emit control events accordingly. */
1245 STATIC void
1246 parse_status_line(const char *line, managed_proxy_t *mp)
1247 {
1248  tor_assert(line);
1249  tor_assert(mp);
1250 
1251  config_line_t *values = NULL;
1252  char *status_message = NULL;
1253 
1254  if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
1255  log_warn(LD_PT, "Managed proxy sent us a %s line "
1256  "with missing argument.", PROTO_STATUS);
1257  goto done;
1258  }
1259 
1260  const char *data = line + strlen(PROTO_STATUS) + 1;
1261 
1262  values = kvline_parse(data, KV_QUOTED);
1263 
1264  if (! values) {
1265  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
1266  "STATUS message: %s", mp->argv[0], escaped(data));
1267  goto done;
1268  }
1269 
1270  /* We check if we received the TRANSPORT parameter, which is the only
1271  * *required* value. */
1272  const config_line_t *type = config_line_find(values, "TRANSPORT");
1273 
1274  if (! type) {
1275  log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
1276  "TRANSPORT: %s", mp->argv[0], escaped(data));
1277  goto done;
1278  }
1279 
1280  /* Prepend the PT name. */
1281  config_line_prepend(&values, "PT", mp->argv[0]);
1282  status_message = kvline_encode(values, KV_QUOTED);
1283 
1284  /* We have checked that TRANSPORT is there, we can now emit the STATUS event
1285  * via the control port. */
1286  control_event_pt_status(status_message);
1287 
1288  done:
1289  config_free_lines(values);
1290  tor_free(status_message);
1291 }
1292 
1293 /** Return a newly allocated string that tor should place in
1294  * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
1295  * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
1296 STATIC char *
1297 get_transport_options_for_server_proxy(const managed_proxy_t *mp)
1298 {
1299  char *options_string = NULL;
1300  smartlist_t *string_sl = smartlist_new();
1301 
1302  tor_assert(mp->is_server);
1303 
1304  /** Loop over the transports of the proxy. If we have options for
1305  any of them, format them appropriately and place them in our
1306  smartlist. Finally, join our smartlist to get the final
1307  string. */
1308  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
1309  smartlist_t *options_tmp_sl = NULL;
1310  options_tmp_sl = pt_get_options_for_server_transport(transport);
1311  if (!options_tmp_sl)
1312  continue;
1313 
1314  /** Loop over the options of this transport, escape them, and
1315  place them in the smartlist. */
1316  SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
1317  char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
1318  smartlist_add_asprintf(string_sl, "%s:%s",
1319  transport, escaped_opts);
1320  tor_free(escaped_opts);
1321  } SMARTLIST_FOREACH_END(options);
1322 
1323  SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
1324  smartlist_free(options_tmp_sl);
1325  } SMARTLIST_FOREACH_END(transport);
1326 
1327  if (smartlist_len(string_sl)) {
1328  options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
1329  }
1330 
1331  SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
1332  smartlist_free(string_sl);
1333 
1334  return options_string;
1335 }
1336 
1337 /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
1338  * while configuring the server managed proxy in <b>mp</b>. The
1339  * string is stored in the heap, and it's the responsibility of
1340  * the caller to deallocate it after its use. */
1341 static char *
1342 get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
1343 {
1344  char *bindaddr_result = NULL;
1345  char *bindaddr_tmp = NULL;
1346  smartlist_t *string_tmp = smartlist_new();
1347 
1348  tor_assert(mp->is_server);
1349 
1350  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
1351  bindaddr_tmp = get_stored_bindaddr_for_server_transport(t);
1352 
1353  smartlist_add_asprintf(string_tmp, "%s-%s", t, bindaddr_tmp);
1354 
1355  tor_free(bindaddr_tmp);
1356  } SMARTLIST_FOREACH_END(t);
1357 
1358  bindaddr_result = smartlist_join_strings(string_tmp, ",", 0, NULL);
1359 
1360  SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
1361  smartlist_free(string_tmp);
1362 
1363  return bindaddr_result;
1364 }
1365 
1366 /** Return a newly allocated process_environment_t * for <b>mp</b>'s
1367  * process. */
1368 static smartlist_t *
1369 create_managed_proxy_environment(const managed_proxy_t *mp)
1370 {
1371  const or_options_t *options = get_options();
1372 
1373  /* Environment variables to be added to or set in mp's environment. */
1374  smartlist_t *envs = smartlist_new();
1375  /* XXXX The next time someone touches this code, shorten the name of
1376  * set_environment_variable_in_smartlist, add a
1377  * set_env_var_in_smartlist_asprintf function, and get rid of the
1378  * silly extra envs smartlist. */
1379 
1380  /* The final environment to be passed to mp. */
1382 
1383  {
1384  char *state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
1385  smartlist_add_asprintf(envs, "TOR_PT_STATE_LOCATION=%s", state_tmp);
1386  tor_free(state_tmp);
1387  }
1388 
1389  smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
1390 
1391  {
1392  char *transports_to_launch =
1393  smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
1394 
1396  mp->is_server ?
1397  "TOR_PT_SERVER_TRANSPORTS=%s" :
1398  "TOR_PT_CLIENT_TRANSPORTS=%s",
1399  transports_to_launch);
1400 
1401  tor_free(transports_to_launch);
1402  }
1403 
1404  if (mp->is_server) {
1405  {
1406  char *orport_tmp =
1408  if (orport_tmp) {
1409  smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
1410  tor_free(orport_tmp);
1411  }
1412  }
1413 
1414  {
1415  char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
1416  smartlist_add_asprintf(envs, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
1417  tor_free(bindaddr_tmp);
1418  }
1419 
1420  {
1421  char *server_transport_options =
1423  if (server_transport_options) {
1424  smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1425  server_transport_options);
1426  tor_free(server_transport_options);
1427  }
1428  }
1429 
1430  /* XXXX Remove the '=' here once versions of obfsproxy which
1431  * assert that this env var exists are sufficiently dead.
1432  *
1433  * (If we remove this line entirely, some joker will stick this
1434  * variable in Tor's environment and crash PTs that try to parse
1435  * it even when not run in server mode.) */
1436 
1437  if (options->ExtORPort_lines) {
1438  char *ext_or_addrport_tmp =
1440  char *cookie_file_loc = get_ext_or_auth_cookie_file_name();
1441 
1442  if (ext_or_addrport_tmp) {
1443  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1444  ext_or_addrport_tmp);
1445  }
1446  if (cookie_file_loc) {
1447  smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s",
1448  cookie_file_loc);
1449  }
1450 
1451  tor_free(ext_or_addrport_tmp);
1452  tor_free(cookie_file_loc);
1453 
1454  } else {
1455  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
1456  }
1457  } else {
1458  /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
1459  * TOR_PT_PROXY line.
1460  */
1461 
1462  if (mp->proxy_uri) {
1463  smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
1464  }
1465  }
1466 
1467  /* All new versions of tor will keep stdin open, so PTs can use it
1468  * as a reliable termination detection mechanism.
1469  */
1470  smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
1471 
1472  /* Specify which IPv4 and IPv6 addresses the PT should make its outgoing
1473  * connections from. See: https://bugs.torproject.org/5304 for more
1474  * information about this. */
1475  {
1476  /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V4. */
1477  const tor_addr_t *ipv4_addr = managed_proxy_outbound_address(options,
1478  AF_INET);
1479 
1480  /* managed_proxy_outbound_address() only returns a non-NULL value if
1481  * tor_addr_is_null() was false, which means we don't have to check that
1482  * here. */
1483  if (ipv4_addr) {
1484  char *ipv4_addr_str = tor_addr_to_str_dup(ipv4_addr);
1486  "TOR_PT_OUTBOUND_BIND_ADDRESS_V4=%s",
1487  ipv4_addr_str);
1488  tor_free(ipv4_addr_str);
1489  }
1490 
1491  /* Set TOR_PT_OUTBOUND_BIND_ADDRESS_V6. */
1492  const tor_addr_t *ipv6_addr = managed_proxy_outbound_address(options,
1493  AF_INET6);
1494  if (ipv6_addr) {
1495  char *ipv6_addr_str = tor_addr_to_str_dup(ipv6_addr);
1497  "TOR_PT_OUTBOUND_BIND_ADDRESS_V6=[%s]",
1498  ipv6_addr_str);
1499  tor_free(ipv6_addr_str);
1500  }
1501  }
1502 
1503  SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
1504  set_environment_variable_in_smartlist(merged_env_vars, env_var,
1505  tor_free_, 1);
1506  } SMARTLIST_FOREACH_END(env_var);
1507 
1508  smartlist_free(envs);
1509 
1510  return merged_env_vars;
1511 }
1512 
1513 /** Create and return a new managed proxy for <b>transport</b> using
1514  * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
1515  * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
1516  * <b>proxy_argv</b>.
1517  *
1518  * Requires that proxy_argv have at least one element. */
1519 STATIC managed_proxy_t *
1520 managed_proxy_create(const smartlist_t *with_transport_list,
1521  char **proxy_argv, int is_server)
1522 {
1523  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
1524  mp->conf_state = PT_PROTO_INFANT;
1525  mp->is_server = is_server;
1526  mp->argv = proxy_argv;
1527  mp->transports = smartlist_new();
1528  mp->proxy_uri = get_pt_proxy_uri();
1529  mp->process = process_new(proxy_argv[0]);
1530 
1531  mp->transports_to_launch = smartlist_new();
1532  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1533  add_transport_to_proxy(transport, mp));
1534 
1535  /* register the managed proxy */
1536  if (!managed_proxy_list)
1540 
1542 
1543  return mp;
1544 }
1545 
1546 /** Register proxy with <b>proxy_argv</b>, supporting transports in
1547  * <b>transport_list</b>, to the managed proxy subsystem.
1548  * If <b>is_server</b> is true, then the proxy is a server proxy.
1549  *
1550  * Takes ownership of proxy_argv.
1551  *
1552  * Requires that proxy_argv be a NULL-terminated array of command-line
1553  * elements, containing at least one element.
1554  **/
1555 MOCK_IMPL(void,
1556 pt_kickstart_proxy, (const smartlist_t *with_transport_list,
1557  char **proxy_argv, int is_server))
1558 {
1559  managed_proxy_t *mp=NULL;
1560  transport_t *old_transport = NULL;
1561 
1562  if (!proxy_argv || !proxy_argv[0]) {
1563  return;
1564  }
1565 
1566  mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
1567 
1568  if (!mp) { /* we haven't seen this proxy before */
1569  managed_proxy_create(with_transport_list, proxy_argv, is_server);
1570 
1571  } else { /* known proxy. add its transport to its transport list */
1572  if (mp->was_around_before_config_read) {
1573  /* If this managed proxy was around even before we read the
1574  config this time, it means that it was already enabled before
1575  and is not useless and should be kept. If it's marked for
1576  removal, unmark it and make sure that we check whether it
1577  needs to be restarted. */
1578  if (mp->marked_for_removal) {
1579  mp->marked_for_removal = 0;
1581  }
1582 
1583  /* For each new transport, check if the managed proxy used to
1584  support it before the SIGHUP. If that was the case, make sure
1585  it doesn't get removed because we might reuse it. */
1586  SMARTLIST_FOREACH_BEGIN(with_transport_list, const char *, transport) {
1587  old_transport = transport_get_by_name(transport);
1588  if (old_transport)
1589  old_transport->marked_for_removal = 0;
1590  } SMARTLIST_FOREACH_END(transport);
1591  }
1592 
1593  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1594  add_transport_to_proxy(transport, mp));
1595  free_execve_args(proxy_argv);
1596  }
1597 }
1598 
1599 /** Frees the array of pointers in <b>arg</b> used as arguments to
1600  execve(2). */
1601 STATIC void
1602 free_execve_args(char **arg)
1603 {
1604  char **tmp = arg;
1605  while (*tmp) /* use the fact that the last element of the array is a
1606  NULL pointer to know when to stop freeing */
1607  tor_free_(*tmp++);
1608 
1609  tor_free(arg);
1610 }
1611 
1612 /** Tor will read its config.
1613  * Prepare the managed proxy list so that proxies not used in the new
1614  * config will shutdown, and proxies that need to spawn different
1615  * transports will do so. */
1616 void
1618 {
1619  if (!managed_proxy_list)
1620  return;
1621 
1623  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1624  /* Destroy unconfigured proxies. */
1625  if (mp->conf_state != PT_PROTO_COMPLETED) {
1627  managed_proxy_destroy(mp, 1);
1629  continue;
1630  }
1631 
1632  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1633 
1634  /* Mark all proxies for removal, and also note that they have been
1635  here before the config read. */
1636  mp->marked_for_removal = 1;
1637  mp->was_around_before_config_read = 1;
1638  SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
1639  smartlist_clear(mp->transports_to_launch);
1640  } SMARTLIST_FOREACH_END(mp);
1641 
1643 
1645 }
1646 
1647 /** Return a smartlist containing the ports where our pluggable
1648  * transports are listening. */
1649 smartlist_t *
1651 {
1652  smartlist_t *sl = NULL;
1653 
1654  if (!managed_proxy_list)
1655  return NULL;
1656 
1657  /** XXX assume that external proxy ports have been forwarded
1658  manually */
1659  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1660  if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED)
1661  continue;
1662 
1663  if (!sl) sl = smartlist_new();
1664 
1665  tor_assert(mp->transports);
1666  SMARTLIST_FOREACH(mp->transports, const transport_t *, t,
1667  smartlist_add_asprintf(sl, "%u:%u", t->port, t->port));
1668 
1669  } SMARTLIST_FOREACH_END(mp);
1670 
1671  return sl;
1672 }
1673 
1674 /** Return the pluggable transport string that we should display in
1675  * our extra-info descriptor. If we shouldn't display such a string,
1676  * or we have nothing to display, return NULL. The string is
1677  * allocated on the heap and it's the responsibility of the caller to
1678  * free it. */
1679 char *
1681 {
1682  char *the_string = NULL;
1683  smartlist_t *string_chunks = NULL;
1684 
1685  if (!managed_proxy_list)
1686  return NULL;
1687 
1688  string_chunks = smartlist_new();
1689 
1690  /* For each managed proxy, add its transports to the chunks list. */
1691  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1692  if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
1693  continue;
1694 
1695  tor_assert(mp->transports);
1696 
1697  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1698  char *transport_args = NULL;
1699  const char *addrport = NULL;
1700 
1701  /* If the transport proxy returned "0.0.0.0" as its address, and
1702  * we know our external IP address, use it. Otherwise, use the
1703  * returned address. */
1704  if (tor_addr_is_null(&t->addr)) {
1705  tor_addr_t addr;
1706  /* Attempt to find the IPv4 and then attempt to find the IPv6 if we
1707  * can't find it. */
1708  bool found = relay_find_addr_to_publish(get_options(), AF_INET,
1709  RELAY_FIND_ADDR_NO_FLAG,
1710  &addr);
1711  if (!found) {
1712  found = relay_find_addr_to_publish(get_options(), AF_INET6,
1713  RELAY_FIND_ADDR_NO_FLAG, &addr);
1714  }
1715  if (!found) {
1716  log_err(LD_PT, "Unable to find address for transport %s", t->name);
1717  continue;
1718  }
1719  addrport = fmt_addrport(&addr, t->port);
1720  } else {
1721  addrport = fmt_addrport(&t->addr, t->port);
1722  }
1723 
1724  /* If this transport has any arguments with it, prepend a space
1725  to them so that we can add them to the transport line. */
1726  if (t->extra_info_args)
1727  tor_asprintf(&transport_args, " %s", t->extra_info_args);
1728 
1729  smartlist_add_asprintf(string_chunks,
1730  "transport %s %s%s",
1731  t->name, addrport,
1732  transport_args ? transport_args : "");
1733  tor_free(transport_args);
1734  } SMARTLIST_FOREACH_END(t);
1735 
1736  } SMARTLIST_FOREACH_END(mp);
1737 
1738  if (smartlist_len(string_chunks) == 0) {
1739  smartlist_free(string_chunks);
1740  return NULL;
1741  }
1742 
1743  /* Join all the chunks into the final string. */
1744  the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1745 
1746  SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1747  smartlist_free(string_chunks);
1748 
1749  return the_string;
1750 }
1751 
1752 /** Stringify the SOCKS arguments in <b>socks_args</b> according to
1753  * 180_pluggable_transport.txt. The string is allocated on the heap
1754  * and it's the responsibility of the caller to free it after use. */
1755 char *
1757 {
1758  /* tmp place to store escaped socks arguments, so that we can
1759  concatenate them up afterwards */
1760  smartlist_t *sl_tmp = NULL;
1761  char *escaped_string = NULL;
1762  char *new_string = NULL;
1763 
1764  tor_assert(socks_args);
1765  tor_assert(smartlist_len(socks_args) > 0);
1766 
1767  sl_tmp = smartlist_new();
1768 
1769  SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
1770  /* Escape ';' and '\'. */
1771  escaped_string = tor_escape_str_for_pt_args(s, ";\\");
1772  if (!escaped_string)
1773  goto done;
1774 
1775  smartlist_add(sl_tmp, escaped_string);
1776  } SMARTLIST_FOREACH_END(s);
1777 
1778  new_string = smartlist_join_strings(sl_tmp, ";", 0, NULL);
1779 
1780  done:
1781  SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
1782  smartlist_free(sl_tmp);
1783 
1784  return new_string;
1785 }
1786 
1787 /** Return a string of the SOCKS arguments that we should pass to the
1788  * pluggable transports proxy in <b>addr</b>:<b>port</b> according to
1789  * 180_pluggable_transport.txt. The string is allocated on the heap
1790  * and it's the responsibility of the caller to free it after use. */
1791 char *
1793 {
1794  const smartlist_t *socks_args = NULL;
1795 
1796  socks_args = get_socks_args_by_bridge_addrport(addr, port);
1797  if (!socks_args)
1798  return NULL;
1799 
1800  return pt_stringify_socks_args(socks_args);
1801 }
1802 
1803 /** The tor config was read.
1804  * Destroy all managed proxies that were marked by a previous call to
1805  * prepare_proxy_list_for_config_read() and are not used by the new
1806  * config. */
1807 void
1809 {
1810  if (!managed_proxy_list)
1811  return;
1813  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1814  if (mp->marked_for_removal) {
1816  managed_proxy_destroy(mp, 1);
1817  }
1818  } SMARTLIST_FOREACH_END(mp);
1820 }
1821 
1822 /** Release all storage held by the pluggable transports subsystem. */
1823 void
1825 {
1826  if (transport_list) {
1828  smartlist_free(transport_list);
1829  transport_list = NULL;
1830  }
1831 
1832  if (managed_proxy_list) {
1833  /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1834  transports and it's the duty of the circuitbuild.c subsystem to
1835  free them. Otherwise, it hasn't registered its transports yet
1836  and we should free them here. */
1837  SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
1839  managed_proxy_destroy(mp, 1);
1840  });
1841 
1842  smartlist_free(managed_proxy_list);
1843  managed_proxy_list=NULL;
1844  }
1845 }
1846 
1847 /** Return a newly allocated string equal to <b>string</b>, except that every
1848  * character in <b>chars_to_escape</b> is preceded by a backslash. */
1849 char *
1850 tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
1851 {
1852  char *new_string = NULL;
1853  char *new_cp = NULL;
1854  size_t length, new_length;
1855 
1856  tor_assert(string);
1857 
1858  length = strlen(string);
1859 
1860  if (!length) /* If we were given the empty string, return the same. */
1861  return tor_strdup("");
1862  /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
1863  (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
1864  if (length > (SIZE_MAX - 1)/2) /* check for overflow */
1865  return NULL;
1866 
1867  /* this should be enough even if all characters must be escaped */
1868  new_length = (length * 2) + 1;
1869 
1870  new_string = new_cp = tor_malloc(new_length);
1871 
1872  while (*string) {
1873  if (strchr(chars_to_escape, *string))
1874  *new_cp++ = '\\';
1875 
1876  *new_cp++ = *string++;
1877  }
1878 
1879  *new_cp = '\0'; /* NUL-terminate the new string */
1880 
1881  return new_string;
1882 }
1883 
1884 /** Callback function that is called when our PT process have data on its
1885  * stdout. Our process can be found in <b>process</b>, the data can be found in
1886  * <b>line</b> and the length of our line is given in <b>size</b>. */
1887 STATIC void
1889  const char *line,
1890  size_t size)
1891 {
1892  tor_assert(process);
1893  tor_assert(line);
1894 
1895  (void)size;
1896 
1897  managed_proxy_t *mp = process_get_data(process);
1898 
1899  if (mp == NULL)
1900  return;
1901 
1902  handle_proxy_line(line, mp);
1903 
1906 }
1907 
1908 /** Callback function that is called when our PT process have data on its
1909  * stderr. Our process can be found in <b>process</b>, the data can be found in
1910  * <b>line</b> and the length of our line is given in <b>size</b>. */
1911 STATIC void
1913  const char *line,
1914  size_t size)
1915 {
1916  tor_assert(process);
1917  tor_assert(line);
1918 
1919  (void)size;
1920 
1921  managed_proxy_t *mp = process_get_data(process);
1922 
1923  if (BUG(mp == NULL))
1924  return;
1925 
1926  log_info(LD_PT,
1927  "Managed proxy at '%s' reported via standard error: %s",
1928  mp->argv[0], line);
1929 }
1930 
1931 /** Callback function that is called when our PT process terminates. The
1932  * process exit code can be found in <b>exit_code</b> and our process can be
1933  * found in <b>process</b>. Returns true iff we want the process subsystem to
1934  * free our process_t handle for us. */
1935 STATIC bool
1936 managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
1937 {
1938  tor_assert(process);
1939 
1940  log_warn(LD_PT,
1941  "Pluggable Transport process terminated with status code %" PRIu64,
1942  exit_code);
1943 
1944  /* Returning true here means that the process subsystem will take care of
1945  * calling process_free() on our process_t. */
1946  return true;
1947 }
1948 
1949 /** Returns a valid integer log severity level from <b>severity</b> that
1950  * is compatible with Tor's logging functions. Returns <b>-1</b> on
1951  * error. */
1952 STATIC int
1953 managed_proxy_severity_parse(const char *severity)
1954 {
1955  tor_assert(severity);
1956 
1957  /* Slightly different than log.c's parse_log_level :-( */
1958  if (! strcmp(severity, "debug"))
1959  return LOG_DEBUG;
1960 
1961  if (! strcmp(severity, "info"))
1962  return LOG_INFO;
1963 
1964  if (! strcmp(severity, "notice"))
1965  return LOG_NOTICE;
1966 
1967  if (! strcmp(severity, "warning"))
1968  return LOG_WARN;
1969 
1970  if (! strcmp(severity, "error"))
1971  return LOG_ERR;
1972 
1973  return -1;
1974 }
1975 
1976 /** Return the outbound address from the given <b>family</b>. Returns NULL if
1977  * the user haven't specified a specific outbound address in either
1978  * OutboundBindAddress or OutboundBindAddressPT. */
1979 STATIC const tor_addr_t *
1981 {
1982  tor_assert(options);
1983 
1984  const tor_addr_t *address = NULL;
1985  int family_index;
1986 
1987  switch (family) {
1988  case AF_INET:
1989  family_index = 0;
1990  break;
1991  case AF_INET6:
1992  family_index = 1;
1993  break;
1994  default:
1995  /* LCOV_EXCL_START */
1996  tor_assert_unreached();
1997  return NULL;
1998  /* LCOV_EXCL_STOP */
1999  }
2000 
2001  /* We start by checking if the user specified an address in
2002  * OutboundBindAddressPT. */
2003  address = &options->OutboundBindAddresses[OUTBOUND_ADDR_PT][family_index];
2004 
2005  if (! tor_addr_is_null(address))
2006  return address;
2007 
2008  /* We fallback to check if the user specified an address in
2009  * OutboundBindAddress. */
2010  address = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY][family_index];
2011 
2012  if (! tor_addr_is_null(address))
2013  return address;
2014 
2015  /* The user have not specified a preference for outgoing connections. */
2016  return NULL;
2017 }
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
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:2434
transport_free_
void transport_free_(transport_t *transport)
Definition: transports.c:167
or_options_t::Socks5Proxy
char * Socks5Proxy
Definition: or_options_st.h:454
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:69
managed_proxy_has_argv
static int managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
Definition: transports.c:423
pt_prepare_proxy_list_for_config_read
void pt_prepare_proxy_list_for_config_read(void)
Definition: transports.c:1617
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.
managed_proxy_has_transport
bool managed_proxy_has_transport(const char *transport_name)
Definition: transports.c:374
or_options_t::HTTPSProxyAuthenticator
char * HTTPSProxyAuthenticator
Definition: or_options_st.h:448
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:1953
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:1165
or_options_t::Socks5ProxyPort
uint16_t Socks5ProxyPort
Definition: or_options_st.h:456
string_is_C_identifier
int string_is_C_identifier(const char *string)
Definition: util_string.c:423
get_transport_options_for_server_proxy
STATIC char * get_transport_options_for_server_proxy(const managed_proxy_t *mp)
Definition: transports.c:1297
pt_kickstart_proxy
void pt_kickstart_proxy(const smartlist_t *with_transport_list, char **proxy_argv, int is_server)
Definition: transports.c:1557
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:1905
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:664
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:1008
relay_find_addr_to_publish
bool relay_find_addr_to_publish(const or_options_t *options, int family, int flags, tor_addr_t *addr_out)
Definition: relay_find_addr.c:114
TOR_ADDR_BUF_LEN
#define TOR_ADDR_BUF_LEN
Definition: address.h:224
parse_version
STATIC int parse_version(const char *line, managed_proxy_t *mp)
Definition: transports.c:986
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:679
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:73
or_options_t::Socks5ProxyUsername
char * Socks5ProxyUsername
Definition: or_options_st.h:457
CONN_TYPE_OR_LISTENER
#define CONN_TYPE_OR_LISTENER
Definition: connection.h:41
handle_proxy_line
STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:858
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:841
get_transport_proxy_ports
smartlist_t * get_transport_proxy_ports(void)
Definition: transports.c:1650
sweep_proxy_list
void sweep_proxy_list(void)
Definition: transports.c:1808
LD_PT
#define LD_PT
Definition: log.h:117
strcmp_opt
int strcmp_opt(const char *s1, const char *s2)
Definition: util_string.c:197
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:796
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:1850
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:1894
pt_proxies_configuration_pending
int pt_proxies_configuration_pending(void)
Definition: transports.c:396
pt_stringify_socks_args
char * pt_stringify_socks_args(const smartlist_t *socks_args)
Definition: transports.c:1756
or_options_t::Socks4ProxyAddr
tor_addr_t Socks4ProxyAddr
Definition: or_options_st.h:451
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:445
or_options_t::OutboundBindAddresses
tor_addr_t OutboundBindAddresses[OUTBOUND_ADDR_MAX][2]
Definition: or_options_st.h:157
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:1912
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:650
or_options_t::Socks4ProxyPort
uint16_t Socks4ProxyPort
Definition: or_options_st.h:452
or_options_t::HTTPSProxy
char * HTTPSProxy
Definition: or_options_st.h:445
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:446
or_options_t::Socks5ProxyAddr
tor_addr_t Socks5ProxyAddr
Definition: or_options_st.h:455
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:472
configure_proxy
STATIC int configure_proxy(managed_proxy_t *mp)
Definition: transports.c:646
parse_log_line
STATIC void parse_log_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1180
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:215
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:515
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:550
tor_addr_to_str_dup
char * tor_addr_to_str_dup(const tor_addr_t *addr)
Definition: address.c:1164
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:1792
get_stored_bindaddr_for_server_transport
char * get_stored_bindaddr_for_server_transport(const char *transport)
Definition: statefile.c:689
pt_free_all
void pt_free_all(void)
Definition: transports.c:1824
transports.h
Headers for transports.c.
tor_addr_parse
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1349
ext_orport.h
Header for ext_orport.c.
or_options_t::ExtORPort_lines
struct config_line_t * ExtORPort_lines
Definition: or_options_st.h:166
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:919
save_transport_to_state
void save_transport_to_state(const char *transport, const tor_addr_t *addr, uint16_t port)
Definition: statefile.c:722
circuitbuild.h
Header file for circuitbuild.c.
fmt_addrport
const char * fmt_addrport(const tor_addr_t *addr, uint16_t port)
Definition: address.c:1199
free_execve_args
STATIC void free_execve_args(char **arg)
Definition: transports.c:1602
get_pt_proxy_uri
STATIC char * get_pt_proxy_uri(void)
Definition: transports.c:756
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:1156
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:1520
pt_configure_remaining_proxies
void pt_configure_remaining_proxies(void)
Definition: transports.c:589
managed_proxy_stdout_callback
STATIC void managed_proxy_stdout_callback(process_t *process, const char *line, size_t size)
Definition: transports.c:1888
register_proxy
static void register_proxy(const managed_proxy_t *mp)
Definition: transports.c:708
tor_addr_is_null
int tor_addr_is_null(const tor_addr_t *addr)
Definition: address.c:780
or_options_t::HTTPSProxyPort
uint16_t HTTPSProxyPort
Definition: or_options_st.h:447
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:1369
managed_proxy_destroy
STATIC void managed_proxy_destroy(managed_proxy_t *mp, int also_terminate_process)
Definition: transports.c:718
LOG_WARN
#define LOG_WARN
Definition: log.h:53
assert_unconfigured_count_ok
static void assert_unconfigured_count_ok(void)
Definition: transports.c:404
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:1915
managed_proxy_outbound_address
STATIC const tor_addr_t * managed_proxy_outbound_address(const or_options_t *options, sa_family_t family)
Definition: transports.c:1980
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:461
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
OUTBOUND_ADDR_ANY
@ OUTBOUND_ADDR_ANY
Definition: or_options_st.h:45
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:590
OUTBOUND_ADDR_PT
@ OUTBOUND_ADDR_PT
Definition: or_options_st.h:39
sa_family_t
uint16_t sa_family_t
Definition: inaddr_st.h:77
get_first_listener_addrport_string
char * get_first_listener_addrport_string(int listener_type)
Definition: config.c:6612
or_options_t
Definition: or_options_st.h:64
or_options_t::Socks4Proxy
char * Socks4Proxy
Definition: or_options_st.h:450
parse_smethod_line
STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1146
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:970
STATIC
#define STATIC
Definition: testsupport.h:32
proxy_configuration_finished
static int proxy_configuration_finished(const managed_proxy_t *mp)
Definition: transports.c:832
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:458
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:1029
tor_addr_port_split
int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out)
Definition: address.c:1916
tor_addr_eq
#define tor_addr_eq(a, b)
Definition: address.h:280
get_bindaddr_for_server_proxy
static char * get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
Definition: transports.c:1342
mark_my_descriptor_dirty
void mark_my_descriptor_dirty(const char *reason)
Definition: router.c:2569
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:933
managed_proxy_exit_callback
STATIC bool managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
Definition: transports.c:1936
pt_get_extra_info_descriptor_string
char * pt_get_extra_info_descriptor_string(void)
Definition: transports.c:1680
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:1246