From 28cf9f2186a96bba74b0870b95a9fa1630305388 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 11 Mar 2015 14:52:28 -0400 Subject: [PATCH] Control: unbolt rend_data from HS desc event The HS_DESC event was using rend_data_t from the dir connection to reply the onion address and authentication type. With the new HSFETCH command, it's now possible to fetch a descriptor only using the descriptor id thus resulting in not having an onion address in any HS_DESC event. This patch removes rend_query from the hs desc control functions and replace it by an onion address string and an auth type. On a successful fetch, the service id is taken from the fetched descriptor. For that, an extra parameter is added to "store as a client" function that contains the cache entry stored. This will make the control event functions scale more easily over time if other values not present in rend_data_t are needed since the rend_data from the dir connection might not contained everything we need. Signed-off-by: David Goulet --- src/or/control.c | 64 +++++++++++++++++++++++++++++++-------------- src/or/control.h | 17 +++++++----- src/or/directory.c | 24 +++++++++++++---- src/or/rendcommon.c | 12 +++++++-- src/or/rendcommon.h | 3 ++- src/test/test_hs.c | 9 ++++--- 6 files changed, 92 insertions(+), 37 deletions(-) diff --git a/src/or/control.c b/src/or/control.c index 9258678e02..d5dc2f5ef3 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -5343,6 +5343,31 @@ node_describe_longname_by_id,(const char *id_digest)) return longname; } + +/** Return either the onion address if the given pointer is a non empty + * string else the unknown string. */ +static const char * +rend_hsaddress_str_or_unknown(const char *onion_address) +{ + static const char *str_unknown = "UNKNOWN"; + const char *str_ret = str_unknown; + + /* No valid pointer, unknown it is. */ + if (!onion_address) { + goto end; + } + /* Empty onion address thus we don't know, unknown it is. */ + if (onion_address[0] == '\0') { + goto end; + } + /* All checks are good so return the given onion address. */ + str_ret = onion_address; + +end: + return str_ret; +} + + /** send HS_DESC requested event. * * rend_query is used to fetch requested onion address and auth type. @@ -5363,7 +5388,7 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, send_control_event(EVENT_HS_DESC, ALL_FORMATS, "650 HS_DESC REQUESTED %s %s %s %s\r\n", - rend_query->onion_address, + rend_hsaddress_str_or_unknown(rend_query->onion_address), rend_auth_type_to_string(rend_query->auth_type), node_describe_longname_by_id(id_digest), desc_id_base32); @@ -5379,15 +5404,16 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, */ void control_event_hs_descriptor_receive_end(const char *action, - const rend_data_t *rend_query, + const char *onion_address, + rend_auth_type_t auth_type, const char *id_digest, const char *reason) { char *reason_field = NULL; - if (!action || !rend_query || !id_digest) { - log_warn(LD_BUG, "Called with action==%p, rend_query==%p, " - "id_digest==%p", action, rend_query, id_digest); + 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); return; } @@ -5398,8 +5424,8 @@ control_event_hs_descriptor_receive_end(const char *action, send_control_event(EVENT_HS_DESC, ALL_FORMATS, "650 HS_DESC %s %s %s %s%s\r\n", action, - rend_query->onion_address, - rend_auth_type_to_string(rend_query->auth_type), + rend_hsaddress_str_or_unknown(onion_address), + rend_auth_type_to_string(auth_type), node_describe_longname_by_id(id_digest), reason_field ? reason_field : ""); @@ -5411,16 +5437,16 @@ control_event_hs_descriptor_receive_end(const char *action, * called when a we successfully received a hidden service descriptor. */ void -control_event_hs_descriptor_received(const rend_data_t *rend_query, +control_event_hs_descriptor_received(const char *onion_address, + rend_auth_type_t auth_type, const char *id_digest) { - if (!rend_query || !id_digest) { - log_warn(LD_BUG, "Called with rend_query==%p, id_digest==%p", - rend_query, id_digest); + if (!id_digest) { + log_warn(LD_BUG, "Called with id_digest==%p", id_digest); return; } - control_event_hs_descriptor_receive_end("RECEIVED", rend_query, - id_digest, NULL); + control_event_hs_descriptor_receive_end("RECEIVED", onion_address, + auth_type, id_digest, NULL); } /** Send HS_DESC event to inform controller that query rend_query @@ -5429,16 +5455,16 @@ control_event_hs_descriptor_received(const rend_data_t *rend_query, * field. */ void -control_event_hs_descriptor_failed(const rend_data_t *rend_query, +control_event_hs_descriptor_failed(const char *onion_address, + rend_auth_type_t auth_type, const char *id_digest, const char *reason) { - if (!rend_query || !id_digest) { - log_warn(LD_BUG, "Called with rend_query==%p, id_digest==%p", - rend_query, id_digest); + if (!id_digest) { + log_warn(LD_BUG, "Called with id_digest==%p", id_digest); return; } - control_event_hs_descriptor_receive_end("FAILED", rend_query, + control_event_hs_descriptor_receive_end("FAILED", onion_address, auth_type, id_digest, reason); } @@ -5465,7 +5491,7 @@ control_event_hs_descriptor_content(const char *onion_address, send_control_event(EVENT_HS_DESC_CONTENT, ALL_FORMATS, "650 %s %s %s %s\r\n%s", event_name, - onion_address, + rend_hsaddress_str_or_unknown(onion_address), desc_id, node_describe_longname_by_id(hsdir_id_digest), esc_content); diff --git a/src/or/control.h b/src/or/control.h index ae49284965..93bcb8ef3d 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -107,13 +107,16 @@ void control_event_hs_descriptor_requested(const rend_data_t *rend_query, const char *desc_id_base32, const char *hs_dir); void control_event_hs_descriptor_receive_end(const char *action, - const rend_data_t *rend_query, - const char *hs_dir, - const char *reason); -void control_event_hs_descriptor_received(const rend_data_t *rend_query, - const char *hs_dir); -void control_event_hs_descriptor_failed(const rend_data_t *rend_query, - const char *hs_dir, + const char *onion_address, + rend_auth_type_t auth_type, + const char *id_digest, + const char *reason); +void control_event_hs_descriptor_received(const char *onion_address, + rend_auth_type_t auth_type, + const char *id_digest); +void control_event_hs_descriptor_failed(const char *onion_address, + rend_auth_type_t auth_type, + const char *id_digest, const char *reason); void control_event_hs_descriptor_content(const char *onion_address, const char *desc_id, diff --git a/src/or/directory.c b/src/or/directory.c index b6b0a5d7e0..0e7b9542dc 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2099,7 +2099,8 @@ 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, \ + control_event_hs_descriptor_failed(conn->rend_data->onion_address, \ + conn->rend_data->auth_type, \ conn->identity_digest, \ reason) ) #define SEND_HS_DESC_FAILED_CONTENT() ( \ @@ -2113,8 +2114,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn) (int)body_len, status_code, escaped(reason)); switch (status_code) { case 200: + { + rend_cache_entry_t *entry = NULL; + switch (rend_cache_store_v2_desc_as_client(body, - conn->requested_resource, conn->rend_data)) { + conn->requested_resource, conn->rend_data, + &entry)) { case RCS_BADDESC: case RCS_NOTDIR: /* Impossible */ log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. " @@ -2126,20 +2131,29 @@ connection_dir_client_reached_eof(dir_connection_t *conn) break; case RCS_OKAY: default: + { + char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; + /* Should never be NULL here for an OKAY returned code. */ + tor_assert(entry); + rend_get_service_id(entry->parsed->pk, service_id); + /* success. notify pending connections about this. */ log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor."); - control_event_hs_descriptor_received(conn->rend_data, + control_event_hs_descriptor_received(service_id, + conn->rend_data->auth_type, conn->identity_digest); - control_event_hs_descriptor_content(conn->rend_data->onion_address, + control_event_hs_descriptor_content(service_id, conn->requested_resource, conn->identity_digest, body); conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2; - rend_client_desc_trynow(conn->rend_data->onion_address); + rend_client_desc_trynow(service_id); break; + } } break; + } case 404: /* Not there. We'll retry when * connection_about_to_close_connection() cleans this conn up. */ diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 3d9cc23af4..95d16f1362 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1136,12 +1136,14 @@ rend_cache_store_v2_desc_as_dir(const char *desc) * If the descriptor's descriptor ID doesn't match desc_id_base32, * reject it. * - * Return an appropriate rend_cache_store_status_t. + * Return an appropriate rend_cache_store_status_t. If entry is not NULL, + * set it with the cache entry pointer of the descriptor. */ rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc, const char *desc_id_base32, - const rend_data_t *rend_query) + const rend_data_t *rend_query, + rend_cache_entry_t **entry) { /*XXXX this seems to have a bit of duplicate code with * rend_cache_store_v2_desc_as_dir(). Fix that. */ @@ -1289,9 +1291,15 @@ rend_cache_store_v2_desc_as_client(const char *desc, rend_cache_increment_allocation(rend_cache_entry_allocation(e)); log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.", safe_str_client(service_id), (int)encoded_size); + if (entry) { + *entry = e; + } return RCS_OKAY; okay: + if (entry) { + *entry = e; + } retval = RCS_OKAY; err: diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index 8396cc3551..f4f2051890 100644 --- a/src/or/rendcommon.h +++ b/src/or/rendcommon.h @@ -50,7 +50,8 @@ typedef enum { rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc); rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc, const char *desc_id_base32, - const rend_data_t *rend_query); + const rend_data_t *rend_query, + rend_cache_entry_t **entry); int rend_encode_v2_descriptors(smartlist_t *descs_out, rend_service_descriptor_t *desc, time_t now, uint8_t period, rend_auth_type_t auth_type, diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 910ac39c1a..130411efcb 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -159,7 +159,8 @@ test_hs_desc_event(void *arg) /* test received event */ rend_query.auth_type = 1; - control_event_hs_descriptor_received(&rend_query, HSDIR_EXIST_ID); + control_event_hs_descriptor_received(rend_query.onion_address, + rend_query.auth_type, HSDIR_EXIST_ID); expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\ STR_HSDIR_EXIST_LONGNAME"\r\n"; tt_assert(received_msg); @@ -168,7 +169,8 @@ test_hs_desc_event(void *arg) /* test failed event */ rend_query.auth_type = 2; - control_event_hs_descriptor_failed(&rend_query, HSDIR_NONE_EXIST_ID, + control_event_hs_descriptor_failed(rend_query.onion_address, + rend_query.auth_type, 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"; @@ -178,7 +180,8 @@ test_hs_desc_event(void *arg) /* test invalid auth type */ rend_query.auth_type = 999; - control_event_hs_descriptor_failed(&rend_query, HSDIR_EXIST_ID, + control_event_hs_descriptor_failed(rend_query.onion_address, + rend_query.auth_type, HSDIR_EXIST_ID, "QUERY_REJECTED"); expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\ STR_HSDIR_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n";