commit c1ffeadff4db375886d40bb5928ddd4fe761ba9f Author: David Goulet dgoulet@ev0ke.net Date: Thu Apr 30 12:28:11 2015 -0400
Add missing descriptor ID to HS_DESC control event
For FAILED and RECEIVED action of the HS_DESC event, we now sends back the descriptor ID at the end like specified in the control-spec section 4.1.25.
Fixes #15881
Signed-off-by: David Goulet dgoulet@ev0ke.net --- changes/bug15881 | 3 ++ src/or/control.c | 87 +++++++++++++++++++++++++++++++++++++++++---------- src/or/control.h | 7 ++--- src/or/directory.c | 5 ++- src/or/or.h | 4 +++ src/or/rendclient.c | 7 +++++ src/or/rendcommon.c | 9 +++++- src/or/rendcommon.h | 6 ++++ src/test/test_hs.c | 10 +++--- 9 files changed, 109 insertions(+), 29 deletions(-)
diff --git a/changes/bug15881 b/changes/bug15881 new file mode 100644 index 0000000..5cf561e --- /dev/null +++ b/changes/bug15881 @@ -0,0 +1,3 @@ + o Controller fixes: + - Add the descriptor ID in each HS_DESC control event. It was missing + but specified in control-spec.txt. Fixes ticket 15881. diff --git a/src/or/control.c b/src/or/control.c index d4e106e..b8b29d7 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -5904,6 +5904,44 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, desc_id_base32); }
+/** For an HS descriptor query <b>rend_data</b>, using the + * <b>onion_address</b> and HSDir fingerprint <b>hsdir_fp</b>, find out + * which descriptor ID in the query is the right one. + * + * Return a pointer of the binary descriptor ID found in the query's object + * or NULL if not found. */ +static const char * +get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp) +{ + int replica; + const char *desc_id = NULL; + + /* Possible if the fetch was done using a descriptor ID. This means that + * the HSFETCH command was used. */ + if (!tor_digest_is_zero(rend_data->desc_id_fetch)) { + desc_id = rend_data->desc_id_fetch; + goto end; + } + + /* OK, we have an onion address so now let's find which descriptor ID + * is the one associated with the HSDir fingerprint. */ + for (replica = 0; replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; + replica++) { + const char *digest = rend_data->descriptor_id[replica]; + + SMARTLIST_FOREACH_BEGIN(rend_data->hsdirs_fp, char *, fingerprint) { + if (tor_memcmp(fingerprint, hsdir_fp, DIGEST_LEN) == 0) { + /* Found it! This descriptor ID is the right one. */ + desc_id = digest; + goto end; + } + } SMARTLIST_FOREACH_END(fingerprint); + } + +end: + return desc_id; +} + /** send HS_DESC upload event. * * <b>service_id</b> is the descriptor onion address. @@ -5940,30 +5978,45 @@ control_event_hs_descriptor_upload(const char *service_id, void control_event_hs_descriptor_receive_end(const char *action, const char *onion_address, - rend_auth_type_t auth_type, + const rend_data_t *rend_data, const char *id_digest, const char *reason) { + char *desc_id_field = NULL; char *reason_field = NULL; + char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; + const char *desc_id = NULL;
- if (!action || !id_digest || !onion_address) { - log_warn(LD_BUG, "Called with action==%p, id_digest==%p " - "onion_address==%p", action, id_digest, onion_address); + if (!action || !id_digest || !rend_data || !onion_address) { + log_warn(LD_BUG, "Called with action==%p, id_digest==%p, " + "rend_data==%p, onion_address==%p", action, id_digest, + rend_data, onion_address); return; }
+ desc_id = get_desc_id_from_query(rend_data, id_digest); + if (desc_id != NULL) { + /* Set the descriptor ID digest to base32 so we can send it. */ + base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id, + DIGEST_LEN); + /* Extra whitespace is needed before the value. */ + tor_asprintf(&desc_id_field, " %s", desc_id_base32); + } + if (reason) { tor_asprintf(&reason_field, " REASON=%s", reason); }
send_control_event(EVENT_HS_DESC, ALL_FORMATS, - "650 HS_DESC %s %s %s %s%s\r\n", + "650 HS_DESC %s %s %s %s%s%s\r\n", action, rend_hsaddress_str_or_unknown(onion_address), - rend_auth_type_to_string(auth_type), + rend_auth_type_to_string(rend_data->auth_type), node_describe_longname_by_id(id_digest), + desc_id_field ? desc_id_field : "", reason_field ? reason_field : "");
+ tor_free(desc_id_field); tor_free(reason_field); }
@@ -6007,15 +6060,16 @@ control_event_hs_descriptor_upload_end(const char *action, */ void control_event_hs_descriptor_received(const char *onion_address, - rend_auth_type_t auth_type, + const rend_data_t *rend_data, const char *id_digest) { - if (!id_digest) { - log_warn(LD_BUG, "Called with id_digest==%p", id_digest); + if (!rend_data || !id_digest || !onion_address) { + log_warn(LD_BUG, "Called with rend_data==%p, id_digest==%p, " + "onion_address==%p", rend_data, id_digest, onion_address); return; } control_event_hs_descriptor_receive_end("RECEIVED", onion_address, - auth_type, id_digest, NULL); + rend_data, id_digest, NULL); }
/** send HS_DESC UPLOADED event @@ -6039,17 +6093,18 @@ control_event_hs_descriptor_uploaded(const char *id_digest) * field. */ void -control_event_hs_descriptor_failed(const char *onion_address, - rend_auth_type_t auth_type, +control_event_hs_descriptor_failed(const rend_data_t *rend_data, const char *id_digest, const char *reason) { - if (!id_digest) { - log_warn(LD_BUG, "Called with id_digest==%p", id_digest); + if (!rend_data || !id_digest) { + log_warn(LD_BUG, "Called with rend_data==%p, id_digest==%p", + rend_data, id_digest); return; } - control_event_hs_descriptor_receive_end("FAILED", onion_address, auth_type, - id_digest, reason); + control_event_hs_descriptor_receive_end("FAILED", + rend_data->onion_address, + rend_data, id_digest, reason); }
/** send HS_DESC_CONTENT event after completion of a successful fetch from diff --git a/src/or/control.h b/src/or/control.h index 644caf8..a9f2725 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -111,18 +111,17 @@ void control_event_hs_descriptor_upload(const char *service_id, const char *hs_dir); void control_event_hs_descriptor_receive_end(const char *action, const char *onion_address, - rend_auth_type_t auth_type, + const rend_data_t *rend_data, const char *id_digest, const char *reason); void control_event_hs_descriptor_upload_end(const char *action, const char *hs_dir, const char *reason); void control_event_hs_descriptor_received(const char *onion_address, - rend_auth_type_t auth_type, + const rend_data_t *rend_data, const char *id_digest); void control_event_hs_descriptor_uploaded(const char *hs_dir); -void control_event_hs_descriptor_failed(const char *onion_address, - rend_auth_type_t auth_type, +void control_event_hs_descriptor_failed(const rend_data_t *rend_data, const char *id_digest, const char *reason); void control_event_hs_descriptor_upload_failed(const char *hs_dir, diff --git a/src/or/directory.c b/src/or/directory.c index 85da97f..9fe3052 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2099,8 +2099,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { #define SEND_HS_DESC_FAILED_EVENT(reason) ( \ - control_event_hs_descriptor_failed(conn->rend_data->onion_address, \ - conn->rend_data->auth_type, \ + control_event_hs_descriptor_failed(conn->rend_data, \ conn->identity_digest, \ reason) ) #define SEND_HS_DESC_FAILED_CONTENT() ( \ @@ -2141,7 +2140,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor."); control_event_hs_descriptor_received(service_id, - conn->rend_data->auth_type, + conn->rend_data, conn->identity_digest); control_event_hs_descriptor_content(service_id, conn->requested_resource, diff --git a/src/or/or.h b/src/or/or.h index d9be1be..5bb080f 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -814,6 +814,10 @@ typedef struct rend_data_t {
/** Rendezvous cookie used by both, client and service. */ char rend_cookie[REND_COOKIE_LEN]; + + /** List of HSDir fingerprints on which this request has been sent to. + * This contains binary identity digest of the directory. */ + smartlist_t *hsdirs_fp; } rend_data_t;
/** Time interval for tracking replays of DH public keys received in diff --git a/src/or/rendclient.c b/src/or/rendclient.c index d0c4b87..59e938e 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -686,6 +686,7 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query, routerstatus_t *rs_hsdir) { routerstatus_t *hs_dir = rs_hsdir; + char *hsdir_fp; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64]; #ifdef ENABLE_TOR2WEB_MODE @@ -709,6 +710,12 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query, } }
+ /* Add a copy of the HSDir identity digest to the query so we can track it + * on the control port. */ + hsdir_fp = tor_memdup(hs_dir->identity_digest, + sizeof(hs_dir->identity_digest)); + smartlist_add(rend_query->hsdirs_fp, hsdir_fp); + /* Encode descriptor cookie for logging purposes. Also, if the cookie is * malformed, no fetch is triggered thus this needs to be done before the * fetch request. */ diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index c3f0d32..f06a5ff 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1400,8 +1400,14 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, rend_data_t * rend_data_dup(const rend_data_t *data) { + rend_data_t *data_dup; tor_assert(data); - return tor_memdup(data, sizeof(rend_data_t)); + data_dup = tor_memdup(data, sizeof(rend_data_t)); + data_dup->hsdirs_fp = smartlist_new(); + SMARTLIST_FOREACH(data->hsdirs_fp, char *, fp, + smartlist_add(data_dup->hsdirs_fp, + tor_memdup(fp, DIGEST_LEN))); + return data_dup; }
/** Compute descriptor ID for each replicas and save them. A valid onion @@ -1495,6 +1501,7 @@ rend_data_client_create(const char *onion_address, const char *desc_id, }
rend_data->auth_type = auth_type; + rend_data->hsdirs_fp = smartlist_new();
return rend_data;
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index a4d55d2..806851c 100644 --- a/src/or/rendcommon.h +++ b/src/or/rendcommon.h @@ -16,6 +16,12 @@ static INLINE void rend_data_free(rend_data_t *data) { + if (!data) { + return; + } + /* Cleanup the HSDir identity digest. */ + SMARTLIST_FOREACH(data->hsdirs_fp, char *, d, tor_free(d)); + smartlist_free(data->hsdirs_fp); tor_free(data); }
diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 4c43ebd..89438f2 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -160,7 +160,7 @@ test_hs_desc_event(void *arg) /* test received event */ rend_query.auth_type = 1; control_event_hs_descriptor_received(rend_query.onion_address, - rend_query.auth_type, HSDIR_EXIST_ID); + &rend_query, HSDIR_EXIST_ID); expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\ STR_HSDIR_EXIST_LONGNAME"\r\n"; tt_assert(received_msg); @@ -169,8 +169,8 @@ test_hs_desc_event(void *arg)
/* test failed event */ rend_query.auth_type = 2; - control_event_hs_descriptor_failed(rend_query.onion_address, - rend_query.auth_type, HSDIR_NONE_EXIST_ID, + control_event_hs_descriptor_failed(&rend_query, + HSDIR_NONE_EXIST_ID, "QUERY_REJECTED"); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\ STR_HSDIR_NONE_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n"; @@ -180,8 +180,8 @@ test_hs_desc_event(void *arg)
/* test invalid auth type */ rend_query.auth_type = 999; - control_event_hs_descriptor_failed(rend_query.onion_address, - rend_query.auth_type, HSDIR_EXIST_ID, + control_event_hs_descriptor_failed(&rend_query, + HSDIR_EXIST_ID, "QUERY_REJECTED"); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\ STR_HSDIR_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n";
tor-commits@lists.torproject.org