diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-11-05 18:15:52 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-11-05 18:15:52 +0000 |
commit | 323490303e9864e9116e5a740a48316ada801983 (patch) | |
tree | c63afeb5b9f02f8e38e84e01b96a9116a9a27e64 /src/common/tortls.c | |
parent | ea1bea5830ad90d9ea14a84ffa4b465827ff8af4 (diff) | |
download | tor-323490303e9864e9116e5a740a48316ada801983.tar.gz tor-323490303e9864e9116e5a740a48316ada801983.zip |
r16412@catbus: nickm | 2007-11-05 11:45:17 -0500
Make TLS contexts reference-counted, and add a reference from TLS objects to their corresponding context. This lets us reliably get the certificates for a given TLS connection, even if we have rotated TLS contexts.
svn:r12383
Diffstat (limited to 'src/common/tortls.c')
-rw-r--r-- | src/common/tortls.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c index c6ffe12108..512847f1de 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -43,6 +43,7 @@ const char tortls_c_id[] = /** Structure holding the TLS state for a single connection. */ typedef struct tor_tls_context_t { + int refcnt; SSL_CTX *ctx; X509 *my_cert; X509 *my_id_cert; @@ -52,21 +53,23 @@ typedef struct tor_tls_context_t { * accessed from within tortls.c. */ struct tor_tls_t { + tor_tls_context_t *context; /**DOCDOC */ SSL *ssl; /**< An OpenSSL SSL object. */ int socket; /**< The underlying file descriptor for this TLS connection. */ enum { TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE, TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED - } state; /**< The current SSL state, depending on which operations have - * completed successfully. */ - int isServer; /**< True iff this is a server-side connection */ + } state : 7; /**< The current SSL state, depending on which operations have + * completed successfully. */ + unsigned int isServer:1; /**< True iff this is a server-side connection */ size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last * time. */ unsigned long last_write_count; unsigned long last_read_count; }; -static void tor_tls_context_free(tor_tls_context_t *ctx); +static void tor_tls_context_decref(tor_tls_context_t *ctx); +static void tor_tls_context_incref(tor_tls_context_t *ctx); static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, crypto_pk_env_t *rsa_sign, const char *cname, @@ -214,7 +217,7 @@ void tor_tls_free_all(void) { if (global_tls_context) { - tor_tls_context_free(global_tls_context); + tor_tls_context_decref(global_tls_context); global_tls_context = NULL; } } @@ -345,12 +348,22 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, /** DOCDOC */ static void -tor_tls_context_free(tor_tls_context_t *ctx) +tor_tls_context_decref(tor_tls_context_t *ctx) { - SSL_CTX_free(ctx->ctx); - X509_free(ctx->my_cert); - X509_free(ctx->my_id_cert); - tor_free(ctx); + tor_assert(ctx); + if (--ctx->refcnt == 0) { + SSL_CTX_free(ctx->ctx); + X509_free(ctx->my_cert); + X509_free(ctx->my_id_cert); + tor_free(ctx); + } +} + +/** DOCDOC */ +static void +tor_tls_context_incref(tor_tls_context_t *ctx) +{ + ++ctx->refcnt; } /** Create a new TLS context for use with Tor TLS handshakes. @@ -394,6 +407,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname, } result = tor_malloc_zero(sizeof(tor_tls_context_t)); + result->refcnt = 1; result->my_cert = X509_dup(cert); result->my_id_cert = X509_dup(idcert); @@ -446,7 +460,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname, 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_free(global_tls_context); + tor_tls_context_decref(global_tls_context); } global_tls_context = result; if (rsa) @@ -461,10 +475,8 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname, crypto_free_pk_env(rsa); if (dh) crypto_dh_free(dh); - if (result && result->ctx) - SSL_CTX_free(result->ctx); if (result) - tor_free(result); + tor_tls_context_decref(result); if (cert) X509_free(cert); if (idcert) @@ -495,10 +507,13 @@ tor_tls_new(int sock, int isServer) #endif if (! bio) { tls_log_errors(LOG_WARN, "opening BIO"); + SSL_free(result->ssl); tor_free(result); return NULL; } SSL_set_bio(result->ssl, bio, bio); + tor_tls_context_incref(global_tls_context); + result->context = global_tls_context; result->state = TOR_TLS_ST_HANDSHAKE; result->isServer = isServer; result->wantwrite_n = 0; @@ -525,6 +540,8 @@ tor_tls_free(tor_tls_t *tls) tor_assert(tls && tls->ssl); SSL_free(tls->ssl); tls->ssl = NULL; + if (tls->context) + tor_tls_context_decref(tls->context); tor_free(tls); } @@ -701,7 +718,8 @@ tor_tls_get_cert_digests(tor_tls_t *tls, { X509 *cert; unsigned int len; - cert = SSL_get_certificate(tls->ssl); + tor_assert(tls->context); + cert = tls->context->my_cert; if (cert) { X509_digest(cert, EVP_sha1(), (unsigned char*)my_digest_out, &len); if (len != DIGEST_LEN) |