tor  0.4.0.0-alpha-dev
transports.c
Go to the documentation of this file.
1 /* Copyright (c) 2011-2018, 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"
103 #include "feature/control/control.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  process_terminate(mp->process);
718 
719  process_free(mp->process);
720 
721  tor_free(mp);
722 }
723 
727 STATIC char *
729 {
730  const or_options_t *options = get_options();
731  char *uri = NULL;
732 
733  if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
734  char addr[TOR_ADDR_BUF_LEN+1];
735 
736  if (options->Socks4Proxy) {
737  tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
738  tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
739  } else if (options->Socks5Proxy) {
740  tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
741  if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
742  tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
743  } else {
744  tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
745  options->Socks5ProxyUsername,
746  options->Socks5ProxyPassword,
747  addr, options->Socks5ProxyPort);
748  }
749  } else if (options->HTTPSProxy) {
750  tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
751  if (!options->HTTPSProxyAuthenticator) {
752  tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
753  } else {
754  tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
755  addr, options->HTTPSProxyPort);
756  }
757  }
758  }
759 
760  return uri;
761 }
762 
764 static void
765 handle_finished_proxy(managed_proxy_t *mp)
766 {
767  switch (mp->conf_state) {
768  case PT_PROTO_BROKEN: /* if broken: */
769  managed_proxy_destroy(mp, 1); /* annihilate it. */
770  break;
771  case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */
772  managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
773  break;
774  case PT_PROTO_CONFIGURED: /* if configured correctly: */
775  if (mp->proxy_uri && !mp->proxy_supported) {
776  log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
777  "specified outgoing proxy and will be terminated.",
778  mp->argv[0]);
779  managed_proxy_destroy(mp, 1); /* annihilate it. */
780  break;
781  }
782  register_proxy(mp); /* register its transports */
783  mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
784  break;
785  case PT_PROTO_INFANT:
786  case PT_PROTO_LAUNCHED:
787  case PT_PROTO_ACCEPTING_METHODS:
788  case PT_PROTO_COMPLETED:
789  default:
790  log_warn(LD_CONFIG, "Unexpected state '%d' of managed proxy '%s'.",
791  (int)mp->conf_state, mp->argv[0]);
792  tor_assert(0);
793  }
794 
796 }
797 
800 static inline int
801 proxy_configuration_finished(const managed_proxy_t *mp)
802 {
803  return (mp->conf_state == PT_PROTO_CONFIGURED ||
804  mp->conf_state == PT_PROTO_BROKEN ||
805  mp->conf_state == PT_PROTO_FAILED_LAUNCH);
806 }
807 
809 static void
810 handle_methods_done(const managed_proxy_t *mp)
811 {
812  tor_assert(mp->transports);
813 
814  if (smartlist_len(mp->transports) == 0)
815  log_notice(LD_GENERAL, "Managed proxy '%s' was spawned successfully, "
816  "but it didn't launch any pluggable transport listeners!",
817  mp->argv[0]);
818 
819  log_info(LD_CONFIG, "%s managed proxy '%s' configuration completed!",
820  mp->is_server ? "Server" : "Client",
821  mp->argv[0]);
822 }
823 
826 STATIC void
827 handle_proxy_line(const char *line, managed_proxy_t *mp)
828 {
829  log_info(LD_GENERAL, "Got a line from managed proxy '%s': (%s)",
830  mp->argv[0], line);
831 
832  if (!strcmpstart(line, PROTO_ENV_ERROR)) {
833  if (mp->conf_state != PT_PROTO_LAUNCHED)
834  goto err;
835 
836  parse_env_error(line);
837  goto err;
838  } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
839  if (mp->conf_state != PT_PROTO_LAUNCHED)
840  goto err;
841 
842  log_warn(LD_CONFIG, "Managed proxy could not pick a "
843  "configuration protocol version.");
844  goto err;
845  } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
846  if (mp->conf_state != PT_PROTO_LAUNCHED)
847  goto err;
848 
849  if (parse_version(line,mp) < 0)
850  goto err;
851 
852  tor_assert(mp->conf_protocol != 0);
853  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
854  return;
855  } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
856  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
857  goto err;
858 
860 
861  mp->conf_state = PT_PROTO_CONFIGURED;
862  return;
863  } else if (!strcmpstart(line, PROTO_SMETHODS_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_CMETHOD_ERROR)) {
872  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
873  goto err;
874 
875  parse_client_method_error(line);
876  goto err;
877  } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
878  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
879  goto err;
880 
881  parse_server_method_error(line);
882  goto err;
883  } else if (!strcmpstart(line, PROTO_CMETHOD)) {
884  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
885  goto err;
886 
887  if (parse_cmethod_line(line, mp) < 0)
888  goto err;
889 
890  return;
891  } else if (!strcmpstart(line, PROTO_SMETHOD)) {
892  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
893  goto err;
894 
895  if (parse_smethod_line(line, mp) < 0)
896  goto err;
897 
898  return;
899  } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
900  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
901  goto err;
902 
903  if (mp->proxy_uri) {
904  mp->proxy_supported = 1;
905  return;
906  }
907 
908  /* No proxy was configured, this should log */
909  } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
910  if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
911  goto err;
912 
913  parse_proxy_error(line);
914  goto err;
915 
916  /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
917  * string to make sure we can later extend this big if/else-if table with
918  * something that begins with "LOG" without having to get the order right.
919  * */
920  } else if (!strcmpstart(line, PROTO_LOG " ")) {
921  parse_log_line(line, mp);
922  return;
923  } else if (!strcmpstart(line, PROTO_STATUS " ")) {
924  parse_status_line(line, mp);
925  return;
926  }
927 
928  log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
929  return;
930 
931  err:
932  mp->conf_state = PT_PROTO_BROKEN;
933  log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol"
934  " and will be destroyed.", mp->argv[0]);
935 }
936 
938 STATIC void
939 parse_env_error(const char *line)
940 {
941  /* (Length of the protocol string) plus (a space) and (the first char of
942  the error message) */
943  if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
944  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
945  "message.", PROTO_ENV_ERROR);
946 
947  log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
948  "pluggable transport environment variables. (%s)",
949  line+strlen(PROTO_ENV_ERROR)+1);
950 }
951 
954 STATIC int
955 parse_version(const char *line, managed_proxy_t *mp)
956 {
957  if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
958  log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
959  PROTO_NEG_SUCCESS);
960  return -1;
961  }
962 
963  if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
964  log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
965  "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
966  return -1;
967  }
968 
969  mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
970  return 0;
971 }
972 
976 static void
977 parse_method_error(const char *line, int is_server)
978 {
979  const char* error = is_server ?
980  PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
981 
982  /* (Length of the protocol string) plus (a space) and (the first char of
983  the error message) */
984  if (strlen(line) < (strlen(error) + 2))
985  log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
986  "message.", error);
987 
988  log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
989  is_server ? "Server" : "Client",
990  line+strlen(error)+1);
991 }
992 
997 static int
998 parse_method_line_helper(const char *line,
999  managed_proxy_t *mp,
1000  int is_smethod)
1001 {
1002  int item_index = 0;
1003  int r;
1004 
1005  char *transport_name=NULL;
1006  char *args_string=NULL;
1007  char *addrport=NULL;
1008  int socks_ver=PROXY_NONE;
1009  char *address=NULL;
1010  uint16_t port = 0;
1011 
1012  const char *method_str = is_smethod ? PROTO_SMETHOD : PROTO_CMETHOD;
1013  const int min_args_count = is_smethod ? 3 : 4;
1014 
1015  tor_addr_t tor_addr;
1016  transport_t *transport=NULL;
1017  smartlist_t *items= smartlist_new();
1018 
1019  smartlist_split_string(items, line, NULL,
1020  SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1021  if (smartlist_len(items) < min_args_count) {
1022  log_warn(LD_CONFIG, "Managed proxy sent us a %s line "
1023  "with too few arguments.", method_str);
1024  goto err;
1025  }
1026 
1027  tor_assert(!strcmp(smartlist_get(items, item_index),method_str));
1028  ++item_index;
1029 
1030  transport_name = smartlist_get(items,item_index);
1031  ++item_index;
1032  if (!string_is_C_identifier(transport_name)) {
1033  log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
1034  transport_name);
1035  goto err;
1036  }
1037 
1039  if (!is_smethod) {
1040  const char *socks_ver_str = smartlist_get(items,item_index);
1041  ++item_index;
1042 
1043  if (!strcmp(socks_ver_str,"socks4")) {
1044  socks_ver = PROXY_SOCKS4;
1045  } else if (!strcmp(socks_ver_str,"socks5")) {
1046  socks_ver = PROXY_SOCKS5;
1047  } else {
1048  log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
1049  "we don't recognize. (%s)", socks_ver_str);
1050  goto err;
1051  }
1052  }
1053 
1054  addrport = smartlist_get(items, item_index);
1055  ++item_index;
1056  if (tor_addr_port_split(LOG_WARN, addrport, &address, &port)<0) {
1057  log_warn(LD_CONFIG, "Error parsing transport address '%s'", addrport);
1058  goto err;
1059  }
1060 
1061  if (!port) {
1062  log_warn(LD_CONFIG,
1063  "Transport address '%s' has no port.", addrport);
1064  goto err;
1065  }
1066 
1067  if (tor_addr_parse(&tor_addr, address) < 0) {
1068  log_warn(LD_CONFIG, "Error parsing transport address '%s'", address);
1069  goto err;
1070  }
1071 
1073  if (is_smethod && smartlist_len(items) > min_args_count) {
1074  /* Seems like there are also some [options] in the SMETHOD line.
1075  Let's see if we can parse them. */
1076  char *options_string = smartlist_get(items, item_index);
1077  log_debug(LD_CONFIG, "Got options_string: %s", options_string);
1078  if (!strcmpstart(options_string, "ARGS:")) {
1079  args_string = options_string+strlen("ARGS:");
1080  log_debug(LD_CONFIG, "Got ARGS: %s", args_string);
1081  }
1082  }
1083 
1084  transport = transport_new(&tor_addr, port, transport_name,
1085  socks_ver, args_string);
1086 
1087  smartlist_add(mp->transports, transport);
1088 
1090  if (is_smethod) {
1091  log_info(LD_CONFIG, "Server transport %s at %s:%d.",
1092  transport_name, address, (int)port);
1093  } else {
1094  log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
1095  "Attached to managed proxy.",
1096  transport_name, address, (int)port, socks_ver);
1097  }
1098 
1099  r=0;
1100  goto done;
1101 
1102  err:
1103  r = -1;
1104 
1105  done:
1106  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
1107  smartlist_free(items);
1108  tor_free(address);
1109  return r;
1110 }
1111 
1114 STATIC int
1115 parse_smethod_line(const char *line, managed_proxy_t *mp)
1116 {
1117  /* Example of legit SMETHOD line:
1118  SMETHOD obfs2 0.0.0.0:25612 ARGS:secret=supersekrit,key=superkey */
1119  return parse_method_line_helper(line, mp, 1);
1120 }
1121 
1124 STATIC int
1125 parse_cmethod_line(const char *line, managed_proxy_t *mp)
1126 {
1127  /* Example of legit CMETHOD line:
1128  CMETHOD obfs2 socks5 127.0.0.1:35713 */
1129  return parse_method_line_helper(line, mp, 0);
1130 }
1131 
1133 STATIC void
1134 parse_proxy_error(const char *line)
1135 {
1136  /* (Length of the protocol string) plus (a space) and (the first char of
1137  the error message) */
1138  if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
1139  log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
1140  "message.", PROTO_PROXY_ERROR);
1141 
1142  log_warn(LD_CONFIG, "Managed proxy failed to configure the "
1143  "pluggable transport's outgoing proxy. (%s)",
1144  line+strlen(PROTO_PROXY_ERROR)+1);
1145 }
1146 
1148 STATIC void
1149 parse_log_line(const char *line, managed_proxy_t *mp)
1150 {
1151  tor_assert(line);
1152  tor_assert(mp);
1153 
1154  config_line_t *values = NULL;
1155  char *log_message = NULL;
1156 
1157  if (strlen(line) < (strlen(PROTO_LOG) + 1)) {
1158  log_warn(LD_PT, "Managed proxy sent us a %s line "
1159  "with missing argument.", PROTO_LOG);
1160  goto done;
1161  }
1162 
1163  const char *data = line + strlen(PROTO_LOG) + 1;
1164  values = kvline_parse(data, KV_QUOTED);
1165 
1166  if (! values) {
1167  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid LOG message: %s",
1168  mp->argv[0], data);
1169  goto done;
1170  }
1171 
1172  const config_line_t *severity = config_line_find(values, "SEVERITY");
1173  const config_line_t *message = config_line_find(values, "MESSAGE");
1174 
1175  /* Check if we got a message. */
1176  if (! message) {
1177  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1178  "MESSAGE: %s", mp->argv[0], escaped(data));
1179  goto done;
1180  }
1181 
1182  /* Check if severity is there and whether it's valid. */
1183  if (! severity) {
1184  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line without "
1185  "SEVERITY: %s", mp->argv[0], escaped(data));
1186  goto done;
1187  }
1188 
1189  int log_severity = managed_proxy_severity_parse(severity->value);
1190 
1191  if (log_severity == -1) {
1192  log_warn(LD_PT, "Managed proxy \"%s\" wrote a LOG line with an "
1193  "invalid severity level: %s",
1194  mp->argv[0], severity->value);
1195  goto done;
1196  }
1197 
1198  tor_log(log_severity, LD_PT, "Managed proxy \"%s\": %s",
1199  mp->argv[0], message->value);
1200 
1201  /* Prepend the PT name. */
1202  config_line_prepend(&values, "PT", mp->argv[0]);
1203  log_message = kvline_encode(values, KV_QUOTED);
1204 
1205  /* Emit control port event. */
1206  control_event_pt_log(log_message);
1207 
1208  done:
1209  config_free_lines(values);
1210  tor_free(log_message);
1211 }
1212 
1214 STATIC void
1215 parse_status_line(const char *line, managed_proxy_t *mp)
1216 {
1217  tor_assert(line);
1218  tor_assert(mp);
1219 
1220  config_line_t *values = NULL;
1221  char *status_message = NULL;
1222 
1223  if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
1224  log_warn(LD_PT, "Managed proxy sent us a %s line "
1225  "with missing argument.", PROTO_STATUS);
1226  goto done;
1227  }
1228 
1229  const char *data = line + strlen(PROTO_STATUS) + 1;
1230 
1231  values = kvline_parse(data, KV_QUOTED);
1232 
1233  if (! values) {
1234  log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
1235  "STATUS message: %s", mp->argv[0], escaped(data));
1236  goto done;
1237  }
1238 
1239  /* We check if we received the TYPE parameter, which is the only *required*
1240  * value. */
1241  const config_line_t *type = config_line_find(values, "TYPE");
1242 
1243  if (! type) {
1244  log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
1245  "TYPE: %s", mp->argv[0], escaped(data));
1246  goto done;
1247  }
1248 
1249  /* Prepend the PT name. */
1250  config_line_prepend(&values, "PT", mp->argv[0]);
1251  status_message = kvline_encode(values, KV_QUOTED);
1252 
1253  /* We have checked that TYPE is there, we can now emit the STATUS event via
1254  * the control port. */
1255  control_event_pt_status(status_message);
1256 
1257  done:
1258  config_free_lines(values);
1259  tor_free(status_message);
1260 }
1261 
1265 STATIC char *
1266 get_transport_options_for_server_proxy(const managed_proxy_t *mp)
1267 {
1268  char *options_string = NULL;
1269  smartlist_t *string_sl = smartlist_new();
1270 
1271  tor_assert(mp->is_server);
1272 
1277  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
1278  smartlist_t *options_tmp_sl = NULL;
1279  options_tmp_sl = get_options_for_server_transport(transport);
1280  if (!options_tmp_sl)
1281  continue;
1282 
1285  SMARTLIST_FOREACH_BEGIN(options_tmp_sl, const char *, options) {
1286  char *escaped_opts = tor_escape_str_for_pt_args(options, ":;\\");
1287  smartlist_add_asprintf(string_sl, "%s:%s",
1288  transport, escaped_opts);
1289  tor_free(escaped_opts);
1290  } SMARTLIST_FOREACH_END(options);
1291 
1292  SMARTLIST_FOREACH(options_tmp_sl, char *, c, tor_free(c));
1293  smartlist_free(options_tmp_sl);
1294  } SMARTLIST_FOREACH_END(transport);
1295 
1296  if (smartlist_len(string_sl)) {
1297  options_string = smartlist_join_strings(string_sl, ";", 0, NULL);
1298  }
1299 
1300  SMARTLIST_FOREACH(string_sl, char *, t, tor_free(t));
1301  smartlist_free(string_sl);
1302 
1303  return options_string;
1304 }
1305 
1310 static char *
1311 get_bindaddr_for_server_proxy(const managed_proxy_t *mp)
1312 {
1313  char *bindaddr_result = NULL;
1314  char *bindaddr_tmp = NULL;
1315  smartlist_t *string_tmp = smartlist_new();
1316 
1317  tor_assert(mp->is_server);
1318 
1319  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
1320  bindaddr_tmp = get_stored_bindaddr_for_server_transport(t);
1321 
1322  smartlist_add_asprintf(string_tmp, "%s-%s", t, bindaddr_tmp);
1323 
1324  tor_free(bindaddr_tmp);
1325  } SMARTLIST_FOREACH_END(t);
1326 
1327  bindaddr_result = smartlist_join_strings(string_tmp, ",", 0, NULL);
1328 
1329  SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
1330  smartlist_free(string_tmp);
1331 
1332  return bindaddr_result;
1333 }
1334 
1337 static smartlist_t *
1338 create_managed_proxy_environment(const managed_proxy_t *mp)
1339 {
1340  const or_options_t *options = get_options();
1341 
1342  /* Environment variables to be added to or set in mp's environment. */
1343  smartlist_t *envs = smartlist_new();
1344  /* XXXX The next time someone touches this code, shorten the name of
1345  * set_environment_variable_in_smartlist, add a
1346  * set_env_var_in_smartlist_asprintf function, and get rid of the
1347  * silly extra envs smartlist. */
1348 
1349  /* The final environment to be passed to mp. */
1351 
1352  {
1353  char *state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */
1354  smartlist_add_asprintf(envs, "TOR_PT_STATE_LOCATION=%s", state_tmp);
1355  tor_free(state_tmp);
1356  }
1357 
1358  smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
1359 
1360  {
1361  char *transports_to_launch =
1362  smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
1363 
1365  mp->is_server ?
1366  "TOR_PT_SERVER_TRANSPORTS=%s" :
1367  "TOR_PT_CLIENT_TRANSPORTS=%s",
1368  transports_to_launch);
1369 
1370  tor_free(transports_to_launch);
1371  }
1372 
1373  if (mp->is_server) {
1374  {
1375  char *orport_tmp =
1377  if (orport_tmp) {
1378  smartlist_add_asprintf(envs, "TOR_PT_ORPORT=%s", orport_tmp);
1379  tor_free(orport_tmp);
1380  }
1381  }
1382 
1383  {
1384  char *bindaddr_tmp = get_bindaddr_for_server_proxy(mp);
1385  smartlist_add_asprintf(envs, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp);
1386  tor_free(bindaddr_tmp);
1387  }
1388 
1389  {
1390  char *server_transport_options =
1392  if (server_transport_options) {
1393  smartlist_add_asprintf(envs, "TOR_PT_SERVER_TRANSPORT_OPTIONS=%s",
1394  server_transport_options);
1395  tor_free(server_transport_options);
1396  }
1397  }
1398 
1399  /* XXXX Remove the '=' here once versions of obfsproxy which
1400  * assert that this env var exists are sufficiently dead.
1401  *
1402  * (If we remove this line entirely, some joker will stick this
1403  * variable in Tor's environment and crash PTs that try to parse
1404  * it even when not run in server mode.) */
1405 
1406  if (options->ExtORPort_lines) {
1407  char *ext_or_addrport_tmp =
1409  char *cookie_file_loc = get_ext_or_auth_cookie_file_name();
1410 
1411  if (ext_or_addrport_tmp) {
1412  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=%s",
1413  ext_or_addrport_tmp);
1414  }
1415  smartlist_add_asprintf(envs, "TOR_PT_AUTH_COOKIE_FILE=%s",
1416  cookie_file_loc);
1417 
1418  tor_free(ext_or_addrport_tmp);
1419  tor_free(cookie_file_loc);
1420 
1421  } else {
1422  smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
1423  }
1424 
1425  /* All new versions of tor will keep stdin open, so PTs can use it
1426  * as a reliable termination detection mechanism.
1427  */
1428  smartlist_add_asprintf(envs, "TOR_PT_EXIT_ON_STDIN_CLOSE=1");
1429  } else {
1430  /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
1431  * TOR_PT_PROXY line.
1432  */
1433 
1434  if (mp->proxy_uri) {
1435  smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
1436  }
1437  }
1438 
1439  SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
1440  set_environment_variable_in_smartlist(merged_env_vars, env_var,
1441  tor_free_, 1);
1442  } SMARTLIST_FOREACH_END(env_var);
1443 
1444  smartlist_free(envs);
1445 
1446  return merged_env_vars;
1447 }
1448 
1455 STATIC managed_proxy_t *
1456 managed_proxy_create(const smartlist_t *with_transport_list,
1457  char **proxy_argv, int is_server)
1458 {
1459  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
1460  mp->conf_state = PT_PROTO_INFANT;
1461  mp->is_server = is_server;
1462  mp->argv = proxy_argv;
1463  mp->transports = smartlist_new();
1464  mp->proxy_uri = get_pt_proxy_uri();
1465  mp->process = process_new(proxy_argv[0]);
1466 
1467  mp->transports_to_launch = smartlist_new();
1468  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1469  add_transport_to_proxy(transport, mp));
1470 
1471  /* register the managed proxy */
1472  if (!managed_proxy_list)
1473  managed_proxy_list = smartlist_new();
1476 
1478 
1479  return mp;
1480 }
1481 
1492 pt_kickstart_proxy, (const smartlist_t *with_transport_list,
1493  char **proxy_argv, int is_server))
1494 {
1495  managed_proxy_t *mp=NULL;
1496  transport_t *old_transport = NULL;
1497 
1498  if (!proxy_argv || !proxy_argv[0]) {
1499  return;
1500  }
1501 
1502  mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
1503 
1504  if (!mp) { /* we haven't seen this proxy before */
1505  managed_proxy_create(with_transport_list, proxy_argv, is_server);
1506 
1507  } else { /* known proxy. add its transport to its transport list */
1508  if (mp->was_around_before_config_read) {
1509  /* If this managed proxy was around even before we read the
1510  config this time, it means that it was already enabled before
1511  and is not useless and should be kept. If it's marked for
1512  removal, unmark it and make sure that we check whether it
1513  needs to be restarted. */
1514  if (mp->marked_for_removal) {
1515  mp->marked_for_removal = 0;
1517  }
1518 
1519  /* For each new transport, check if the managed proxy used to
1520  support it before the SIGHUP. If that was the case, make sure
1521  it doesn't get removed because we might reuse it. */
1522  SMARTLIST_FOREACH_BEGIN(with_transport_list, const char *, transport) {
1523  old_transport = transport_get_by_name(transport);
1524  if (old_transport)
1525  old_transport->marked_for_removal = 0;
1526  } SMARTLIST_FOREACH_END(transport);
1527  }
1528 
1529  SMARTLIST_FOREACH(with_transport_list, const char *, transport,
1530  add_transport_to_proxy(transport, mp));
1531  free_execve_args(proxy_argv);
1532  }
1533 }
1534 
1537 STATIC void
1538 free_execve_args(char **arg)
1539 {
1540  char **tmp = arg;
1541  while (*tmp) /* use the fact that the last element of the array is a
1542  NULL pointer to know when to stop freeing */
1543  tor_free_(*tmp++);
1544 
1545  tor_free(arg);
1546 }
1547 
1552 void
1554 {
1555  if (!managed_proxy_list)
1556  return;
1557 
1559  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1560  /* Destroy unconfigured proxies. */
1561  if (mp->conf_state != PT_PROTO_COMPLETED) {
1563  managed_proxy_destroy(mp, 1);
1565  continue;
1566  }
1567 
1568  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1569 
1570  /* Mark all proxies for removal, and also note that they have been
1571  here before the config read. */
1572  mp->marked_for_removal = 1;
1573  mp->was_around_before_config_read = 1;
1574  SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
1575  smartlist_clear(mp->transports_to_launch);
1576  } SMARTLIST_FOREACH_END(mp);
1577 
1579 
1581 }
1582 
1585 smartlist_t *
1587 {
1588  smartlist_t *sl = NULL;
1589 
1590  if (!managed_proxy_list)
1591  return NULL;
1592 
1595  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1596  if (!mp->is_server || mp->conf_state != PT_PROTO_COMPLETED)
1597  continue;
1598 
1599  if (!sl) sl = smartlist_new();
1600 
1601  tor_assert(mp->transports);
1602  SMARTLIST_FOREACH(mp->transports, const transport_t *, t,
1603  smartlist_add_asprintf(sl, "%u:%u", t->port, t->port));
1604 
1605  } SMARTLIST_FOREACH_END(mp);
1606 
1607  return sl;
1608 }
1609 
1615 char *
1617 {
1618  char *the_string = NULL;
1619  smartlist_t *string_chunks = NULL;
1620 
1621  if (!managed_proxy_list)
1622  return NULL;
1623 
1624  string_chunks = smartlist_new();
1625 
1626  /* For each managed proxy, add its transports to the chunks list. */
1627  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) {
1628  if ((!mp->is_server) || (mp->conf_state != PT_PROTO_COMPLETED))
1629  continue;
1630 
1631  tor_assert(mp->transports);
1632 
1633  SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) {
1634  char *transport_args = NULL;
1635 
1636  /* If the transport proxy returned "0.0.0.0" as its address, and
1637  * we know our external IP address, use it. Otherwise, use the
1638  * returned address. */
1639  const char *addrport = NULL;
1640  uint32_t external_ip_address = 0;
1641  if (tor_addr_is_null(&t->addr) &&
1642  router_pick_published_address(get_options(),
1643  &external_ip_address, 0) >= 0) {
1644  tor_addr_t addr;
1645  tor_addr_from_ipv4h(&addr, external_ip_address);
1646  addrport = fmt_addrport(&addr, t->port);
1647  } else {
1648  addrport = fmt_addrport(&t->addr, t->port);
1649  }
1650 
1651  /* If this transport has any arguments with it, prepend a space
1652  to them so that we can add them to the transport line. */
1653  if (t->extra_info_args)
1654  tor_asprintf(&transport_args, " %s", t->extra_info_args);
1655 
1656  smartlist_add_asprintf(string_chunks,
1657  "transport %s %s%s",
1658  t->name, addrport,
1659  transport_args ? transport_args : "");
1660  tor_free(transport_args);
1661  } SMARTLIST_FOREACH_END(t);
1662 
1663  } SMARTLIST_FOREACH_END(mp);
1664 
1665  if (smartlist_len(string_chunks) == 0) {
1666  smartlist_free(string_chunks);
1667  return NULL;
1668  }
1669 
1670  /* Join all the chunks into the final string. */
1671  the_string = smartlist_join_strings(string_chunks, "\n", 1, NULL);
1672 
1673  SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
1674  smartlist_free(string_chunks);
1675 
1676  return the_string;
1677 }
1678 
1682 char *
1684 {
1685  /* tmp place to store escaped socks arguments, so that we can
1686  concatenate them up afterwards */
1687  smartlist_t *sl_tmp = NULL;
1688  char *escaped_string = NULL;
1689  char *new_string = NULL;
1690 
1691  tor_assert(socks_args);
1692  tor_assert(smartlist_len(socks_args) > 0);
1693 
1694  sl_tmp = smartlist_new();
1695 
1696  SMARTLIST_FOREACH_BEGIN(socks_args, const char *, s) {
1697  /* Escape ';' and '\'. */
1698  escaped_string = tor_escape_str_for_pt_args(s, ";\\");
1699  if (!escaped_string)
1700  goto done;
1701 
1702  smartlist_add(sl_tmp, escaped_string);
1703  } SMARTLIST_FOREACH_END(s);
1704 
1705  new_string = smartlist_join_strings(sl_tmp, ";", 0, NULL);
1706 
1707  done:
1708  SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
1709  smartlist_free(sl_tmp);
1710 
1711  return new_string;
1712 }
1713 
1718 char *
1720 {
1721  const smartlist_t *socks_args = NULL;
1722 
1723  socks_args = get_socks_args_by_bridge_addrport(addr, port);
1724  if (!socks_args)
1725  return NULL;
1726 
1727  return pt_stringify_socks_args(socks_args);
1728 }
1729 
1734 void
1736 {
1737  if (!managed_proxy_list)
1738  return;
1740  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
1741  if (mp->marked_for_removal) {
1743  managed_proxy_destroy(mp, 1);
1744  }
1745  } SMARTLIST_FOREACH_END(mp);
1747 }
1748 
1750 void
1752 {
1753  if (transport_list) {
1755  smartlist_free(transport_list);
1756  transport_list = NULL;
1757  }
1758 
1759  if (managed_proxy_list) {
1760  /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
1761  transports and it's the duty of the circuitbuild.c subsystem to
1762  free them. Otherwise, it hasn't registered its transports yet
1763  and we should free them here. */
1764  SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, {
1766  managed_proxy_destroy(mp, 1);
1767  });
1768 
1769  smartlist_free(managed_proxy_list);
1770  managed_proxy_list=NULL;
1771  }
1772 }
1773 
1776 char *
1777 tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
1778 {
1779  char *new_string = NULL;
1780  char *new_cp = NULL;
1781  size_t length, new_length;
1782 
1783  tor_assert(string);
1784 
1785  length = strlen(string);
1786 
1787  if (!length) /* If we were given the empty string, return the same. */
1788  return tor_strdup("");
1789  /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
1790  (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
1791  if (length > (SIZE_MAX - 1)/2) /* check for overflow */
1792  return NULL;
1793 
1794  /* this should be enough even if all characters must be escaped */
1795  new_length = (length * 2) + 1;
1796 
1797  new_string = new_cp = tor_malloc(new_length);
1798 
1799  while (*string) {
1800  if (strchr(chars_to_escape, *string))
1801  *new_cp++ = '\\';
1802 
1803  *new_cp++ = *string++;
1804  }
1805 
1806  *new_cp = '\0'; /* NUL-terminate the new string */
1807 
1808  return new_string;
1809 }
1810 
1814 STATIC void
1816  const char *line,
1817  size_t size)
1818 {
1819  tor_assert(process);
1820  tor_assert(line);
1821 
1822  (void)size;
1823 
1824  managed_proxy_t *mp = process_get_data(process);
1825 
1826  handle_proxy_line(line, mp);
1827 
1828  if (proxy_configuration_finished(mp)) {
1830  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
1831  }
1832 }
1833 
1837 STATIC void
1839  const char *line,
1840  size_t size)
1841 {
1842  tor_assert(process);
1843  tor_assert(line);
1844 
1845  (void)size;
1846 
1847  managed_proxy_t *mp = process_get_data(process);
1848 
1849  log_warn(LD_PT, "Managed proxy at '%s' reported: %s", mp->argv[0], line);
1850 }
1851 
1856 STATIC bool
1857 managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
1858 {
1859  tor_assert(process);
1860 
1861  log_warn(LD_PT,
1862  "Pluggable Transport process terminated with status code %" PRIu64,
1863  exit_code);
1864 
1865  /* We detach ourself from the MP (if we are attached) and free ourself. */
1866  managed_proxy_t *mp = process_get_data(process);
1867 
1868  /* If we are still attached to the process, it is probably because our PT
1869  * process crashed before we got to call process_set_data(p, NULL); */
1870  if (BUG(mp != NULL)) {
1871  /* FIXME(ahf): Our process stopped without us having told it to stop
1872  * (crashed). Should we restart it here? */
1873  mp->process = NULL;
1874  process_set_data(process, NULL);
1875  }
1876 
1877  return true;
1878 }
1879 
1883 STATIC int
1884 managed_proxy_severity_parse(const char *severity)
1885 {
1886  tor_assert(severity);
1887 
1888  /* Slightly different than log.c's parse_log_level :-( */
1889  if (! strcmp(severity, "debug"))
1890  return LOG_DEBUG;
1891 
1892  if (! strcmp(severity, "info"))
1893  return LOG_INFO;
1894 
1895  if (! strcmp(severity, "notice"))
1896  return LOG_NOTICE;
1897 
1898  if (! strcmp(severity, "warning"))
1899  return LOG_WARN;
1900 
1901  if (! strcmp(severity, "error"))
1902  return LOG_ERR;
1903 
1904  return -1;
1905 }
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:1683
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
Definition: address.c:317
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:977
config_line_t * kvline_parse(const char *line, unsigned flags)
Definition: kvline.c:160
uint16_t port
Definition: transports.h:26
#define TOR_ADDR_BUF_LEN
Definition: address.h:205
void control_event_pt_status(const char *status)
Definition: control.c:7066
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:1538
char * get_first_listener_addrport_string(int listener_type)
Definition: config.c:7626
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:1815
#define LD_GENERAL
Definition: log.h:58
char * pt_get_extra_info_descriptor_string(void)
Definition: transports.c:1616
tor_addr_t HTTPSProxyAddr
#define LOG_INFO
Definition: log.h:41
struct config_line_t * ExtORPort_lines
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:631
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:1149
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:1777
#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:827
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:1586
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:209
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:46
static void handle_finished_proxy(managed_proxy_t *mp)
Definition: transports.c:765
#define SMARTLIST_DEL_CURRENT(sl, var)
STATIC void parse_proxy_error(const char *line)
Definition: transports.c:1134
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
void control_event_pt_log(const char *log)
Definition: control.c:7056
STATIC int parse_version(const char *line, managed_proxy_t *mp)
Definition: transports.c:955
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:417
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:1215
void control_event_transport_launched(const char *mode, const char *transport_name, tor_addr_t *addr, uint16_t port)
Definition: control.c:7045
void save_transport_to_state(const char *transport, const tor_addr_t *addr, uint16_t port)
Definition: statefile.c:653
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:1311
smartlist_t * get_options_for_server_transport(const char *transport)
Definition: config.c:6298
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:998
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:1157
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:1185
char * get_stored_bindaddr_for_server_transport(const char *transport)
Definition: statefile.c:620
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:49
int tor_addr_is_null(const tor_addr_t *addr)
Definition: address.c:758
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:939
Header for process.c.
void mark_my_descriptor_dirty(const char *reason)
Definition: router.c:2244
#define PROTO_ENV_ERROR
Definition: transports.c:121
STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1115
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:801
void process_set_stderr_read_callback(process_t *process, process_read_callback_t callback)
Definition: process.c:336
#define LOG_ERR
Definition: log.h:52
static smartlist_t * create_managed_proxy_environment(const managed_proxy_t *mp)
Definition: transports.c:1338
STATIC int parse_cmethod_line(const char *line, managed_proxy_t *mp)
Definition: transports.c:1125
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:1884
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)
Header for kvline.c.
STATIC bool managed_proxy_exit_callback(process_t *process, process_exit_code_t exit_code)
Definition: transports.c:1857
uint16_t Socks5ProxyPort
static smartlist_t * transport_list
Definition: transports.c:140
Header file for control.c.
#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:728
STATIC void managed_proxy_stderr_callback(process_t *process, const char *line, size_t size)
Definition: transports.c:1838
#define LOG_DEBUG
Definition: log.h:38
int strcmp_opt(const char *s1, const char *s2)
Definition: util_string.c:191
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:810
#define LD_PT
Definition: log.h:113
void pt_free_all(void)
Definition: transports.c:1751
void pt_prepare_proxy_list_for_config_read(void)
Definition: transports.c:1553
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:892
STATIC managed_proxy_t * managed_proxy_create(const smartlist_t *with_transport_list, char **proxy_argv, int is_server)
Definition: transports.c:1456
char * kvline_encode(const config_line_t *line, unsigned flags)
Definition: kvline.c:103
int socks_version
Definition: transports.h:19
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:64
STATIC char * get_transport_options_for_server_proxy(const managed_proxy_t *mp)
Definition: transports.c:1266
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:1735
char * pt_get_socks_args_for_proxy_addrport(const tor_addr_t *addr, uint16_t port)
Definition: transports.c:1719
int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out)
Definition: address.c:1751
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)