[tor-commits] [tor/master] Maintain separate server and client TLS contexts.

arma at torproject.org arma at torproject.org
Wed Oct 26 20:37:08 UTC 2011


commit 9976df9e5619b89339390c322138f7228b8fa715
Author: Robert Ransom <rransom.8774 at gmail.com>
Date:   Sun Oct 3 18:14:08 2010 -0700

    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 d3435e7..c78a9ec 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 <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.
@@ -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 3f80d99..55fee81 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 fe1f42e..00fce80 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 9afa983..dce2ad6 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;
   }





More information about the tor-commits mailing list