diff --git a/src/or/or.h b/src/or/or.h index dee1881034..d9be1be37d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -793,6 +793,11 @@ typedef struct rend_data_t { /** Onion address (without the .onion part) that a client requests. */ char onion_address[REND_SERVICE_ID_LEN_BASE32+1]; + /** Descriptor ID for each replicas computed from the onion address. If + * the onion address is empty, this array MUST be empty. We keep them so + * we know when to purge our entry in the last hsdir request table. */ + char descriptor_id[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS][DIGEST_LEN]; + /** (Optional) descriptor cookie that is used by a client. */ char descriptor_cookie[REND_DESC_COOKIE_LEN]; @@ -800,8 +805,9 @@ typedef struct rend_data_t { rend_auth_type_t auth_type; /** Descriptor ID for a client request. The control port command HSFETCH - * can use this. */ - char descriptor_id[DIGEST_LEN]; + * uses this. It's set if the descriptor query should only use this + * descriptor ID. */ + char desc_id_fetch[DIGEST_LEN]; /** Hash of the hidden service's PK used by a service. */ char rend_pk_digest[DIGEST_LEN]; diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 13781c212e..8a8d8f7243 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -860,8 +860,8 @@ rend_client_fetch_v2_desc(const rend_data_t *query, if (query->onion_address[0] != '\0') { ret = fetch_v2_desc_by_addr(query, hsdirs); - } else if (query->descriptor_id[0] != '\0') { - ret = fetch_v2_desc_by_descid(query->descriptor_id, query, hsdirs); + } else if (!tor_digest_is_zero(query->desc_id_fetch)) { + ret = fetch_v2_desc_by_descid(query->desc_id_fetch, query, hsdirs); } else { /* Query data is invalid. */ ret = -1; diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 03dd757921..1b042f9fe9 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1404,3 +1404,100 @@ rend_data_dup(const rend_data_t *data) return tor_memdup(data, sizeof(rend_data_t)); } +/** Compute descriptor ID for each replicas and save them. A valid onion + * address must be present in the rend_data. + * + * Return 0 on success else -1. */ +static int +compute_desc_id(rend_data_t *rend_data) +{ + int ret, replica; + time_t now = time(NULL); + + tor_assert(rend_data); + + /* Compute descriptor ID for each replicas. */ + for (replica = 0; replica < ARRAY_LENGTH(rend_data->descriptor_id); + replica++) { + ret = rend_compute_v2_desc_id(rend_data->descriptor_id[replica], + rend_data->onion_address, + rend_data->descriptor_cookie, + now, replica); + if (ret < 0) { + goto end; + } + } + +end: + return ret; +} + +/** Allocate and initialize a rend_data_t object for a service using the + * given arguments. Only the onion_address is not optional. + * + * Return a valid rend_data_t pointer. */ +rend_data_t * +rend_data_service_create(const char *onion_address, const char *pk_digest, + const uint8_t *cookie, rend_auth_type_t auth_type) +{ + rend_data_t *rend_data = tor_malloc_zero(sizeof(*rend_data)); + + /* We need at least one else the call is wrong. */ + tor_assert(onion_address != NULL); + + if (pk_digest) { + memcpy(rend_data->rend_pk_digest, pk_digest, + sizeof(rend_data->rend_pk_digest)); + } + if (cookie) { + memcpy(rend_data->rend_cookie, cookie, + sizeof(rend_data->rend_cookie)); + } + + strlcpy(rend_data->onion_address, onion_address, + sizeof(rend_data->onion_address)); + rend_data->auth_type = auth_type; + + return rend_data; +} + +/** Allocate and initialize a rend_data_t object for a client request using + * the given arguments. Either an onion address or a descriptor ID is + * needed. Both can be given but only the onion address will be used to make + * the descriptor fetch. + * + * Return a valid rend_data_t pointer or NULL on error meaning the + * descriptor IDs couldn't be computed from the given data. */ +rend_data_t * +rend_data_client_create(const char *onion_address, const char *desc_id, + const char *cookie, rend_auth_type_t auth_type) +{ + rend_data_t *rend_data = tor_malloc_zero(sizeof(*rend_data)); + + /* We need at least one else the call is wrong. */ + tor_assert(onion_address != NULL || desc_id != NULL); + + if (cookie) { + memcpy(rend_data->descriptor_cookie, cookie, + sizeof(rend_data->descriptor_cookie)); + } + if (desc_id) { + memcpy(rend_data->desc_id_fetch, desc_id, + sizeof(rend_data->desc_id_fetch)); + } + if (onion_address) { + strlcpy(rend_data->onion_address, onion_address, + sizeof(rend_data->onion_address)); + if (compute_desc_id(rend_data) < 0) { + goto error; + } + } + + rend_data->auth_type = auth_type; + + return rend_data; + +error: + rend_data_free(rend_data); + return NULL; +} diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index b86cdb7fa6..a4d55d21d0 100644 --- a/src/or/rendcommon.h +++ b/src/or/rendcommon.h @@ -67,5 +67,13 @@ void rend_get_descriptor_id_bytes(char *descriptor_id_out, const char *secret_id_part); size_t rend_cache_get_total_allocation(void); +rend_data_t *rend_data_client_create(const char *onion_address, + const char *desc_id, + const char *cookie, + rend_auth_type_t auth_type); +rend_data_t *rend_data_service_create(const char *onion_address, + const char *pk_digest, + const uint8_t *cookie, + rend_auth_type_t auth_type); #endif