diff options
Diffstat (limited to 'src/feature/hs')
-rw-r--r-- | src/feature/hs/hs_cache.c | 7 | ||||
-rw-r--r-- | src/feature/hs/hs_client.c | 32 | ||||
-rw-r--r-- | src/feature/hs/hs_client.h | 1 | ||||
-rw-r--r-- | src/feature/hs/hs_config.c | 30 | ||||
-rw-r--r-- | src/feature/hs/hs_descriptor.c | 101 | ||||
-rw-r--r-- | src/feature/hs/hs_service.c | 144 | ||||
-rw-r--r-- | src/feature/hs/hs_service.h | 75 |
7 files changed, 263 insertions, 127 deletions
diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c index b9bcb446a1..afd69e1bec 100644 --- a/src/feature/hs/hs_cache.c +++ b/src/feature/hs/hs_cache.c @@ -647,6 +647,13 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc) } /* Remove old entry. Make space for the new one! */ remove_v3_desc_as_client(cache_entry); + + /* We just removed an old descriptor and will replace it. We'll close all + * intro circuits related to this old one so we don't have leftovers. We + * leave the rendezvous circuits opened because they could be in use. */ + hs_client_close_intro_circuits_from_desc(cache_entry->desc); + + /* Free it. */ cache_client_desc_free(cache_entry); } diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index 11e24a3660..dfad216abb 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -1844,6 +1844,38 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ) return ret; } +/* Close all client introduction circuits related to the given descriptor. + * This is called with a descriptor that is about to get replaced in the + * client cache. + * + * Even though the introduction point might be exactly the same, we'll rebuild + * them if needed but the odds are very low that an existing matching + * introduction circuit exists at that stage. */ +void +hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc) +{ + origin_circuit_t *ocirc = NULL; + + tor_assert(desc); + + /* We iterate over all client intro circuits because they aren't kept in the + * HS circuitmap. That is probably something we want to do one day. */ + while ((ocirc = circuit_get_next_intro_circ(ocirc, true))) { + if (ocirc->hs_ident == NULL) { + /* Not a v3 circuit, ignore it. */ + continue; + } + + /* Does it match any IP in the given descriptor? If not, ignore. */ + if (find_desc_intro_point_by_ident(ocirc->hs_ident, desc) == NULL) { + continue; + } + + /* We have a match. Close the circuit as consider it expired. */ + circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED); + } +} + /* Release all the storage held by the client subsystem. */ void hs_client_free_all(void) diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index fb4f9e9e9f..f6fb167ea2 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -77,6 +77,7 @@ int hs_config_client_authorization(const or_options_t *options, int validate_only); int hs_client_reextend_intro_circuit(origin_circuit_t *circ); +void hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc); void hs_client_purge_state(void); diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c index 93d7403dfb..497e31fbb4 100644 --- a/src/feature/hs/hs_config.c +++ b/src/feature/hs/hs_config.c @@ -419,7 +419,7 @@ config_generic_service(const config_line_t *line_, dup_opt_seen = line->key; goto err; } - have_version = 1; + have_version = service->config.hs_version_explicitly_set = 1; continue; } /* Virtual port. */ @@ -534,18 +534,15 @@ config_service(const config_line_t *line, const or_options_t *options, /* We have a new hidden service. */ service = hs_service_new(options); + /* We'll configure that service as a generic one and then pass it to a * specific function according to the configured version number. */ if (config_generic_service(line, options, service) < 0) { goto err; } + tor_assert(service->config.version <= HS_VERSION_MAX); - /* Before we configure the service on a per-version basis, we'll make - * sure that this set of options for a service are valid that is for - * instance an option only for v2 is not used for v3. */ - if (config_has_invalid_options(line->next, service)) { - goto err; - } + /* Check permission on service directory that was just parsed. And this must * be done regardless of the service version. Do not ask for the directory * to be created, this is done when the keys are loaded because we could be @@ -556,11 +553,19 @@ config_service(const config_line_t *line, const or_options_t *options, 0) < 0) { goto err; } + /* We'll try to learn the service version here by loading the key(s) if - * present. Depending on the key format, we can figure out the service - * version. If we can't find a key, the configuration version will be used - * which has been set previously. */ - service->config.version = config_learn_service_version(service); + * present and we did not set HiddenServiceVersion. Depending on the key + * format, we can figure out the service version. */ + if (!service->config.hs_version_explicitly_set) { + service->config.version = config_learn_service_version(service); + } + + /* We make sure that this set of options for a service are valid that is for + * instance an option only for v2 is not used for v3. */ + if (config_has_invalid_options(line->next, service)) { + goto err; + } /* Different functions are in charge of specific options for a version. We * start just after the service directory line so once we hit another @@ -580,13 +585,16 @@ config_service(const config_line_t *line, const or_options_t *options, if (ret < 0) { goto err; } + /* We'll check if this service can be kept depending on the others * configured previously. */ if (service_is_duplicate_in_list(service_list, service)) { goto err; } + /* Passes, add it to the given list. */ smartlist_add(service_list, service); + return 0; err: diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c index 8515314b38..1b2008c804 100644 --- a/src/feature/hs/hs_descriptor.c +++ b/src/feature/hs/hs_descriptor.c @@ -1400,6 +1400,50 @@ encrypted_data_length_is_valid(size_t len) return 0; } +/* Build the KEYS component for the authorized client computation. The format + * of the construction is: + * + * SECRET_SEED = x25519(sk, pk) + * KEYS = KDF(subcredential | SECRET_SEED, 40) + * + * Set the <b>keys_out</b> argument to point to the buffer containing the KEYS, + * and return the buffer's length. The caller should wipe and free its content + * once done with it. This function can't fail. */ +static size_t +build_descriptor_cookie_keys(const uint8_t *subcredential, + size_t subcredential_len, + const curve25519_secret_key_t *sk, + const curve25519_public_key_t *pk, + uint8_t **keys_out) +{ + uint8_t secret_seed[CURVE25519_OUTPUT_LEN]; + uint8_t *keystream; + size_t keystream_len = HS_DESC_CLIENT_ID_LEN + HS_DESC_COOKIE_KEY_LEN; + crypto_xof_t *xof; + + tor_assert(subcredential); + tor_assert(sk); + tor_assert(pk); + tor_assert(keys_out); + + keystream = tor_malloc_zero(keystream_len); + + /* Calculate x25519(sk, pk) to get the secret seed. */ + curve25519_handshake(secret_seed, sk, pk); + + /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */ + xof = crypto_xof_new(); + crypto_xof_add_bytes(xof, subcredential, subcredential_len); + crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed)); + crypto_xof_squeeze_bytes(xof, keystream, keystream_len); + crypto_xof_free(xof); + + memwipe(secret_seed, 0, sizeof(secret_seed)); + + *keys_out = keystream; + return keystream_len; +} + /* Decrypt the descriptor cookie given the descriptor, the auth client, * and the client secret key. On sucess, return 0 and a newly allocated * descriptor cookie descriptor_cookie_out. On error or if the client id @@ -1412,12 +1456,11 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc, uint8_t **descriptor_cookie_out) { int ret = -1; - uint8_t secret_seed[CURVE25519_OUTPUT_LEN]; - uint8_t keystream[HS_DESC_CLIENT_ID_LEN + HS_DESC_COOKIE_KEY_LEN]; - uint8_t *cookie_key = NULL; + uint8_t *keystream = NULL; + size_t keystream_length = 0; uint8_t *descriptor_cookie = NULL; + const uint8_t *cookie_key = NULL; crypto_cipher_t *cipher = NULL; - crypto_xof_t *xof = NULL; tor_assert(desc); tor_assert(client); @@ -1429,16 +1472,13 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc, sizeof(*client_auth_sk))); tor_assert(!tor_mem_is_zero((char *) desc->subcredential, DIGEST256_LEN)); - /* Calculate x25519(client_x, hs_Y) */ - curve25519_handshake(secret_seed, client_auth_sk, - &desc->superencrypted_data.auth_ephemeral_pubkey); - - /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */ - xof = crypto_xof_new(); - crypto_xof_add_bytes(xof, desc->subcredential, DIGEST256_LEN); - crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed)); - crypto_xof_squeeze_bytes(xof, keystream, sizeof(keystream)); - crypto_xof_free(xof); + /* Get the KEYS component to derive the CLIENT-ID and COOKIE-KEY. */ + keystream_length = + build_descriptor_cookie_keys(desc->subcredential, DIGEST256_LEN, + client_auth_sk, + &desc->superencrypted_data.auth_ephemeral_pubkey, + &keystream); + tor_assert(keystream_length > 0); /* If the client id of auth client is not the same as the calculcated * client id, it means that this auth client is invaild according to the @@ -1464,8 +1504,8 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc, if (cipher) { crypto_cipher_free(cipher); } - memwipe(secret_seed, 0, sizeof(secret_seed)); - memwipe(keystream, 0, sizeof(keystream)); + memwipe(keystream, 0, keystream_length); + tor_free(keystream); return ret; } @@ -2878,11 +2918,10 @@ hs_desc_build_authorized_client(const uint8_t *subcredential, const uint8_t *descriptor_cookie, hs_desc_authorized_client_t *client_out) { - uint8_t secret_seed[CURVE25519_OUTPUT_LEN]; - uint8_t keystream[HS_DESC_CLIENT_ID_LEN + HS_DESC_COOKIE_KEY_LEN]; - uint8_t *cookie_key; + uint8_t *keystream = NULL; + size_t keystream_length = 0; + const uint8_t *cookie_key; crypto_cipher_t *cipher; - crypto_xof_t *xof; tor_assert(client_auth_pk); tor_assert(auth_ephemeral_sk); @@ -2898,18 +2937,14 @@ hs_desc_build_authorized_client(const uint8_t *subcredential, tor_assert(!tor_mem_is_zero((char *) subcredential, DIGEST256_LEN)); - /* Calculate x25519(hs_y, client_X) */ - curve25519_handshake(secret_seed, - auth_ephemeral_sk, - client_auth_pk); - - /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */ - xof = crypto_xof_new(); - crypto_xof_add_bytes(xof, subcredential, DIGEST256_LEN); - crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed)); - crypto_xof_squeeze_bytes(xof, keystream, sizeof(keystream)); - crypto_xof_free(xof); + /* Get the KEYS part so we can derive the CLIENT-ID and COOKIE-KEY. */ + keystream_length = + build_descriptor_cookie_keys(subcredential, DIGEST256_LEN, + auth_ephemeral_sk, client_auth_pk, + &keystream); + tor_assert(keystream_length > 0); + /* Extract the CLIENT-ID and COOKIE-KEY from the KEYS. */ memcpy(client_out->client_id, keystream, HS_DESC_CLIENT_ID_LEN); cookie_key = keystream + HS_DESC_CLIENT_ID_LEN; @@ -2924,8 +2959,8 @@ hs_desc_build_authorized_client(const uint8_t *subcredential, (const char *) descriptor_cookie, HS_DESC_DESCRIPTOR_COOKIE_LEN); - memwipe(secret_seed, 0, sizeof(secret_seed)); - memwipe(keystream, 0, sizeof(keystream)); + memwipe(keystream, 0, keystream_length); + tor_free(keystream); crypto_cipher_free(cipher); } diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c index 78654bfb23..7d56c9e2ad 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -1696,6 +1696,32 @@ build_desc_intro_points(const hs_service_t *service, } DIGEST256MAP_FOREACH_END; } +/* Build the descriptor signing key certificate. */ +static void +build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now) +{ + hs_desc_plaintext_data_t *plaintext; + + tor_assert(desc); + tor_assert(desc->desc); + + /* Ease our life a bit. */ + plaintext = &desc->desc->plaintext_data; + + /* Get rid of what we have right now. */ + tor_cert_free(plaintext->signing_key_cert); + + /* Fresh certificate for the signing key. */ + plaintext->signing_key_cert = + tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC, + &desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME, + CERT_FLAG_INCLUDE_SIGNING_KEY); + /* If the cert creation fails, the descriptor encoding will fail and thus + * ultimately won't be uploaded. We'll get a stack trace to help us learn + * where the call came from and the tor_cert_create() will log the error. */ + tor_assert_nonfatal(plaintext->signing_key_cert); +} + /* Populate the descriptor encrypted section from the given service object. * This will generate a valid list of introduction points that can be used * after for circuit creation. Return 0 on success else -1 on error. */ @@ -1811,17 +1837,15 @@ build_service_desc_superencrypted(const hs_service_t *service, /* Populate the descriptor plaintext section from the given service object. * The caller must make sure that the keys in the descriptors are valid that - * is are non-zero. Return 0 on success else -1 on error. */ -static int + * is are non-zero. This can't fail. */ +static void build_service_desc_plaintext(const hs_service_t *service, - hs_service_descriptor_t *desc, time_t now) + hs_service_descriptor_t *desc) { - int ret = -1; hs_desc_plaintext_data_t *plaintext; tor_assert(service); tor_assert(desc); - /* XXX: Use a "assert_desc_ok()" ? */ tor_assert(!tor_mem_is_zero((char *) &desc->blinded_kp, sizeof(desc->blinded_kp))); tor_assert(!tor_mem_is_zero((char *) &desc->signing_kp, @@ -1835,24 +1859,13 @@ build_service_desc_plaintext(const hs_service_t *service, plaintext->version = service->config.version; plaintext->lifetime_sec = HS_DESC_DEFAULT_LIFETIME; - plaintext->signing_key_cert = - tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC, - &desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME, - CERT_FLAG_INCLUDE_SIGNING_KEY); - if (plaintext->signing_key_cert == NULL) { - log_warn(LD_REND, "Unable to create descriptor signing certificate for " - "service %s", - safe_str_client(service->onion_address)); - goto end; - } /* Copy public key material to go in the descriptor. */ ed25519_pubkey_copy(&plaintext->signing_pubkey, &desc->signing_kp.pubkey); ed25519_pubkey_copy(&plaintext->blinded_pubkey, &desc->blinded_kp.pubkey); - /* Success. */ - ret = 0; - end: - return ret; + /* Create the signing key certificate. This will be updated before each + * upload but we create it here so we don't complexify our unit tests. */ + build_desc_signing_key_cert(desc, approx_time()); } /** Compute the descriptor's OPE cipher for encrypting revision counters. */ @@ -1924,12 +1937,10 @@ build_service_desc_keys(const hs_service_t *service, goto end; } - /* Random a descriptor cookie to be used as a part of a key to encrypt the - * descriptor, if the client auth is enabled. */ - if (service->config.is_client_auth_enabled) { - crypto_strongest_rand(desc->descriptor_cookie, - sizeof(desc->descriptor_cookie)); - } + /* Random descriptor cookie to be used as a part of a key to encrypt the + * descriptor, only if the client auth is enabled will it be used. */ + crypto_strongest_rand(desc->descriptor_cookie, + sizeof(desc->descriptor_cookie)); /* Success. */ ret = 0; @@ -1944,8 +1955,7 @@ build_service_desc_keys(const hs_service_t *service, * * This can error if we are unable to create keys or certificate. */ static void -build_service_descriptor(hs_service_t *service, time_t now, - uint64_t time_period_num, +build_service_descriptor(hs_service_t *service, uint64_t time_period_num, hs_service_descriptor_t **desc_out) { char *encoded_desc; @@ -1964,9 +1974,8 @@ build_service_descriptor(hs_service_t *service, time_t now, goto err; } /* Setup plaintext descriptor content. */ - if (build_service_desc_plaintext(service, desc, now) < 0) { - goto err; - } + build_service_desc_plaintext(service, desc); + /* Setup superencrypted descriptor content. */ if (build_service_desc_superencrypted(service, desc) < 0) { goto err; @@ -2039,10 +2048,8 @@ build_descriptors_for_new_service(hs_service_t *service, time_t now) } /* Build descriptors. */ - build_service_descriptor(service, now, current_desc_tp, - &service->desc_current); - build_service_descriptor(service, now, next_desc_tp, - &service->desc_next); + build_service_descriptor(service, current_desc_tp, &service->desc_current); + build_service_descriptor(service, next_desc_tp, &service->desc_next); log_info(LD_REND, "Hidden service %s has just started. Both descriptors " "built. Now scheduled for upload.", safe_str_client(service->onion_address)); @@ -2072,7 +2079,7 @@ build_all_descriptors(time_t now) } if (service->desc_next == NULL) { - build_service_descriptor(service, now, hs_get_next_time_period_num(0), + build_service_descriptor(service, hs_get_next_time_period_num(0), &service->desc_next); log_info(LD_REND, "Hidden service %s next descriptor successfully " "built. Now scheduled for upload.", @@ -2284,12 +2291,9 @@ service_desc_schedule_upload(hs_service_descriptor_t *desc, } } -/* Update the given descriptor from the given service. The possible update - * actions includes: - * - Picking missing intro points if needed. - */ +/* Pick missing intro points for this descriptor if needed. */ static void -update_service_descriptor(hs_service_t *service, +update_service_descriptor_intro_points(hs_service_t *service, hs_service_descriptor_t *desc, time_t now) { unsigned int num_intro_points; @@ -2328,15 +2332,17 @@ update_service_descriptor(hs_service_t *service, } } -/* Update descriptors for each service if needed. */ +/* Update descriptor intro points for each service if needed. We do this as + * part of the periodic event because we need to establish intro point circuits + * before we publish descriptors. */ STATIC void -update_all_descriptors(time_t now) +update_all_descriptors_intro_points(time_t now) { FOR_EACH_SERVICE_BEGIN(service) { /* We'll try to update each descriptor that is if certain conditions apply * in order for the descriptor to be updated. */ FOR_EACH_DESCRIPTOR_BEGIN(service, desc) { - update_service_descriptor(service, desc, now); + update_service_descriptor_intro_points(service, desc, now); } FOR_EACH_DESCRIPTOR_END; } FOR_EACH_SERVICE_END; } @@ -2621,10 +2627,10 @@ run_build_descriptor_event(time_t now) * been rotated or we just started up. */ build_all_descriptors(now); - /* Finally, we'll check if we should update the descriptors. Missing - * introduction points will be picked in this function which is useful for - * newly built descriptors. */ - update_all_descriptors(now); + /* Finally, we'll check if we should update the descriptors' intro + * points. Missing introduction points will be picked in this function which + * is useful for newly built descriptors. */ + update_all_descriptors_intro_points(now); } /* For the given service, launch any intro point circuits that could be @@ -3085,6 +3091,37 @@ should_service_upload_descriptor(const hs_service_t *service, return 0; } +/* Refresh the given service descriptor meaning this will update every mutable + * field that needs to be updated before we upload. + * + * This should ONLY be called before uploading a descriptor. It assumes that + * the descriptor has been built (desc->desc) and that all intro point + * circuits have been established. */ +static void +refresh_service_descriptor(const hs_service_t *service, + hs_service_descriptor_t *desc, time_t now) +{ + /* There are few fields that we consider "mutable" in the descriptor meaning + * we need to update them regurlarly over the lifetime fo the descriptor. + * The rest are set once and should not be modified. + * + * - Signing key certificate. + * - Revision counter. + * - Introduction points which includes many thing. See + * hs_desc_intro_point_t. and the setup_desc_intro_point() function. + */ + + /* Create the signing key certificate. */ + build_desc_signing_key_cert(desc, now); + + /* Build the intro points descriptor section. The refresh step is just + * before we upload so all circuits have been properly established. */ + build_desc_intro_points(service, desc, now); + + /* Set the desc revision counter right before uploading */ + set_descriptor_revision_counter(desc, now, service->desc_current == desc); +} + /* Scheduled event run from the main loop. Try to upload the descriptor for * each service. */ STATIC void @@ -3120,15 +3157,12 @@ run_upload_descriptor_event(time_t now) service->config.num_intro_points, (desc->missing_intro_points) ? " (couldn't pick more)" : ""); - /* At this point, we have to upload the descriptor so start by building - * the intro points descriptor section which we are now sure to be - * accurate because all circuits have been established. */ - build_desc_intro_points(service, desc, now); - - /* Set the desc revision counter right before uploading */ - set_descriptor_revision_counter(desc, approx_time(), - service->desc_current == desc); + /* We are about to upload so we need to do one last step which is to + * update the service's descriptor mutable fields in order to upload a + * coherent descriptor. */ + refresh_service_descriptor(service, desc, now); + /* Proceed with the upload, the descriptor is ready to be encoded. */ upload_descriptor_to_all(service, desc); } FOR_EACH_DESCRIPTOR_END; } FOR_EACH_SERVICE_END; diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h index 6fb15b9d37..a8a9faaea9 100644 --- a/src/feature/hs/hs_service.h +++ b/src/feature/hs/hs_service.h @@ -99,49 +99,65 @@ typedef struct hs_service_intropoints_t { digestmap_t *failed_id; } hs_service_intropoints_t; -/* Representation of a service descriptor. */ +/* Representation of a service descriptor. + * + * Some elements of the descriptor are mutable whereas others are immutable: + + * Immutable elements are initialized once when the descriptor is built (when + * service descriptors gets rotated). This means that these elements are + * initialized once and then they don't change for the lifetime of the + * descriptor. See build_service_descriptor(). + * + * Mutable elements are initialized when we build the descriptor but they are + * also altered during the lifetime of the descriptor. They could be + * _refreshed_ everytime we upload the descriptor (which happens multiple times + * over the lifetime of the descriptor), or through periodic events. We do this + * for elements like the descriptor revision counter and various + * certificates. See refresh_service_descriptor() and + * update_service_descriptor_intro_points(). + */ typedef struct hs_service_descriptor_t { - /* Decoded descriptor. This object is used for encoding when the service - * publishes the descriptor. */ - hs_descriptor_t *desc; - - /* Client authorization ephemeral keypair. */ + /* Immutable: Client authorization ephemeral keypair. */ curve25519_keypair_t auth_ephemeral_kp; - /* Descriptor cookie used to encrypt the descriptor, when the client - * authorization is enabled */ + /* Immutable: Descriptor cookie used to encrypt the descriptor, when the + * client authorization is enabled */ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; - /* Descriptor signing keypair. */ + /* Immutable: Descriptor signing keypair. */ ed25519_keypair_t signing_kp; - /* Blinded keypair derived from the master identity public key. */ + /* Immutable: Blinded keypair derived from the master identity public key. */ ed25519_keypair_t blinded_kp; - /* When is the next time when we should upload the descriptor. */ + /* Immutable: The time period number this descriptor has been created for. */ + uint64_t time_period_num; + + /** Immutable: The OPE cipher for encrypting revision counters for this + * descriptor. Tied to the descriptor blinded key. */ + struct crypto_ope_t *ope_cipher; + + /* Mutable: Decoded descriptor. This object is used for encoding when the + * service publishes the descriptor. */ + hs_descriptor_t *desc; + + /* Mutable: When is the next time when we should upload the descriptor. */ time_t next_upload_time; - /* Introduction points assign to this descriptor which contains - * hs_service_intropoints_t object indexed by authentication key (the RSA - * key if the node is legacy). */ + /* Mutable: Introduction points assign to this descriptor which contains + * hs_service_intropoints_t object indexed by authentication key (the RSA key + * if the node is legacy). */ hs_service_intropoints_t intro_points; - /* The time period number this descriptor has been created for. */ - uint64_t time_period_num; - - /* True iff we have missing intro points for this descriptor because we - * couldn't pick any nodes. */ + /* Mutable: True iff we have missing intro points for this descriptor because + * we couldn't pick any nodes. */ unsigned int missing_intro_points : 1; - /** List of the responsible HSDirs (their b64ed identity digest) last time we - * uploaded this descriptor. If the set of responsible HSDirs is different - * from this list, this means we received new dirinfo and we need to - * reupload our descriptor. */ + /** Mutable: List of the responsible HSDirs (their b64ed identity digest) + * last time we uploaded this descriptor. If the set of responsible HSDirs + * is different from this list, this means we received new dirinfo and we + * need to reupload our descriptor. */ smartlist_t *previous_hsdirs; - - /** The OPE cipher for encrypting revision counters for this descriptor. - * Tied to the descriptor blinded key. */ - struct crypto_ope_t *ope_cipher; } hs_service_descriptor_t; /* Service key material. */ @@ -178,6 +194,9 @@ typedef struct hs_service_config_t { * option. */ uint32_t version; + /* Have we explicitly set HiddenServiceVersion? */ + unsigned int hs_version_explicitly_set : 1; + /* List of rend_service_port_config_t */ smartlist_t *ports; @@ -387,7 +406,7 @@ STATIC int intro_point_should_expire(const hs_service_intro_point_t *ip, STATIC void run_housekeeping_event(time_t now); STATIC void rotate_all_descriptors(time_t now); STATIC void build_all_descriptors(time_t now); -STATIC void update_all_descriptors(time_t now); +STATIC void update_all_descriptors_intro_points(time_t now); STATIC void run_upload_descriptor_event(time_t now); STATIC void service_descriptor_free_(hs_service_descriptor_t *desc); |