aboutsummaryrefslogtreecommitdiff
path: root/src/or/router.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-05-22 17:58:25 +0000
committerNick Mathewson <nickm@torproject.org>2007-05-22 17:58:25 +0000
commitc9fa4e65832abc4b5d69fcba77edeb77fbf0dcdf (patch)
tree30482a85e9cadd89a9e158204e8384b695d44cb7 /src/or/router.c
parent6975a093e965e73ee88efe70b79a2211b9f5d7d3 (diff)
downloadtor-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.c127
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));