summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-10-21 16:23:01 -0400
committerNick Mathewson <nickm@torproject.org>2010-10-21 16:23:01 -0400
commit17fdde3d9251e92f01be839efe7fc7cac4854484 (patch)
treef22d97b3a46d499dc40c9b958afa1e634909ea55 /src/common
parentf3eb2a10ae432eb0907418ff69b5e9535b3c7970 (diff)
parent441241c13692051ff1b4ae86eaf472a8782cd5d6 (diff)
downloadtor-17fdde3d9251e92f01be839efe7fc7cac4854484.tar.gz
tor-17fdde3d9251e92f01be839efe7fc7cac4854484.zip
Merge remote branch 'origin/maint-0.2.2'
Conflicts: src/common/tortls.c
Diffstat (limited to 'src/common')
-rw-r--r--src/common/tortls.c138
-rw-r--r--src/common/tortls.h5
2 files changed, 119 insertions, 24 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 716cfa1241..ba450e4b19 100644
--- a/src/common/tortls.c
+++ b/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;
diff --git a/src/common/tortls.h b/src/common/tortls.h
index c1de456611..50d14da52f 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,