summaryrefslogtreecommitdiff
path: root/src/feature/hs/hs_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/hs/hs_service.c')
-rw-r--r--src/feature/hs/hs_service.c119
1 files changed, 100 insertions, 19 deletions
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index c29f39c6b4..908ac02044 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -16,6 +16,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
+#include "core/or/extendinfo.h"
#include "core/or/relay.h"
#include "feature/client/circpathbias.h"
#include "feature/dirclient/dirclient.h"
@@ -40,6 +41,7 @@
#include "feature/hs/hs_descriptor.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_intropoint.h"
+#include "feature/hs/hs_metrics.h"
#include "feature/hs/hs_service.h"
#include "feature/hs/hs_stats.h"
#include "feature/hs/hs_ob.h"
@@ -195,6 +197,10 @@ register_service(hs_service_ht *map, hs_service_t *service)
if (map == hs_service_map) {
hs_service_map_has_changed();
}
+ /* Setup metrics. This is done here because in order to initialize metrics,
+ * we require tor to have fully initialized a service so the ports of the
+ * service can be looked at for instance. */
+ hs_metrics_service_init(service);
return 0;
}
@@ -543,7 +549,7 @@ service_intro_point_remove(const hs_service_t *service,
/* Trying all descriptors. */
FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
/* We'll try to remove the descriptor on both descriptors which is not
- * very expensive to do instead of doing loopup + remove. */
+ * very expensive to do instead of doing lookup + remove. */
digest256map_remove(desc->intro_points.map,
ip->auth_key_kp.pubkey.pubkey);
} FOR_EACH_DESCRIPTOR_END;
@@ -564,7 +570,7 @@ service_intro_point_find(const hs_service_t *service,
*
* Even if we use the same node as intro point in both descriptors, the node
* will have a different intro auth key for each descriptor since we generate
- * a new one everytime we pick an intro point.
+ * a new one every time we pick an intro point.
*
* After #22893 gets implemented, intro points will be moved to be
* per-service instead of per-descriptor so this function will need to
@@ -781,7 +787,7 @@ close_service_rp_circuits(hs_service_t *service)
ed25519_pubkey_eq(&ocirc->hs_ident->identity_pk,
&service->keys.identity_pk)) {
/* Reason is FINISHED because service has been removed and thus the
- * circuit is considered old/uneeded. When freed, it is removed from the
+ * circuit is considered old/unneeded. When freed, it is removed from the
* hs circuitmap. */
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
@@ -799,7 +805,7 @@ close_intro_circuits(hs_service_intropoints_t *intro_points)
origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
if (ocirc) {
/* Reason is FINISHED because service has been removed and thus the
- * circuit is considered old/uneeded. When freed, the circuit is removed
+ * circuit is considered old/unneeded. When freed, the circuit is removed
* from the HS circuitmap. */
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
@@ -990,7 +996,7 @@ write_address_to_file(const hs_service_t *service, const char *fname_)
tor_asprintf(&addr_buf, "%s.%s\n", service->onion_address, address_tld);
/* Notice here that we use the given "fname_". */
fname = hs_path_from_filename(service->config.directory_path, fname_);
- if (write_str_to_file(fname, addr_buf, 0) < 0) {
+ if (write_str_to_file_if_not_equal(fname, addr_buf)) {
log_warn(LD_REND, "Could not write onion address to hostname file %s",
escaped(fname));
goto end;
@@ -1083,7 +1089,7 @@ load_service_keys(hs_service_t *service)
goto end;
}
- /* Succes. */
+ /* Success. */
ret = 0;
end:
tor_free(fname);
@@ -1587,7 +1593,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
memcpy(&desc_ip->onion_key, &ip->onion_key, sizeof(desc_ip->onion_key));
/* Key and certificate material. */
- desc_ip->auth_key_cert = tor_cert_create(signing_kp,
+ desc_ip->auth_key_cert = tor_cert_create_ed25519(signing_kp,
CERT_TYPE_AUTH_HS_IP_KEY,
&ip->auth_key_kp.pubkey,
nearest_hour,
@@ -1638,7 +1644,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
ed25519_public_key_from_curve25519_public_key(&ed25519_pubkey,
&ip->enc_key_kp.pubkey,
0);
- desc_ip->enc_key_cert = tor_cert_create(signing_kp,
+ desc_ip->enc_key_cert = tor_cert_create_ed25519(signing_kp,
CERT_TYPE_CROSS_HS_IP_KEYS,
&ed25519_pubkey, nearest_hour,
HS_DESC_CERT_LIFETIME,
@@ -1712,12 +1718,13 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
/* Fresh certificate for the signing key. */
plaintext->signing_key_cert =
- tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
+ tor_cert_create_ed25519(&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. */
+ * where the call came from and the tor_cert_create_ed25519() will log the
+ * error. */
tor_assert_nonfatal(plaintext->signing_key_cert);
}
@@ -2190,7 +2197,7 @@ pick_needed_intro_points(hs_service_t *service,
}
/* Build an exclude list of nodes of our intro point(s). The expiring intro
- * points are OK to pick again because this is afterall a concept of round
+ * points are OK to pick again because this is after all a concept of round
* robin so they are considered valid nodes to pick again. */
DIGEST256MAP_FOREACH(desc->intro_points.map, key,
hs_service_intro_point_t *, ip) {
@@ -2374,7 +2381,7 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now)
tor_assert(ip);
- /* Any one of the following needs to be True to furfill the criteria to
+ /* Any one of the following needs to be True to fulfill the criteria to
* remove an intro point. */
bool has_no_retries = (ip->circuit_retries >
MAX_INTRO_POINT_CIRCUIT_RETRIES);
@@ -2875,6 +2882,9 @@ upload_descriptor_to_hsdir(const hs_service_t *service,
hsdir->hsdir_index.store_first;
char *blinded_pubkey_log_str =
tor_strdup(hex_str((char*)&desc->blinded_kp.pubkey.pubkey, 32));
+ /* This log message is used by Chutney as part of its bootstrap
+ * detection mechanism. Please don't change without first checking
+ * Chutney. */
log_info(LD_REND, "Service %s %s descriptor of revision %" PRIu64
" initiated upload request to %s with index %s (%s)",
safe_str_client(service->onion_address),
@@ -2991,7 +3001,7 @@ upload_descriptor_to_all(const hs_service_t *service,
/* Get our list of responsible HSDir. */
responsible_dirs = smartlist_new();
/* The parameter 0 means that we aren't a client so tell the function to use
- * the spread store consensus paremeter. */
+ * the spread store consensus parameter. */
hs_get_responsible_hsdirs(&desc->blinded_kp.pubkey, desc->time_period_num,
service->desc_next == desc, 0, responsible_dirs);
@@ -3226,7 +3236,7 @@ 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.
+ * we need to update them regularly over the lifetime for the descriptor.
* The rest are set once and should not be modified.
*
* - Signing key certificate.
@@ -3386,6 +3396,15 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ)
/* If the cell can't be sent, the circuit will be closed within this
* function. */
hs_circ_service_rp_has_opened(service, circ);
+
+ /* Update metrics that we have an established rendezvous circuit. It is not
+ * entirely true until the client receives the RENDEZVOUS2 cell and starts
+ * sending but if that circuit collapes, we'll decrement the counter thus it
+ * will even out the metric. */
+ if (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
+ hs_metrics_new_established_rdv(service);
+ }
+
goto done;
err:
@@ -3437,6 +3456,9 @@ service_handle_intro_established(origin_circuit_t *circ,
goto err;
}
+ /* Update metrics. */
+ hs_metrics_new_established_intro(service);
+
log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
"on circuit %u for service %s",
TO_CIRCUIT(circ)->n_circ_id,
@@ -3489,6 +3511,8 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
payload, payload_len) < 0) {
goto err;
}
+ /* Update metrics that a new introduction was successful. */
+ hs_metrics_new_introduction(service);
return 0;
err:
@@ -3510,7 +3534,7 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
s_dir = service->config.directory_path;
/* The hostname file. */
smartlist_add(list, hs_path_from_filename(s_dir, fname_hostname));
- /* The key files splitted in two. */
+ /* The key files split in two. */
tor_snprintf(fname, sizeof(fname), "%s_secret_key", fname_keyfile_prefix);
smartlist_add(list, hs_path_from_filename(s_dir, fname));
tor_snprintf(fname, sizeof(fname), "%s_public_key", fname_keyfile_prefix);
@@ -3572,7 +3596,33 @@ service_encode_descriptor(const hs_service_t *service,
/* Public API */
/* ========== */
-/** This is called everytime the service map (v2 or v3) changes that is if an
+/** Called when a circuit was just cleaned up. This is done right before the
+ * circuit is marked for close. */
+void
+hs_service_circuit_cleanup_on_close(const circuit_t *circ)
+{
+ tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+ switch (circ->purpose) {
+ case CIRCUIT_PURPOSE_S_INTRO:
+ /* About to close an established introduction circuit. Update the metrics
+ * to reflect how many we have at the moment. */
+ hs_metrics_close_established_intro(
+ &CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident->identity_pk);
+ break;
+ case CIRCUIT_PURPOSE_S_REND_JOINED:
+ /* About to close an established rendezvous circuit. Update the metrics to
+ * reflect how many we have at the moment. */
+ hs_metrics_close_established_rdv(
+ &CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident->identity_pk);
+ break;
+ default:
+ break;
+ }
+}
+
+/** This is called every time the service map (v2 or v3) changes that is if an
* element is added or removed. */
void
hs_service_map_has_changed(void)
@@ -3862,7 +3912,7 @@ hs_service_set_conn_addr_port(const origin_circuit_t *circ,
goto err_no_close;
}
- /* Find a virtual port of that service mathcing the one in the connection if
+ /* Find a virtual port of that service matching the one in the connection if
* successful, set the address in the connection. */
if (hs_set_conn_addr_port(service->config.ports, conn) < 0) {
log_info(LD_REND, "No virtual port mapping exists for port %d for "
@@ -3903,7 +3953,7 @@ hs_service_exports_circuit_id(const ed25519_public_key_t *pk)
/** Add to file_list every filename used by a configured hidden service, and to
* dir_list every directory path used by a configured hidden service. This is
- * used by the sandbox subsystem to whitelist those. */
+ * used by the sandbox subsystem to allowlist those. */
void
hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
smartlist_t *dir_list)
@@ -4167,7 +4217,35 @@ hs_service_stage_services(const smartlist_t *service_list)
smartlist_add_all(hs_service_staging_list, service_list);
}
-/** Allocate and initilize a service object. The service configuration will
+/** Return a newly allocated list of all the service's metrics store. */
+smartlist_t *
+hs_service_get_metrics_stores(void)
+{
+ smartlist_t *list = smartlist_new();
+
+ if (hs_service_map) {
+ FOR_EACH_SERVICE_BEGIN(service) {
+ smartlist_add(list, service->metrics.store);
+ } FOR_EACH_SERVICE_END;
+ }
+
+ return list;
+}
+
+/** Lookup the global service map for the given identitiy public key and
+ * return the service object if found, NULL if not. */
+hs_service_t *
+hs_service_find(const ed25519_public_key_t *identity_pk)
+{
+ tor_assert(identity_pk);
+
+ if (!hs_service_map) {
+ return NULL;
+ }
+ return find_service(hs_service_map, identity_pk);
+}
+
+/** Allocate and initialize a service object. The service configuration will
* contain the default values. Return the newly allocated object pointer. This
* function can't fail. */
hs_service_t *
@@ -4213,6 +4291,9 @@ hs_service_free_(hs_service_t *service)
tor_free(service->state.ob_subcreds);
}
+ /* Free metrics object. */
+ hs_metrics_service_free(service);
+
/* Wipe service keys. */
memwipe(&service->keys.identity_sk, 0, sizeof(service->keys.identity_sk));