Tor  0.4.3.1-alpha-dev
transports.c
Go to the documentation of this file.
1 /* Copyright (c) 2011-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * \file transports.c
6  * \brief Pluggable Transports related code.
7  *
8  * \details
9  * Each managed proxy is represented by a <b>managed_proxy_t</b>.
10  * Each managed proxy can support multiple transports.
11  * Each managed proxy gets configured through a multistep process.
12  *
13  * ::managed_proxy_list contains all the managed proxies this tor
14  * instance is supporting.
15  * In the ::managed_proxy_list there are ::unconfigured_proxies_n
16  * managed proxies that are still unconfigured.
17  *
18  * In every run_scheduled_event() tick, we attempt to launch and then
19  * configure the unconfiged managed proxies, using the configuration
20  * protocol defined in the 180_pluggable_transport.txt proposal. A
21  * managed proxy might need several ticks to get fully configured.
22  *
23  * When a managed proxy is fully configured, we register all its
24  * transports to the circuitbuild.c subsystem. At that point the
25  * transports are owned by the circuitbuild.c subsystem.
26  *
27  * When a managed proxy fails to follow the 180 configuration
28  * protocol, it gets marked as broken and gets destroyed.
29  *
30  * <b>In a little more detail:</b>
31  *
32  * While we are serially parsing torrc, we store all the transports
33  * that a proxy should spawn in its <em>transports_to_launch</em>
34  * element.
35  *
36  * When we finish reading the torrc, we spawn the managed proxy and
37  * expect {S,C}METHOD lines from its output. We add transports
38  * described by METHOD lines to its <em>transports</em> element, as
39  * transport_t structs.
40  *
41  * When the managed proxy stops spitting METHOD lines (signified by a
42  * '{S,C}METHODS DONE' message) we pass copies of its transports to
43  * the bridge subsystem. We keep copies of the 'transport_t's on the
44  * managed proxy to be able to associate the proxy with its
45  * transports, and we pass copies to the bridge subsystem so that
46  * transports can be associated with bridges.
47  * [ XXX We should try see whether the two copies are really needed
48  * and maybe cut it into a single copy of the 'transport_t' shared
49  * between the managed proxy and the bridge subsystem. Preliminary
50  * analysis shows that both copies are needed with the current code
51  * logic, because of race conditions that can cause dangling
52  * pointers. ]
53  *
54  * <b>In even more detail, this is what happens when a config read
55  * (like a SIGHUP or a SETCONF) occurs:</b>
56  *
57  * We immediately destroy all unconfigured proxies (We shouldn't have
58  * unconfigured proxies in the first place, except when the config
59  * read happens immediately after tor is launched.).
60  *
61  * We mark all managed proxies and transports to signify that they
62  * must be removed if they don't contribute by the new torrc
63  * (we mark using the <b>marked_for_removal</b> element).
64  * We also mark all managed proxies to signify that they might need to
65  * be restarted so that they end up supporting all the transports the
66  * new torrc wants them to support
67  * (we mark using the <b>was_around_before_config_read</b> element).
68  * We also clear their <b>transports_to_launch</b> list so that we can
69  * put there the transports we need to launch according to the new
70  * torrc.
71  *
72  * We then start parsing torrc again.
73  *
74  * Everytime we encounter a transport line using a managed proxy that
75  * was around before the config read, we cleanse that proxy from the
76  * removal mark. We also toggle the <b>check_if_restarts_needed</b>
77  * flag, so that on the next <b>pt_configure_remaining_proxies</b>
78  * tick, we investigate whether we need to restart the proxy so that
79  * it also spawns the new transports. If the post-config-read
80  * <b>transports_to_launch</b> list is identical to the pre-config-read
81  * one, it means that no changes were introduced to this proxy during
82  * the config read and no restart has to take place.
83  *
84  * During the post-config-read torrc parsing, we unmark all transports
85  * spawned by managed proxies that we find in our torrc.
86  * We do that so that if we don't need to restart a managed proxy, we
87  * can continue using its old transports normally.
88  * If we end up restarting the proxy, we destroy and unregister all
89  * old transports from the circuitbuild.c subsystem.
90  **/
91 
92 #define PT_PRIVATE
93 #include "core/or/or.h"
94 #include "feature/client/bridges.h"
95 #include "app/config/config.h"
97 #include "core/or/circuitbuild.h"
99 #include "feature/relay/router.h"
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  /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
739  * there isn't a standard URI scheme for some proxy protocols, such as
740  * haproxy. */
741  if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
742  char addr[TOR_ADDR_BUF_LEN+1];
743 
744  if (options->Socks4Proxy) {
745  tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
746  tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
747  } else if (options->Socks5Proxy) {
748  tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
749  if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
750  tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
751  } else {
752  tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
753  options->Socks5ProxyUsername,
754  options->Socks5ProxyPassword,
755  addr, options->Socks5ProxyPort);
756  }
757  } else if (options->HTTPSProxy) {
758  tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
759  if (!options->HTTPSProxyAuthenticator) {
760  tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
761  } else {
762  tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
763  addr, options->HTTPSProxyPort);
764  }
765  }
766  }
767 
768  return uri;
769 }
770 
771 /** Handle a configured or broken managed proxy <b>mp</b>. */
772 static void
773 handle_finished_proxy(managed_proxy_t *mp)
774 {
775  switch (mp->conf_state) {
776  case PT_PROTO_BROKEN: /* if broken: */
777  managed_proxy_destroy(mp, 1); /* annihilate it. */
778  break;
779  case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
780  managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
781  break;
782  case PT_PROTO_CONFIGURED: /* if configured correctly: */
783  if (mp->proxy_uri && !mp->proxy_supported) {
784  log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
785  "specified outgoing proxy and will be terminated.",
786  mp->argv[0]);
787  managed_proxy_destroy(mp, 1); /* annihilate it. */
788  break;
789  }
790  register_proxy(mp); /* register its transports */
791  mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
792  break;
793  case PT_PROTO_INFANT:
794  case PT_PROTO_LAUNCHED:
795  case PT_PROTO_ACCEPTING_METHODS:
796  case PT_PROTO_COMPLETED:
797  default:
798  log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
799  (int)mp->conf_state, mp->argv[0]);
800  tor_assert(0);
801  }
802 
804 }
805 
806 /** Return true if the configuration of the managed proxy <b>mp</b> is
807  finished. */
808 static inline int
809 proxy_configuration_finished(const managed_proxy_t *mp)
810 {
811  return (mp->conf_state == PT_PROTO_CONFIGURED ||
812  mp->conf_state == PT_PROTO_BROKEN ||
813  mp->conf_state == PT_PROTO_FAILED_LAUNCH);
814 }
815 
816 /** This function is called when a proxy sends an {S,C}METHODS DONE message. */
817 static void
818 handle_methods_done(const managed_proxy_t *mp)
819 {
820  tor_assert(mp->transports);
821 
822  if (smartlist_len(mp->transports) == 0)
823  log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
824  "but it didn't launch any pluggable transport listeners!",
825  mp->argv[0]);
826 
827  log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
828  mp->is_server ? "Server" : "Client",
829  mp->argv[0]);
830 }
831 
832 /** Handle a configuration protocol <b>line</b> received from a
833  * managed proxy <b>mp</b>. */
834 STATIC void
835 handle_proxy_line(const char *line, managed_proxy_t *mp)
836 {
837  log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
838  mp->argv[0], line);
839 
840  if (!strcmpstart(line, PROTO_ENV_ERROR)) {
841  if (mp->conf_state != PT_PROTO_LAUNCHED)
842  goto err;
843 
844  parse_env_error(line);
845  goto err;
846  } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
847  if (mp->conf_state != PT_PROTO_LAUNCHED)
848  goto err;
849 
850  log_warn(LD_CONFIG, "Managed proxy could not pick a "
851  "configuration protocol version.");
852  goto err;
853  } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
854  if (mp->conf_state != PT_PROTO_LAUNCHED)
855  goto err;
856 
857  if (parse_version(line,mp) < 0)
858  goto err;
859 
860  tor_assert(mp->conf_protocol != 0);
861  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
862  return;
863  } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
864  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
865  goto err;
866 
868 
869  mp->conf_state = PT_PROTO_CONFIGURED;
870  return;
871  } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
872  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
873  goto err;
874 
876 
877  mp->conf_state = PT_PROTO_CONFIGURED;
878  return;
879  } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
880  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
881  goto err;
882 
883  parse_client_method_error(line);
884  goto err;
885  } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
886  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
887  goto err;
888 
889  parse_server_method_error(line);
890  goto err;
891  } else if (!strcmpstart(line, PROTO_CMETHOD)) {
892  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
893  goto err;
894 
895  if (parse_cmethod_line(line, mp) < 0)
896  goto err;
897 
898  return;
899  } else if (!strcmpstart(line, PROTO_SMETHOD)) {
900  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
901  goto err;
902 
903  if (parse_smethod_line(line, mp) < 0)
904  goto err;
905 
906  return;
907  } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
908  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
909  goto err;
910 
911  if (mp->proxy_uri) {
912  mp->proxy_supported = 1;
913  return;
914  }
915 
916  /* No proxy was configured, this should log */
917  } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
918  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
919  goto err;
920 
921  parse_proxy_error(line);
922  goto err;
923 
924  /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
925  * string to make sure we can later extend this big if/else-if table with
926  * something that begins with "LOG" without having to get the order right.
927  * */
928  } else if (!strcmpstart(line, PROTO_LOG " ")) {
929  parse_log_line(line, mp);
930  return;
931  } else if (!strcmpstart(line, PROTO_STATUS " ")) {
932  parse_status_line(line, mp);
933  return;
934  }
935 
936  log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
937  return;
938 
939  err:
940  mp->conf_state = PT_PROTO_BROKEN;
941  log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
942  " and will be destroyed.", mp->argv[0]);
943 }
944 
945 /** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
946 STATIC void
947 parse_env_error(const char *line)
948 {
949  /* (Length of the protocol string) plus (a space) and (the first char of
950  the error message) */
951  if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
952  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
953  "message.", PROTO_ENV_ERROR);
954 
955  log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
956  "pluggable transport environment variables. (%s)",
957  line+strlen(PROTO_ENV_ERROR)+1);
958 }
959 
960 /** Handles a VERSION <b>line</b>. Updates the configuration protocol
961  * version in <b>mp</b>. */
962 STATIC int
963 parse_version(const char *line, managed_proxy_t *mp)
964 {
965  if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
966  log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
967  PROTO_NEG_SUCCESS);
968  return -1;
969  }
970 
971  if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
972  log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
973  "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
974  return -1;
975  }
976 
977  mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
978  return 0;
979 }
980 
981 /** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
982  * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
983  * otherwise it is a CMETHOD-ERROR. */
984 static void
985 parse_method_error(const char *line, int is_server)
986 {
987  const char* error = is_server ?
988  PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
989 
990  /* (Length of the protocol string) plus (a space) and (the first char of
991  the error message) */
992  if (strlen(line) < (strlen(error) + 2))
993  log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
994  "message.", error);
995 
996  log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
997  is_server ? "Server" : "Client",
998  line+strlen(error)+1);
999 }
1000 
1001 /** A helper for parse_{c,s}method_line(), bootstraps its
1002  * functionalities. If <b>is_smethod</b> is true then the
1003  * the line to parse is a SMETHOD line otherwise it is a
1004  * CMETHOD line*/
1005 static int
1006 parse_method_line_helper(const char *line,
1007  managed_proxy_t *mp,
1008  int is_smethod)
1009 {
1010  int item_index = 0;
1011  int r;
1012 
1013  char *transport_name=NULL;
1014  char *args_string=NULL;
1015  char *addrport=NULL;
1016  int socks_ver=PROXY_NONE;
1017  char *address=NULL;
1018  uint16_t port = 0;
1019 
1020  const char *method_str = is_smethod ? PROTO_SMETHOD : PROTO_CMETHOD;
1021  const int min_args_count = is_smethod ? 3 : 4;
1022 
1023  tor_addr_t tor_addr;
1024  transport_t *transport=NULL;
1025  smartlist_t *items= smartlist_new();
1026 
1027  smartlist_split_string(items, line, NULL,
1028  SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1029  if (smartlist_len(items) < min_args_count) {
1030  log_warn(LD_CONFIG, "Managed proxy sent us a %s line "
1031  "with too few arguments.", method_str);
1032  goto err;
1033  }
1034 
1035  tor_assert(!strcmp(smartlist_get(items, item_index),method_str));
1036  ++item_index;
1037 
1038  transport_name = smartlist_get(items,item_index);
1039  ++item_index;
1040  if (!string_is_C_identifier(transport_name)) {
1041  log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
1042  transport_name);
1043  goto err;
1044  }
1045 
1046  /** Check for the proxy method sent to us in CMETHOD line. */
1047  if (!is_smethod) {
1048  const char *socks_ver_str = smartlist_get(items,item_index);
1049  ++item_index;
1050 
1051  if (!strcmp(socks_ver_str,"socks4")) {
1052  socks_ver = PROXY_SOCKS4;
1053  } else if (!strcmp(socks_ver_str,"socks5")) {
1054  socks_ver = PROXY_SOCKS5;
1055  } else {
1056  log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
1057  "we don't recognize. (%s)", socks_ver_str);
1058  goto err;
1059  }
1060  }
1061 
1062  addrport = smartlist_get(items, item_index);
1063  ++item_index;
1064  if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) {
1065  log_warn(LD_CONFIG, "Error parsing transport address '%s'", addrport);
1066  goto err;
1067  }
1068 
1069  if (!port) {
1070  log_warn(LD_CONFIG,
1071  "Transport address '%s' has no port.", addrport);
1072  goto err;
1073  }
1074 
1075  if (tor_addr_parse(&tor_addr, address) < 0) {
1076  log_warn(LD_CONFIG, "Error parsing transport address '%s'", address);
1077  goto err;
1078  }
1079 
1080  /** Check for options in the SMETHOD line. */
1081  if (is_smethod && smartlist_len(items) > min_args_count) {
1082  /* Seems like there are also some [options] in the SMETHOD line.
1083  Let's see if we can parse them. */
1084  char *options_string = smartlist_get(items, item_index);
1085  log_debug(LD_CONFIG, "Got options_string: %s", options_string);
1086  if (!strcmpstart(options_string, "ARGS:")) {
1087  args_string = options_string+strlen("ARGS:");
1088  log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
1089  }
1090  }
1091 
1092  transport = transport_new(&tor_addr, port, transport_name,
1093  socks_ver, args_string);
1094 
1095  smartlist_add(mp->transports, transport);
1096 
1097  /** Logs info about line parsing success for client or server */
1098  if (is_smethod) {
1099  log_info(LD_CONFIG, "Server transport %s at %s:%d.",
1100  transport_name, address, (int)port);
1101  } else {
1102  log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
1103  "Attached to managed proxy.",
1104  transport_name, address, (int)port, socks_ver);
1105  }
1106 
1107  r=0;
1108  goto done;
1109 
1110  err:
1111  r = -1;
1112 
1113  done:
1114  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
1115  smartlist_free(items);
1116  tor_free(address);
1117  return r;
1118 }
1119 
1120 /** Parses an SMETHOD <b>line</b> and if well-formed it registers the
1121  * new transport in <b>mp</b>. */
1122 STATIC int
1123 parse_smethod_line(const char *line, managed_proxy_t *mp)
1124 {
1125  /* Example of legit SMETHOD line:
1126  SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
1127  return parse_method_line_helper(line, mp, 1);
1128 }
1129 
1130 /** Parses a CMETHOD <b>line</b>, and if well-formed it registers
1131  * the new transport in <b>mp</b>. */
1132 STATIC int
1133 parse_cmethod_line(const char *line, managed_proxy_t *mp)
1134 {
1135  /* Example of legit CMETHOD line:
1136  CMETHOD obfs2 socks5 127.0.0.1:35713 */
1137  return parse_method_line_helper(line, mp, 0);
1138 }
1139 
1140 /** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
1141 STATIC void
1142 parse_proxy_error(const char *line)
1143 {
1144  /* (Length of the protocol string) plus (a space) and (the first char of
1145  the error message) */
1146  if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
1147  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
1148  "message.", PROTO_PROXY_ERROR);
1149 
1150  log_warn(LD_CONFIG, "Managed proxy failed to configure the "
1151  "pluggable transport's outgoing proxy. (%s)",
1152  line+strlen(PROTO_PROXY_ERROR)+1);
1153 }
1154 
1155 /** Parses a LOG <b>line</b> and emit log events accordingly. */
1156 STATIC void
1157 parse_log_line(const char *line, managed_proxy_t *mp)
1158 {
1159  tor_assert(line);
1160  tor_assert(mp);
1161 
1162  config_line_t *values = NULL;
1163  char *log_message = NULL;
1164 
1165  if (strlen(line) < (strlen(PROTO_LOG) + 1)) {
1166  log_warn(LD_PT, "Managed proxy sent us a %s line "
1167  "with missing argument.", PROTO_LOG);
1168  goto done;
1169  }
1170 
1171  const char *data = line + strlen(PROTO_LOG) + 1;
1172  values = kvline_parse(data, KV_QUOTED);
1173 
1174  if (! values) {
1175  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid LOG message: %s",
1176  mp->argv[0], data);
1177  goto done;
1178  }
1179 
1180  const config_line_t *severity = config_line_find(values, "SEVERITY");
1181  const config_line_t *message = config_line_find(values, "MESSAGE");
1182 
1183  /* Check if we got a message. */
1184  if (! message) {
1185  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1186  "MESSAGE: %s", mp->argv[0], escaped(data));
1187  goto done;
1188  }
1189 
1190  /* Check if severity is there and whether it's valid. */
1191  if (! severity) {
1192  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1193  "SEVERITY: %s", mp->argv[0], escaped(data));
1194  goto done;
1195  }
1196 
1197  int log_severity = managed_proxy_severity_parse(severity->value);
1198 
1199  if (log_severity == -1) {
1200  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line with an "
1201  "invalid severity level: %s",
1202  mp->argv[0], severity->value);
1203  goto done;
1204  }
1205 
1206  tor_log(log_severity, LD_PT, "Managed proxy \"%s\": %s",
1207  mp->argv[0], message->value);
1208 
1209  /* Prepend the PT name. */
1210  config_line_prepend(&values, "PT", mp->argv[0]);
1211  log_message = kvline_encode(values, KV_QUOTED);
1212 
1213  /* Emit control port event. */
1214  control_event_pt_log(log_message);
1215 
1216  done:
1217  config_free_lines(values);
1218  tor_free(log_message);
1219 }
1220 
1221 /** Parses a STATUS <b>line</b> and emit control events accordingly. */
1222 STATIC void
1223 parse_status_line(const char *line, managed_proxy_t *mp)
1224 {
1225  tor_assert(line);
1226  tor_assert(mp);
1227 
1228  config_line_t *values = NULL;
1229  char *status_message = NULL;
1230 
1231  if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
1232  log_warn(LD_PT, "Managed proxy sent us a %s line "
1233  "with missing argument.", PROTO_STATUS);
1234  goto done;
1235  }
1236 
1237  const char *data = line + strlen(PROTO_STATUS) + 1;
1238 
1239  values = kvline_parse(data, KV_QUOTED);
1240 
1241  if (! values) {
1242  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
1243  "STATUS message: %s", mp->argv[0], escaped(data));
1244  goto done;
1245  }
1246 
1247  /* We check if we received the TRANSPORT parameter, which is the only
1248  * *required* value. */
1249  const config_line_t *type = config_line_find(values, "TRANSPORT");
1250 
1251  if (! type) {
1252  log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
1253  "TRANSPORT: %s", mp->argv[0], escaped(data));
1254  goto done;
1255  }
1256 
1257  /* Prepend the PT name. */
1258  config_line_prepend(&values, "PT", mp->argv[0]);
1259  status_message = kvline_encode(values, KV_QUOTED);
1260 
1261  /* We have checked that TRANSPORT is there, we can now emit the STATUS event
1262  * via the control port. */
1263  control_event_pt_status(status_message);
1264 
1265  done:
1266  config_free_lines(values);
1267  tor_free(status_message);
1268 }
1269 
1270 /** Return a newly allocated string that tor should place in
1271  * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
1272  * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
1273 STATIC char *
1274 get_transport_options_for_server_proxy(const managed_proxy_t *mp)
1275 {
1276  char *options_string = NULL;
1277  smartlist_t *string_sl = smartlist_new();
1278 
1279  tor_assert(mp->is_server);
1280 
1281  /** Loop over the transports of the proxy. If we have options for
1282  any of them, format them appropriately and place them in our
1283  smartlist. Finally, join our smartlist to get the final
1284  string. */
1285  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
1286  smartlist_t *options_tmp_sl = NULL;
1287  options_tmp_sl = pt_get_options_for_server_transport(transport);
1288  if (!options_tmp_sl)
1289  continue;
1290 
1291  /** Loop over the options of this transport, escape them, and
1292  place them in the smartlist. */
1293  SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
1294  char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
1295  smartlist_add_asprintf(string_sl, "%s:%s",
1296  transport, escaped_opts);
1297  tor_free(escaped_opts);
1298  } SMARTLIST_FOREACH_END(options);
1299 
1300  SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
1301  smartlist_free(options_tmp_sl);
1302  } SMARTLIST_FOREACH_END(transport);
1303 
1304  if (smartlist_len(string_sl)) {
1305  options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
1306  }
1307 
1308  SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
1309  smartlist_free(string_sl);
1310 
1311  return options_string;
1312 }
1313 
1314 /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
1315  * while configuring the server managed proxy in <b>mp</b>. The
1316  * string is stored in the heap, and it's the responsibility of
1317  * the caller to deallocate it after its use. */
1318 static char *
1319 get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
1320 {
1321  char *bindaddr_result = NULL;
1322  char *bindaddr_tmp = NULL;
1323  smartlist_t *string_tmp = smartlist_new();
1324 
1325  tor_assert(mp->is_server);
1326 
1327  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
1328  bindaddr_tmp = get_stored_bindaddr_for_server_transport(t);
1329 
1330  smartlist_add_asprintf(string_tmp, "%s-%s", t, bindaddr_tmp);
1331 
1332  tor_free(bindaddr_tmp);
1333  } SMARTLIST_FOREACH_END(t);
1334 
1335  bindaddr_result = smartlist_join_strings(string_tmp, ",", 0, NULL);
1336 
1337  SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
1338  smartlist_free(string_tmp);
1339 
1340  return bindaddr_result;
1341 }
1342 
1343 /** Return a newly allocated process_environment_t * for <b>mp</b>'s
1344  * process. */
1345 static smartlist_t *
1346 create_managed_proxy_environment(const managed_proxy_t *mp)
1347 {
1348  const or_options_t *options = get_options();
1349 
1350  /* Environment variables to be added to or set in mp's environment. */
1351  smartlist_t *envs = smartlist_new();
1352  /* XXXX The next time someone touches this code, shorten the name of
1353  * set_environment_variable_in_smartlist, add a
1354  * set_env_var_in_smartlist_asprintf function, and get rid of the
1355  * silly extra envs smartlist. */
1356 
1357  /* The final environment to be passed to mp. */
1359 
1360  {
1361  char *state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
1362  smartlist_add_asprintf(envs, "TOR_PT_STATE_LOCATION=%s", state_tmp);
1363  tor_free(state_tmp);
1364  }
1365 
1366  smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
1367 
1368  {
1369  char *transports_to_launch =
1370  smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
1371 
1373  mp->is_server ?
1374  "TOR_PT_SERVER_TRANSPORTS=%s" :
1375  "TOR_PT_CLIENT_TRANSPORTS=%s",
1376  transports_to_launch);
1377 
1378  tor_free(transports_to_launch);
1379  }
1380 
1381  if (mp->is_server) {
1382  {
1383  char *orport_tmp =
1385  if (orport_tmp) {
1386  smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
1387  tor_free(orport_tmp);
1388  }
1389  }
1390 
1391  {
1392  char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
1393  smartlist_add_asprintf(envs, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
1394  tor_free(bindaddr_tmp);
1395  }
1396 
1397  {
1398  char *server_transport_options =
1400  if (server_transport_options) {
1401  smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1402  server_transport_options);
1403  tor_free(server_transport_options);
1404  }
1405  }
1406 
1407  /* XXXX Remove the '=' here once versions of obfsproxy which
1408  * assert that this env var exists are sufficiently dead.
1409  *
1410  * (If we remove this line entirely, some joker will stick this
1411  * variable in Tor's environment and crash PTs that try to parse
1412  * it even when not run in server mode.) */
1413 
1414  if (options->ExtORPort_lines) {
1415  char *ext_or_addrport_tmp =
1417  char *cookie_file_loc = get_ext_or_auth_cookie_file_name();
1418 
1419  if (ext_or_addrport_tmp) {
1420  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1421  ext_or_addrport_tmp);
1422  }
1423  smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s",
1424  cookie_file_loc);
1425 
1426  tor_free(ext_or_addrport_tmp);
1427  tor_free(cookie_file_loc);
1428 
1429  } else {
1430  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
1431  }
1432  } else {
1433  /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
1434  * TOR_PT_PROXY line.
1435  */
1436 
1437  if (mp->proxy_uri) {
1438  smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
1439  }
1440  }
1441 
1442  /* All new versions of tor will keep stdin open, so PTs can use it
1443  * as a reliable termination detection mechanism.
1444  */
1445  smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
1446 
1447  SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
1448  set_environment_variable_in_smartlist(merged_env_vars, env_var,
1449  tor_free_, 1);
1450  } SMARTLIST_FOREACH_END(env_var);
1451 
1452  smartlist_free(envs);
1453 
1454  return merged_env_vars;
1455 }
1456 
1457 /** Create and return a new managed proxy for <b>transport</b> using
1458  * <b>proxy_argv</b>. Also, add it to the global managed proxy list. If
1459  * <b>is_server</b> is true, it's a server managed proxy. Takes ownership of
1460  * <b>proxy_argv</b>.
1461  *
1462  * Requires that proxy_argv have at least one element. */
1463 STATIC managed_proxy_t *
1464 managed_proxy_create(const smartlist_t *with_transport_list,
1465  char **proxy_argv, int is_server)
1466 {
1467  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
1468  mp->conf_state = PT_PROTO_INFANT;
1469  mp->is_server = is_server;
1470  mp->argv = proxy_argv;
1471  mp->transports = smartlist_new();
1472  mp->proxy_uri = get_pt_proxy_uri();
1473  mp->process = process_new(proxy_argv[0]);
1474 
1475  mp->transports_to_launch = smartlist_new();
1476  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1477  add_transport_to_proxy(transport, mp));
1478 
1479  /* register the managed proxy */
1480  if (!managed_proxy_list)
1484 
1486 
1487  return mp;
1488 }
1489 
1490 /** Register proxy with <b>proxy_argv</b>, supporting transports in
1491  * <b>transport_list</b>, to the managed proxy subsystem.
1492  * If <b>is_server</b> is true, then the proxy is a server proxy.
1493  *
1494  * Takes ownership of proxy_argv.
1495  *
1496  * Requires that proxy_argv be a NULL-terminated array of command-line
1497  * elements, containing at least one element.
1498  **/
1499 MOCK_IMPL(void,
1500 pt_kickstart_proxy, (const smartlist_t *with_transport_list,
1501  char **proxy_argv, int is_server))
1502 {
1503  managed_proxy_t *mp=NULL;
1504  transport_t *old_transport = NULL;
1505 
1506  if (!proxy_argv || !proxy_argv[0]) {
1507  return;
1508  }
1509 
1510  mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
1511 
1512  if (!mp) { /* we haven't seen this proxy before */
1513  managed_proxy_create(with_transport_list, proxy_argv, is_server);
1514 
1515  } else { /* known proxy. add its transport to its transport list */
1516  if (mp->was_around_before_config_read) {
1517  /* If this managed proxy was around even before we read the
1518  config this time, it means that it was already enabled before
1519  and is not useless and should be kept. If it's marked for
1520  removal, unmark it and make sure that we check whether it
1521  needs to be restarted. */
1522  if (mp->marked_for_removal) {
1523  mp->marked_for_removal = 0;
1525  }
1526 
1527  /* For each new transport, check if the managed proxy used to
1528  support it before the SIGHUP. If that was the case, make sure
1529  it doesn't get removed because we might reuse it. */
1530  SMARTLIST_FOREACH_BEGIN(with_transport_list, const char *, transport) {
1531  old_transport = transport_get_by_name(transport);
1532  if (old_transport)
1533  old_transport->marked_for_removal = 0;
1534  } SMARTLIST_FOREACH_END(transport);
1535  }
1536 
1537  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1538  add_transport_to_proxy(transport, mp));
1539  free_execve_args(proxy_argv);
1540  }
1541 }
1542 
1543 /** Frees the array of pointers in <b>arg</b> used as arguments to
1544  execve(2). */
1545 STATIC void
1546 free_execve_args(char **arg)
1547 {
1548  char **tmp = arg;
1549  while (*tmp) /* use the fact that the last element of the array is a
1550  NULL pointer to know when to stop freeing */
1551  tor_free_(*tmp++);
1552 
1553  tor_free(arg);
1554 }
1555 
1556 /** Tor will read its config.
1557  * Prepare the managed proxy list so that proxies not used in the new
1558  * config will shutdown, and proxies that need to spawn different
1559  * transports will do so. */
1560 void
1562 {
1563  if (!managed_proxy_list)
1564  return;
1565 
1567  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1568  /* Destroy unconfigured proxies. */
1569  if (mp->conf_state != PT_PROTO_COMPLETED) {
1571  managed_proxy_destroy(mp, 1);
1573  continue;
1574  }
1575 
1576  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1577 
1578  /* Mark all proxies for removal, and also note that they have been
1579  here before the config read. */
1580  mp->marked_for_removal = 1;
1581  mp->was_around_before_config_read = 1;
1582  SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
1583  smartlist_clear(mp->transports_to_launch);
1584  } SMARTLIST_FOREACH_END(mp);
1585 
1587 
1589 }
1590 
1591 /** Return a smartlist containing the ports where our pluggable
1592  * transports are listening. */
1593 smartlist_t *
1595 {
1596  smartlist_t *sl = NULL;
1597 
1598  if (!managed_proxy_list)
1599  return NULL;
1600 
1601  /** XXX assume that external proxy ports have been forwarded
1602  manually */
1603  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1604  if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED)
1605  continue;
1606 
1607  if (!sl) sl = smartlist_new();
1608 
1609  tor_assert(mp->transports);
1610  SMARTLIST_FOREACH(mp->transports, const transport_t *, t,
1611  smartlist_add_asprintf(sl, "%u:%u", t->port, t->port));
1612 
1613  } SMARTLIST_FOREACH_END(mp);
1614 
1615  return sl;
1616 }
1617 
1618 /** Return the pluggable transport string that we should display in
1619  * our extra-info descriptor. If we shouldn't display such a string,
1620  * or we have nothing to display, return NULL. The string is
1621  * allocated on the heap and it's the responsibility of the caller to
1622  * free it. */
1623 char *
1625 {
1626  char *the_string = NULL;
1627  smartlist_t *string_chunks = NULL;
1628 
1629  if (!managed_proxy_list)
1630  return NULL;
1631 
1632  string_chunks = smartlist_new();
1633 
1634  /* For each managed proxy, add its transports to the chunks list. */
1635  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1636  if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
1637  continue;
1638 
1639  tor_assert(mp->transports);
1640 
1641  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1642  char *transport_args = NULL;
1643 
1644  /* If the transport proxy returned "0.0.0.0" as its address, and
1645  * we know our external IP address, use it. Otherwise, use the
1646  * returned address. */
1647  const char *addrport = NULL;
1648  uint32_t external_ip_address = 0;
1649  if (tor_addr_is_null(&t->addr) &&
1651  &external_ip_address, 0) >= 0) {
1652  tor_addr_t addr;
1653  tor_addr_from_ipv4h(&addr, external_ip_address);
1654  addrport = fmt_addrport(&addr, t->port);
1655  } else {
1656  addrport = fmt_addrport(&t->addr, t->port);
1657  }
1658 
1659  /* If this transport has any arguments with it, prepend a space
1660  to them so that we can add them to the transport line. */
1661  if (t->extra_info_args)
1662  tor_asprintf(&transport_args, " %s", t->extra_info_args);
1663 
1664  smartlist_add_asprintf(string_chunks,
1665  "transport %s %s%s",
1666  t->name, addrport,
1667  transport_args ? transport_args : "");
1668  tor_free(transport_args);
1669  } SMARTLIST_FOREACH_END(t);
1670 
1671  } SMARTLIST_FOREACH_END(mp);
1672 
1673  if (smartlist_len(string_chunks) == 0) {
1674  smartlist_free(string_chunks);
1675  return NULL;
1676  }
1677 
1678  /* Join all the chunks into the final string. */
1679  the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1680 
1681  SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1682  smartlist_free(string_chunks);
1683 
1684  return the_string;
1685 }
1686 
1687 /** Stringify the SOCKS arguments in <b>socks_args</b> according to
1688  * 180_pluggable_transport.txt. The string is allocated on the heap
1689  * and it's the responsibility of the caller to free it after use. */
1690 char *
1692 {
1693  /* tmp place to store escaped socks arguments, so that we can
1694  concatenate them up afterwards */
1695  smartlist_t *sl_tmp = NULL;
1696  char *escaped_string = NULL;
1697  char *new_string = NULL;
1698 
1699  tor_assert(socks_args);
1700  tor_assert(smartlist_len(socks_args) > 0);
1701 
1702  sl_tmp = smartlist_new();
1703 
1704  SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
1705  /* Escape ';' and '\'. */
1706  escaped_string = tor_escape_str_for_pt_args(s, ";\\");
1707  if (!escaped_string)
1708  goto done;
1709 
1710  smartlist_add(sl_tmp, escaped_string);
1711  } SMARTLIST_FOREACH_END(s);
1712 
1713  new_string = smartlist_join_strings(sl_tmp, ";", 0, NULL);
1714 
1715  done:
1716  SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
1717  smartlist_free(sl_tmp);
1718 
1719  return new_string;
1720 }
1721 
1722 /** Return a string of the SOCKS arguments that we should pass to the
1723  * pluggable transports proxy in <b>addr</b>:<b>port</b> according to
1724  * 180_pluggable_transport.txt. The string is allocated on the heap
1725  * and it's the responsibility of the caller to free it after use. */
1726 char *
1728 {
1729  const smartlist_t *socks_args = NULL;
1730 
1731  socks_args = get_socks_args_by_bridge_addrport(addr, port);
1732  if (!socks_args)
1733  return NULL;
1734 
1735  return pt_stringify_socks_args(socks_args);
1736 }
1737 
1738 /** The tor config was read.
1739  * Destroy all managed proxies that were marked by a previous call to
1740  * prepare_proxy_list_for_config_read() and are not used by the new
1741  * config. */
1742 void
1744 {
1745  if (!managed_proxy_list)
1746  return;
1748  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1749  if (mp->marked_for_removal) {
1751  managed_proxy_destroy(mp, 1);
1752  }
1753  } SMARTLIST_FOREACH_END(mp);
1755 }
1756 
1757 /** Release all storage held by the pluggable transports subsystem. */
1758 void
1760 {
1761  if (transport_list) {
1763  smartlist_free(transport_list);
1764  transport_list = NULL;
1765  }
1766 
1767  if (managed_proxy_list) {
1768  /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1769  transports and it's the duty of the circuitbuild.c subsystem to
1770  free them. Otherwise, it hasn't registered its transports yet
1771  and we should free them here. */
1772  SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
1774  managed_proxy_destroy(mp, 1);
1775  });
1776 
1777  smartlist_free(managed_proxy_list);
1778  managed_proxy_list=NULL;
1779  }
1780 }
1781 
1782 /** Return a newly allocated string equal to <b>string</b>, except that every
1783  * character in <b>chars_to_escape</b> is preceded by a backslash. */
1784 char *
1785 tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
1786 {
1787  char *new_string = NULL;
1788  char *new_cp = NULL;
1789  size_t length, new_length;
1790 
1791  tor_assert(string);
1792 
1793  length = strlen(string);
1794 
1795  if (!length) /* If we were given the empty string, return the same. */
1796  return tor_strdup("");
1797  /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
1798  (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
1799  if (length > (SIZE_MAX - 1)/2) /* check for overflow */
1800  return NULL;
1801 
1802  /* this should be enough even if all characters must be escaped */
1803  new_length = (length * 2) + 1;
1804 
1805  new_string = new_cp = tor_malloc(new_length);
1806 
1807  while (*string) {
1808  if (strchr(chars_to_escape, *string))
1809  *new_cp++ = '\\';
1810 
1811  *new_cp++ = *string++;
1812  }
1813 
1814  *new_cp = '\0'; /* NUL-terminate the new string */
1815 
1816  return new_string;
1817 }
1818 
1819 /** Callback function that is called when our PT process have data on its
1820  * stdout. Our process can be found in <b>process</b>, the data can be found in
1821  * <b>line</b> and the length of our line is given in <b>size</b>. */
1822 STATIC void
1824  const char *line,
1825  size_t size)
1826 {
1827  tor_assert(process);
1828  tor_assert(line);
1829 
1830  (void)size;
1831 
1832  managed_proxy_t *mp = process_get_data(process);
1833 
1834  if (mp == NULL)
1835  return;
1836 
1837  handle_proxy_line(line, mp);
1838 
1841 }
1842 
1843 /** Callback function that is called when our PT process have data on its
1844  * stderr. Our process can be found in <b>process</b>, the data can be found in
1845  * <b>line</b> and the length of our line is given in <b>size</b>. */
1846 STATIC void
1848  const char *line,
1849  size_t size)
1850 {
1851  tor_assert(process);
1852  tor_assert(line);
1853 
1854  (void)size;
1855 
1856  managed_proxy_t *mp = process_get_data(process);
1857 
1858  if (BUG(mp == NULL))
1859  return;
1860 
1861  log_info(LD_PT,
1862  "Managed proxy at '%s' reported via standard error: %s",
1863  mp->argv[0], line);
1864 }
1865 
1866 /** Callback function that is called when our PT process terminates. The
1867  * process exit code can be found in <b>exit_code</b> and our process can be
1868  * found in <b>process</b>. Returns true iff we want the process subsystem to
1869  * free our process_t handle for us. */
1870 STATIC bool
1871 managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
1872 {
1873  tor_assert(process);
1874 
1875  log_warn(LD_PT,
1876  "Pluggable Transport process terminated with status code %" PRIu64,
1877  exit_code);
1878 
1879  /* Returning true here means that the process subsystem will take care of
1880  * calling process_free() on our process_t. */
1881  return true;
1882 }
1883 
1884 /** Returns a valid integer log severity level from <b>severity</b> that
1885  * is compatible with Tor's logging functions. Returns <b>-1</b> on
1886  * error. */
1887 STATIC int
1888 managed_proxy_severity_parse(const char *severity)
1889 {
1890  tor_assert(severity);
1891 
1892  /* Slightly different than log.c's parse_log_level :-( */
1893  if (! strcmp(severity, "debug"))
1894  return LOG_DEBUG;
1895 
1896  if (! strcmp(severity, "info"))
1897  return LOG_INFO;
1898 
1899  if (! strcmp(severity, "notice"))
1900  return LOG_NOTICE;
1901 
1902  if (! strcmp(severity, "warning"))
1903  return LOG_WARN;
1904 
1905  if (! strcmp(severity, "error"))
1906  return LOG_ERR;
1907 
1908  return -1;
1909 }
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:1691
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:985
config_line_t * kvline_parse(const char *line, unsigned flags)
Definition: kvline.c:199
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:189
#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:1546
char * get_first_listener_addrport_string(int listener_type)
Definition: config.c:6735
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:1823
#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:1624
#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:1157
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:1785
char * Socks5ProxyUsername
#define CONN_TYPE_OR_LISTENER
Definition: connection.h:39
STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:835
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:926
#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:1716
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:1594
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:2441
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:773
#define SMARTLIST_DEL_CURRENT(sl, var)
STATIC void parse_proxy_error(const char *line)
Definition: transports.c:1142
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:963
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:1501
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:1223
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:1319
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:1006
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:206
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:947
Header for process.c.
void mark_my_descriptor_dirty(const char *reason)
Definition: router.c:2422
#define PROTO_ENV_ERROR
Definition: transports.c:123
STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1123
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:809
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:1346
STATIC int parse_cmethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1133
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:1888
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:1871
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:1847
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:818
#define LD_PT
Definition: log.h:117
void pt_free_all(void)
Definition: transports.c:1759
void pt_prepare_proxy_list_for_config_read(void)
Definition: transports.c:1561
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:1464
char * kvline_encode(const config_line_t *line, unsigned flags)
Definition: kvline.c:126
char * HTTPSProxy
Header file for control_events.c.
void smartlist_clear(smartlist_t *sl)
#define CONN_TYPE_EXT_OR_LISTENER
Definition: connection.h:71
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:1274
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:1743
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:1727
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)