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