diff options
Diffstat (limited to 'src/or/control.c')
-rw-r--r-- | src/or/control.c | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/src/or/control.c b/src/or/control.c index 1cc2e1464e..96cc41bc4b 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -5,7 +5,31 @@ /** * \file control.c * \brief Implementation for Tor's control-socket interface. - * See doc/spec/control-spec.txt for full details on protocol. + * + * A "controller" is an external program that monitors and controls a Tor + * instance via a text-based protocol. It connects to Tor via a connection + * to a local socket. + * + * The protocol is line-driven. The controller sends commands terminated by a + * CRLF. Tor sends lines that are either <em>replies</em> to what the + * controller has said, or <em>events</em> that Tor sends to the controller + * asynchronously based on occurrences in the Tor network model. + * + * See the control-spec.txt file in the torspec.git repository for full + * details on protocol. + * + * This module generally has two kinds of entry points: those based on having + * received a command on a controller socket, which are handled in + * connection_control_process_inbuf(), and dispatched to individual functions + * with names like control_handle_COMMANDNAME(); and those based on events + * that occur elsewhere in Tor, which are handled by functions with names like + * control_event_EVENTTYPE(). + * + * Controller events are not sent immediately; rather, they are inserted into + * the queued_control_events array, and flushed later from + * flush_queued_events_cb(). Doing this simplifies our callgraph greatly, + * by limiting the number of places in Tor that can call back into the network + * stack. **/ #define CONTROL_PRIVATE @@ -919,7 +943,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body, ++body; } - smartlist_add(entries, tor_strdup("")); + smartlist_add_strdup(entries, ""); config = smartlist_join_strings(entries, "\n", 0, NULL); SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp)); smartlist_free(entries); @@ -3116,7 +3140,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, if (!ans) { smartlist_add(unrecognized, (char*)q); } else { - smartlist_add(answers, tor_strdup(q)); + smartlist_add_strdup(answers, q); smartlist_add(answers, ans); } } SMARTLIST_FOREACH_END(q); @@ -4058,7 +4082,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len, * of the id. */ desc_id = digest; } else { - connection_printf_to_buf(conn, "513 Unrecognized \"%s\"\r\n", + connection_printf_to_buf(conn, "513 Invalid argument \"%s\"\r\n", arg1); goto done; } @@ -4250,6 +4274,8 @@ handle_control_add_onion(control_connection_t *conn, int max_streams = 0; int max_streams_close_circuit = 0; rend_auth_type_t auth_type = REND_NO_AUTH; + /* Default to adding an anonymous hidden service if no flag is given */ + int non_anonymous = 0; for (size_t i = 1; i < arg_len; i++) { static const char *port_prefix = "Port="; static const char *flags_prefix = "Flags="; @@ -4286,11 +4312,16 @@ handle_control_add_onion(control_connection_t *conn, * * 'MaxStreamsCloseCircuit' - Close the circuit if MaxStreams is * exceeded. * * 'BasicAuth' - Client authorization using the 'basic' method. + * * 'NonAnonymous' - Add a non-anonymous Single Onion Service. If this + * flag is present, tor must be in non-anonymous + * hidden service mode. If this flag is absent, + * tor must be in anonymous hidden service mode. */ static const char *discard_flag = "DiscardPK"; static const char *detach_flag = "Detach"; static const char *max_s_close_flag = "MaxStreamsCloseCircuit"; static const char *basicauth_flag = "BasicAuth"; + static const char *non_anonymous_flag = "NonAnonymous"; smartlist_t *flags = smartlist_new(); int bad = 0; @@ -4311,6 +4342,8 @@ handle_control_add_onion(control_connection_t *conn, max_streams_close_circuit = 1; } else if (!strcasecmp(flag, basicauth_flag)) { auth_type = REND_BASIC_AUTH; + } else if (!strcasecmp(flag, non_anonymous_flag)) { + non_anonymous = 1; } else { connection_printf_to_buf(conn, "512 Invalid 'Flags' argument: %s\r\n", @@ -4379,6 +4412,19 @@ handle_control_add_onion(control_connection_t *conn, smartlist_len(auth_clients) > 16)) { connection_printf_to_buf(conn, "512 Too many auth clients\r\n"); goto out; + } else if (non_anonymous != rend_service_non_anonymous_mode_enabled( + get_options())) { + /* If we failed, and the non-anonymous flag is set, Tor must be in + * anonymous hidden service mode. + * The error message changes based on the current Tor config: + * 512 Tor is in anonymous hidden service mode + * 512 Tor is in non-anonymous hidden service mode + * (I've deliberately written them out in full here to aid searchability.) + */ + connection_printf_to_buf(conn, "512 Tor is in %sanonymous hidden service " + "mode\r\n", + non_anonymous ? "" : "non-"); + goto out; } /* Parse the "keytype:keyblob" argument. */ @@ -6000,9 +6046,9 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses, return 0; strs = smartlist_new(); - smartlist_add(strs, tor_strdup("650+")); - smartlist_add(strs, tor_strdup(event_string)); - smartlist_add(strs, tor_strdup("\r\n")); + smartlist_add_strdup(strs, "650+"); + smartlist_add_strdup(strs, event_string); + smartlist_add_strdup(strs, "\r\n"); SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs, { s = networkstatus_getinfo_helper_single(rs); |