commit 084be23697e14b9ee26b3ac1eef2448af6368d10 Author: David Goulet dgoulet@ev0ke.net Date: Thu Feb 19 14:53:41 2015 -0500
Control: groud work for the HSFETCH command
This adds the command on the controller side that parses and validate arguments but does nothing for now. The HS desriptor fetch must be modularized a bit more before we can use the command.
See control-spec.txt section 3.26 for more information on this command.
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/or/control.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+)
diff --git a/src/or/control.c b/src/or/control.c index d4216d2..1bc8333 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -157,6 +157,8 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len, static int handle_control_usefeature(control_connection_t *conn, uint32_t len, const char *body); +static int handle_control_hsfetch(control_connection_t *conn, uint32_t len, + const char *body); static int write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len); static void orconn_target_get_name(char *buf, size_t len, @@ -3253,6 +3255,98 @@ handle_control_dropguards(control_connection_t *conn, return 0; }
+/** Implementation for the HSFETCH command. */ +static int +handle_control_hsfetch(control_connection_t *conn, uint32_t len, + const char *body) +{ + char digest[DIGEST_LEN], *hsaddress = NULL, *arg1 = NULL, *desc_id = NULL; + smartlist_t *args = NULL, *hsdirs = NULL; + (void) len; /* body is nul-terminated; it's safe to ignore the length */ + static const char *v2_str = "v2-"; + const size_t v2_str_len = strlen(v2_str); + + /* Make sure we have at least one argument, the HSAddress. */ + args = getargs_helper("HSFETCH", conn, body, 1, -1); + if (!args) { + goto done; + } + + /* Extract the HS address that should NOT contain the .onion part. */ + arg1 = smartlist_get(args, 0); + /* Remove the HS address from the argument list so we can safely iterate + * on all the rest to find optional argument(s). */ + smartlist_del(args, 0); + /* Test if it's an HS address without the .onion part. */ + if (strlen(arg1) == REND_SERVICE_ID_LEN_BASE32 && + base32_decode(digest, sizeof(digest), arg1, + REND_SERVICE_ID_LEN_BASE32) == 0) { + hsaddress = arg1; + } else if (strstr(arg1, v2_str) && + strlen(arg1 + v2_str_len) == REND_DESC_ID_V2_LEN_BASE32 && + base32_decode(digest, sizeof(digest), arg1 + v2_str_len, + REND_DESC_ID_V2_LEN_BASE32) == 0) { + /* We have a well formed version 2 descriptor ID. */ + desc_id = arg1 + v2_str_len; + } else { + connection_printf_to_buf(conn, "552 Unrecognized "%s"\r\n", + arg1); + goto done; + } + + /* Stores routerstatus_t object for each specified server. */ + hsdirs = smartlist_new(); + + /* Skip first argument because it's the HSAddress. */ + SMARTLIST_FOREACH_BEGIN(args, char *, arg) { + const node_t *node; + static const char *opt_server = "SERVER="; + + if (!strcasecmpstart(arg, opt_server)) { + const char *server; + + memset(digest, 0, sizeof(digest)); + server = arg + strlen(opt_server); + /* Is the server fingerprint valid?. */ + if (!string_is_hex(server) || strlen(server) != HEX_DIGEST_LEN || + base16_decode(digest, sizeof(digest), server, HEX_DIGEST_LEN)) { + connection_printf_to_buf(conn, "552 Invalid fingerprint "%s"\r\n", + server); + goto done; + } + node = node_get_by_id(digest); + if (!node) { + connection_printf_to_buf(conn, "552 Server "%s" not found\r\n", + server); + goto done; + } + /* Valid server, add it to our local list. */ + smartlist_add(hsdirs, node->rs); + } else { + connection_printf_to_buf(conn, "552 Unexpected argument "%s"\r\n", + arg); + goto done; + } + } SMARTLIST_FOREACH_END(arg); + + /* XXX: Actually trigger the fetch(es). */ + (void) hsaddress; + (void) desc_id; + (void) hsdirs; + + /* All good, thanks and come again! */ + send_control_done(conn); + +done: + if (args) { + SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); + smartlist_free(args); + } + tor_free(arg1); + smartlist_free(hsdirs); + return 0; +} + /** Called when <b>conn</b> has no more bytes left on its outbuf. */ int connection_control_finished_flushing(control_connection_t *conn) @@ -3550,6 +3644,9 @@ connection_control_process_inbuf(control_connection_t *conn) } else if (!strcasecmp(conn->incoming_cmd, "DROPGUARDS")) { if (handle_control_dropguards(conn, cmd_data_len, args)) return -1; + } else if (!strcasecmp(conn->incoming_cmd, "HSFETCH")) { + if (handle_control_hsfetch(conn, cmd_data_len, args)) + return -1; } else { connection_printf_to_buf(conn, "510 Unrecognized command "%s"\r\n", conn->incoming_cmd);
tor-commits@lists.torproject.org