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