diff options
author | Roger Dingledine <arma@torproject.org> | 2011-10-26 16:34:20 -0400 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2011-10-26 16:34:20 -0400 |
commit | 9ac4ceb0d493bb7f743ed621189f5877f128f747 (patch) | |
tree | fe432050ac9fd8ec375060a601c1dbaa27f46ccb | |
parent | 7c29b6996ee315cf2d8fdd6fe53b47512174be77 (diff) | |
parent | cecc5b7aa1030eddcf1a613d103b81f5cb98e959 (diff) | |
download | tor-9ac4ceb0d493bb7f743ed621189f5877f128f747.tar.gz tor-9ac4ceb0d493bb7f743ed621189f5877f128f747.zip |
Merge branch 'maint-0.2.1' into release-0.2.1
-rw-r--r-- | changes/bug2235 | 3 | ||||
-rw-r--r-- | changes/bug2433 | 5 | ||||
-rw-r--r-- | changes/bug2572 | 5 | ||||
-rw-r--r-- | changes/bug3228 | 3 | ||||
-rw-r--r-- | src/common/crypto.c | 4 | ||||
-rw-r--r-- | src/common/tortls.c | 138 | ||||
-rw-r--r-- | src/common/tortls.h | 5 | ||||
-rw-r--r-- | src/or/config.c | 24 | ||||
-rw-r--r-- | src/or/connection_or.c | 5 | ||||
-rw-r--r-- | src/or/dirserv.c | 7 | ||||
-rw-r--r-- | src/or/hibernate.c | 21 | ||||
-rw-r--r-- | src/or/main.c | 15 | ||||
-rw-r--r-- | src/or/or.h | 10 | ||||
-rw-r--r-- | src/or/router.c | 158 |
14 files changed, 312 insertions, 91 deletions
diff --git a/changes/bug2235 b/changes/bug2235 new file mode 100644 index 0000000000..0c3bafa44f --- /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/changes/bug2433 b/changes/bug2433 new file mode 100644 index 0000000000..8e47c4f024 --- /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/changes/bug2572 b/changes/bug2572 new file mode 100644 index 0000000000..a5cca284a1 --- /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/changes/bug3228 b/changes/bug3228 new file mode 100644 index 0000000000..4aca810d3c --- /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/common/crypto.c b/src/common/crypto.c index dffa2c7807..a444cf126a 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -321,10 +321,12 @@ 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; + tor_assert(env->refs == 0); if (env->key) RSA_free(env->key); diff --git a/src/common/tortls.c b/src/common/tortls.c index 7735618ea2..c78a9ec953 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -184,10 +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); - -/** Global tls context. We keep it here because nobody else needs to - * touch it. */ -static tor_tls_context_t *global_tls_context = NULL; +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 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; @@ -400,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."); @@ -589,15 +601,99 @@ tor_tls_context_incref(tor_tls_context_t *ctx) ++ctx->refcnt; } +/** Create new global client and server TLS contexts. + * + * If <b>server_identity</b> is NULL, this will not generate a server + * TLS context. If <b>is_public_server</b> is non-zero, this will use + * the same TLS context for incoming and outgoing connections, and + * ignore <b>client_identity</b>. */ +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. * <b>identity</b> should be set to the identity key used to sign the - * certificate, and <b>nickname</b> 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 +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 = *ppcontext; + + if (new_ctx != NULL) { + *ppcontext = 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. + * <b>identity</b> 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 +788,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 +809,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 @@ -899,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; } @@ -941,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 9644b87f2c..55fee81aea 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -50,7 +50,10 @@ 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(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); void tor_tls_set_renegotiate_callback(tor_tls_t *tls, diff --git a/src/or/config.c b/src/or/config.c index fbfa771ed3..16b5e9cfa4 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1269,6 +1269,8 @@ 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) @@ -1319,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) @@ -1368,14 +1381,11 @@ 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 (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(); @@ -1387,9 +1397,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 */ @@ -3763,6 +3770,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; diff --git a/src/or/connection_or.c b/src/or/connection_or.c index d402563fb5..95cc02e34f 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_tlsclient_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 e367cb1c3a..46775805cd 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 9ec63756fa..dfc4edfc82 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -456,21 +456,26 @@ 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); } } - format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_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]; diff --git a/src/or/main.c b/src/or/main.c index 3c879dcd0e..ba704f53f1 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,8 +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_new(get_identity_key(), - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (tor_tls_context_init(public_server_mode(options), + 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"); /* XXX is it a bug here, that we just keep going? -RD */ } @@ -1111,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 { @@ -1387,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; @@ -2017,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 0f5b2bb17b..4105ff42eb 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_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); 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); @@ -4239,6 +4242,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 2afde746d4..7354267a6f 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,79 @@ get_onion_key_set_at(void) return onionkey_set_at; } -/** Set the current identity key to k. +/** Set the current server identity key to <b>k</b>. */ 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. +/** 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, and that we are running as a Tor server. */ crypto_pk_env_t * -get_identity_key(void) +get_server_identity_key(void) { - tor_assert(identitykey); - return identitykey; + tor_assert(server_identitykey); + tor_assert(server_mode(get_options())); + assert_identity_keys_ok(); + 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 server_identitykey != NULL; +} + +/** Set the current client identity key to <b>k</b>. + */ +void +set_client_identity_key(crypto_pk_env_t *k) { - return identitykey != NULL; + if (client_identitykey) + crypto_free_pk_env(client_identitykey); + client_identitykey = k; +} + +/** Returns the current client identity key for use on outgoing TLS + * connections; requires that the key has been set. + */ +crypto_pk_env_t * +get_tlsclient_identity_key(void) +{ + tor_assert(client_identitykey); + assert_identity_keys_ok(); + 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 +507,12 @@ init_keys(void) crypto_free_pk_env(prkey); return -1; } - 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) { + set_client_identity_key(prkey); + /* Create a TLS context. */ + if (tor_tls_context_init(0, + get_tlsclient_identity_key(), + NULL, + MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); return -1; } @@ -494,13 +547,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(crypto_pk_dup_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"); @@ -537,19 +605,22 @@ init_keys(void) tor_free(keydir); /* 3. Initialize link key and TLS context. */ - if (tor_tls_context_new(get_identity_key(), - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (tor_tls_context_init(public_server_mode(options), + get_tlsclient_identity_key(), + get_server_identity_key(), + MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; } /* 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. */ - 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; } @@ -570,7 +641,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; @@ -608,7 +680,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) | @@ -954,6 +1026,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; @@ -1117,11 +1198,12 @@ router_compare_to_my_exit_policy(edge_connection_t *conn) } /** Return true iff I'm a server and <b>digest</b> 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 <b>digest</b> is equal to @@ -1258,7 +1340,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); @@ -1350,7 +1432,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); @@ -1367,7 +1449,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); @@ -2016,8 +2098,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) |