Tor 0.4.9.13
Loading...
Searching...
No Matches
control_cmd.c
Go to the documentation of this file.
1/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2021, The Tor Project, Inc. */
3/* See LICENSE for licensing information */
4
5/**
6 * \file control_cmd.c
7 * \brief Implement various commands for Tor's control-socket interface.
8 **/
9
10#define CONTROL_MODULE_PRIVATE
11#define CONTROL_CMD_PRIVATE
12#define CONTROL_EVENTS_PRIVATE
13
14#include "core/or/or.h"
15#include "app/config/config.h"
16#include "lib/confmgt/confmgt.h"
17#include "app/main/main.h"
20#include "core/or/circuitlist.h"
21#include "core/or/circuituse.h"
24#include "core/or/extendinfo.h"
31#include "feature/control/control_hs.h"
33#include "feature/control/control_getinfo.h"
45#include "lib/encoding/kvline.h"
46
55
57
59 const control_cmd_args_t *args,
60 int use_defaults);
61
62/** Yield true iff <b>s</b> is the state of a control_connection_t that has
63 * finished authentication and is accepting commands. */
64#define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN)
65
66/**
67 * Release all storage held in <b>args</b>
68 **/
69void
71{
72 if (! args)
73 return;
74
75 if (args->args) {
76 SMARTLIST_FOREACH(args->args, char *, c, tor_free(c));
77 smartlist_free(args->args);
78 }
79 config_free_lines(args->kwargs);
80 tor_free(args->cmddata);
81
82 tor_free(args);
83}
84
85/** Erase all memory held in <b>args</b>. */
86void
88{
89 if (!args)
90 return;
91
92 if (args->args) {
93 SMARTLIST_FOREACH(args->args, char *, c, memwipe(c, 0, strlen(c)));
94 }
95 for (config_line_t *line = args->kwargs; line; line = line->next) {
96 memwipe(line->key, 0, strlen(line->key));
97 memwipe(line->value, 0, strlen(line->value));
98 }
99 if (args->cmddata)
100 memwipe(args->cmddata, 0, args->cmddata_len);
101}
102
103/**
104 * Return true iff any element of the NULL-terminated <b>array</b> matches
105 * <b>kwd</b>. Case-insensitive.
106 **/
107static bool
108string_array_contains_keyword(const char **array, const char *kwd)
109{
110 for (unsigned i = 0; array[i]; ++i) {
111 if (! strcasecmp(array[i], kwd))
112 return true;
113 }
114 return false;
115}
116
117/** Helper for argument parsing: check whether the keyword arguments just
118 * parsed in <b>result</b> were well-formed according to <b>syntax</b>.
119 *
120 * On success, return 0. On failure, return -1 and set *<b>error_out</b>
121 * to a newly allocated error string.
122 **/
123static int
125 const control_cmd_syntax_t *syntax,
126 char **error_out)
127{
128 if (result->kwargs == NULL) {
129 tor_asprintf(error_out, "Cannot parse keyword argument(s)");
130 return -1;
131 }
132
133 if (! syntax->allowed_keywords) {
134 /* All keywords are permitted. */
135 return 0;
136 }
137
138 /* Check for unpermitted arguments */
139 const config_line_t *line;
140 for (line = result->kwargs; line; line = line->next) {
142 line->key)) {
143 tor_asprintf(error_out, "Unrecognized keyword argument %s",
144 escaped(line->key));
145 return -1;
146 }
147 }
148
149 return 0;
150}
151
152/**
153 * Helper: parse the arguments to a command according to <b>syntax</b>. On
154 * success, set *<b>error_out</b> to NULL and return a newly allocated
155 * control_cmd_args_t. On failure, set *<b>error_out</b> to newly allocated
156 * error string, and return NULL.
157 **/
160 const control_cmd_syntax_t *syntax,
161 size_t body_len,
162 const char *body,
163 char **error_out)
164{
165 *error_out = NULL;
166 control_cmd_args_t *result = tor_malloc_zero(sizeof(control_cmd_args_t));
167 const char *cmdline;
168 char *cmdline_alloc = NULL;
169 tor_assert(syntax->max_args < INT_MAX || syntax->max_args == UINT_MAX);
170
171 result->command = command;
172
173 if (syntax->store_raw_body) {
174 tor_assert(body[body_len] == 0);
175 result->raw_body = body;
176 }
177
178 const char *eol = memchr(body, '\n', body_len);
179 if (syntax->want_cmddata) {
180 if (! eol || (eol+1) == body+body_len) {
181 *error_out = tor_strdup("Empty body");
182 goto err;
183 }
184 cmdline_alloc = tor_memdup_nulterm(body, eol-body);
185 cmdline = cmdline_alloc;
186 ++eol;
187 result->cmddata_len = read_escaped_data(eol, (body+body_len)-eol,
188 &result->cmddata);
189 } else {
190 if (eol && (eol+1) != body+body_len) {
191 *error_out = tor_strdup("Unexpected body");
192 goto err;
193 }
194 cmdline = body;
195 }
196
197 result->args = smartlist_new();
198 smartlist_split_string(result->args, cmdline, " ",
199 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,
200 (int)(syntax->max_args+1));
201 size_t n_args = smartlist_len(result->args);
202 if (n_args < syntax->min_args) {
203 tor_asprintf(error_out, "Need at least %u argument(s)",
204 syntax->min_args);
205 goto err;
206 } else if (n_args > syntax->max_args && ! syntax->accept_keywords) {
207 tor_asprintf(error_out, "Cannot accept more than %u argument(s)",
208 syntax->max_args);
209 goto err;
210 }
211
212 if (n_args > syntax->max_args) {
213 /* We have extra arguments after the positional arguments, and we didn't
214 treat them as an error, so they must count as keyword arguments: Either
215 K=V pairs, or flags, or both. */
216 tor_assert(n_args == syntax->max_args + 1);
218 char *remainder = smartlist_pop_last(result->args);
219 result->kwargs = kvline_parse(remainder, syntax->kvline_flags);
220 tor_free(remainder);
221 if (kvline_check_keyword_args(result, syntax, error_out) < 0) {
222 goto err;
223 }
224 }
225
226 tor_assert_nonfatal(*error_out == NULL);
227 goto done;
228 err:
229 tor_assert_nonfatal(*error_out != NULL);
230 control_cmd_args_free(result);
231 done:
232 tor_free(cmdline_alloc);
233 return result;
234}
235
236/**
237 * Return true iff <b>lines</b> contains <b>flags</b> as a no-value
238 * (keyword-only) entry.
239 **/
240static bool
241config_lines_contain_flag(const config_line_t *lines, const char *flag)
242{
243 const config_line_t *line = config_line_find_case(lines, flag);
244 return line && !strcmp(line->value, "");
245}
246
247static const control_cmd_syntax_t setconf_syntax = {
248 .max_args=0,
249 .accept_keywords=true,
250 .kvline_flags=KV_OMIT_VALS|KV_QUOTED,
251};
252
253/** Called when we receive a SETCONF message: parse the body and try
254 * to update our configuration. Reply with a DONE or ERROR message.
255 * Modifies the contents of body.*/
256static int
258 const control_cmd_args_t *args)
259{
260 return control_setconf_helper(conn, args, 0);
261}
262
263static const control_cmd_syntax_t resetconf_syntax = {
264 .max_args=0,
265 .accept_keywords=true,
266 .kvline_flags=KV_OMIT_VALS|KV_QUOTED,
267};
268
269/** Called when we receive a RESETCONF message: parse the body and try
270 * to update our configuration. Reply with a DONE or ERROR message.
271 * Modifies the contents of body. */
272static int
274 const control_cmd_args_t *args)
275{
276 return control_setconf_helper(conn, args, 1);
277}
278
279static const control_cmd_syntax_t getconf_syntax = {
280 .max_args=UINT_MAX
281};
282
283/** Called when we receive a GETCONF message. Parse the request, and
284 * reply with a CONFVALUE or an ERROR message */
285static int
287 const control_cmd_args_t *args)
288{
289 const smartlist_t *questions = args->args;
290 smartlist_t *answers = smartlist_new();
291 smartlist_t *unrecognized = smartlist_new();
292 const or_options_t *options = get_options();
293
294 SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
295 if (!option_is_recognized(q)) {
296 control_reply_add_printf(unrecognized, 552,
297 "Unrecognized configuration key \"%s\"", q);
298 } else {
299 config_line_t *answer = option_get_assignment(options,q);
300 if (!answer) {
301 const char *name = option_get_canonical_name(q);
302 control_reply_add_one_kv(answers, 250, KV_OMIT_VALS, name, "");
303 }
304
305 while (answer) {
306 config_line_t *next;
307 control_reply_add_one_kv(answers, 250, KV_RAW, answer->key,
308 answer->value);
309 next = answer->next;
310 tor_free(answer->key);
311 tor_free(answer->value);
312 tor_free(answer);
313 answer = next;
314 }
315 }
316 } SMARTLIST_FOREACH_END(q);
317
318 if (smartlist_len(unrecognized)) {
319 control_write_reply_lines(conn, unrecognized);
320 } else if (smartlist_len(answers)) {
321 control_write_reply_lines(conn, answers);
322 } else {
323 send_control_done(conn);
324 }
325
326 control_reply_free(answers);
327 control_reply_free(unrecognized);
328 return 0;
329}
330
331static const control_cmd_syntax_t loadconf_syntax = {
332 .want_cmddata = true
333};
334
335/** Called when we get a +LOADCONF message. */
336static int
338 const control_cmd_args_t *args)
339{
340 setopt_err_t retval;
341 char *errstring = NULL;
342
343 retval = options_init_from_string(NULL, args->cmddata,
344 CMD_RUN_TOR, NULL, &errstring);
345
346 if (retval != SETOPT_OK)
347 log_warn(LD_CONTROL,
348 "Controller gave us config file that didn't validate: %s",
349 errstring);
350
351#define SEND_ERRMSG(code, msg) \
352 control_printf_endreply(conn, code, msg "%s%s", \
353 errstring ? ": " : "", \
354 errstring ? errstring : "")
355 switch (retval) {
356 case SETOPT_ERR_PARSE:
357 SEND_ERRMSG(552, "Invalid config file");
358 break;
359 case SETOPT_ERR_TRANSITION:
360 SEND_ERRMSG(553, "Transition not allowed");
361 break;
362 case SETOPT_ERR_SETTING:
363 SEND_ERRMSG(553, "Unable to set option");
364 break;
365 case SETOPT_ERR_MISC:
366 default:
367 SEND_ERRMSG(550, "Unable to load config");
368 break;
369 case SETOPT_OK:
370 send_control_done(conn);
371 break;
372 }
373#undef SEND_ERRMSG
374 tor_free(errstring);
375 return 0;
376}
377
378static const control_cmd_syntax_t setevents_syntax = {
379 .max_args = UINT_MAX
380};
381
382/** Called when we get a SETEVENTS message: update conn->event_mask,
383 * and reply with DONE or ERROR. */
384static int
386 const control_cmd_args_t *args)
387{
388 int event_code;
389 event_mask_t event_mask = 0;
390 const smartlist_t *events = args->args;
391
392 SMARTLIST_FOREACH_BEGIN(events, const char *, ev)
393 {
394 if (!strcasecmp(ev, "EXTENDED") ||
395 !strcasecmp(ev, "AUTHDIR_NEWDESCS")) {
396 log_warn(LD_CONTROL, "The \"%s\" SETEVENTS argument is no longer "
397 "supported.", ev);
398 continue;
399 } else {
400 int i;
401 event_code = -1;
402
403 for (i = 0; control_event_table[i].event_name != NULL; ++i) {
404 if (!strcasecmp(ev, control_event_table[i].event_name)) {
405 event_code = control_event_table[i].event_code;
406 break;
407 }
408 }
409
410 if (event_code == -1) {
411 control_printf_endreply(conn, 552, "Unrecognized event \"%s\"", ev);
412 return 0;
413 }
414 }
415 event_mask |= (((event_mask_t)1) << event_code);
416 }
417 SMARTLIST_FOREACH_END(ev);
418
419 conn->event_mask = event_mask;
420
422 send_control_done(conn);
423 return 0;
424}
425
426static const control_cmd_syntax_t saveconf_syntax = {
427 .max_args = 0,
428 .accept_keywords = true,
429 .kvline_flags=KV_OMIT_VALS,
430};
431
432/** Called when we get a SAVECONF command. Try to flush the current options to
433 * disk, and report success or failure. */
434static int
436 const control_cmd_args_t *args)
437{
438 bool force = config_lines_contain_flag(args->kwargs, "FORCE");
439 const or_options_t *options = get_options();
440 if ((!force && options->IncludeUsed) || options_save_current() < 0) {
441 control_write_endreply(conn, 551,
442 "Unable to write configuration to disk.");
443 } else {
444 send_control_done(conn);
445 }
446 return 0;
447}
448
449static const control_cmd_syntax_t signal_syntax = {
450 .min_args = 1,
451 .max_args = 1,
452};
453
454/** Called when we get a SIGNAL command. React to the provided signal, and
455 * report success or failure. (If the signal results in a shutdown, success
456 * may not be reported.) */
457static int
459 const control_cmd_args_t *args)
460{
461 int sig = -1;
462 int i;
463
464 tor_assert(smartlist_len(args->args) == 1);
465 const char *s = smartlist_get(args->args, 0);
466
467 for (i = 0; signal_table[i].signal_name != NULL; ++i) {
468 if (!strcasecmp(s, signal_table[i].signal_name)) {
469 sig = signal_table[i].sig;
470 break;
471 }
472 }
473
474 if (sig < 0)
475 control_printf_endreply(conn, 552, "Unrecognized signal code \"%s\"", s);
476 if (sig < 0)
477 return 0;
478
479 send_control_done(conn);
480 /* Flush the "done" first if the signal might make us shut down. */
481 if (sig == SIGTERM || sig == SIGINT)
483
484 activate_signal(sig);
485
486 return 0;
487}
488
489static const control_cmd_syntax_t takeownership_syntax = {
490 .max_args = UINT_MAX, // This should probably become zero. XXXXX
491};
492
493/** Called when we get a TAKEOWNERSHIP command. Mark this connection
494 * as an owning connection, so that we will exit if the connection
495 * closes. */
496static int
498 const control_cmd_args_t *args)
499{
500 (void)args;
501
503
504 log_info(LD_CONTROL, "Control connection %d has taken ownership of this "
505 "Tor instance.",
506 (int)(conn->base_.s));
507
508 send_control_done(conn);
509 return 0;
510}
511
512static const control_cmd_syntax_t dropownership_syntax = {
513 .max_args = UINT_MAX, // This should probably become zero. XXXXX
514};
515
516/** Called when we get a DROPOWNERSHIP command. Mark this connection
517 * as a non-owning connection, so that we will not exit if the connection
518 * closes. */
519static int
521 const control_cmd_args_t *args)
522{
523 (void)args;
524
526
527 log_info(LD_CONTROL, "Control connection %d has dropped ownership of this "
528 "Tor instance.",
529 (int)(conn->base_.s));
530
531 send_control_done(conn);
532 return 0;
533}
534
535/** Given a text circuit <b>id</b>, return the corresponding circuit. */
536static origin_circuit_t *
537get_circ(const char *id)
538{
539 uint32_t n_id;
540 int ok;
541 n_id = (uint32_t) tor_parse_ulong(id, 10, 0, UINT32_MAX, &ok, NULL);
542 if (!ok)
543 return NULL;
544 return circuit_get_by_global_id(n_id);
545}
546
547/** Given a text stream <b>id</b>, return the corresponding AP connection. */
548static entry_connection_t *
549get_stream(const char *id)
550{
551 uint64_t n_id;
552 int ok;
553 connection_t *conn;
554 n_id = tor_parse_uint64(id, 10, 0, UINT64_MAX, &ok, NULL);
555 if (!ok)
556 return NULL;
557 conn = connection_get_by_global_id(n_id);
558 if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close)
559 return NULL;
560 return TO_ENTRY_CONN(conn);
561}
562
563/** Helper for setconf and resetconf. Acts like setconf, except
564 * it passes <b>use_defaults</b> on to options_trial_assign(). Modifies the
565 * contents of body.
566 */
567static int
569 const control_cmd_args_t *args,
570 int use_defaults)
571{
572 setopt_err_t opt_err;
573 char *errstring = NULL;
574 const unsigned flags =
575 CAL_CLEAR_FIRST | (use_defaults ? CAL_USE_DEFAULTS : 0);
576
577 // We need a copy here, since confmgt.c wants to canonicalize cases.
578 config_line_t *lines = config_lines_dup(args->kwargs);
579
580 opt_err = options_trial_assign(lines, flags, &errstring);
581 {
582#define SEND_ERRMSG(code, msg) \
583 control_printf_endreply(conn, code, msg ": %s", errstring);
584
585 switch (opt_err) {
586 case SETOPT_ERR_MISC:
587 SEND_ERRMSG(552, "Unrecognized option");
588 break;
589 case SETOPT_ERR_PARSE:
590 SEND_ERRMSG(513, "Unacceptable option value");
591 break;
592 case SETOPT_ERR_TRANSITION:
593 SEND_ERRMSG(553, "Transition not allowed");
594 break;
595 case SETOPT_ERR_SETTING:
596 default:
597 SEND_ERRMSG(553, "Unable to set option");
598 break;
599 case SETOPT_OK:
600 config_free_lines(lines);
601 send_control_done(conn);
602 return 0;
603 }
604#undef SEND_ERRMSG
605 log_warn(LD_CONTROL,
606 "Controller gave us config lines that didn't validate: %s",
607 errstring);
608 config_free_lines(lines);
609 tor_free(errstring);
610 return 0;
611 }
612}
613
614/** Return true iff <b>addr</b> is unusable as a mapaddress target because of
615 * containing funny characters. */
616static int
618{
619 if (!strcmpstart(addr, "*."))
620 return address_is_invalid_destination(addr+2, 1);
621 else
622 return address_is_invalid_destination(addr, 1);
623}
624
625static const control_cmd_syntax_t mapaddress_syntax = {
626 // no positional arguments are expected
627 .max_args=0,
628 // an arbitrary number of K=V entries are supported.
629 .accept_keywords=true,
630};
631
632/** Called when we get a MAPADDRESS command; try to bind all listed addresses,
633 * and report success or failure. */
634static int
636 const control_cmd_args_t *args)
637{
638 smartlist_t *reply;
639 char *r;
640 size_t sz;
641
642 reply = smartlist_new();
643 const config_line_t *line;
644 for (line = args->kwargs; line; line = line->next) {
645 const char *from = line->key;
646 const char *to = line->value;
647 {
650 "512-syntax error: invalid address '%s'", to);
651 log_warn(LD_CONTROL,
652 "Skipping invalid argument '%s' in MapAddress msg", to);
653 } else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0") ||
654 !strcmp(from, "::")) {
655 const char type =
656 !strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME :
657 (!strcmp(from, "0.0.0.0") ? RESOLVED_TYPE_IPV4 : RESOLVED_TYPE_IPV6);
658 const char *address = addressmap_register_virtual_address(
659 type, tor_strdup(to));
660 if (!address) {
662 "451-resource exhausted: skipping '%s=%s'", from,to);
663 log_warn(LD_CONTROL,
664 "Unable to allocate address for '%s' in MapAddress msg",
665 safe_str_client(to));
666 } else {
667 smartlist_add_asprintf(reply, "250-%s=%s", address, to);
668 }
669 } else {
670 const char *msg;
671 if (addressmap_register_auto(from, to, 1,
672 ADDRMAPSRC_CONTROLLER, &msg) < 0) {
674 "512-syntax error: invalid address mapping "
675 " '%s=%s': %s", from, to, msg);
676 log_warn(LD_CONTROL,
677 "Skipping invalid argument '%s=%s' in MapAddress msg: %s",
678 from, to, msg);
679 } else {
680 smartlist_add_asprintf(reply, "250-%s=%s", from, to);
681 }
682 }
683 }
684 }
685
686 if (smartlist_len(reply)) {
687 ((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
688 r = smartlist_join_strings(reply, "\r\n", 1, &sz);
689 connection_buf_add(r, sz, TO_CONN(conn));
690 tor_free(r);
691 } else {
692 control_write_endreply(conn, 512, "syntax error: "
693 "not enough arguments to mapaddress.");
694 }
695
696 SMARTLIST_FOREACH(reply, char *, cp, tor_free(cp));
697 smartlist_free(reply);
698 return 0;
699}
700
701/** Given a string, convert it to a circuit purpose. */
702static uint8_t
704{
705 if (!strcasecmpstart(string, "purpose="))
706 string += strlen("purpose=");
707
708 if (!strcasecmp(string, "general"))
710 else if (!strcasecmp(string, "controller"))
712 else
714}
715
716static const control_cmd_syntax_t extendcircuit_syntax = {
717 .min_args=1,
718 .max_args=1, // see note in function
719 .accept_keywords=true,
720 .kvline_flags=KV_OMIT_VALS
721};
722
723/** Called when we get an EXTENDCIRCUIT message. Try to extend the listed
724 * circuit, and report success or failure. */
725static int
727 const control_cmd_args_t *args)
728{
729 smartlist_t *router_nicknames=smartlist_new(), *nodes=NULL;
730 origin_circuit_t *circ = NULL;
731 uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
732 const config_line_t *kwargs = args->kwargs;
733 const char *circ_id = smartlist_get(args->args, 0);
734 const char *path_str = NULL;
735 char *path_str_alloc = NULL;
736
737 /* The syntax for this command is unfortunate. The second argument is
738 optional, and is a comma-separated list long-format fingerprints, which
739 can (historically!) contain an equals sign.
740
741 Here we check the second argument to see if it's a path, and if so we
742 remove it from the kwargs list and put it in path_str.
743 */
744 if (kwargs) {
745 const config_line_t *arg1 = kwargs;
746 if (!strcmp(arg1->value, "")) {
747 path_str = arg1->key;
748 kwargs = kwargs->next;
749 } else if (arg1->key[0] == '$') {
750 tor_asprintf(&path_str_alloc, "%s=%s", arg1->key, arg1->value);
751 path_str = path_str_alloc;
752 kwargs = kwargs->next;
753 }
754 }
755
756 const config_line_t *purpose_line = config_line_find_case(kwargs, "PURPOSE");
757 bool zero_circ = !strcmp("0", circ_id);
758
759 if (purpose_line) {
760 intended_purpose = circuit_purpose_from_string(purpose_line->value);
761 if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
762 control_printf_endreply(conn, 552, "Unknown purpose \"%s\"",
763 purpose_line->value);
764 goto done;
765 }
766 }
767
768 if (zero_circ) {
769 if (!path_str) {
770 // "EXTENDCIRCUIT 0" with no path.
771 circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
772 if (!circ) {
773 control_write_endreply(conn, 551, "Couldn't start circuit");
774 } else {
775 control_printf_endreply(conn, 250, "EXTENDED %lu",
776 (unsigned long)circ->global_identifier);
777 }
778 goto done;
779 }
780 }
781
782 if (!zero_circ && !(circ = get_circ(circ_id))) {
783 control_printf_endreply(conn, 552, "Unknown circuit \"%s\"", circ_id);
784 goto done;
785 }
786
787 if (!path_str) {
788 control_write_endreply(conn, 512, "syntax error: path required.");
789 goto done;
790 }
791
792 smartlist_split_string(router_nicknames, path_str, ",", 0, 0);
793
794 nodes = smartlist_new();
795 bool first_node = zero_circ;
796 SMARTLIST_FOREACH_BEGIN(router_nicknames, const char *, n) {
797 const node_t *node = node_get_by_nickname(n, 0);
798 if (!node) {
799 control_printf_endreply(conn, 552, "No such router \"%s\"", n);
800 goto done;
801 }
802 if (!node_has_preferred_descriptor(node, first_node)) {
803 control_printf_endreply(conn, 552, "No descriptor for \"%s\"", n);
804 goto done;
805 }
806 smartlist_add(nodes, (void*)node);
807 first_node = false;
808 } SMARTLIST_FOREACH_END(n);
809
810 if (!smartlist_len(nodes)) {
811 control_write_endreply(conn, 512, "No router names provided");
812 goto done;
813 }
814
815 if (zero_circ) {
816 /* start a new circuit */
817 circ = origin_circuit_init(intended_purpose, 0);
819 }
820
821 circ->any_hop_from_controller = 1;
822
823 /* now circ refers to something that is ready to be extended */
824 first_node = zero_circ;
825 SMARTLIST_FOREACH(nodes, const node_t *, node,
826 {
827 /* We treat every hop as an exit to try to negotiate congestion
828 * control, because we have no idea which hop the controller wil
829 * try to use for streams and when */
830 extend_info_t *info = extend_info_from_node(node, first_node, true);
831 if (!info) {
832 tor_assert_nonfatal(first_node);
833 log_warn(LD_CONTROL,
834 "controller tried to connect to a node that lacks a suitable "
835 "descriptor, or which doesn't have any "
836 "addresses that are allowed by the firewall configuration; "
837 "circuit marked for closing.");
838 circuit_mark_for_close(TO_CIRCUIT(circ), -END_CIRC_REASON_CONNECTFAILED);
839 control_write_endreply(conn, 551, "Couldn't start circuit");
840 goto done;
841 }
842 circuit_append_new_exit(circ, info);
843 if (circ->build_state->desired_path_len > 1) {
844 circ->build_state->onehop_tunnel = 0;
845 }
846 extend_info_free(info);
847 first_node = 0;
848 });
849
850 /* now that we've populated the cpath, start extending */
851 if (zero_circ) {
852 int err_reason = 0;
853 if ((err_reason = circuit_handle_first_hop(circ)) < 0) {
854 circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
855 control_write_endreply(conn, 551, "Couldn't start circuit");
856 goto done;
857 }
858 } else {
859 if (circ->base_.state == CIRCUIT_STATE_OPEN ||
860 circ->base_.state == CIRCUIT_STATE_GUARD_WAIT) {
861 int err_reason = 0;
863 if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
864 log_info(LD_CONTROL,
865 "send_next_onion_skin failed; circuit marked for closing.");
866 circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason);
867 control_write_endreply(conn, 551, "Couldn't send onion skin");
868 goto done;
869 }
870 }
871 }
872
873 control_printf_endreply(conn, 250, "EXTENDED %lu",
874 (unsigned long)circ->global_identifier);
875 if (zero_circ) /* send a 'launched' event, for completeness */
876 circuit_event_status(circ, CIRC_EVENT_LAUNCHED, 0);
877 done:
878 SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
879 smartlist_free(router_nicknames);
880 smartlist_free(nodes);
881 tor_free(path_str_alloc);
882 return 0;
883}
884
885static const control_cmd_syntax_t setcircuitpurpose_syntax = {
886 .min_args=1,
887 .max_args=1,
888 .accept_keywords=true,
889};
890
891/** Called when we get a SETCIRCUITPURPOSE message. If we can find the
892 * circuit and it's a valid purpose, change it. */
893static int
895 const control_cmd_args_t *args)
896{
897 origin_circuit_t *circ = NULL;
898 uint8_t new_purpose;
899 const char *circ_id = smartlist_get(args->args,0);
900
901 if (!(circ = get_circ(circ_id))) {
902 control_printf_endreply(conn, 552, "Unknown circuit \"%s\"", circ_id);
903 goto done;
904 }
905
906 {
907 const config_line_t *purp = config_line_find_case(args->kwargs, "PURPOSE");
908 if (!purp) {
909 control_write_endreply(conn, 552, "No purpose given");
910 goto done;
911 }
912 new_purpose = circuit_purpose_from_string(purp->value);
913 if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
914 control_printf_endreply(conn, 552, "Unknown purpose \"%s\"",
915 purp->value);
916 goto done;
917 }
918 }
919
920 circuit_change_purpose(TO_CIRCUIT(circ), new_purpose);
921 send_control_done(conn);
922
923 done:
924 return 0;
925}
926
927static const char *attachstream_keywords[] = {
928 "HOP", NULL
929};
930static const control_cmd_syntax_t attachstream_syntax = {
931 .min_args=2, .max_args=2,
932 .accept_keywords=true,
933 .allowed_keywords=attachstream_keywords
934};
935
936/** Called when we get an ATTACHSTREAM message. Try to attach the requested
937 * stream, and report success or failure. */
938static int
940 const control_cmd_args_t *args)
941{
942 entry_connection_t *ap_conn = NULL;
943 origin_circuit_t *circ = NULL;
944 crypt_path_t *cpath=NULL;
945 int hop=0, hop_line_ok=1;
946 const char *stream_id = smartlist_get(args->args, 0);
947 const char *circ_id = smartlist_get(args->args, 1);
948 int zero_circ = !strcmp(circ_id, "0");
949 const config_line_t *hoparg = config_line_find_case(args->kwargs, "HOP");
950
951 if (!(ap_conn = get_stream(stream_id))) {
952 control_printf_endreply(conn, 552, "Unknown stream \"%s\"", stream_id);
953 return 0;
954 } else if (!zero_circ && !(circ = get_circ(circ_id))) {
955 control_printf_endreply(conn, 552, "Unknown circuit \"%s\"", circ_id);
956 return 0;
957 } else if (circ) {
958 if (hoparg) {
959 hop = (int) tor_parse_ulong(hoparg->value, 10, 0, INT_MAX,
960 &hop_line_ok, NULL);
961 if (!hop_line_ok) { /* broken hop line */
962 control_printf_endreply(conn, 552, "Bad value hop=%s",
963 hoparg->value);
964 return 0;
965 }
966 }
967 }
968
969 if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT &&
970 ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONNECT_WAIT &&
971 ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_RESOLVE_WAIT) {
972 control_write_endreply(conn, 555,
973 "Connection is not managed by controller.");
974 return 0;
975 }
976
977 /* Do we need to detach it first? */
978 if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT) {
979 edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
980 circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn);
981 connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT);
982 /* Un-mark it as ending, since we're going to reuse it. */
983 edge_conn->edge_has_sent_end = 0;
984 edge_conn->end_reason = 0;
985 if (tmpcirc)
986 circuit_detach_stream(tmpcirc, edge_conn);
988 }
989
990 if (circ && (circ->base_.state != CIRCUIT_STATE_OPEN)) {
991 control_write_endreply(conn, 551,
992 "Can't attach stream to non-open origin circuit");
993 return 0;
994 }
995 /* Is this a single hop circuit? */
996 if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
997 control_write_endreply(conn, 551,
998 "Can't attach stream to this one-hop circuit.");
999 return 0;
1000 }
1001
1002 if (circ && hop>0) {
1003 /* find this hop in the circuit, and set cpath */
1004 cpath = circuit_get_cpath_hop(circ, hop);
1005 if (!cpath) {
1006 control_printf_endreply(conn, 551, "Circuit doesn't have %d hops.", hop);
1007 return 0;
1008 }
1009 }
1010 if (connection_ap_handshake_rewrite_and_attach(ap_conn, circ, cpath) < 0) {
1011 control_write_endreply(conn, 551, "Unable to attach stream");
1012 return 0;
1013 }
1014 send_control_done(conn);
1015 return 0;
1016}
1017
1018static const char *postdescriptor_keywords[] = {
1019 "cache", "purpose", NULL,
1020};
1021
1022static const control_cmd_syntax_t postdescriptor_syntax = {
1023 .max_args = 0,
1024 .accept_keywords = true,
1025 .allowed_keywords = postdescriptor_keywords,
1026 .want_cmddata = true,
1027};
1028
1029/** Called when we get a POSTDESCRIPTOR message. Try to learn the provided
1030 * descriptor, and report success or failure. */
1031static int
1033 const control_cmd_args_t *args)
1034{
1035 const char *msg=NULL;
1036 uint8_t purpose = ROUTER_PURPOSE_GENERAL;
1037 int cache = 0; /* eventually, we may switch this to 1 */
1038 const config_line_t *line;
1039
1040 line = config_line_find_case(args->kwargs, "purpose");
1041 if (line) {
1042 purpose = router_purpose_from_string(line->value);
1043 if (purpose == ROUTER_PURPOSE_UNKNOWN) {
1044 control_printf_endreply(conn, 552, "Unknown purpose \"%s\"",
1045 line->value);
1046 goto done;
1047 }
1048 }
1049 line = config_line_find_case(args->kwargs, "cache");
1050 if (line) {
1051 if (!strcasecmp(line->value, "no"))
1052 cache = 0;
1053 else if (!strcasecmp(line->value, "yes"))
1054 cache = 1;
1055 else {
1056 control_printf_endreply(conn, 552, "Unknown cache request \"%s\"",
1057 line->value);
1058 goto done;
1059 }
1060 }
1061
1062 switch (router_load_single_router(args->cmddata, purpose, cache, &msg)) {
1063 case -1:
1064 if (!msg) msg = "Could not parse descriptor";
1065 control_write_endreply(conn, 554, msg);
1066 break;
1067 case 0:
1068 if (!msg) msg = "Descriptor not added";
1069 control_write_endreply(conn, 251, msg);
1070 break;
1071 case 1:
1072 send_control_done(conn);
1073 break;
1074 }
1075
1076 done:
1077 return 0;
1078}
1079
1080static const control_cmd_syntax_t redirectstream_syntax = {
1081 .min_args = 2,
1082 .max_args = UINT_MAX, // XXX should be 3.
1083};
1084
1085/** Called when we receive a REDIRECTSTREAM command. Try to change the target
1086 * address of the named AP stream, and report success or failure. */
1087static int
1089 const control_cmd_args_t *cmd_args)
1090{
1091 entry_connection_t *ap_conn = NULL;
1092 char *new_addr = NULL;
1093 uint16_t new_port = 0;
1094 const smartlist_t *args = cmd_args->args;
1095
1096 if (!(ap_conn = get_stream(smartlist_get(args, 0)))
1097 || !ap_conn->socks_request) {
1098 control_printf_endreply(conn, 552, "Unknown stream \"%s\"",
1099 (char*)smartlist_get(args, 0));
1100 } else {
1101 int ok = 1;
1102 if (smartlist_len(args) > 2) { /* they included a port too */
1103 new_port = (uint16_t) tor_parse_ulong(smartlist_get(args, 2),
1104 10, 1, 65535, &ok, NULL);
1105 }
1106 if (!ok) {
1107 control_printf_endreply(conn, 512, "Cannot parse port \"%s\"",
1108 (char*)smartlist_get(args, 2));
1109 } else {
1110 new_addr = tor_strdup(smartlist_get(args, 1));
1111 }
1112 }
1113
1114 if (!new_addr)
1115 return 0;
1116
1117 strlcpy(ap_conn->socks_request->address, new_addr,
1118 sizeof(ap_conn->socks_request->address));
1119 if (new_port)
1120 ap_conn->socks_request->port = new_port;
1121 tor_free(new_addr);
1122 send_control_done(conn);
1123 return 0;
1124}
1125
1126static const control_cmd_syntax_t closestream_syntax = {
1127 .min_args = 2,
1128 .max_args = UINT_MAX, /* XXXX This is the original behavior, but
1129 * maybe we should change the spec. */
1130};
1131
1132/** Called when we get a CLOSESTREAM command; try to close the named stream
1133 * and report success or failure. */
1134static int
1136 const control_cmd_args_t *cmd_args)
1137{
1138 entry_connection_t *ap_conn=NULL;
1139 uint8_t reason=0;
1140 int ok;
1141 const smartlist_t *args = cmd_args->args;
1142
1143 tor_assert(smartlist_len(args) >= 2);
1144
1145 if (!(ap_conn = get_stream(smartlist_get(args, 0))))
1146 control_printf_endreply(conn, 552, "Unknown stream \"%s\"",
1147 (char*)smartlist_get(args, 0));
1148 else {
1149 reason = (uint8_t) tor_parse_ulong(smartlist_get(args,1), 10, 0, 255,
1150 &ok, NULL);
1151 if (!ok) {
1152 control_printf_endreply(conn, 552, "Unrecognized reason \"%s\"",
1153 (char*)smartlist_get(args, 1));
1154 ap_conn = NULL;
1155 }
1156 }
1157 if (!ap_conn)
1158 return 0;
1159
1160 connection_mark_unattached_ap(ap_conn, reason);
1161 send_control_done(conn);
1162 return 0;
1163}
1164
1165static const control_cmd_syntax_t closecircuit_syntax = {
1166 .min_args=1, .max_args=1,
1167 .accept_keywords=true,
1168 .kvline_flags=KV_OMIT_VALS,
1169 // XXXX we might want to exclude unrecognized flags, but for now we
1170 // XXXX just ignore them for backward compatibility.
1171};
1172
1173/** Called when we get a CLOSECIRCUIT command; try to close the named circuit
1174 * and report success or failure. */
1175static int
1177 const control_cmd_args_t *args)
1178{
1179 const char *circ_id = smartlist_get(args->args, 0);
1180 origin_circuit_t *circ = NULL;
1181
1182 if (!(circ=get_circ(circ_id))) {
1183 control_printf_endreply(conn, 552, "Unknown circuit \"%s\"", circ_id);
1184 return 0;
1185 }
1186
1187 bool safe = config_lines_contain_flag(args->kwargs, "IfUnused");
1188
1189 if (!safe || !circ->p_streams) {
1190 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_REQUESTED);
1191 }
1192
1193 send_control_done(conn);
1194 return 0;
1195}
1196
1197static const control_cmd_syntax_t resolve_syntax = {
1198 .max_args=0,
1199 .accept_keywords=true,
1200 .kvline_flags=KV_OMIT_VALS,
1201};
1202
1203/** Called when we get a RESOLVE command: start trying to resolve
1204 * the listed addresses. */
1205static int
1207 const control_cmd_args_t *args)
1208{
1209 smartlist_t *failed;
1210 int is_reverse = 0;
1211
1212 if (!(conn->event_mask & (((event_mask_t)1)<<EVENT_ADDRMAP))) {
1213 log_warn(LD_CONTROL, "Controller asked us to resolve an address, but "
1214 "isn't listening for ADDRMAP events. It probably won't see "
1215 "the answer.");
1216 }
1217
1218 {
1219 const config_line_t *modearg = config_line_find_case(args->kwargs, "mode");
1220 if (modearg && !strcasecmp(modearg->value, "reverse"))
1221 is_reverse = 1;
1222 }
1223 failed = smartlist_new();
1224 for (const config_line_t *line = args->kwargs; line; line = line->next) {
1225 if (!strlen(line->value)) {
1226 const char *addr = line->key;
1227 if (dnsserv_launch_request(addr, is_reverse, conn)<0)
1228 smartlist_add(failed, (char*)addr);
1229 } else {
1230 // XXXX arguably we should reject unrecognized keyword arguments,
1231 // XXXX but the old implementation didn't do that.
1232 }
1233 }
1234
1235 send_control_done(conn);
1236 SMARTLIST_FOREACH(failed, const char *, arg, {
1237 control_event_address_mapped(arg, arg, time(NULL),
1238 "internal", 0, 0);
1239 });
1240
1241 smartlist_free(failed);
1242 return 0;
1243}
1244
1245static const control_cmd_syntax_t protocolinfo_syntax = {
1246 .max_args = UINT_MAX
1247};
1248
1249/** Return a comma-separated list of authentication methods for
1250 handle_control_protocolinfo(). Caller must free this string. */
1251static char *
1253{
1254 int cookies = options->CookieAuthentication;
1255 char *methods;
1256 int passwd = (options->HashedControlPassword != NULL ||
1257 options->HashedControlSessionPassword != NULL);
1258 smartlist_t *mlist = smartlist_new();
1259
1260 if (cookies) {
1261 smartlist_add(mlist, (char*)"COOKIE");
1262 smartlist_add(mlist, (char*)"SAFECOOKIE");
1263 }
1264 if (passwd)
1265 smartlist_add(mlist, (char*)"HASHEDPASSWORD");
1266 if (!cookies && !passwd)
1267 smartlist_add(mlist, (char*)"NULL");
1268 methods = smartlist_join_strings(mlist, ",", 0, NULL);
1269 smartlist_free(mlist);
1270
1271 return methods;
1272}
1273
1274/** Return escaped cookie filename. Caller must free this string.
1275 Return NULL if cookie authentication is disabled. */
1276static char *
1278{
1279 char *cfile = NULL, *abs_cfile = NULL, *esc_cfile = NULL;
1280
1281 if (!options->CookieAuthentication)
1282 return NULL;
1283
1285 abs_cfile = make_path_absolute(cfile);
1286 esc_cfile = esc_for_log(abs_cfile);
1287 tor_free(cfile);
1288 tor_free(abs_cfile);
1289 return esc_cfile;
1290}
1291
1292/** Compose the auth methods line of a PROTOCOLINFO reply. */
1293static void
1295{
1296 const or_options_t *options = get_options();
1297 char *methods = get_authmethods(options);
1298 char *esc_cfile = get_esc_cfile(options);
1299
1300 control_reply_add_str(reply, 250, "AUTH");
1301 control_reply_append_kv(reply, "METHODS", methods);
1302 if (esc_cfile)
1303 control_reply_append_kv(reply, "COOKIEFILE", esc_cfile);
1304
1305 tor_free(methods);
1306 tor_free(esc_cfile);
1307}
1308
1309/** Called when we get a PROTOCOLINFO command: send back a reply. */
1310static int
1312 const control_cmd_args_t *cmd_args)
1313{
1314 const char *bad_arg = NULL;
1315 const smartlist_t *args = cmd_args->args;
1316 smartlist_t *reply = NULL;
1317
1318 conn->have_sent_protocolinfo = 1;
1319
1320 SMARTLIST_FOREACH(args, const char *, arg, {
1321 int ok;
1322 tor_parse_long(arg, 10, 0, LONG_MAX, &ok, NULL);
1323 if (!ok) {
1324 bad_arg = arg;
1325 break;
1326 }
1327 });
1328 if (bad_arg) {
1329 control_printf_endreply(conn, 513, "No such version %s",
1330 escaped(bad_arg));
1331 /* Don't tolerate bad arguments when not authenticated. */
1332 if (!STATE_IS_OPEN(TO_CONN(conn)->state))
1333 connection_mark_for_close(TO_CONN(conn));
1334 return 0;
1335 }
1336 reply = smartlist_new();
1337 control_reply_add_str(reply, 250, "PROTOCOLINFO 1");
1338 add_authmethods(reply);
1339 control_reply_add_str(reply, 250, "VERSION");
1340 control_reply_append_kv(reply, "Tor", escaped(VERSION));
1342
1343 control_write_reply_lines(conn, reply);
1344 control_reply_free(reply);
1345 return 0;
1346}
1347
1348static const control_cmd_syntax_t usefeature_syntax = {
1349 .max_args = UINT_MAX
1350};
1351
1352/** Called when we get a USEFEATURE command: parse the feature list, and
1353 * set up the control_connection's options properly. */
1354static int
1356 const control_cmd_args_t *cmd_args)
1357{
1358 const smartlist_t *args = cmd_args->args;
1359 int bad = 0;
1360 SMARTLIST_FOREACH_BEGIN(args, const char *, arg) {
1361 if (!strcasecmp(arg, "VERBOSE_NAMES"))
1362 ;
1363 else if (!strcasecmp(arg, "EXTENDED_EVENTS"))
1364 ;
1365 else {
1366 control_printf_endreply(conn, 552, "Unrecognized feature \"%s\"",
1367 arg);
1368 bad = 1;
1369 break;
1370 }
1371 } SMARTLIST_FOREACH_END(arg);
1372
1373 if (!bad) {
1374 send_control_done(conn);
1375 }
1376
1377 return 0;
1378}
1379
1380static const control_cmd_syntax_t dropguards_syntax = {
1381 .max_args = 0,
1382};
1383
1384/** Implementation for the DROPGUARDS command. */
1385static int
1387 const control_cmd_args_t *args)
1388{
1389 (void) args; /* We don't take arguments. */
1390
1391 static int have_warned = 0;
1392 if (! have_warned) {
1393 log_warn(LD_CONTROL, "DROPGUARDS is dangerous; make sure you understand "
1394 "the risks before using it. It may be removed in a future "
1395 "version of Tor.");
1396 have_warned = 1;
1397 }
1398
1400 send_control_done(conn);
1401
1402 return 0;
1403}
1404
1405static const control_cmd_syntax_t droptimeouts_syntax = {
1406 .max_args = 0,
1407};
1408
1409/** Implementation for the DROPTIMEOUTS command. */
1410static int
1412 const control_cmd_args_t *args)
1413{
1414 (void) args; /* We don't take arguments. */
1415
1416 static int have_warned = 0;
1417 if (! have_warned) {
1418 log_warn(LD_CONTROL, "DROPTIMEOUTS is dangerous; make sure you understand "
1419 "the risks before using it. It may be removed in a future "
1420 "version of Tor.");
1421 have_warned = 1;
1422 }
1423
1425 send_control_done(conn);
1427 cbt_control_event_buildtimeout_set(get_circuit_build_times(),
1428 BUILDTIMEOUT_SET_EVENT_RESET);
1429
1430 return 0;
1431}
1432
1433static const char *hsfetch_keywords[] = {
1434 "SERVER", NULL,
1435};
1436static const control_cmd_syntax_t hsfetch_syntax = {
1437 .min_args = 1, .max_args = 1,
1438 .accept_keywords = true,
1439 .allowed_keywords = hsfetch_keywords,
1440};
1441
1442/** Implementation for the HSFETCH command. */
1443static int
1445 const control_cmd_args_t *args)
1446
1447{
1448 smartlist_t *hsdirs = NULL;
1450 uint32_t version;
1451 const char *hsaddress = NULL;
1452
1453 /* Extract the first argument (either HSAddress or DescID). */
1454 const char *arg1 = smartlist_get(args->args, 0);
1455 if (hs_address_is_valid(arg1)) {
1456 hsaddress = arg1;
1457 version = HS_VERSION_THREE;
1458 hs_parse_address(hsaddress, &v3_pk, NULL, NULL);
1459 } else {
1460 control_printf_endreply(conn, 513, "Invalid argument \"%s\"", arg1);
1461 goto done;
1462 }
1463
1464 for (const config_line_t *line = args->kwargs; line; line = line->next) {
1465 if (!strcasecmp(line->key, "SERVER")) {
1466 const char *server = line->value;
1467
1468 const node_t *node = node_get_by_hex_id(server, 0);
1469 /* As with HSPOST, we need a routerstatus to use this as an HSDir. */
1470 if (!node || !node->rs) {
1471 control_printf_endreply(conn, 552, "Server \"%s\" not found", server);
1472 goto done;
1473 }
1474 if (!hsdirs) {
1475 /* Stores routerstatus_t cmddata for each specified server. */
1476 hsdirs = smartlist_new();
1477 }
1478 /* Valid server, add it to our local list. */
1479 smartlist_add(hsdirs, node->rs);
1480 } else {
1482 }
1483 }
1484
1485 /* We are about to trigger HSDir fetch so send the OK now because after
1486 * that 650 event(s) are possible so better to have the 250 OK before them
1487 * to avoid out of order replies. */
1488 send_control_done(conn);
1489
1490 /* Trigger the fetch using the built rend query and possibly a list of HS
1491 * directory to use. This function ignores the client cache thus this will
1492 * always send a fetch command. */
1493 if (version == HS_VERSION_THREE) {
1494 hs_control_hsfetch_command(&v3_pk, hsdirs);
1495 }
1496
1497 done:
1498 /* Contains data pointer that we don't own thus no cleanup. */
1499 smartlist_free(hsdirs);
1500 return 0;
1501}
1502
1503static const char *hspost_keywords[] = {
1504 "SERVER", "HSADDRESS", NULL
1505};
1506static const control_cmd_syntax_t hspost_syntax = {
1507 .min_args = 0, .max_args = 0,
1508 .accept_keywords = true,
1509 .want_cmddata = true,
1510 .allowed_keywords = hspost_keywords
1511};
1512
1513/** Implementation for the HSPOST command. */
1514static int
1516 const control_cmd_args_t *args)
1517{
1518 smartlist_t *hs_dirs = NULL;
1519 const char *encoded_desc = args->cmddata;
1520 const char *onion_address = NULL;
1521 const config_line_t *line;
1522
1523 for (line = args->kwargs; line; line = line->next) {
1524 if (!strcasecmpstart(line->key, "SERVER")) {
1525 const char *server = line->value;
1526 const node_t *node = node_get_by_hex_id(server, 0);
1527
1528 if (!node || !node->rs) {
1529 control_printf_endreply(conn, 552, "Server \"%s\" not found",
1530 server);
1531 goto done;
1532 }
1533 /* Valid server, add it to our local list. */
1534 if (!hs_dirs)
1535 hs_dirs = smartlist_new();
1536 smartlist_add(hs_dirs, node->rs);
1537 } else if (!strcasecmpstart(line->key, "HSADDRESS")) {
1538 const char *address = line->value;
1539 if (!hs_address_is_valid(address)) {
1540 control_write_endreply(conn, 512, "Malformed onion address");
1541 goto done;
1542 }
1543 onion_address = address;
1544 } else {
1546 }
1547 }
1548
1549 /* Handle the v3 case. */
1550 if (onion_address) {
1551 if (hs_control_hspost_command(encoded_desc, onion_address, hs_dirs) < 0) {
1552 control_write_endreply(conn, 554, "Invalid descriptor");
1553 } else {
1554 send_control_done(conn);
1555 }
1556 goto done;
1557 }
1558
1559 done:
1560 smartlist_free(hs_dirs); /* Contents belong to the rend service code. */
1561 return 0;
1562}
1563
1564/* Helper function for ADD_ONION that adds an ephemeral service depending on
1565 * the given hs_version.
1566 *
1567 * The secret key in pk depends on the hs_version. The ownership of the key
1568 * used in pk is given to the HS subsystem so the caller must stop accessing
1569 * it after.
1570 *
1571 * The port_cfgs is a list of service port. Ownership transferred to service.
1572 * The max_streams refers to the MaxStreams= key.
1573 * The max_streams_close_circuit refers to the MaxStreamsCloseCircuit key.
1574 * The ownership of that list is transferred to the service.
1575 *
1576 * On success (RSAE_OKAY), the address_out points to a newly allocated string
1577 * containing the onion address without the .onion part. On error, address_out
1578 * is untouched. */
1580add_onion_helper_add_service(int hs_version,
1581 add_onion_secret_key_t *pk,
1582 smartlist_t *port_cfgs, int max_streams,
1583 int max_streams_close_circuit,
1584 int pow_defenses_enabled,
1585 uint32_t pow_queue_rate,
1586 uint32_t pow_queue_burst,
1587 smartlist_t *auth_clients_v3, char **address_out)
1588{
1590
1591 tor_assert(pk);
1592 tor_assert(port_cfgs);
1593 tor_assert(address_out);
1594
1595 switch (hs_version) {
1596 case HS_VERSION_THREE:
1597 ret = hs_service_add_ephemeral(pk->v3, port_cfgs, max_streams,
1598 max_streams_close_circuit,
1599 pow_defenses_enabled,
1600 pow_queue_rate,
1601 pow_queue_burst,
1602 auth_clients_v3, address_out);
1603 break;
1604 default:
1605 tor_assert_unreached();
1606 }
1607
1608 return ret;
1609}
1610
1611/** The list of onion services that have been added via ADD_ONION that do not
1612 * belong to any particular control connection.
1613 */
1615
1616/**
1617 * Return a list of detached onion services, or NULL if none exist.
1618 **/
1624
1625static const char *add_onion_keywords[] = {
1626 "Port",
1627 "Flags",
1628 "MaxStreams",
1629 "PoWDefensesEnabled",
1630 "PoWQueueRate",
1631 "PoWQueueBurst",
1632 "ClientAuth",
1633 "ClientAuthV3",
1634 NULL
1635};
1636static const control_cmd_syntax_t add_onion_syntax = {
1637 .min_args = 1, .max_args = 1,
1638 .accept_keywords = true,
1639 .allowed_keywords = add_onion_keywords
1640};
1641
1642/** Called when we get a ADD_ONION command; parse the body, and set up
1643 * the new ephemeral Onion Service. */
1644static int
1646 const control_cmd_args_t *args)
1647{
1648 /* Parse all of the arguments that do not involve handling cryptographic
1649 * material first, since there's no reason to touch that at all if any of
1650 * the other arguments are malformed.
1651 */
1652 rend_auth_type_t auth_type = REND_NO_AUTH;
1653 smartlist_t *port_cfgs = smartlist_new();
1654 smartlist_t *auth_clients_v3 = NULL;
1655 smartlist_t *auth_clients_v3_str = NULL;
1656 int discard_pk = 0;
1657 int detach = 0;
1658 int max_streams = 0;
1659 int max_streams_close_circuit = 0;
1660 int non_anonymous = 0;
1661 int pow_defenses_enabled = HS_CONFIG_V3_POW_DEFENSES_DEFAULT;
1662 uint32_t pow_queue_rate = HS_CONFIG_V3_POW_QUEUE_RATE;
1663 uint32_t pow_queue_burst = HS_CONFIG_V3_POW_QUEUE_BURST;
1664 const config_line_t *arg;
1665
1666 for (arg = args->kwargs; arg; arg = arg->next) {
1667 if (!strcasecmp(arg->key, "Port")) {
1668 /* "Port=VIRTPORT[,TARGET]". */
1669 hs_port_config_t *cfg = hs_parse_port_config(arg->value, ",", NULL);
1670 if (!cfg) {
1671 control_write_endreply(conn, 512, "Invalid VIRTPORT/TARGET");
1672 goto out;
1673 }
1674 smartlist_add(port_cfgs, cfg);
1675 } else if (!strcasecmp(arg->key, "MaxStreams")) {
1676 /* "MaxStreams=[0..65535]". */
1677 int ok = 0;
1678 max_streams = (int)tor_parse_long(arg->value, 10, 0, 65535, &ok, NULL);
1679 if (!ok) {
1680 control_write_endreply(conn, 512, "Invalid MaxStreams");
1681 goto out;
1682 }
1683 } else if (!strcasecmp(arg->key, "PoWDefensesEnabled")) {
1684 int ok = 0;
1685 pow_defenses_enabled = (int)tor_parse_long(arg->value, 10,
1686 0, 1, &ok, NULL);
1687 if (!ok) {
1688 control_write_endreply(conn, 512, "Invalid PoWDefensesEnabled");
1689 goto out;
1690 }
1691 } else if (!strcasecmp(arg->key, "PoWQueueRate")) {
1692 int ok = 0;
1693 pow_queue_rate = (uint32_t)tor_parse_ulong(arg->value, 10,
1694 0, UINT32_MAX, &ok, NULL);
1695 if (!ok) {
1696 control_write_endreply(conn, 512, "Invalid PoWQueueRate");
1697 goto out;
1698 }
1699 } else if (!strcasecmp(arg->key, "PoWQueueBurst")) {
1700 int ok = 0;
1701 pow_queue_burst = (uint32_t)tor_parse_ulong(arg->value, 10,
1702 0, UINT32_MAX, &ok, NULL);
1703 if (!ok) {
1704 control_write_endreply(conn, 512, "Invalid PoWQueueBurst");
1705 goto out;
1706 }
1707 } else if (!strcasecmp(arg->key, "Flags")) {
1708 /* "Flags=Flag[,Flag]", where Flag can be:
1709 * * 'DiscardPK' - If tor generates the keypair, do not include it in
1710 * the response.
1711 * * 'Detach' - Do not tie this onion service to any particular control
1712 * connection.
1713 * * 'MaxStreamsCloseCircuit' - Close the circuit if MaxStreams is
1714 * exceeded.
1715 * * 'BasicAuth' - Client authorization using the 'basic' method.
1716 * * 'NonAnonymous' - Add a non-anonymous Single Onion Service. If this
1717 * flag is present, tor must be in non-anonymous
1718 * hidden service mode. If this flag is absent,
1719 * tor must be in anonymous hidden service mode.
1720 */
1721 static const char *discard_flag = "DiscardPK";
1722 static const char *detach_flag = "Detach";
1723 static const char *max_s_close_flag = "MaxStreamsCloseCircuit";
1724 static const char *v3auth_flag = "V3Auth";
1725 static const char *non_anonymous_flag = "NonAnonymous";
1726
1727 smartlist_t *flags = smartlist_new();
1728 int bad = 0;
1729
1730 smartlist_split_string(flags, arg->value, ",", SPLIT_IGNORE_BLANK, 0);
1731 if (smartlist_len(flags) < 1) {
1732 control_write_endreply(conn, 512, "Invalid 'Flags' argument");
1733 bad = 1;
1734 }
1735 SMARTLIST_FOREACH_BEGIN(flags, const char *, flag)
1736 {
1737 if (!strcasecmp(flag, discard_flag)) {
1738 discard_pk = 1;
1739 } else if (!strcasecmp(flag, detach_flag)) {
1740 detach = 1;
1741 } else if (!strcasecmp(flag, max_s_close_flag)) {
1742 max_streams_close_circuit = 1;
1743 } else if (!strcasecmp(flag, v3auth_flag)) {
1744 auth_type = REND_V3_AUTH;
1745 } else if (!strcasecmp(flag, non_anonymous_flag)) {
1746 non_anonymous = 1;
1747 } else {
1748 control_printf_endreply(conn, 512, "Invalid 'Flags' argument: %s",
1749 escaped(flag));
1750 bad = 1;
1751 break;
1752 }
1753 } SMARTLIST_FOREACH_END(flag);
1754 SMARTLIST_FOREACH(flags, char *, cp, tor_free(cp));
1755 smartlist_free(flags);
1756 if (bad)
1757 goto out;
1758 } else if (!strcasecmp(arg->key, "ClientAuthV3")) {
1761 if (!client_v3) {
1762 control_write_endreply(conn, 512, "Cannot decode v3 client auth key");
1763 goto out;
1764 }
1765
1766 if (auth_clients_v3 == NULL) {
1767 auth_clients_v3 = smartlist_new();
1768 auth_clients_v3_str = smartlist_new();
1769 }
1770
1771 smartlist_add(auth_clients_v3, client_v3);
1772 smartlist_add(auth_clients_v3_str, tor_strdup(arg->value));
1773 } else {
1775 goto out;
1776 }
1777 }
1778 if (smartlist_len(port_cfgs) == 0) {
1779 control_write_endreply(conn, 512, "Missing 'Port' argument");
1780 goto out;
1781 } else if (auth_type == REND_NO_AUTH && auth_clients_v3 != NULL) {
1782 control_write_endreply(conn, 512, "No auth type specified");
1783 goto out;
1784 } else if (auth_type != REND_NO_AUTH && auth_clients_v3 == NULL) {
1785 control_write_endreply(conn, 512, "No auth clients specified");
1786 goto out;
1787 } else if (non_anonymous != hs_service_non_anonymous_mode_enabled(
1788 get_options())) {
1789 /* If we failed, and the non-anonymous flag is set, Tor must be in
1790 * anonymous hidden service mode.
1791 * The error message changes based on the current Tor config:
1792 * 512 Tor is in anonymous hidden service mode
1793 * 512 Tor is in non-anonymous hidden service mode
1794 * (I've deliberately written them out in full here to aid searchability.)
1795 */
1796 control_printf_endreply(conn, 512,
1797 "Tor is in %sanonymous hidden service " "mode",
1798 non_anonymous ? "" : "non-");
1799 goto out;
1800 }
1801
1802 /* Parse the "keytype:keyblob" argument. */
1803 int hs_version = 0;
1804 add_onion_secret_key_t pk = { NULL };
1805 const char *key_new_alg = NULL;
1806 char *key_new_blob = NULL;
1807
1808 const char *onionkey = smartlist_get(args->args, 0);
1809 if (add_onion_helper_keyarg(onionkey, discard_pk,
1810 &key_new_alg, &key_new_blob, &pk, &hs_version,
1811 conn) < 0) {
1812 goto out;
1813 }
1814
1815 /* Create the HS, using private key pk and port config port_cfg.
1816 * hs_service_add_ephemeral() will take ownership of pk and port_cfg,
1817 * regardless of success/failure. */
1818 char *service_id = NULL;
1819 int ret = add_onion_helper_add_service(hs_version, &pk, port_cfgs,
1820 max_streams,
1821 max_streams_close_circuit,
1822 pow_defenses_enabled,
1823 pow_queue_rate,
1824 pow_queue_burst,
1825 auth_clients_v3, &service_id);
1826 port_cfgs = NULL; /* port_cfgs is now owned by the hs_service code. */
1827 auth_clients_v3 = NULL; /* so is auth_clients_v3 */
1828 switch (ret) {
1829 case RSAE_OKAY:
1830 {
1831 if (detach) {
1835 } else {
1836 if (!conn->ephemeral_onion_services)
1838 smartlist_add(conn->ephemeral_onion_services, service_id);
1839 }
1840
1841 tor_assert(service_id);
1842 control_printf_midreply(conn, 250, "ServiceID=%s", service_id);
1843 if (key_new_alg) {
1844 tor_assert(key_new_blob);
1845 control_printf_midreply(conn, 250, "PrivateKey=%s:%s",
1846 key_new_alg, key_new_blob);
1847 }
1848 if (auth_clients_v3_str) {
1849 SMARTLIST_FOREACH(auth_clients_v3_str, char *, client_str, {
1850 control_printf_midreply(conn, 250, "ClientAuthV3=%s", client_str);
1851 });
1852 }
1853
1854 send_control_done(conn);
1855 break;
1856 }
1857 case RSAE_BADPRIVKEY:
1858 control_write_endreply(conn, 551, "Failed to generate onion address");
1859 break;
1860 case RSAE_ADDREXISTS:
1861 control_write_endreply(conn, 550, "Onion address collision");
1862 break;
1863 case RSAE_BADVIRTPORT:
1864 control_write_endreply(conn, 512, "Invalid VIRTPORT/TARGET");
1865 break;
1866 case RSAE_BADAUTH:
1867 control_write_endreply(conn, 512, "Invalid client authorization");
1868 break;
1869 case RSAE_INTERNAL: FALLTHROUGH;
1870 default:
1871 control_write_endreply(conn, 551, "Failed to add Onion Service");
1872 }
1873 if (key_new_blob) {
1874 memwipe(key_new_blob, 0, strlen(key_new_blob));
1875 tor_free(key_new_blob);
1876 }
1877
1878 out:
1879 if (port_cfgs) {
1880 SMARTLIST_FOREACH(port_cfgs, hs_port_config_t*, p,
1881 hs_port_config_free(p));
1882 smartlist_free(port_cfgs);
1883 }
1884 if (auth_clients_v3) {
1886 service_authorized_client_free(ac));
1887 smartlist_free(auth_clients_v3);
1888 }
1889 if (auth_clients_v3_str) {
1890 SMARTLIST_FOREACH(auth_clients_v3_str, char *, client_str,
1891 tor_free(client_str));
1892 smartlist_free(auth_clients_v3_str);
1893 }
1894
1895 return 0;
1896}
1897
1898/** Helper function to handle parsing the KeyType:KeyBlob argument to the
1899 * ADD_ONION command. Return a new crypto_pk_t and if a new key was generated
1900 * and the private key not discarded, the algorithm and serialized private key,
1901 * or NULL and an optional control protocol error message on failure. The
1902 * caller is responsible for freeing the returned key_new_blob.
1903 *
1904 * Note: The error messages returned are deliberately vague to avoid echoing
1905 * key material.
1906 *
1907 * Note: conn is only used for writing control replies. For testing
1908 * purposes, it can be NULL if control_write_reply() is appropriately
1909 * mocked.
1910 */
1911STATIC int
1912add_onion_helper_keyarg(const char *arg, int discard_pk,
1913 const char **key_new_alg_out, char **key_new_blob_out,
1914 add_onion_secret_key_t *decoded_key, int *hs_version,
1916{
1917 smartlist_t *key_args = smartlist_new();
1918 const char *key_new_alg = NULL;
1919 char *key_new_blob = NULL;
1920 int ret = -1;
1921
1922 smartlist_split_string(key_args, arg, ":", SPLIT_IGNORE_BLANK, 0);
1923 if (smartlist_len(key_args) != 2) {
1924 control_write_endreply(conn, 512, "Invalid key type/blob");
1925 goto err;
1926 }
1927
1928 /* The format is "KeyType:KeyBlob". */
1929 static const char *key_type_new = "NEW";
1930 static const char *key_type_best = "BEST";
1931 static const char *key_type_ed25519_v3 = "ED25519-V3";
1932
1933 const char *key_type = smartlist_get(key_args, 0);
1934 const char *key_blob = smartlist_get(key_args, 1);
1935
1936 if (!strcasecmp(key_type_ed25519_v3, key_type)) {
1937 /* parsing of private ed25519 key */
1938 /* "ED25519-V3:<Base64 Blob>" - Loading a pre-existing ed25519 key. */
1939 ed25519_secret_key_t *sk = tor_malloc_zero(sizeof(*sk));
1940 if (base64_decode((char *) sk->seckey, sizeof(sk->seckey), key_blob,
1941 strlen(key_blob)) != sizeof(sk->seckey)) {
1942 tor_free(sk);
1943 control_write_endreply(conn, 512, "Failed to decode ED25519-V3 key");
1944 goto err;
1945 }
1946 decoded_key->v3 = sk;
1947 *hs_version = HS_VERSION_THREE;
1948 } else if (!strcasecmp(key_type_new, key_type)) {
1949 /* "NEW:<Algorithm>" - Generating a new key, blob as algorithm. */
1950 if (!strcasecmp(key_type_ed25519_v3, key_blob) ||
1951 !strcasecmp(key_type_best, key_blob)) {
1952 /* "ED25519-V3", ed25519 key, also currently "BEST" by default. */
1953 ed25519_secret_key_t *sk = tor_malloc_zero(sizeof(*sk));
1954 if (ed25519_secret_key_generate(sk, 1) < 0) {
1955 tor_free(sk);
1956 control_printf_endreply(conn, 551, "Failed to generate %s key",
1957 key_type_ed25519_v3);
1958 goto err;
1959 }
1960 if (!discard_pk) {
1961 ssize_t len = base64_encode_size(sizeof(sk->seckey), 0) + 1;
1962 key_new_blob = tor_malloc_zero(len);
1963 if (base64_encode(key_new_blob, len, (const char *) sk->seckey,
1964 sizeof(sk->seckey), 0) != (len - 1)) {
1965 tor_free(sk);
1966 tor_free(key_new_blob);
1967 control_printf_endreply(conn, 551, "Failed to encode %s key",
1968 key_type_ed25519_v3);
1969 goto err;
1970 }
1971 key_new_alg = key_type_ed25519_v3;
1972 }
1973 decoded_key->v3 = sk;
1974 *hs_version = HS_VERSION_THREE;
1975 } else {
1976 control_write_endreply(conn, 513, "Invalid key type");
1977 goto err;
1978 }
1979 } else {
1980 control_write_endreply(conn, 513, "Invalid key type");
1981 goto err;
1982 }
1983
1984 /* Succeeded in loading or generating a private key. */
1985 ret = 0;
1986
1987 err:
1988 SMARTLIST_FOREACH(key_args, char *, cp, {
1989 memwipe(cp, 0, strlen(cp));
1990 tor_free(cp);
1991 });
1992 smartlist_free(key_args);
1993
1994 *key_new_alg_out = key_new_alg;
1995 *key_new_blob_out = key_new_blob;
1996
1997 return ret;
1998}
1999
2000static const control_cmd_syntax_t del_onion_syntax = {
2001 .min_args = 1, .max_args = 1,
2002};
2003
2004/** Called when we get a DEL_ONION command; parse the body, and remove
2005 * the existing ephemeral Onion Service. */
2006static int
2008 const control_cmd_args_t *cmd_args)
2009{
2010 int hs_version = 0;
2011 smartlist_t *args = cmd_args->args;
2012 tor_assert(smartlist_len(args) == 1);
2013
2014 const char *service_id = smartlist_get(args, 0);
2015 if (hs_address_is_valid(service_id)) {
2016 hs_version = HS_VERSION_THREE;
2017 } else {
2018 control_write_endreply(conn, 512, "Malformed Onion Service id");
2019 goto out;
2020 }
2021
2022 /* Determine if the onion service belongs to this particular control
2023 * connection, or if it is in the global list of detached services. If it
2024 * is in neither, either the service ID is invalid in some way, or it
2025 * explicitly belongs to a different control connection, and an error
2026 * should be returned.
2027 */
2028 smartlist_t *services[2] = {
2031 };
2032 smartlist_t *onion_services = NULL;
2033 int idx = -1;
2034 for (size_t i = 0; i < ARRAY_LENGTH(services); i++) {
2035 idx = smartlist_string_pos(services[i], service_id);
2036 if (idx != -1) {
2037 onion_services = services[i];
2038 break;
2039 }
2040 }
2041 if (onion_services == NULL) {
2042 control_write_endreply(conn, 552, "Unknown Onion Service id");
2043 } else {
2044 int ret = -1;
2045 switch (hs_version) {
2046 case HS_VERSION_THREE:
2047 ret = hs_service_del_ephemeral(service_id);
2048 break;
2049 default:
2050 /* The ret value will be -1 thus hitting the warning below. This should
2051 * never happen because of the check at the start of the function. */
2052 break;
2053 }
2054 if (ret < 0) {
2055 /* This should *NEVER* fail, since the service is on either the
2056 * per-control connection list, or the global one.
2057 */
2058 log_warn(LD_BUG, "Failed to remove Onion Service %s.",
2059 escaped(service_id));
2061 }
2062
2063 /* Remove/scrub the service_id from the appropriate list. */
2064 char *cp = smartlist_get(onion_services, idx);
2065 smartlist_del(onion_services, idx);
2066 memwipe(cp, 0, strlen(cp));
2067 tor_free(cp);
2068
2069 send_control_done(conn);
2070 }
2071
2072 out:
2073 return 0;
2074}
2075
2076static const control_cmd_syntax_t obsolete_syntax = {
2077 .max_args = UINT_MAX
2078};
2079
2080/**
2081 * Called when we get an obsolete command: tell the controller that it is
2082 * obsolete.
2083 */
2084static int
2086 const control_cmd_args_t *args)
2087{
2088 (void)args;
2089 char *command = tor_strdup(conn->current_cmd);
2091 control_printf_endreply(conn, 511, "%s is obsolete.", command);
2093 return 0;
2094}
2095
2096/**
2097 * Function pointer to a handler function for a controller command.
2098 **/
2100 const control_cmd_args_t *args);
2101
2102/**
2103 * Definition for a controller command.
2104 */
2105typedef struct control_cmd_def_t {
2106 /**
2107 * The name of the command. If the command is multiline, the name must
2108 * begin with "+". This is not case-sensitive. */
2109 const char *name;
2110 /**
2111 * A function to execute the command.
2112 */
2114 /**
2115 * Zero or more CMD_FL_* flags, or'd together.
2116 */
2117 unsigned flags;
2118 /**
2119 * For parsed command: a syntax description.
2120 */
2123
2124/**
2125 * Indicates that the command's arguments are sensitive, and should be
2126 * memwiped after use.
2127 */
2128#define CMD_FL_WIPE (1u<<0)
2129
2130#ifndef COCCI
2131/** Macro: declare a command with a one-line argument, a given set of flags,
2132 * and a syntax definition.
2133 **/
2134#define ONE_LINE(name, flags) \
2135 { \
2136 (#name), \
2137 handle_control_ ##name, \
2138 flags, \
2139 &name##_syntax, \
2140 }
2141
2142/**
2143 * Macro: declare a command with a multi-line argument and a given set of
2144 * flags.
2145 **/
2146#define MULTLINE(name, flags) \
2147 { ("+"#name), \
2148 handle_control_ ##name, \
2149 flags, \
2150 &name##_syntax \
2151 }
2152
2153/**
2154 * Macro: declare an obsolete command. (Obsolete commands give a different
2155 * error than non-existent ones.)
2156 **/
2157#define OBSOLETE(name) \
2158 { #name, \
2159 handle_control_obsolete, \
2160 0, \
2161 &obsolete_syntax, \
2162 }
2163#endif /* !defined(COCCI) */
2164
2165/**
2166 * An array defining all the recognized controller commands.
2167 **/
2169{
2170 ONE_LINE(setconf, 0),
2171 ONE_LINE(resetconf, 0),
2172 ONE_LINE(getconf, 0),
2173 MULTLINE(loadconf, 0),
2174 ONE_LINE(setevents, 0),
2175 ONE_LINE(authenticate, CMD_FL_WIPE),
2176 ONE_LINE(saveconf, 0),
2177 ONE_LINE(signal, 0),
2178 ONE_LINE(takeownership, 0),
2179 ONE_LINE(dropownership, 0),
2180 ONE_LINE(mapaddress, 0),
2181 ONE_LINE(getinfo, 0),
2182 ONE_LINE(extendcircuit, 0),
2183 ONE_LINE(setcircuitpurpose, 0),
2184 OBSOLETE(setrouterpurpose),
2185 ONE_LINE(attachstream, 0),
2186 MULTLINE(postdescriptor, 0),
2187 ONE_LINE(redirectstream, 0),
2188 ONE_LINE(closestream, 0),
2189 ONE_LINE(closecircuit, 0),
2190 ONE_LINE(usefeature, 0),
2191 ONE_LINE(resolve, 0),
2192 ONE_LINE(protocolinfo, 0),
2193 ONE_LINE(authchallenge, CMD_FL_WIPE),
2194 ONE_LINE(dropguards, 0),
2195 ONE_LINE(droptimeouts, 0),
2196 ONE_LINE(hsfetch, 0),
2197 MULTLINE(hspost, 0),
2198 ONE_LINE(add_onion, CMD_FL_WIPE),
2199 ONE_LINE(del_onion, CMD_FL_WIPE),
2200 ONE_LINE(onion_client_auth_add, CMD_FL_WIPE),
2201 ONE_LINE(onion_client_auth_remove, 0),
2202 ONE_LINE(onion_client_auth_view, 0),
2203};
2204
2205/**
2206 * The number of entries in CONTROL_COMMANDS.
2207 **/
2209
2210/**
2211 * Run a single control command, as defined by a control_cmd_def_t,
2212 * with a given set of arguments.
2213 */
2214static int
2217 uint32_t cmd_data_len,
2218 char *args)
2219{
2220 int rv = 0;
2221
2222 control_cmd_args_t *parsed_args;
2223 char *err=NULL;
2224 tor_assert(def->syntax);
2225 parsed_args = control_cmd_parse_args(conn->current_cmd,
2226 def->syntax,
2227 cmd_data_len, args,
2228 &err);
2229 if (!parsed_args) {
2230 control_printf_endreply(conn, 512, "Bad arguments to %s: %s",
2231 conn->current_cmd, err?err:"");
2232 tor_free(err);
2233 } else {
2234 if (BUG(err))
2235 tor_free(err);
2236 if (def->handler(conn, parsed_args))
2237 rv = 0;
2238
2239 if (def->flags & CMD_FL_WIPE)
2240 control_cmd_args_wipe(parsed_args);
2241
2242 control_cmd_args_free(parsed_args);
2243 }
2244
2245 if (def->flags & CMD_FL_WIPE)
2246 memwipe(args, 0, cmd_data_len);
2247
2248 return rv;
2249}
2250
2251/**
2252 * Run a given controller command, as selected by the current_cmd field of
2253 * <b>conn</b>.
2254 */
2255int
2257 uint32_t cmd_data_len,
2258 char *args)
2259{
2260 tor_assert(conn);
2261 tor_assert(args);
2262 tor_assert(args[cmd_data_len] == '\0');
2263
2264 for (unsigned i = 0; i < N_CONTROL_COMMANDS; ++i) {
2265 const control_cmd_def_t *def = &CONTROL_COMMANDS[i];
2266 if (!strcasecmp(conn->current_cmd, def->name)) {
2267 return handle_single_control_command(def, conn, cmd_data_len, args);
2268 }
2269 }
2270
2271 control_printf_endreply(conn, 510, "Unrecognized command \"%s\"",
2272 conn->current_cmd);
2273
2274 return 0;
2275}
2276
2277void
2278control_cmd_free_all(void)
2279{
2280 if (detached_onion_services) { /* Free the detached onion services */
2282 smartlist_free(detached_onion_services);
2283 }
2284}
const char * addressmap_register_virtual_address(int type, char *new_address)
Header for addressmap.c.
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition binascii.c:396
int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, int flags)
Definition binascii.c:215
size_t base64_encode_size(size_t srclen, int flags)
Definition binascii.c:166
int circuit_handle_first_hop(origin_circuit_t *circ)
int circuit_send_next_onion_skin(origin_circuit_t *circ)
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei)
origin_circuit_t * origin_circuit_init(uint8_t purpose, int flags)
Header file for circuitbuild.c.
void circuit_set_state(circuit_t *circ, uint8_t state)
circuit_t * circuit_get_by_edge_conn(edge_connection_t *conn)
origin_circuit_t * circuit_get_by_global_id(uint32_t id)
int circuit_get_cpath_len(origin_circuit_t *circ)
int circuit_event_status(origin_circuit_t *circ, circuit_status_event_t tp, int reason_code)
crypt_path_t * circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum)
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_UNKNOWN
#define CIRCUIT_STATE_OPEN
Definition circuitlist.h:32
#define CIRCUIT_STATE_BUILDING
Definition circuitlist.h:21
#define CIRCUIT_PURPOSE_CONTROLLER
#define CIRCUIT_STATE_GUARD_WAIT
Definition circuitlist.h:30
#define CIRCUIT_PURPOSE_C_GENERAL
Definition circuitlist.h:70
circuit_build_times_t * get_circuit_build_times_mutable(void)
const circuit_build_times_t * get_circuit_build_times(void)
void circuit_build_times_reset(circuit_build_times_t *cbt)
Header file for circuitstats.c.
void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
origin_circuit_t * circuit_launch(uint8_t purpose, int flags)
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Header file for circuituse.c.
#define CIRCLAUNCH_NEED_CAPACITY
Definition circuituse.h:47
#define ARRAY_LENGTH(x)
int options_save_current(void)
Definition config.c:7103
const char * name
Definition config.c:2475
const or_options_t * get_options(void)
Definition config.c:949
int option_is_recognized(const char *key)
Definition config.c:2672
setopt_err_t options_trial_assign(config_line_t *list, unsigned flags, char **msg)
Definition config.c:2703
int addressmap_register_auto(const char *from, const char *to, time_t expires, addressmap_entry_source_t addrmap_source, const char **msg)
Definition config.c:4847
tor_cmdline_mode_t command
Definition config.c:2481
setopt_err_t options_init_from_string(const char *cf_defaults, const char *cf, int command, const char *command_arg, char **msg)
Definition config.c:4677
const char * option_get_canonical_name(const char *key)
Definition config.c:2680
config_line_t * option_get_assignment(const or_options_t *options, const char *key)
Definition config.c:2688
Header file for config.c.
setopt_err_t
Definition config.h:51
const config_line_t * config_line_find_case(const config_line_t *lines, const char *key)
Definition confline.c:87
config_line_t * config_lines_dup(const config_line_t *inp)
Definition confline.c:226
Header for confline.c.
Header for confmgt.c.
#define CAL_USE_DEFAULTS
Definition confmgt.h:50
#define CAL_CLEAR_FIRST
Definition confmgt.h:59
int connection_flush(connection_t *conn)
connection_t * connection_get_by_global_id(uint64_t id)
Header file for connection.c.
#define CONN_TYPE_AP
Definition connection.h:51
int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath)
int connection_edge_end(edge_connection_t *conn, uint8_t reason)
entry_connection_t * TO_ENTRY_CONN(connection_t *c)
void connection_entry_set_controller_wait(entry_connection_t *conn)
Header file for connection_edge.c.
#define AP_CONN_STATE_CONTROLLER_WAIT
int address_is_invalid_destination(const char *address, int client)
#define AP_CONN_STATE_CONNECT_WAIT
#define AP_CONN_STATE_RESOLVE_WAIT
Header file for control.c.
char * get_controller_cookie_file_name(void)
Header file for control_auth.c.
static int handle_control_saveconf(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_droptimeouts(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_usefeature(control_connection_t *conn, const control_cmd_args_t *cmd_args)
static int control_setconf_helper(control_connection_t *conn, const control_cmd_args_t *args, int use_defaults)
static int kvline_check_keyword_args(const control_cmd_args_t *result, const control_cmd_syntax_t *syntax, char **error_out)
static const size_t N_CONTROL_COMMANDS
void control_cmd_args_free_(control_cmd_args_t *args)
Definition control_cmd.c:70
static int handle_control_hspost(control_connection_t *conn, const control_cmd_args_t *args)
#define OBSOLETE(name)
static int handle_control_extendcircuit(control_connection_t *conn, const control_cmd_args_t *args)
static uint8_t circuit_purpose_from_string(const char *string)
static int handle_control_setevents(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_obsolete(control_connection_t *conn, const control_cmd_args_t *args)
STATIC control_cmd_args_t * control_cmd_parse_args(const char *command, const control_cmd_syntax_t *syntax, size_t body_len, const char *body, char **error_out)
#define CMD_FL_WIPE
static int handle_control_hsfetch(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_closestream(control_connection_t *conn, const control_cmd_args_t *cmd_args)
static const control_cmd_def_t CONTROL_COMMANDS[]
static int handle_control_signal(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_single_control_command(const control_cmd_def_t *def, control_connection_t *conn, uint32_t cmd_data_len, char *args)
static smartlist_t * detached_onion_services
static int handle_control_loadconf(control_connection_t *conn, const control_cmd_args_t *args)
static bool string_array_contains_keyword(const char **array, const char *kwd)
void control_cmd_args_wipe(control_cmd_args_t *args)
Definition control_cmd.c:87
int(* handler_fn_t)(control_connection_t *conn, const control_cmd_args_t *args)
#define STATE_IS_OPEN(s)
Definition control_cmd.c:64
static int handle_control_getconf(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_attachstream(control_connection_t *conn, const control_cmd_args_t *args)
STATIC int add_onion_helper_keyarg(const char *arg, int discard_pk, const char **key_new_alg_out, char **key_new_blob_out, add_onion_secret_key_t *decoded_key, int *hs_version, control_connection_t *conn)
static int address_is_invalid_mapaddress_target(const char *addr)
static bool config_lines_contain_flag(const config_line_t *lines, const char *flag)
static int handle_control_dropguards(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_setconf(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_postdescriptor(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_add_onion(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_closecircuit(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_takeownership(control_connection_t *conn, const control_cmd_args_t *args)
static void add_authmethods(smartlist_t *reply)
#define MULTLINE(name, flags)
static origin_circuit_t * get_circ(const char *id)
static char * get_authmethods(const or_options_t *options)
smartlist_t * get_detached_onion_services(void)
static int handle_control_redirectstream(control_connection_t *conn, const control_cmd_args_t *cmd_args)
static int handle_control_resolve(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_dropownership(control_connection_t *conn, const control_cmd_args_t *args)
int handle_control_command(control_connection_t *conn, uint32_t cmd_data_len, char *args)
static int handle_control_setcircuitpurpose(control_connection_t *conn, const control_cmd_args_t *args)
#define ONE_LINE(name, flags)
static int handle_control_mapaddress(control_connection_t *conn, const control_cmd_args_t *args)
static int handle_control_protocolinfo(control_connection_t *conn, const control_cmd_args_t *cmd_args)
static char * get_esc_cfile(const or_options_t *options)
static int handle_control_resetconf(control_connection_t *conn, const control_cmd_args_t *args)
static entry_connection_t * get_stream(const char *id)
static int handle_control_del_onion(control_connection_t *conn, const control_cmd_args_t *cmd_args)
Header file for control_cmd.c.
Definition for control_cmd_args_t.
Controller connection structure.
const struct control_event_t control_event_table[]
int control_event_address_mapped(const char *from, const char *to, time_t expires, const char *error, const int cached, uint64_t stream_id)
void control_update_global_event_mask(void)
Header file for control_events.c.
void control_write_endreply(control_connection_t *conn, int code, const char *s)
void control_printf_midreply(control_connection_t *conn, int code, const char *fmt,...)
void send_control_done(control_connection_t *conn)
void control_printf_endreply(control_connection_t *conn, int code, const char *fmt,...)
size_t read_escaped_data(const char *data, size_t len, char **out)
Header file for control_proto.c.
Circuit-build-stse structure.
int ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out, int extra_strong)
Common functions for using (pseudo-)random number generators.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition crypto_util.c:55
Common functions for cryptographic routines.
int dnsserv_launch_request(const char *name, int reverse, control_connection_t *control_conn)
Definition dnsserv.c:217
Header file for dnsserv.c.
Entry connection structure.
#define ENTRY_TO_EDGE_CONN(c)
void remove_all_entry_guards(void)
Header file for circuitbuild.c.
char * esc_for_log(const char *s)
Definition escape.c:30
const char * escaped(const char *s)
Definition escape.c:126
extend_info_t * extend_info_from_node(const node_t *node, int for_direct_connect, bool for_exit)
Definition extendinfo.c:105
Header for core/or/extendinfo.c.
void control_reply_append_kv(smartlist_t *reply, const char *key, const char *val)
void control_write_reply_lines(control_connection_t *conn, smartlist_t *lines)
void control_reply_add_printf(smartlist_t *reply, int code, const char *fmt,...)
#define control_reply_free(r)
Free and null a smartlist of control_reply_line_t.
void control_reply_add_one_kv(smartlist_t *reply, int code, int flags, const char *key, const char *val)
void control_reply_add_str(smartlist_t *reply, int code, const char *s)
void control_reply_add_done(smartlist_t *reply)
hs_port_config_t * hs_parse_port_config(const char *string, const char *sep, char **err_msg_out)
Definition hs_common.c:686
int hs_parse_address(const char *address, ed25519_public_key_t *key_out, uint8_t *checksum_out, uint8_t *version_out)
Definition hs_common.c:841
int hs_address_is_valid(const char *address)
Definition hs_common.c:857
hs_service_add_ephemeral_status_t
Definition hs_common.h:132
@ RSAE_OKAY
Definition hs_common.h:138
@ RSAE_BADVIRTPORT
Definition hs_common.h:134
@ RSAE_ADDREXISTS
Definition hs_common.h:135
@ RSAE_INTERNAL
Definition hs_common.h:137
@ RSAE_BADPRIVKEY
Definition hs_common.h:136
@ RSAE_BADAUTH
Definition hs_common.h:133
#define HS_VERSION_THREE
Definition hs_common.h:23
Header file containing configuration ABI/API for the HS subsystem.
int hs_control_hspost_command(const char *body, const char *onion_address, const smartlist_t *hsdirs_rs)
Definition hs_control.c:204
void hs_control_hsfetch_command(const ed25519_public_key_t *onion_identity_pk, const smartlist_t *hsdirs)
Definition hs_control.c:256
Header file containing control port event related code.
int hs_service_del_ephemeral(const char *address)
hs_service_authorized_client_t * parse_authorized_client_key(const char *key_str, int severity)
hs_service_add_ephemeral_status_t hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports, int max_streams_per_rdv_circuit, int max_streams_close_circuit, int pow_defenses_enabled, uint32_t pow_queue_rate, uint32_t pow_queue_burst, smartlist_t *auth_clients_v3, char **address_out)
Header file containing service data for the HS subsystem.
config_line_t * kvline_parse(const char *line, unsigned flags)
Definition kvline.c:199
Header for kvline.c.
#define LD_BUG
Definition log.h:86
#define LD_CONTROL
Definition log.h:80
#define LOG_INFO
Definition log.h:45
Header file for main.c.
#define tor_free(p)
Definition malloc.h:56
Node information structure.
const node_t * node_get_by_nickname(const char *nickname, unsigned flags)
Definition nodelist.c:1110
int node_has_preferred_descriptor(const node_t *node, int for_direct_connect)
Definition nodelist.c:1534
const node_t * node_get_by_hex_id(const char *hex_id, unsigned flags)
Definition nodelist.c:1083
Header file for nodelist.c.
Master header file for Tor-specific functionality.
@ ADDRMAPSRC_CONTROLLER
Definition or.h:1023
#define TO_CIRCUIT(x)
Definition or.h:951
rend_auth_type_t
Definition or.h:408
#define TO_CONN(c)
Definition or.h:709
#define ENTRY_TO_CONN(c)
Definition or.h:712
Origin circuit structure.
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, uint64_t max, int *ok, char **next)
Definition parse_int.c:110
long tor_parse_long(const char *s, int base, long min, long max, int *ok, char **next)
Definition parse_int.c:59
unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, unsigned long max, int *ok, char **next)
Definition parse_int.c:78
char * make_path_absolute(const char *fname)
Definition path.c:281
int tor_asprintf(char **strp, const char *fmt,...)
Definition printf.c:75
Header file for rendcommon.c.
static crypto_pk_t * onionkey
Definition router.c:105
uint8_t router_purpose_from_string(const char *s)
Definition routerinfo.c:113
Header file for routerinfo.c.
Router descriptor structure.
#define ROUTER_PURPOSE_UNKNOWN
#define ROUTER_PURPOSE_GENERAL
int router_load_single_router(const char *s, uint8_t purpose, int cache, const char **msg)
Header file for routerlist.c.
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
Definition smartlist.c:36
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition smartlist.c:279
int smartlist_string_pos(const smartlist_t *sl, const char *element)
Definition smartlist.c:106
void * smartlist_pop_last(smartlist_t *sl)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_del(smartlist_t *sl, int idx)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
Client request structure.
void or_state_mark_dirty(or_state_t *state, time_t when)
Definition statefile.c:784
or_state_t * get_or_state(void)
Definition statefile.c:220
Header for statefile.c.
uint8_t state
Definition circuit_st.h:111
unsigned int type
uint16_t marked_for_close
tor_socket_t s
struct smartlist_t * args
struct config_line_t * kwargs
const control_cmd_syntax_t * syntax
handler_fn_t handler
const char * name
unsigned int min_args
Definition control_cmd.h:41
const char ** allowed_keywords
Definition control_cmd.h:58
unsigned int max_args
Definition control_cmd.h:46
smartlist_t * ephemeral_onion_services
unsigned int is_owning_control_connection
uint8_t seckey[ED25519_SECKEY_LEN]
unsigned int edge_has_sent_end
socks_request_t * socks_request
struct config_line_t * HashedControlPassword
struct config_line_t * HashedControlSessionPassword
edge_connection_t * p_streams
unsigned int any_hop_from_controller
cpath_build_state_t * build_state
unsigned first_hop_from_controller
char address[MAX_SOCKS_ADDR_LEN]
#define STATIC
Definition testsupport.h:32
@ CMD_RUN_TOR
#define tor_assert_nonfatal_unreached()
Definition util_bug.h:177
#define tor_assert(expr)
Definition util_bug.h:103
#define tor_fragile_assert()
Definition util_bug.h:278
int strcasecmpstart(const char *s1, const char *s2)
int strcmpstart(const char *s1, const char *s2)
void tor_strupper(char *s)