diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-05-22 17:58:25 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-05-22 17:58:25 +0000 |
commit | c9fa4e65832abc4b5d69fcba77edeb77fbf0dcdf (patch) | |
tree | 30482a85e9cadd89a9e158204e8384b695d44cb7 /src/or/router.c | |
parent | 6975a093e965e73ee88efe70b79a2211b9f5d7d3 (diff) | |
download | tor-c9fa4e65832abc4b5d69fcba77edeb77fbf0dcdf.tar tor-c9fa4e65832abc4b5d69fcba77edeb77fbf0dcdf.tar.gz |
r12898@catbus: nickm | 2007-05-22 13:11:04 -0400
More v3 directory code: have authorities load certificates; have everybody store certificates to disk and load them; provide a way to configure v3 authorities.
svn:r10293
Diffstat (limited to 'src/or/router.c')
-rw-r--r-- | src/or/router.c | 127 |
1 files changed, 104 insertions, 23 deletions
diff --git a/src/or/router.c b/src/or/router.c index 826ccc0eb..c8efd8341 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -38,6 +38,11 @@ static crypto_pk_env_t *lastonionkey=NULL; static crypto_pk_env_t *identitykey=NULL; /** Digest of identitykey. */ static char identitykey_digest[DIGEST_LEN]; +/** Signing key used for v3 directory material; only set for authorities. */ +static crypto_pk_env_t *authority_signing_key = NULL; +/** Key certificate to authenticate v3 directory material; only set for + * authorities. */ +static authority_cert_t *authority_key_certificate = NULL; /** Replace the current onion key with <b>k</b>. Does not affect lastonionkey; * to update onionkey correctly, call rotate_onion_key(). @@ -170,46 +175,48 @@ rotate_onion_key(void) log_warn(LD_GENERAL, "Couldn't rotate onion key."); } -/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist, - * create a new RSA key and save it in <b>fname</b>. Return the read/created - * key, or NULL on error. - */ -crypto_pk_env_t * -init_key_from_file(const char *fname) +/** DOCDOC */ +static crypto_pk_env_t * +init_key_from_file_impl(const char *fname, int generate, int severity) { crypto_pk_env_t *prkey = NULL; FILE *file = NULL; if (!(prkey = crypto_new_pk_env())) { - log_err(LD_GENERAL,"Error constructing key"); + log(severity, LD_GENERAL,"Error constructing key"); goto error; } switch (file_status(fname)) { case FN_DIR: case FN_ERROR: - log_err(LD_FS,"Can't read key from \"%s\"", fname); + log(severity, LD_FS,"Can't read key from \"%s\"", fname); goto error; case FN_NOENT: - log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.", - fname); - if (crypto_pk_generate_key(prkey)) { - log_err(LD_GENERAL,"Error generating onion key"); - goto error; - } - if (crypto_pk_check_key(prkey) <= 0) { - log_err(LD_GENERAL,"Generated key seems invalid"); - goto error; - } - log_info(LD_GENERAL, "Generated key seems valid"); - if (crypto_pk_write_private_key_to_filename(prkey, fname)) { - log_err(LD_FS,"Couldn't write generated key to \"%s\".", fname); - goto error; + if (generate) { + log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.", + fname); + if (crypto_pk_generate_key(prkey)) { + log(severity, LD_GENERAL,"Error generating onion key"); + goto error; + } + if (crypto_pk_check_key(prkey) <= 0) { + log(severity, LD_GENERAL,"Generated key seems invalid"); + goto error; + } + log_info(LD_GENERAL, "Generated key seems valid"); + if (crypto_pk_write_private_key_to_filename(prkey, fname)) { + log(severity, LD_FS, + "Couldn't write generated key to \"%s\".", fname); + goto error; + } + } else { + log_info(LD_GENERAL, "No key found in \"%s\"", fname); } return prkey; case FN_FILE: if (crypto_pk_read_private_key_from_filename(prkey, fname)) { - log_err(LD_GENERAL,"Error loading private key."); + log(severity, LD_GENERAL,"Error loading private key."); goto error; } return prkey; @@ -225,6 +232,71 @@ init_key_from_file(const char *fname) return NULL; } +/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist, + * create a new RSA key and save it in <b>fname</b>. Return the read/created + * key, or NULL on error. + */ +crypto_pk_env_t * +init_key_from_file(const char *fname) +{ + return init_key_from_file_impl(fname, 1, LOG_ERR); +} + +/** DOCDOC; XXXX020 maybe move to dirserv.c */ +static void +init_v3_authority_keys(const char *keydir) +{ + char *fname = NULL, *cert = NULL; + const char *eos = NULL; + size_t fname_len = strlen(keydir) + 64; + crypto_pk_env_t *signing_key = NULL; + authority_cert_t *parsed = NULL; + + fname = tor_malloc(fname_len); + tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_signing_key", + keydir); + signing_key = init_key_from_file_impl(fname, 0, LOG_INFO); + if (!signing_key) { + log_warn(LD_DIR, "No version 3 directory key found in %s", fname); + goto done; + } + tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_certificate", + keydir); + cert = read_file_to_str(fname, 0, NULL); + if (!cert) { + log_warn(LD_DIR, "Signing key found, but no certificate found in %s", + fname); + goto done; + } + parsed = authority_cert_parse_from_string(cert, &eos); + if (!parsed) { + log_warn(LD_DIR, "Unable to parse certificate in %s", fname); + goto done; + } + if (crypto_pk_cmp_keys(signing_key, parsed->signing_key) != 0) { + log_warn(LD_DIR, "Stored signing key does not match signing key in " + "certificate"); + goto done; + } + parsed->cache_info.signed_descriptor_body = cert; + parsed->cache_info.signed_descriptor_len = eos-cert; + cert = NULL; + + authority_key_certificate = parsed; + authority_signing_key = signing_key; + parsed = NULL; + signing_key = NULL; + + done: + tor_free(fname); + tor_free(cert); + if (signing_key) + crypto_free_pk_env(signing_key); + if (parsed) + authority_cert_free(parsed); +} + + /** Initialize all OR private keys, and the TLS context, as necessary. * On OPs, this only initializes the tls context. Return 0 on success, * or -1 if Tor should die. @@ -282,6 +354,11 @@ init_keys(void) prkey = init_key_from_file(keydir); if (!prkey) return -1; set_identity_key(prkey); + + /* 1b. Read v3 directory authority key/cert information. */ + if (authdir_mode(options) && options->V3AuthoritativeDir) + init_v3_authority_keys(keydir); + /* 2. Read onion key. Make it if none is found. */ tor_snprintf(keydir,sizeof(keydir), "%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key",datadir); @@ -1592,6 +1669,10 @@ router_free_all(void) routerinfo_free(desc_routerinfo); if (desc_extrainfo) extrainfo_free(desc_extrainfo); + if (authority_signing_key) + crypto_free_pk_env(authority_signing_key); + if (authority_key_certificate) + authority_cert_free(authority_key_certificate); if (warned_nonexistent_family) { SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp)); |