|
@@ -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. */
|
|
@@ -1944,8 +1957,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 +1976,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 +2050,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 +2081,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.",
|
|
@@ -3085,6 +3094,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 +3160,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;
|