diff --git a/ChangeLog b/ChangeLog index b5123b1faa..4e9774c8e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,6 +43,9 @@ Changes in version 0.1.2.5-xxxx - 200?-??-?? safe.) - When generating bandwidth history, round down to the nearest 1k. When storing accounting data, round up to the nearest 1k. + - When we're running as a server, remember when we last rotated onion + keys, so that we will rotate keys once they're a week old even if we + never stay up for a week ourselves. (Bug 368.) o Controller features: - Have GETINFO dir/status/* work on hosts with DirPort disabled. diff --git a/src/or/config.c b/src/or/config.c index 5ab68a1d5d..b39e187dc9 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -283,6 +283,7 @@ static config_var_t _state_vars[] = { VAR("TorVersion", STRING, TorVersion, NULL), + VAR("LastRotatedOnionKey", ISOTIME, LastRotatedOnionKey, NULL), VAR("LastWritten", ISOTIME, LastWritten, NULL), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } diff --git a/src/or/or.h b/src/or/or.h index c3b442d3e6..0281af2c6e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1698,6 +1698,9 @@ typedef struct { /** Holds any unrecognized values we found in the state file, in the order * in which we found them. */ config_line_t *ExtraLines; + + /** When did we last rotate our onion key? "0" for 'no idea'. */ + time_t LastRotatedOnionKey; } or_state_t; /** Change the next_write time of state to when, unless the @@ -2602,7 +2605,6 @@ int rend_mid_rendezvous(or_circuit_t *circ, const char *request, /********************************* router.c ***************************/ -void set_onion_key(crypto_pk_env_t *k); crypto_pk_env_t *get_onion_key(void); time_t get_onion_key_set_at(void); void set_identity_key(crypto_pk_env_t *k); diff --git a/src/or/router.c b/src/or/router.c index 22de65786c..eeb00fc1a9 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -35,7 +35,7 @@ static crypto_pk_env_t *identitykey=NULL; /** Replace the current onion key with k. Does not affect lastonionkey; * to update onionkey correctly, call rotate_onion_key(). */ -void +static void set_onion_key(crypto_pk_env_t *k) { tor_mutex_acquire(key_lock); @@ -122,6 +122,8 @@ rotate_onion_key(void) char fname[512]; char fname_prev[512]; crypto_pk_env_t *prkey; + or_state_t *state = get_or_state(); + time_t now; tor_snprintf(fname,sizeof(fname), "%s/keys/secret_onion_key",get_options()->DataDirectory); tor_snprintf(fname_prev,sizeof(fname_prev), @@ -148,9 +150,11 @@ rotate_onion_key(void) crypto_free_pk_env(lastonionkey); lastonionkey = onionkey; onionkey = prkey; - onionkey_set_at = time(NULL); + now = time(NULL); + state->LastRotatedOnionKey = onionkey_set_at = now; tor_mutex_release(key_lock); mark_my_descriptor_dirty(); + or_state_mark_dirty(state, now+600); return; error: log_warn(LD_GENERAL, "Couldn't rotate onion key."); @@ -247,6 +251,7 @@ init_keys(void) crypto_pk_env_t *prkey; char digest[20]; or_options_t *options = get_options(); + or_state_t *state = get_or_state(); if (!key_lock) key_lock = tor_mutex_new(); @@ -293,6 +298,17 @@ init_keys(void) prkey = init_key_from_file_name_changed(keydir,keydir2); if (!prkey) return -1; set_onion_key(prkey); + if (state->LastRotatedOnionKey > 100) { /* allow for some parsing slop. */ + onionkey_set_at = state->LastRotatedOnionKey; + } else { + /* We have no LastRotatedOnionKey set; either we just created the key + * or it's a holdover from 0.1.2.4-alpha-dev or earlier. In either case, + * start the clock ticking now so that we will eventually rotate it even + * if we don't stay up for a full MIN_ONION_KEY_LIFETIME. */ + state->LastRotatedOnionKey = time(NULL); + or_state_mark_dirty(state, time(NULL)+600); + } + tor_snprintf(keydir,sizeof(keydir),"%s/keys/secret_onion_key.old",datadir); if (file_status(keydir) == FN_FILE) { prkey = init_key_from_file(keydir);