Browse Source

Merge remote branch 'origin/maint-0.2.2'

Conflicts:
	src/common/tortls.c
Nick Mathewson 13 years ago
parent
commit
17fdde3d92
8 changed files with 263 additions and 70 deletions
  1. 115 23
      src/common/tortls.c
  2. 4 1
      src/common/tortls.h
  3. 4 1
      src/or/connection_or.c
  4. 4 3
      src/or/dirserv.c
  5. 2 2
      src/or/hibernate.c
  6. 9 5
      src/or/main.c
  7. 118 32
      src/or/router.c
  8. 7 3
      src/or/router.h

+ 115 - 23
src/common/tortls.c

@@ -200,9 +200,17 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
                                         const char *cname_sign,
                                         unsigned int lifetime);
 
-/** 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;
 
@@ -448,9 +456,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.");
@@ -637,15 +651,97 @@ tor_tls_context_incref(tor_tls_context_t *ctx)
   ++ctx->refcnt;
 }
 
-/** 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.
+/** 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 MIN(rv1, rv2);
+}
+
+/** Create a new global TLS context.
  *
  * 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;
@@ -740,18 +836,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: we reference-
-     * count tor_tls_context_t 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, LD_NET, "creating TLS context");
@@ -767,7 +857,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
@@ -952,9 +1042,11 @@ 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))) {
+  tor_assert(context); /* make sure somebody made it first */
+  if (!(result->ssl = SSL_new(context->ctx))) {
     tls_log_errors(NULL, LOG_WARN, LD_NET, "creating SSL object");
     tor_free(result);
     return NULL;
@@ -994,8 +1086,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;

+ 4 - 1
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,

+ 4 - 1
src/or/connection_or.c

@@ -1142,6 +1142,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
     started_here ? conn->_base.address :
                    safe_str_client(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();
@@ -1179,7 +1182,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;

+ 4 - 3
src/or/dirserv.c

@@ -1578,7 +1578,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;
@@ -1608,7 +1609,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;
 
@@ -2734,7 +2735,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");

+ 2 - 2
src/or/hibernate.c

@@ -522,7 +522,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);
@@ -530,7 +530,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);

+ 9 - 5
src/or/main.c

@@ -1037,6 +1037,7 @@ run_scheduled_events(time_t now)
   static int should_init_bridge_stats = 1;
   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;
 
@@ -1068,7 +1069,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();
@@ -1103,7 +1104,10 @@ run_scheduled_events(time_t now)
     last_rotated_x509_certificate = now;
   if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME < now) {
     log_info(LD_GENERAL,"Rotating tls context.");
-    if (tor_tls_context_new(get_identity_key(), MAX_SSL_KEY_LIFETIME) < 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) < 0) {
       log_warn(LD_BUG, "Error reinitializing TLS context");
       /* XXX is it a bug here, that we just keep going? -RD */
     }
@@ -1386,7 +1390,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 {
@@ -1660,7 +1664,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;
@@ -2299,7 +2303,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;
   }

+ 118 - 32
src/or/router.c

@@ -51,11 +51,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
@@ -125,31 +129,78 @@ 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)
 {
-  crypto_free_pk_env(identitykey);
-  identitykey = k;
-  crypto_pk_get_digest(identitykey, identitykey_digest);
+  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;
+  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
@@ -472,9 +523,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) < 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) < 0) {
       log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
       return -1;
     }
@@ -509,13 +563,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");
@@ -552,7 +621,10 @@ 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) < 0) {
+  if (tor_tls_context_init(public_server_mode(options),
+                           get_tlsclient_identity_key(),
+                           get_server_identity_key(),
+                           MAX_SSL_KEY_LIFETIME) < 0) {
     log_err(LD_GENERAL,"Error initializing TLS context");
     return -1;
   }
@@ -563,7 +635,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;
     }
@@ -584,7 +657,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;
@@ -622,7 +696,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) |
@@ -981,6 +1055,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);
+}
+
 /** Return true iff the combination of options in <b>options</b> and parameters
  * in the consensus mean that we don't want to allow exits from circuits
  * we got from addresses not known to be servers. */
@@ -1168,11 +1251,12 @@ router_my_exit_policy_is_reject_star(void)
 }
 
 /** 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 && !memcmp(identitykey_digest, digest, DIGEST_LEN);
+  return (server_identitykey &&
+          !memcmp(server_identitykey_digest, digest, DIGEST_LEN));
 }
 
 /** Return true iff I'm a server and <b>digest</b> is equal to
@@ -1311,7 +1395,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);
@@ -1406,7 +1490,8 @@ router_rebuild_descriptor(int force)
   ei_size = options->ExtraInfoStatistics ? MAX_EXTRAINFO_UPLOAD_SIZE : 8192;
   ei->cache_info.signed_descriptor_body = tor_malloc(ei_size);
   if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body,
-                               ei_size, ei, get_identity_key()) < 0) {
+                               ei_size, ei,
+                               get_server_identity_key()) < 0) {
     log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
     routerinfo_free(ri);
     extrainfo_free(ei);
@@ -1423,7 +1508,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);
@@ -2175,7 +2260,8 @@ router_free_all(void)
 {
   crypto_free_pk_env(onionkey);
   crypto_free_pk_env(lastonionkey);
-  crypto_free_pk_env(identitykey);
+  crypto_free_pk_env(server_identitykey);
+  crypto_free_pk_env(client_identitykey);
   tor_mutex_free(key_lock);
   routerinfo_free(desc_routerinfo);
   extrainfo_free(desc_extrainfo);

+ 7 - 3
src/or/router.h

@@ -14,9 +14,12 @@
 
 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_server_identity_key(crypto_pk_env_t *k);
+crypto_pk_env_t *get_server_identity_key(void);
+int server_identity_key_is_set(void);
+void set_client_identity_key(crypto_pk_env_t *k);
+crypto_pk_env_t *get_tlsclient_identity_key(void);
+int client_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);
@@ -48,6 +51,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);