mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
hs: Learn service version by trying to load the keys
In order to switch the default HS version from 2 to 3, we need tor to be smart and be able to decide on the version by trying to load the service keys during configuration validation. Part of #27215 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
cb466ee7d6
commit
61ad81c36e
@ -143,6 +143,24 @@ helper_parse_uint64(const char *opt, const char *value, uint64_t min,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the service version by trying to learn it from the key on disk if
|
||||
* any. If nothing is found, the current service configured version is
|
||||
* returned. */
|
||||
static int
|
||||
config_learn_service_version(hs_service_t *service)
|
||||
{
|
||||
int version;
|
||||
|
||||
tor_assert(service);
|
||||
|
||||
version = hs_service_get_version_from_key(service);
|
||||
if (version < 0) {
|
||||
version = service->config.version;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/* Return true iff the given options starting at line_ for a hidden service
|
||||
* contains at least one invalid option. Each hidden service option don't
|
||||
* apply to all versions so this function can find out. The line_ MUST start
|
||||
@ -490,6 +508,12 @@ 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);
|
||||
|
||||
/* Different functions are in charge of specific options for a version. We
|
||||
* start just after the service directory line so once we hit another
|
||||
* directory line, the function knows that it has to stop parsing. */
|
||||
|
@ -2884,6 +2884,29 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
|
||||
smartlist_add(list, hs_path_from_filename(s_dir, fname));
|
||||
}
|
||||
|
||||
/* Return true iff the given service identity key is present on disk. */
|
||||
static int
|
||||
service_key_on_disk(const char *directory_path)
|
||||
{
|
||||
int ret = 0;
|
||||
char *fname;
|
||||
ed25519_keypair_t *kp = NULL;
|
||||
|
||||
tor_assert(directory_path);
|
||||
|
||||
/* Build the v3 key path name and then try to load it. */
|
||||
fname = hs_path_from_filename(directory_path, fname_keyfile_prefix);
|
||||
kp = ed_key_init_from_file(fname, INIT_ED_KEY_SPLIT,
|
||||
LOG_DEBUG, NULL, 0, 0, 0, NULL, NULL);
|
||||
if (kp) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
ed25519_keypair_free(kp);
|
||||
tor_free(fname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* Public API */
|
||||
/* ========== */
|
||||
@ -3375,6 +3398,36 @@ hs_service_circuit_has_opened(origin_circuit_t *circ)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the service version by looking at the key in the service directory.
|
||||
* If the key is not found or unrecognized, -1 is returned. Else, the service
|
||||
* version is returned. */
|
||||
int
|
||||
hs_service_get_version_from_key(const hs_service_t *service)
|
||||
{
|
||||
int version = -1; /* Unknown version. */
|
||||
const char *directory_path;
|
||||
|
||||
tor_assert(service);
|
||||
|
||||
/* We'll try to load the key for version 3. If not found, we'll try version
|
||||
* 2 and if not found, we'll send back an unknown version (0). */
|
||||
directory_path = service->config.directory_path;
|
||||
|
||||
/* Version 3 check. */
|
||||
if (service_key_on_disk(directory_path)) {
|
||||
version = HS_VERSION_THREE;
|
||||
goto end;
|
||||
}
|
||||
/* Version 2 check. */
|
||||
if (rend_service_key_on_disk(directory_path)) {
|
||||
version = HS_VERSION_TWO;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return version;
|
||||
}
|
||||
|
||||
/* Load and/or generate keys for all onion services including the client
|
||||
* authorization if any. Return 0 on success, -1 on failure. */
|
||||
int
|
||||
|
@ -262,6 +262,7 @@ void hs_service_free_(hs_service_t *service);
|
||||
unsigned int hs_service_get_num_services(void);
|
||||
void hs_service_stage_services(const smartlist_t *service_list);
|
||||
int hs_service_load_all_keys(void);
|
||||
int hs_service_get_version_from_key(const hs_service_t *service);
|
||||
void hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
|
||||
smartlist_t *dir_list);
|
||||
int hs_service_set_conn_addr_port(const origin_circuit_t *circ,
|
||||
|
@ -1341,6 +1341,29 @@ rend_service_poison_new_single_onion_dir(const rend_service_t *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return true iff the given service identity key is present on disk. This is
|
||||
* used to try to learn the service version during configuration time. */
|
||||
int
|
||||
rend_service_key_on_disk(const char *directory_path)
|
||||
{
|
||||
int ret = 0;
|
||||
char *fname;
|
||||
crypto_pk_t *pk = NULL;
|
||||
|
||||
tor_assert(directory_path);
|
||||
|
||||
/* Load key */
|
||||
fname = hs_path_from_filename(directory_path, private_key_fname);
|
||||
pk = init_key_from_file(fname, 0, LOG_DEBUG, 0);
|
||||
if (pk) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
crypto_pk_free(pk);
|
||||
tor_free(fname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Load and/or generate private keys for all hidden services, possibly
|
||||
* including keys for client authorization.
|
||||
* If a <b>service_list</b> is provided, treat it as the list of hidden
|
||||
|
@ -145,6 +145,7 @@ int rend_config_service(const struct config_line_t *line_,
|
||||
void rend_service_prune_list(void);
|
||||
void rend_service_free_staging_list(void);
|
||||
int rend_service_load_all_keys(const smartlist_t *service_list);
|
||||
int rend_service_key_on_disk(const char *directory_path);
|
||||
void rend_services_add_filenames_to_lists(smartlist_t *open_lst,
|
||||
smartlist_t *stat_lst);
|
||||
void rend_consider_services_intro_points(time_t now);
|
||||
|
Loading…
Reference in New Issue
Block a user