diff options
author | Robert Ransom <rransom.8774@gmail.com> | 2010-10-03 18:14:08 -0700 |
---|---|---|
committer | Sebastian Hahn <sebastian@torproject.org> | 2011-10-26 14:13:55 +0200 |
commit | 9976df9e5619b89339390c322138f7228b8fa715 (patch) | |
tree | c27f98930644472c31fa1f71b8d841b662eeecba /src/common | |
parent | 878164011108c16574d6ce1d9530fe83a3109bad (diff) | |
download | tor-9976df9e5619b89339390c322138f7228b8fa715.tar tor-9976df9e5619b89339390c322138f7228b8fa715.tar.gz |
Maintain separate server and client TLS contexts.
Fixes bug #988.
Conflicts:
src/or/main.c
src/or/router.c
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/tortls.c | 101 | ||||
-rw-r--r-- | src/common/tortls.h | 4 |
2 files changed, 89 insertions, 16 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 <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 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); |