From 07ab559a8e9932fbed1e00e3210a1bb855cf1508 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Fri, 1 Oct 2010 00:07:10 -0700 Subject: [PATCH 01/13] Add public_server_mode function. --- src/or/or.h | 1 + src/or/router.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/or/or.h b/src/or/or.h index 0f5b2bb17..f40511330 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4239,6 +4239,7 @@ int authdir_mode_tests_reachability(or_options_t *options); int authdir_mode_bridge(or_options_t *options); int server_mode(or_options_t *options); +int public_server_mode(or_options_t *options); int advertised_server_mode(void); int proxy_mode(or_options_t *options); void consider_publishable_server(int force); diff --git a/src/or/router.c b/src/or/router.c index 2afde746d..45eeca09f 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -954,6 +954,15 @@ server_mode(or_options_t *options) return (options->ORPort != 0 || options->ORListenAddress); } +/** Return true iff we are trying to be a non-bridge server. + */ +int +public_server_mode(or_options_t *options) +{ + if (!server_mode(options)) return 0; + return (!options->BridgeRelay); +} + /** Remember if we've advertised ourselves to the dirservers. */ static int server_is_advertised=0; From 878164011108c16574d6ce1d9530fe83a3109bad Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Fri, 1 Oct 2010 14:06:57 -0700 Subject: [PATCH 02/13] Refactor tor_tls_context_new: * Make tor_tls_context_new internal to tortls.c, and return the new tor_tls_context_t from it. * Add a public tor_tls_context_init wrapper function to replace it. Conflicts: src/or/main.c src/or/router.c --- src/common/tortls.c | 41 +++++++++++++++++++++++++++++++---------- src/common/tortls.h | 3 ++- src/or/main.c | 3 +-- src/or/router.c | 5 ++--- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/common/tortls.c b/src/common/tortls.c index 7735618ea..d3435e760 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -184,6 +184,8 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, const char *cname_sign, unsigned int lifetime); static void tor_tls_unblock_renegotiation(tor_tls_t *tls); +static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity, + unsigned int key_lifetime); /** Global tls context. We keep it here because nobody else needs to * touch it. */ @@ -591,13 +593,38 @@ tor_tls_context_incref(tor_tls_context_t *ctx) /** Create a new TLS context for use with Tor TLS handshakes. * identity should be set to the identity key used to sign the - * certificate, and nickname set to the nickname to use. + * certificate. * * You can call this function multiple times. Each time you call it, * it generates new certificates; all new connections will use * the new SSL context. */ int +tor_tls_context_init(crypto_pk_env_t *identity, unsigned int key_lifetime) +{ + tor_tls_context_t *new_ctx = tor_tls_context_new(identity, + key_lifetime); + tor_tls_context_t *old_ctx = global_tls_context; + + if (new_ctx != NULL) { + global_tls_context = new_ctx; + + /* Free the old context if one existed. */ + if (old_ctx != NULL) { + /* This is safe even if there are open connections: we reference- + * count tor_tls_context_t objects. */ + tor_tls_context_decref(old_ctx); + } + } + + return ((new_ctx != NULL) ? 0 : -1); +} + +/** Create a new TLS context for use with Tor TLS handshakes. + * identity should be set to the identity key used to sign the + * certificate. + */ +static tor_tls_context_t * tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) { crypto_pk_env_t *rsa = NULL; @@ -692,18 +719,12 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) always_accept_verify_cb); /* let us realloc bufs that we're writing from */ SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - /* Free the old context if one exists. */ - if (global_tls_context) { - /* This is safe even if there are open connections: OpenSSL does - * reference counting with SSL and SSL_CTX objects. */ - tor_tls_context_decref(global_tls_context); - } - global_tls_context = result; + if (rsa) crypto_free_pk_env(rsa); tor_free(nickname); tor_free(nn2); - return 0; + return result; error: tls_log_errors(NULL, LOG_WARN, "creating TLS context"); @@ -719,7 +740,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) X509_free(cert); if (idcert) X509_free(idcert); - return -1; + return NULL; } #ifdef V2_HANDSHAKE_SERVER diff --git a/src/common/tortls.h b/src/common/tortls.h index 9644b87f2..3f80d998b 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -50,7 +50,8 @@ typedef struct tor_tls_t tor_tls_t; const char *tor_tls_err_to_string(int err); void tor_tls_free_all(void); -int tor_tls_context_new(crypto_pk_env_t *rsa, unsigned int key_lifetime); +int tor_tls_context_init(crypto_pk_env_t *identity, + unsigned int key_lifetime); tor_tls_t *tor_tls_new(int sock, int is_server); void tor_tls_set_logged_address(tor_tls_t *tls, const char *address); void tor_tls_set_renegotiate_callback(tor_tls_t *tls, diff --git a/src/or/main.c b/src/or/main.c index 3c879dcd0..fe1f42ece 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -872,8 +872,7 @@ run_scheduled_events(time_t now) last_rotated_x509_certificate = now; if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) { log_info(LD_GENERAL,"Rotating tls context."); - if (tor_tls_context_new(get_identity_key(), - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (tor_tls_context_init(get_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ } diff --git a/src/or/router.c b/src/or/router.c index 45eeca09f..9afa983bc 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -458,8 +458,7 @@ init_keys(void) } set_identity_key(prkey); /* Create a TLS context; default the client nickname to "client". */ - if (tor_tls_context_new(get_identity_key(), - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (tor_tls_context_init(get_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); return -1; } @@ -537,7 +536,7 @@ init_keys(void) tor_free(keydir); /* 3. Initialize link key and TLS context. */ - if (tor_tls_context_new(get_identity_key(), + if (tor_tls_context_init(get_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; From 9976df9e5619b89339390c322138f7228b8fa715 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Sun, 3 Oct 2010 18:14:08 -0700 Subject: [PATCH 03/13] Maintain separate server and client TLS contexts. Fixes bug #988. Conflicts: src/or/main.c src/or/router.c --- src/common/tortls.c | 101 +++++++++++++++++++++++++++++++++++++------- src/common/tortls.h | 4 +- src/or/main.c | 10 +++-- src/or/router.c | 13 ++++-- 4 files changed, 105 insertions(+), 23 deletions(-) diff --git a/src/common/tortls.c b/src/common/tortls.c index d3435e760..c78a9ec95 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -184,12 +184,16 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, const char *cname_sign, unsigned int lifetime); static void tor_tls_unblock_renegotiation(tor_tls_t *tls); +static int tor_tls_context_init_one(tor_tls_context_t **ppcontext, + crypto_pk_env_t *identity, + unsigned int key_lifetime); static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime); -/** Global tls context. We keep it here because nobody else needs to - * touch it. */ -static tor_tls_context_t *global_tls_context = NULL; +/** Global TLS contexts. We keep them here because nobody else needs + * to touch them. */ +static tor_tls_context_t *server_tls_context = NULL; +static tor_tls_context_t *client_tls_context = NULL; /** True iff tor_tls_init() has been called. */ static int tls_library_is_initialized = 0; @@ -402,9 +406,15 @@ tor_tls_init(void) void tor_tls_free_all(void) { - if (global_tls_context) { - tor_tls_context_decref(global_tls_context); - global_tls_context = NULL; + if (server_tls_context) { + tor_tls_context_t *ctx = server_tls_context; + server_tls_context = NULL; + tor_tls_context_decref(ctx); + } + if (client_tls_context) { + tor_tls_context_t *ctx = client_tls_context; + client_tls_context = NULL; + tor_tls_context_decref(ctx); } if (!HT_EMPTY(&tlsmap_root)) { log_warn(LD_MM, "Still have entries in the tlsmap at shutdown."); @@ -591,6 +601,63 @@ tor_tls_context_incref(tor_tls_context_t *ctx) ++ctx->refcnt; } +/** Create new global client and server TLS contexts. + * + * If server_identity is NULL, this will not generate a server + * TLS context. If is_public_server is non-zero, this will use + * the same TLS context for incoming and outgoing connections, and + * ignore client_identity. */ +int +tor_tls_context_init(int is_public_server, + crypto_pk_env_t *client_identity, + crypto_pk_env_t *server_identity, + unsigned int key_lifetime) +{ + int rv1 = 0; + int rv2 = 0; + + if (is_public_server) { + tor_tls_context_t *new_ctx; + tor_tls_context_t *old_ctx; + + tor_assert(server_identity != NULL); + + rv1 = tor_tls_context_init_one(&server_tls_context, + server_identity, + key_lifetime); + + if (rv1 >= 0) { + new_ctx = server_tls_context; + tor_tls_context_incref(new_ctx); + old_ctx = client_tls_context; + client_tls_context = new_ctx; + + if (old_ctx != NULL) { + tor_tls_context_decref(old_ctx); + } + } + } else { + if (server_identity != NULL) { + rv1 = tor_tls_context_init_one(&server_tls_context, + server_identity, + key_lifetime); + } else { + tor_tls_context_t *old_ctx = server_tls_context; + server_tls_context = NULL; + + if (old_ctx != NULL) { + tor_tls_context_decref(old_ctx); + } + } + + rv2 = tor_tls_context_init_one(&client_tls_context, + client_identity, + key_lifetime); + } + + return rv1 < rv2 ? rv1 : rv2; +} + /** Create a new TLS context for use with Tor TLS handshakes. * identity should be set to the identity key used to sign the * certificate. @@ -599,15 +666,17 @@ tor_tls_context_incref(tor_tls_context_t *ctx) * it generates new certificates; all new connections will use * the new SSL context. */ -int -tor_tls_context_init(crypto_pk_env_t *identity, unsigned int key_lifetime) +static int +tor_tls_context_init_one(tor_tls_context_t **ppcontext, + crypto_pk_env_t *identity, + unsigned int key_lifetime) { tor_tls_context_t *new_ctx = tor_tls_context_new(identity, key_lifetime); - tor_tls_context_t *old_ctx = global_tls_context; + tor_tls_context_t *old_ctx = *ppcontext; if (new_ctx != NULL) { - global_tls_context = new_ctx; + *ppcontext = new_ctx; /* Free the old context if one existed. */ if (old_ctx != NULL) { @@ -920,10 +989,12 @@ tor_tls_new(int sock, int isServer) { BIO *bio = NULL; tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t)); + tor_tls_context_t *context = isServer ? server_tls_context : + client_tls_context; - tor_assert(global_tls_context); /* make sure somebody made it first */ - if (!(result->ssl = SSL_new(global_tls_context->ctx))) { - tls_log_errors(NULL, LOG_WARN, "generating TLS context"); + tor_assert(context); /* make sure somebody made it first */ + if (!(result->ssl = SSL_new(context->ctx))) { + tls_log_errors(NULL, LOG_WARN, "creating SSL object"); tor_free(result); return NULL; } @@ -962,8 +1033,8 @@ tor_tls_new(int sock, int isServer) } HT_INSERT(tlsmap, &tlsmap_root, result); SSL_set_bio(result->ssl, bio, bio); - tor_tls_context_incref(global_tls_context); - result->context = global_tls_context; + tor_tls_context_incref(context); + result->context = context; result->state = TOR_TLS_ST_HANDSHAKE; result->isServer = isServer; result->wantwrite_n = 0; diff --git a/src/common/tortls.h b/src/common/tortls.h index 3f80d998b..55fee81ae 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -50,7 +50,9 @@ typedef struct tor_tls_t tor_tls_t; const char *tor_tls_err_to_string(int err); void tor_tls_free_all(void); -int tor_tls_context_init(crypto_pk_env_t *identity, +int tor_tls_context_init(int is_public_server, + crypto_pk_env_t *client_identity, + crypto_pk_env_t *server_identity, unsigned int key_lifetime); tor_tls_t *tor_tls_new(int sock, int is_server); void tor_tls_set_logged_address(tor_tls_t *tls, const char *address); diff --git a/src/or/main.c b/src/or/main.c index fe1f42ece..00fce8002 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -816,6 +816,7 @@ run_scheduled_events(time_t now) static time_t time_to_dump_geoip_stats = 0; static time_t time_to_retry_dns_init = 0; or_options_t *options = get_options(); + int is_server = server_mode(options); int i; int have_dir_info; @@ -837,7 +838,7 @@ run_scheduled_events(time_t now) * shut down and restart all cpuworkers, and update the directory if * necessary. */ - if (server_mode(options) && + if (is_server && get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME < now) { log_info(LD_GENERAL,"Rotating onion key."); rotate_onion_key(); @@ -872,7 +873,10 @@ run_scheduled_events(time_t now) last_rotated_x509_certificate = now; if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) { log_info(LD_GENERAL,"Rotating tls context."); - if (tor_tls_context_init(get_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (tor_tls_context_init(public_server_mode(options), + get_identity_key(), + is_server ? get_identity_key() : NULL, + MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ } @@ -1110,7 +1114,7 @@ run_scheduled_events(time_t now) /** 9. and if we're a server, check whether our DNS is telling stories to * us. */ - if (server_mode(options) && time_to_check_for_correct_dns < now) { + if (is_server && time_to_check_for_correct_dns < now) { if (!time_to_check_for_correct_dns) { time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120); } else { diff --git a/src/or/router.c b/src/or/router.c index 9afa983bc..dce2ad601 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -457,8 +457,11 @@ init_keys(void) return -1; } set_identity_key(prkey); - /* Create a TLS context; default the client nickname to "client". */ - if (tor_tls_context_init(get_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + /* Create a TLS context. */ + if (tor_tls_context_init(0, + get_identity_key(), + NULL, + MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); return -1; } @@ -536,8 +539,10 @@ init_keys(void) tor_free(keydir); /* 3. Initialize link key and TLS context. */ - if (tor_tls_context_init(get_identity_key(), - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (tor_tls_context_init(public_server_mode(options), + get_identity_key(), + get_identity_key(), + MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; } From 299a78c5fed3447a450cea3d4f686c2140c7aaed Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 12 Nov 2010 20:21:50 -0500 Subject: [PATCH 04/13] Make crypto_free_pk_env tolerate NULL arg in 0.2.1. Error-proofing against bug 988 backport --- src/common/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/crypto.c b/src/common/crypto.c index dffa2c780..c723c33dd 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -321,7 +321,8 @@ crypto_new_pk_env(void) void crypto_free_pk_env(crypto_pk_env_t *env) { - tor_assert(env); + if (!env) + return; if (--env->refs > 0) return; From 59e565e2a258f6ca78273585187ff0ab9052cbe7 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Sun, 3 Oct 2010 22:38:53 -0700 Subject: [PATCH 05/13] Maintain separate server and client identity keys when appropriate. Fixes a bug described in ticket #988. Conflicts: src/or/main.c src/or/router.c --- src/or/connection_or.c | 5 +- src/or/dirserv.c | 7 +-- src/or/hibernate.c | 4 +- src/or/main.c | 8 +-- src/or/or.h | 9 ++-- src/or/router.c | 119 +++++++++++++++++++++++++++++------------ 6 files changed, 105 insertions(+), 47 deletions(-) diff --git a/src/or/connection_or.c b/src/or/connection_or.c index d402563fb..7817db89c 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -961,6 +961,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, const char *safe_address = started_here ? conn->_base.address : safe_str(conn->_base.address); const char *conn_type = started_here ? "outgoing" : "incoming"; + crypto_pk_env_t *our_identity = + started_here ? get_client_identity_key() : + get_server_identity_key(); int has_cert = 0, has_identity=0; check_no_tls_errors(); @@ -997,7 +1000,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, if (identity_rcvd) { has_identity = 1; crypto_pk_get_digest(identity_rcvd, digest_rcvd_out); - if (crypto_pk_cmp_keys(get_identity_key(), identity_rcvd)<0) { + if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) { conn->circ_id_type = CIRC_ID_TYPE_LOWER; } else { conn->circ_id_type = CIRC_ID_TYPE_HIGHER; diff --git a/src/or/dirserv.c b/src/or/dirserv.c index e367cb1c3..46775805c 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1520,7 +1520,8 @@ dirserv_regenerate_directory(void) { char *new_directory=NULL; - if (dirserv_dump_directory_to_string(&new_directory, get_identity_key())) { + if (dirserv_dump_directory_to_string(&new_directory, + get_server_identity_key())) { log_warn(LD_BUG, "Error creating directory."); tor_free(new_directory); return NULL; @@ -1550,7 +1551,7 @@ generate_runningrouters(void) char digest[DIGEST_LEN]; char published[ISO_TIME_LEN+1]; size_t len; - crypto_pk_env_t *private_key = get_identity_key(); + crypto_pk_env_t *private_key = get_server_identity_key(); char *identity_pkey; /* Identity key, DER64-encoded. */ size_t identity_pkey_len; @@ -2441,7 +2442,7 @@ generate_v2_networkstatus_opinion(void) smartlist_t *routers = NULL; digestmap_t *omit_as_sybil = NULL; - private_key = get_identity_key(); + private_key = get_server_identity_key(); if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 9ec63756f..04e06c816 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -456,7 +456,7 @@ accounting_set_wakeup_time(void) uint64_t time_to_exhaust_bw; int time_to_consider; - if (! identity_key_is_set()) { + if (! server_identity_key_is_set()) { if (init_keys() < 0) { log_err(LD_BUG, "Error initializing keys"); tor_assert(0); @@ -464,7 +464,7 @@ accounting_set_wakeup_time(void) } format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_identity_key(), digest); + crypto_pk_get_digest(get_server_identity_key(), digest); d_env = crypto_new_digest_env(); crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); diff --git a/src/or/main.c b/src/or/main.c index 00fce8002..466801cb3 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -874,8 +874,8 @@ run_scheduled_events(time_t now) if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) { log_info(LD_GENERAL,"Rotating tls context."); if (tor_tls_context_init(public_server_mode(options), - get_identity_key(), - is_server ? get_identity_key() : NULL, + get_client_identity_key(), + is_server ? get_server_identity_key() : NULL, MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ @@ -1390,7 +1390,7 @@ do_main_loop(void) /* load the private keys, if we're supposed to have them, and set up the * TLS context. */ - if (! identity_key_is_set()) { + if (! client_identity_key_is_set()) { if (init_keys() < 0) { log_err(LD_BUG,"Error initializing keys; exiting"); return -1; @@ -2020,7 +2020,7 @@ do_list_fingerprint(void) log_err(LD_BUG,"Error initializing keys; can't display fingerprint"); return -1; } - if (!(k = get_identity_key())) { + if (!(k = get_server_identity_key())) { log_err(LD_GENERAL,"Error: missing identity key."); return -1; } diff --git a/src/or/or.h b/src/or/or.h index f40511330..a594d6f89 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4205,9 +4205,12 @@ int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, 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); -crypto_pk_env_t *get_identity_key(void); -int identity_key_is_set(void); +void set_client_identity_key(crypto_pk_env_t *k); +void set_server_identity_key(crypto_pk_env_t *k); +crypto_pk_env_t *get_client_identity_key(void); +crypto_pk_env_t *get_server_identity_key(void); +int client_identity_key_is_set(void); +int server_identity_key_is_set(void); authority_cert_t *get_my_v3_authority_cert(void); crypto_pk_env_t *get_my_v3_authority_signing_key(void); authority_cert_t *get_my_v3_legacy_cert(void); diff --git a/src/or/router.c b/src/or/router.c index dce2ad601..c53bb8b4e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -31,11 +31,15 @@ static crypto_pk_env_t *onionkey=NULL; /** Previous private onionskin decryption key: used to decode CREATE cells * generated by clients that have an older version of our descriptor. */ static crypto_pk_env_t *lastonionkey=NULL; -/** Private "identity key": used to sign directory info and TLS +/** Private server "identity key": used to sign directory info and TLS * certificates. Never changes. */ -static crypto_pk_env_t *identitykey=NULL; -/** Digest of identitykey. */ -static char identitykey_digest[DIGEST_LEN]; +static crypto_pk_env_t *server_identitykey=NULL; +/** Digest of server_identitykey. */ +static char server_identitykey_digest[DIGEST_LEN]; +/** Private client "identity key": used to sign bridges' and clients' + * outbound TLS certificates. Regenerated on startup and on IP address + * change. */ +static crypto_pk_env_t *client_identitykey=NULL; /** 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 @@ -106,32 +110,59 @@ get_onion_key_set_at(void) return onionkey_set_at; } -/** Set the current identity key to k. +/** Set the current server identity key to k. */ void -set_identity_key(crypto_pk_env_t *k) +set_server_identity_key(crypto_pk_env_t *k) { - if (identitykey) - crypto_free_pk_env(identitykey); - identitykey = k; - crypto_pk_get_digest(identitykey, identitykey_digest); + if (server_identitykey) + crypto_free_pk_env(server_identitykey); + server_identitykey = k; + crypto_pk_get_digest(server_identitykey, server_identitykey_digest); } -/** Returns the current identity key; requires that the identity key has been - * set. +/** Returns the current server identity key; requires that the key has + * been set. */ crypto_pk_env_t * -get_identity_key(void) +get_server_identity_key(void) { - tor_assert(identitykey); - return identitykey; + tor_assert(server_identitykey); + return server_identitykey; } -/** Return true iff the identity key has been set. */ +/** Return true iff the server identity key has been set. */ int -identity_key_is_set(void) +server_identity_key_is_set(void) { - return identitykey != NULL; + return server_identitykey != NULL; +} + +/** Set the current client identity key to k. + */ +void +set_client_identity_key(crypto_pk_env_t *k) +{ + if (client_identitykey) + crypto_free_pk_env(client_identitykey); + client_identitykey = k; +} + +/** Returns the current client identity key; requires that the key has + * been set. + */ +crypto_pk_env_t * +get_client_identity_key(void) +{ + tor_assert(client_identitykey); + return client_identitykey; +} + +/** Return true iff the client identity key has been set. */ +int +client_identity_key_is_set(void) +{ + return client_identitykey != NULL; } /** Return the key certificate for this v3 (voting) authority, or NULL @@ -456,10 +487,10 @@ init_keys(void) crypto_free_pk_env(prkey); return -1; } - set_identity_key(prkey); + set_client_identity_key(prkey); /* Create a TLS context. */ if (tor_tls_context_init(0, - get_identity_key(), + get_client_identity_key(), NULL, MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); @@ -496,13 +527,28 @@ init_keys(void) } } - /* 1. Read identity key. Make it if none is found. */ + /* 1b. Read identity key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_id_key"); log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR); tor_free(keydir); if (!prkey) return -1; - set_identity_key(prkey); + set_server_identity_key(prkey); + + /* 1c. If we are configured as a bridge, generate a client key; + * otherwise, set the server identity key as our client identity + * key. */ + if (public_server_mode(options)) { + set_client_identity_key(prkey); /* set above */ + } else { + if (!(prkey = crypto_new_pk_env())) + return -1; + if (crypto_pk_generate_key(prkey)) { + crypto_free_pk_env(prkey); + return -1; + } + set_client_identity_key(prkey); + } /* 2. Read onion key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_onion_key"); @@ -540,8 +586,8 @@ init_keys(void) /* 3. Initialize link key and TLS context. */ if (tor_tls_context_init(public_server_mode(options), - get_identity_key(), - get_identity_key(), + get_client_identity_key(), + get_server_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; @@ -553,7 +599,8 @@ init_keys(void) const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ - if (dirserv_add_own_fingerprint(options->Nickname, get_identity_key())) { + if (dirserv_add_own_fingerprint(options->Nickname, + get_server_identity_key())) { log_err(LD_GENERAL,"Error adding own fingerprint to approved set"); return -1; } @@ -574,7 +621,8 @@ init_keys(void) /* 5. Dump fingerprint to 'fingerprint' */ keydir = get_datadir_fname("fingerprint"); log_info(LD_GENERAL,"Dumping fingerprint to \"%s\"...",keydir); - if (crypto_pk_get_fingerprint(get_identity_key(), fingerprint, 0)<0) { + if (crypto_pk_get_fingerprint(get_server_identity_key(), + fingerprint, 0) < 0) { log_err(LD_GENERAL,"Error computing fingerprint"); tor_free(keydir); return -1; @@ -612,7 +660,7 @@ init_keys(void) return -1; } /* 6b. [authdirserver only] add own key to approved directories. */ - crypto_pk_get_digest(get_identity_key(), digest); + crypto_pk_get_digest(get_server_identity_key(), digest); type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) | (options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) | (options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) | @@ -1130,11 +1178,12 @@ router_compare_to_my_exit_policy(edge_connection_t *conn) } /** Return true iff I'm a server and digest is equal to - * my identity digest. */ + * my server identity key digest. */ int router_digest_is_me(const char *digest) { - return identitykey && tor_memeq(identitykey_digest, digest, DIGEST_LEN); + return (server_identitykey && + tor_memeq(server_identitykey_digest, digest, DIGEST_LEN)); } /** Return true iff I'm a server and digest is equal to @@ -1271,7 +1320,7 @@ router_rebuild_descriptor(int force) ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ - ri->identity_pkey = crypto_pk_dup_key(get_identity_key()); + ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key()); if (crypto_pk_get_digest(ri->identity_pkey, ri->cache_info.identity_digest)<0) { routerinfo_free(ri); @@ -1363,7 +1412,7 @@ router_rebuild_descriptor(int force) DIGEST_LEN); ei->cache_info.signed_descriptor_body = tor_malloc(8192); if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, 8192, - ei, get_identity_key()) < 0) { + ei, get_server_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -1380,7 +1429,7 @@ router_rebuild_descriptor(int force) DIGEST_LEN); ri->cache_info.signed_descriptor_body = tor_malloc(8192); if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192, - ri, get_identity_key())<0) { + ri, get_server_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate router descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -2029,8 +2078,10 @@ router_free_all(void) crypto_free_pk_env(onionkey); if (lastonionkey) crypto_free_pk_env(lastonionkey); - if (identitykey) - crypto_free_pk_env(identitykey); + if (server_identitykey) + crypto_free_pk_env(server_identitykey); + if (client_identitykey) + crypto_free_pk_env(client_identitykey); if (key_lock) tor_mutex_free(key_lock); if (desc_routerinfo) From 2a2301e41117ad8439dbe8039085202fa0d6f6ed Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 21 Oct 2010 13:53:31 -0400 Subject: [PATCH 06/13] Rename get_client_identity_key to get_tlsclient_identity_key --- src/or/connection_or.c | 2 +- src/or/main.c | 2 +- src/or/or.h | 2 +- src/or/router.c | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 7817db89c..95cc02e34 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -962,7 +962,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, started_here ? conn->_base.address : safe_str(conn->_base.address); const char *conn_type = started_here ? "outgoing" : "incoming"; crypto_pk_env_t *our_identity = - started_here ? get_client_identity_key() : + started_here ? get_tlsclient_identity_key() : get_server_identity_key(); int has_cert = 0, has_identity=0; diff --git a/src/or/main.c b/src/or/main.c index 466801cb3..ba704f53f 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -874,7 +874,7 @@ run_scheduled_events(time_t now) if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) { log_info(LD_GENERAL,"Rotating tls context."); if (tor_tls_context_init(public_server_mode(options), - get_client_identity_key(), + get_tlsclient_identity_key(), is_server ? get_server_identity_key() : NULL, MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); diff --git a/src/or/or.h b/src/or/or.h index a594d6f89..4105ff42e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4207,7 +4207,7 @@ crypto_pk_env_t *get_onion_key(void); time_t get_onion_key_set_at(void); void set_client_identity_key(crypto_pk_env_t *k); void set_server_identity_key(crypto_pk_env_t *k); -crypto_pk_env_t *get_client_identity_key(void); +crypto_pk_env_t *get_tlsclient_identity_key(void); crypto_pk_env_t *get_server_identity_key(void); int client_identity_key_is_set(void); int server_identity_key_is_set(void); diff --git a/src/or/router.c b/src/or/router.c index c53bb8b4e..f7a50ae88 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -148,11 +148,11 @@ set_client_identity_key(crypto_pk_env_t *k) client_identitykey = k; } -/** Returns the current client identity key; requires that the key has - * been set. +/** Returns the current client identity key for use on outgoing TLS + * connections; requires that the key has been set. */ crypto_pk_env_t * -get_client_identity_key(void) +get_tlsclient_identity_key(void) { tor_assert(client_identitykey); return client_identitykey; @@ -490,7 +490,7 @@ init_keys(void) set_client_identity_key(prkey); /* Create a TLS context. */ if (tor_tls_context_init(0, - get_client_identity_key(), + get_tlsclient_identity_key(), NULL, MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); @@ -586,7 +586,7 @@ init_keys(void) /* 3. Initialize link key and TLS context. */ if (tor_tls_context_init(public_server_mode(options), - get_client_identity_key(), + get_tlsclient_identity_key(), get_server_identity_key(), MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); From dc557e8164003d6c09b620333902d7dae3762794 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 21 Oct 2010 13:54:12 -0400 Subject: [PATCH 07/13] Add some asserts to get_{tlsclient|server}_identity_key We now require that: - Only actual servers should ever call get_server_identity_key - If you're being a client or bridge, the client and server keys should differ. - If you're being a public relay, the client and server keys should be the same. --- src/or/router.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/or/router.c b/src/or/router.c index f7a50ae88..96aca8837 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -121,13 +121,32 @@ set_server_identity_key(crypto_pk_env_t *k) crypto_pk_get_digest(server_identitykey, server_identitykey_digest); } +/** Make sure that we have set up our identity keys to match or not match as + * appropriate, and die with an assertion if we have not. */ +static void +assert_identity_keys_ok(void) +{ + tor_assert(client_identitykey); + if (public_server_mode(get_options())) { + /* assert that we have set the client and server keys to be equal */ + tor_assert(server_identitykey); + tor_assert(0==crypto_pk_cmp_keys(client_identitykey, server_identitykey)); + } else { + /* assert that we have set the client and server keys to be unequal */ + if (server_identitykey) + tor_assert(0!=crypto_pk_cmp_keys(client_identitykey, server_identitykey)); + } +} + /** Returns the current server identity key; requires that the key has - * been set. + * been set, and that we are running as a Tor server. */ crypto_pk_env_t * get_server_identity_key(void) { tor_assert(server_identitykey); + tor_assert(server_mode(get_options())); + assert_identity_keys_ok(); return server_identitykey; } @@ -155,6 +174,7 @@ crypto_pk_env_t * get_tlsclient_identity_key(void) { tor_assert(client_identitykey); + assert_identity_keys_ok(); return client_identitykey; } From 3a890b3b70d53ac864be682f50f07ba07b8f09ba Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Tue, 26 Oct 2010 18:22:04 +0200 Subject: [PATCH 08/13] Properly refcount client_identity_key In a2bb0bf we started using a separate client identity key. When we are in "public server mode" (that means not a bridge) we will use the same key. Reusing the key without doing the proper refcounting leads to a segfault on cleanup during shutdown. Fix that. Also introduce an assert that triggers if our refcount falls below 0. That should never happen. --- src/common/crypto.c | 1 + src/or/router.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/crypto.c b/src/common/crypto.c index c723c33dd..a444cf126 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -326,6 +326,7 @@ crypto_free_pk_env(crypto_pk_env_t *env) if (--env->refs > 0) return; + tor_assert(env->refs == 0); if (env->key) RSA_free(env->key); diff --git a/src/or/router.c b/src/or/router.c index 96aca8837..c471599cb 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -559,7 +559,7 @@ init_keys(void) * otherwise, set the server identity key as our client identity * key. */ if (public_server_mode(options)) { - set_client_identity_key(prkey); /* set above */ + set_client_identity_key(crypto_pk_dup_key(prkey)); /* set above */ } else { if (!(prkey = crypto_new_pk_env())) return -1; From d0a91386e5b85c5a0db3981a294c7a75192f9c3a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 3 Dec 2010 13:37:13 -0500 Subject: [PATCH 09/13] Don't crash when accountingmax is set in non-server Tors We use a hash of the identity key to seed a prng to tell when an accounting period should end. But thanks to the bug998 changes, clients no longer have server-identity keys to use as a long-term seed in accounting calculations. In any case, their identity keys (as used in TLS) were never never fixed. So we can just set the wakeup time from a random seed instead there. Still open is whether everybody should be random. This patch fixes bug 2235, which was introduced in 0.2.2.18-alpha. Diagnosed with help from boboper on irc. --- changes/bug2235 | 3 +++ src/or/hibernate.c | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 changes/bug2235 diff --git a/changes/bug2235 b/changes/bug2235 new file mode 100644 index 000000000..0c3bafa44 --- /dev/null +++ b/changes/bug2235 @@ -0,0 +1,3 @@ + o Minor bugfixes + - Avoid crashes when AccountingMax is set on clients. Fixes bug 2235; + Bugfix on 0.2.2.18-alpha. Diagnosed by boboper. diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 04e06c816..dfc4edfc8 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -463,14 +463,19 @@ accounting_set_wakeup_time(void) } } - format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_server_identity_key(), digest); + if (server_identity_key_is_set()) { + format_iso_time(buf, interval_start_time); - d_env = crypto_new_digest_env(); - crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); - crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); - crypto_digest_get_digest(d_env, digest, DIGEST_LEN); - crypto_free_digest_env(d_env); + crypto_pk_get_digest(get_server_identity_key(), digest); + + d_env = crypto_new_digest_env(); + crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); + crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); + crypto_digest_get_digest(d_env, digest, DIGEST_LEN); + crypto_free_digest_env(d_env); + } else { + crypto_rand(digest, DIGEST_LEN); + } if (!expected_bandwidth_usage) { char buf1[ISO_TIME_LEN+1]; From 908289894419b8fa331197948cb048f08ff5d035 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Tue, 25 Jan 2011 15:28:58 +0100 Subject: [PATCH 10/13] Fix assert for relay/bridge state change When we added support for separate client tls certs on bridges in a2bb0bfdd5 we forgot to correctly initialize this when changing from relay to bridge or vice versa while Tor is running. Fix that by always initializing keys when the state changes. Fixes bug 2433. Conflicts: src/or/config.c --- changes/bug2433 | 5 +++++ src/or/config.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 changes/bug2433 diff --git a/changes/bug2433 b/changes/bug2433 new file mode 100644 index 000000000..8e47c4f02 --- /dev/null +++ b/changes/bug2433 @@ -0,0 +1,5 @@ + o Major bugfixes: + - Don't assert when changing from bridge to relay or vice versa with a controller. + The assert happened because we didn't properly initialize our keys in this case. + Bugfix on 0.2.2.18, fixes bug 2433. Issue first discovered by bastik. + diff --git a/src/or/config.c b/src/or/config.c index fbfa771ed..7d7f2c38d 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1371,11 +1371,12 @@ options_act(or_options_t *old_options) if (options_transition_affects_workers(old_options, options)) { log_info(LD_GENERAL, "Worker-related options changed. Rotating workers."); + + if (init_keys() < 0) { + log_warn(LD_BUG,"Error initializing keys; exiting"); + return -1; + } if (server_mode(options) && !server_mode(old_options)) { - if (init_keys() < 0) { - log_warn(LD_BUG,"Error initializing keys; exiting"); - return -1; - } ip_address_changed(0); if (has_completed_circuit || !any_predicted_circuits(time(NULL))) inform_testing_reachability(); @@ -3763,6 +3764,7 @@ options_transition_affects_workers(or_options_t *old_options, new_options->ServerDNSSearchDomains || old_options->SafeLogging != new_options->SafeLogging || old_options->ClientOnly != new_options->ClientOnly || + public_server_mode(old_options) != public_server_mode(new_options) || !config_lines_eq(old_options->Logs, new_options->Logs)) return 1; From 62c29a93ba78ad6ae91b87755ed8cc0283d27e56 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Wed, 16 Feb 2011 04:12:37 -0800 Subject: [PATCH 11/13] Don't crash a bridge authority on SIGHUP if it's not in the consensus Fixes bug 2572. --- changes/bug2572 | 5 +++++ src/or/router.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changes/bug2572 diff --git a/changes/bug2572 b/changes/bug2572 new file mode 100644 index 000000000..a5cca284a --- /dev/null +++ b/changes/bug2572 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Don't crash a bridge authority on SIGHUP if it can't force itself + into its routerlist. Fixes bug 2572. + + diff --git a/src/or/router.c b/src/or/router.c index c471599cb..7354267a6 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -615,7 +615,7 @@ init_keys(void) /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); - if (authdir_mode(options)) { + if (authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)) { const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ From 55d9e4b8bad18a99d51b0b6347cef46e730dceda Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 23 May 2011 16:38:35 -0400 Subject: [PATCH 12/13] Reinit keys at the start of options_act(). Previously we did this nearer to the end (in the old_options && transition_affects_workers() block). But other stuff cares about keys being consistent with options... particularly anything which tries to access a key, which can die in assert_identity_keys_ok(). Fixes bug 3228; bugfix on 0.2.2.18-alpha. Conflicts: src/or/config.c --- changes/bug3228 | 3 +++ src/or/config.c | 23 +++++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 changes/bug3228 diff --git a/changes/bug3228 b/changes/bug3228 new file mode 100644 index 000000000..4aca810d3 --- /dev/null +++ b/changes/bug3228 @@ -0,0 +1,3 @@ + o Major bugfixes: + - Resolve a crash that occured when setting BridgeRelay to 1 with + accounting enabled. Fixes bug 3228; bugfix on 0.2.2.18-alpha. diff --git a/src/or/config.c b/src/or/config.c index 7d7f2c38d..ea389ffda 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1269,12 +1269,26 @@ options_act(or_options_t *old_options) or_options_t *options = get_options(); int running_tor = options->command == CMD_RUN_TOR; char *msg; + const int transition_affects_workers = + old_options && options_transition_affects_workers(old_options, options); if (running_tor && !have_lockfile()) { if (try_locking(options, 1) < 0) return -1; } + /* We want to reinit keys as needed before we do much of anything else: + keys are important, and other things can depend on them. */ + if (running_tor && + (transition_affects_workers || + (options->V3AuthoritativeDir && (!old_options || + !old_options->V3AuthoritativeDir)))) { + if (init_keys() < 0) { + log_warn(LD_BUG,"Error initializing keys; exiting"); + return -1; + } + } + if (consider_adding_dir_authorities(options, old_options) < 0) return -1; @@ -1368,14 +1382,10 @@ options_act(or_options_t *old_options) geoip_remove_old_clients(time(NULL)+(2*60*60)); } - if (options_transition_affects_workers(old_options, options)) { + if (transition_affects_workers) { log_info(LD_GENERAL, "Worker-related options changed. Rotating workers."); - if (init_keys() < 0) { - log_warn(LD_BUG,"Error initializing keys; exiting"); - return -1; - } if (server_mode(options) && !server_mode(old_options)) { ip_address_changed(0); if (has_completed_circuit || !any_predicted_circuits(time(NULL))) @@ -1388,9 +1398,6 @@ options_act(or_options_t *old_options) if (dns_reset()) return -1; } - - if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir) - init_keys(); } /* Maybe load geoip file */ From cecc5b7aa1030eddcf1a613d103b81f5cb98e959 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Mon, 30 May 2011 23:50:37 -0400 Subject: [PATCH 13/13] stop asserting at boot The patch for 3228 made us try to run init_keys() before we had loaded our state file, resulting in an assert inside init_keys. We had moved it too early in the function. Now it's later in the function, but still above the accounting calls. --- src/or/config.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index ea389ffda..16b5e9cfa 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1277,18 +1277,6 @@ options_act(or_options_t *old_options) return -1; } - /* We want to reinit keys as needed before we do much of anything else: - keys are important, and other things can depend on them. */ - if (running_tor && - (transition_affects_workers || - (options->V3AuthoritativeDir && (!old_options || - !old_options->V3AuthoritativeDir)))) { - if (init_keys() < 0) { - log_warn(LD_BUG,"Error initializing keys; exiting"); - return -1; - } - } - if (consider_adding_dir_authorities(options, old_options) < 0) return -1; @@ -1333,6 +1321,17 @@ options_act(or_options_t *old_options) finish_daemon(options->DataDirectory); } + /* We want to reinit keys as needed before we do much of anything else: + keys are important, and other things can depend on them. */ + if (transition_affects_workers || + (options->V3AuthoritativeDir && (!old_options || + !old_options->V3AuthoritativeDir))) { + if (init_keys() < 0) { + log_warn(LD_BUG,"Error initializing keys; exiting"); + return -1; + } + } + /* Write our PID to the PID file. If we do not have write permissions we * will log a warning */ if (running_tor && options->PidFile)