aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2011-10-26 16:34:20 -0400
committerRoger Dingledine <arma@torproject.org>2011-10-26 16:34:20 -0400
commit9ac4ceb0d493bb7f743ed621189f5877f128f747 (patch)
treefe432050ac9fd8ec375060a601c1dbaa27f46ccb
parent7c29b6996ee315cf2d8fdd6fe53b47512174be77 (diff)
parentcecc5b7aa1030eddcf1a613d103b81f5cb98e959 (diff)
downloadtor-9ac4ceb0d493bb7f743ed621189f5877f128f747.tar.gz
tor-9ac4ceb0d493bb7f743ed621189f5877f128f747.zip
Merge branch 'maint-0.2.1' into release-0.2.1
-rw-r--r--changes/bug22353
-rw-r--r--changes/bug24335
-rw-r--r--changes/bug25725
-rw-r--r--changes/bug32283
-rw-r--r--src/common/crypto.c4
-rw-r--r--src/common/tortls.c138
-rw-r--r--src/common/tortls.h5
-rw-r--r--src/or/config.c24
-rw-r--r--src/or/connection_or.c5
-rw-r--r--src/or/dirserv.c7
-rw-r--r--src/or/hibernate.c21
-rw-r--r--src/or/main.c15
-rw-r--r--src/or/or.h10
-rw-r--r--src/or/router.c158
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)