mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Multiple fixes for the HSFETCH command
Ref: https://trac.torproject.org/projects/tor/ticket/14847?replyto=31#comment:31 Signed-off-by: David Goulet <dgoulet@ev0ke.net>
This commit is contained in:
parent
917c3aac60
commit
a4585405d6
@ -3263,28 +3263,27 @@ static int
|
||||
handle_control_hsfetch(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
int i;
|
||||
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 *hsfetch_command = "HSFETCH";
|
||||
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);
|
||||
args = getargs_helper(hsfetch_command, conn, body, 1, -1);
|
||||
if (!args) {
|
||||
goto done;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Extract the first argument (either HSAddress or DescID). */
|
||||
arg1 = smartlist_get(args, 0);
|
||||
/* 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 (rend_valid_service_id(arg1)) {
|
||||
hsaddress = arg1;
|
||||
} else if (strstr(arg1, v2_str) &&
|
||||
} else if (strcmpstart(arg1, v2_str) == 0 &&
|
||||
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) {
|
||||
@ -3292,15 +3291,17 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
|
||||
* of the id. */
|
||||
desc_id = digest;
|
||||
} else {
|
||||
connection_printf_to_buf(conn, "552 Unrecognized \"%s\"\r\n",
|
||||
connection_printf_to_buf(conn, "513 Unrecognized \"%s\"\r\n",
|
||||
arg1);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Skip first argument because it's the HSAddress. */
|
||||
SMARTLIST_FOREACH_BEGIN(args, char *, arg) {
|
||||
static const char *opt_server = "SERVER=";
|
||||
|
||||
/* Skip first argument because it's the HSAddress or DescID. */
|
||||
for (i = 1; i < smartlist_len(args); ++i) {
|
||||
const char *arg = smartlist_get(args, i);
|
||||
const node_t *node;
|
||||
static const char *opt_server = "SERVER=";
|
||||
|
||||
if (!strcasecmpstart(arg, opt_server)) {
|
||||
const char *server;
|
||||
@ -3319,11 +3320,11 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
|
||||
/* 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",
|
||||
connection_printf_to_buf(conn, "513 Unexpected argument \"%s\"\r\n",
|
||||
arg);
|
||||
goto done;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(arg);
|
||||
}
|
||||
|
||||
rend_query = tor_malloc_zero(sizeof(*rend_query));
|
||||
|
||||
@ -3334,7 +3335,8 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
|
||||
/* 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");
|
||||
connection_printf_to_buf(conn, "512 %s option is required\r\n",
|
||||
opt_server);
|
||||
goto done;
|
||||
}
|
||||
memcpy(rend_query->descriptor_id, desc_id,
|
||||
@ -3354,15 +3356,12 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
|
||||
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);
|
||||
}
|
||||
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
|
||||
smartlist_free(args);
|
||||
/* Contains data pointer that we don't own thus no cleanup. */
|
||||
smartlist_free(hsdirs);
|
||||
tor_free(rend_query);
|
||||
tor_free(arg1);
|
||||
exit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5470,13 +5469,16 @@ control_event_hs_descriptor_content(const char *onion_address,
|
||||
static const char *event_name = "HS_DESC_CONTENT";
|
||||
char *esc_content = NULL;
|
||||
|
||||
if (!onion_address || !desc_id || !hsdir_id_digest || !content) {
|
||||
if (!onion_address || !desc_id || !hsdir_id_digest) {
|
||||
log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, "
|
||||
"hsdir_id_digest==%p, content==%p", onion_address, desc_id,
|
||||
hsdir_id_digest, content);
|
||||
"hsdir_id_digest==%p", onion_address, desc_id, hsdir_id_digest);
|
||||
return;
|
||||
}
|
||||
|
||||
if (content == NULL) {
|
||||
/* Point it to empty content so it can still be escaped. */
|
||||
content = "";
|
||||
}
|
||||
write_escaped_data(content, strlen(content), &esc_content);
|
||||
|
||||
send_control_event(EVENT_HS_DESC_CONTENT, ALL_FORMATS,
|
||||
|
@ -2107,7 +2107,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
control_event_hs_descriptor_content(conn->rend_data->onion_address, \
|
||||
conn->requested_resource, \
|
||||
conn->identity_digest, \
|
||||
"") )
|
||||
NULL) )
|
||||
tor_assert(conn->rend_data);
|
||||
log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
|
||||
"(%s))",
|
||||
@ -2149,6 +2149,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
body);
|
||||
conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
|
||||
rend_client_desc_trynow(service_id);
|
||||
memwipe(service_id, 0, sizeof(service_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -496,11 +496,10 @@ get_last_hid_serv_requests(void)
|
||||
REND_SERVICE_ID_LEN_BASE32)
|
||||
|
||||
/** Look up the last request time to hidden service directory <b>hs_dir</b>
|
||||
* for descriptor ID <b>desc_id_base32</b> for the service specified in
|
||||
* <b>rend_query</b>. If <b>set</b> is non-zero,
|
||||
* assign the current time <b>now</b> and return that. Otherwise, return
|
||||
* the most recent request time, or 0 if no such request has been sent
|
||||
* before. */
|
||||
* for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
|
||||
* assign the current time <b>now</b> and return that. Otherwise, return the
|
||||
* most recent request time, or 0 if no such request has been sent before.
|
||||
*/
|
||||
static time_t
|
||||
lookup_last_hid_serv_request(routerstatus_t *hs_dir,
|
||||
const char *desc_id_base32,
|
||||
@ -612,20 +611,17 @@ rend_client_purge_last_hid_serv_requests(void)
|
||||
*
|
||||
* Return NULL on error else the hsdir node pointer. */
|
||||
static routerstatus_t *
|
||||
pick_hsdir(const char *desc_id)
|
||||
pick_hsdir(const char *desc_id, const char *desc_id_base32)
|
||||
{
|
||||
smartlist_t *responsible_dirs = smartlist_new();
|
||||
smartlist_t *usable_responsible_dirs = smartlist_new();
|
||||
const or_options_t *options = get_options();
|
||||
routerstatus_t *hs_dir;
|
||||
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
|
||||
time_t now = time(NULL);
|
||||
int excluded_some;
|
||||
|
||||
tor_assert(desc_id);
|
||||
|
||||
base32_encode(desc_id_base32, sizeof(desc_id_base32),
|
||||
desc_id, DIGEST_LEN);
|
||||
tor_assert(desc_id_base32);
|
||||
|
||||
/* Determine responsible dirs. Even if we can't get all we want, work with
|
||||
* the ones we have. If it's empty, we'll notice below. */
|
||||
@ -705,7 +701,7 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
|
||||
|
||||
/* Automatically pick an hs dir if none given. */
|
||||
if (!rs_hsdir) {
|
||||
hs_dir = pick_hsdir(desc_id);
|
||||
hs_dir = pick_hsdir(desc_id, desc_id_base32);
|
||||
if (!hs_dir) {
|
||||
/* No suitable hs dir can be found, stop right now. */
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user