diff options
author | David Goulet <dgoulet@ev0ke.net> | 2015-03-10 16:46:56 -0400 |
---|---|---|
committer | David Goulet <dgoulet@ev0ke.net> | 2015-04-21 14:22:48 -0400 |
commit | 59f8dced114f20a147a5425ece67d7d44a81867b (patch) | |
tree | 289e71b7f72cd779a9a98d3c0b1df9e2b06c64b6 /src/or/control.c | |
parent | 7db58445fd00d5bbad72fd80497d20b7bc9a0297 (diff) | |
download | tor-59f8dced114f20a147a5425ece67d7d44a81867b.tar.gz tor-59f8dced114f20a147a5425ece67d7d44a81867b.zip |
Refactor HS descriptor fetch to support descriptor ID
Big refactor of the HS client descriptor fetch functionnality. This allows
to fetch an HS descriptor using only a descriptor ID. Furthermore, it's also
possible to provide a list of HSDir(s) now that are used instead of the
automatically choosen one.
The approach taken was to add a descriptor_id field to the rend_data_t
structure so it can be used, if available, by the HS client. The onion
address field however has priority over it that is if both are set, the
onion address is used to fetch the descriptor.
A new public function is introduced called rend_client_fetch_v2_desc(...)
that does NOT lookup the client cache before fetching and can take a list of
HSDirs as a parameter.
The HSFETCH control command now uses this new function thus making it work
and final.
Signed-off-by: David Goulet <dgoulet@ev0ke.net>
Diffstat (limited to 'src/or/control.c')
-rw-r--r-- | src/or/control.c | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/src/or/control.c b/src/or/control.c index e7d8b5cdef..9258678e02 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -37,6 +37,7 @@ #include "nodelist.h" #include "policies.h" #include "reasons.h" +#include "rendclient.h" #include "rephist.h" #include "router.h" #include "routerlist.h" @@ -3266,6 +3267,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len, (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); + rend_data_t *rend_query = NULL; /* Make sure we have at least one argument, the HSAddress. */ args = getargs_helper("HSFETCH", conn, body, 1, -1); @@ -3273,10 +3275,10 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len, goto done; } - /* Extract the HS address that should NOT contain the .onion part. */ + /* Extract the first argument (either HSAddress or DescID). */ 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). */ + /* Remove it 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 && @@ -3287,40 +3289,42 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len, 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; + /* We have a well formed version 2 descriptor ID. Keep the decoded value + * of the id. */ + desc_id = digest; } 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)) { + char id[DIGEST_LEN] = {0}; const char *server; - memset(digest, 0, sizeof(digest)); server = arg + strlen(opt_server); - /* Is the server fingerprint valid?. */ + /* Is the server's fingerprint valid?. */ if (!string_is_hex(server) || strlen(server) != HEX_DIGEST_LEN || - base16_decode(digest, sizeof(digest), server, HEX_DIGEST_LEN)) { + base16_decode(id, sizeof(id), server, HEX_DIGEST_LEN)) { connection_printf_to_buf(conn, "552 Invalid fingerprint \"%s\"\r\n", server); goto done; } - node = node_get_by_id(digest); + node = node_get_by_id(id); if (!node) { connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n", server); goto done; } + if (!hsdirs) { + /* Stores routerstatus_t object for each specified server. */ + hsdirs = smartlist_new(); + } /* Valid server, add it to our local list. */ smartlist_add(hsdirs, node->rs); } else { @@ -3330,21 +3334,44 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len, } } SMARTLIST_FOREACH_END(arg); - /* XXX: Actually trigger the fetch(es). */ - (void) hsaddress; - (void) desc_id; - (void) hsdirs; + rend_query = tor_malloc_zero(sizeof(*rend_query)); - /* All good, thanks and come again! */ + if (hsaddress) { + strncpy(rend_query->onion_address, hsaddress, + sizeof(rend_query->onion_address)); + } else if (desc_id) { + /* Using a descriptor ID, we force the user to provide at least one + * hsdir server using the SERVER= option. */ + if (!hsdirs || !smartlist_len(hsdirs)) { + connection_printf_to_buf(conn, "552 SERVER= option is required\r\n"); + goto done; + } + memcpy(rend_query->descriptor_id, desc_id, + sizeof(rend_query->descriptor_id)); + } else { + /* We can't get in here because of the first argument check. */ + tor_assert(0); + } + /* We are about to trigger HSDir fetch so send the OK now because after + * that 650 event(s) are possible so better to have the 250 OK before them + * to avoid out of order replies. */ send_control_done(conn); + /* Trigger the fetch using the built rend query and possibly a lit of HS + * directory to use. This function ignores the client cache thus this will + * always send a fetch command. */ + rend_client_fetch_v2_desc(rend_query, hsdirs); + done: + if (hsdirs) { + smartlist_free(hsdirs); + } if (args) { SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); } + tor_free(rend_query); tor_free(arg1); - smartlist_free(hsdirs); return 0; } |