diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c index 1ea50fd350..3b506317b0 100644 --- a/src/feature/dirclient/dirclient.c +++ b/src/feature/dirclient/dirclient.c @@ -2722,6 +2722,7 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn, const char *reason = args->reason; const char *body = args->body; const size_t body_len = args->body_len; + hs_desc_decode_status_t decode_status; tor_assert(conn->hs_ident); @@ -2731,7 +2732,9 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn, switch (status_code) { case 200: /* We got something: Try storing it in the cache. */ - if (hs_cache_store_as_client(body, &conn->hs_ident->identity_pk) < 0) { + decode_status = hs_cache_store_as_client(body, + &conn->hs_ident->identity_pk); + if (decode_status != HS_DESC_DECODE_OK) { log_info(LD_REND, "Failed to store hidden service descriptor"); /* Fire control port FAILED event. */ hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest, diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c index 39c2267462..59b05d8f0a 100644 --- a/src/feature/hs/hs_cache.c +++ b/src/feature/hs/hs_cache.c @@ -395,7 +395,8 @@ lookup_v3_desc_as_client(const uint8_t *key) * hs_cache_client_descriptor_t object. In case of error, return NULL. */ static hs_cache_client_descriptor_t * cache_client_desc_new(const char *desc_str, - const ed25519_public_key_t *service_identity_pk) + const ed25519_public_key_t *service_identity_pk, + hs_desc_decode_status_t *decode_status_out) { hs_desc_decode_status_t ret; hs_descriptor_t *desc = NULL; @@ -435,6 +436,9 @@ cache_client_desc_new(const char *desc_str, client_desc->encoded_desc = tor_strdup(desc_str); end: + if (decode_status_out) { + *decode_status_out = ret; + } return client_desc; } @@ -796,19 +800,34 @@ hs_cache_lookup_as_client(const ed25519_public_key_t *key) return NULL; } -/** Public API: Given an encoded descriptor, store it in the client HS - * cache. Return -1 on error, 0 on success .*/ -int +/** Public API: Given an encoded descriptor, store it in the client HS cache. + * Return a decode status which changes how we handle the SOCKS connection + * depending on its value: + * + * HS_DESC_DECODE_OK: Returned on success. Descriptor was properly decoded + * and is now stored. + * + * HS_DESC_DECODE_NEED_CLIENT_AUTH: Client authorization is needed but the + * descriptor was still stored. + * + * HS_DESC_DECODE_BAD_CLIENT_AUTH: Client authorization for this descriptor + * was not usable but the descriptor was + * still stored. + * + * Any other codes means indicate where the error occured and the descriptor + * was not stored. */ +hs_desc_decode_status_t hs_cache_store_as_client(const char *desc_str, const ed25519_public_key_t *identity_pk) { + hs_desc_decode_status_t ret; hs_cache_client_descriptor_t *client_desc = NULL; tor_assert(desc_str); tor_assert(identity_pk); /* Create client cache descriptor object */ - client_desc = cache_client_desc_new(desc_str, identity_pk); + client_desc = cache_client_desc_new(desc_str, identity_pk, &ret); if (!client_desc) { log_warn(LD_GENERAL, "HSDesc parsing failed!"); log_debug(LD_GENERAL, "Failed to parse HSDesc: %s.", escaped(desc_str)); @@ -817,14 +836,15 @@ hs_cache_store_as_client(const char *desc_str, /* Push it to the cache */ if (cache_store_as_client(client_desc) < 0) { + ret = HS_DESC_DECODE_GENERIC_ERROR; goto err; } - return 0; + return ret; err: cache_client_desc_free(client_desc); - return -1; + return ret; } /** Clean all client caches using the current time now. */ diff --git a/src/feature/hs/hs_cache.h b/src/feature/hs/hs_cache.h index 5df7e54fc0..e7729f2041 100644 --- a/src/feature/hs/hs_cache.h +++ b/src/feature/hs/hs_cache.h @@ -83,8 +83,8 @@ const hs_descriptor_t * hs_cache_lookup_as_client(const struct ed25519_public_key_t *key); const char * hs_cache_lookup_encoded_as_client(const struct ed25519_public_key_t *key); -int hs_cache_store_as_client(const char *desc_str, - const struct ed25519_public_key_t *identity_pk); +hs_desc_decode_status_t hs_cache_store_as_client(const char *desc_str, + const struct ed25519_public_key_t *identity_pk); void hs_cache_clean_as_client(time_t now); void hs_cache_purge_as_client(void); diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index b777dafdfb..e5735ba028 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -393,7 +393,8 @@ test_client_pick_intro(void *arg) tt_assert(encoded); /* store it */ - hs_cache_store_as_client(encoded, &service_kp.pubkey); + ret = hs_cache_store_as_client(encoded, &service_kp.pubkey); + tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK); /* fetch it to make sure it works */ const hs_descriptor_t *fetched_desc = @@ -852,7 +853,7 @@ test_desc_has_arrived_cleanup(void *arg) /* Store in the client cache. */ ret = hs_cache_store_as_client(desc_str, &signing_kp.pubkey); - tt_int_op(ret, OP_EQ, 0); + tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK); cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey); tt_assert(cached_desc); hs_helper_desc_equal(desc, cached_desc); @@ -953,7 +954,7 @@ test_close_intro_circuits_new_desc(void *arg) /* Store it */ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey); - tt_int_op(ret, OP_EQ, 0); + tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK); tor_free(encoded); tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey)); } @@ -988,8 +989,8 @@ test_close_intro_circuits_new_desc(void *arg) tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); - hs_cache_store_as_client(encoded, &service_kp.pubkey); - tt_int_op(ret, OP_EQ, 0); + ret = hs_cache_store_as_client(encoded, &service_kp.pubkey); + tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK); tor_free(encoded); tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey)); }