[tor-commits] [tor/master] Tweak rectify_client_ciphers to work with openssl 1.1
nickm at torproject.org
nickm at torproject.org
Wed May 20 19:35:55 UTC 2015
commit 2f7c9b6ecb1a7855167b2c65781b2c4b1b014807
Author: Nick Mathewson <nickm at torproject.org>
Date: Wed May 13 12:38:17 2015 -0400
Tweak rectify_client_ciphers to work with openssl 1.1
The key here is to never touch ssl->cipher_list directly, but only
via SSL_get_ciphers(). But it's not so simple.
See, if there is no specialized cipher_list on the SSL object,
SSL_get_ciphers returns the cipher_list on the SSL_CTX. But we sure
don't want to modify that one! So we need to use
SSL_set_cipher_list first to make sure that we really have a cipher
list on the SSL object.
---
src/common/tortls.c | 55 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 16 deletions(-)
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 97352c0..08966b6 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -1800,21 +1800,46 @@ log_unsupported_ciphers(smartlist_t *unsupported)
tor_free(joined);
}
-/** Replace *<b>ciphers</b> with a new list of SSL ciphersuites: specifically,
- * a list designed to mimic a common web browser. We might not be able to do
- * that if OpenSSL doesn't support all the ciphers we want. Some of the
- * ciphers in the list won't actually be implemented by OpenSSL: that's okay
- * so long as the server doesn't select them.
+static void
+set_ssl_ciphers_to_list(SSL *ssl, STACK_OF(SSL_CIPHER) *stack)
+{
+ STACK_OF(SSL_CIPHER) *ciphers;
+
+ int r, i;
+ /* #1: ensure that the ssl object has its own list of ciphers. Otherwise we
+ * might be about to stomp the SSL_CTX ciphers list. */
+ r = SSL_set_cipher_list(ssl, "HIGH");
+ tor_assert(r);
+
+ /* #2: Grab ssl_ciphers and clear it. */
+ ciphers = SSL_get_ciphers(ssl);
+ tor_assert(ciphers);
+ sk_SSL_CIPHER_zero(ciphers);
+
+ /* #3: Copy the elements from stack. */
+ for (i = 0; i < sk_SSL_CIPHER_num(stack); ++i) {
+ SSL_CIPHER *c = sk_SSL_CIPHER_value(stack, i);
+ sk_SSL_CIPHER_push(ciphers, c);
+ }
+}
+
+/** Replace the ciphers on <b>ssl</b> with a new list of SSL ciphersuites:
+ * specifically, a list designed to mimic a common web browser. We might not
+ * be able to do that if OpenSSL doesn't support all the ciphers we want.
+ * Some of the ciphers in the list won't actually be implemented by OpenSSL:
+ * that's okay so long as the server doesn't select them.
*
* [If the server <b>does</b> select a bogus cipher, we won't crash or
* anything; we'll just fail later when we try to look up the cipher in
* ssl->cipher_list_by_id.]
*/
static void
-rectify_client_ciphers(STACK_OF(SSL_CIPHER) **ciphers)
+rectify_client_ciphers(SSL *ssl)
{
#ifdef V2_HANDSHAKE_CLIENT
if (PREDICT_UNLIKELY(!CLIENT_CIPHER_STACK)) {
+ STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
+
/* We need to set CLIENT_CIPHER_STACK to an array of the ciphers
* we want to use/advertise. */
int i = 0, j = 0;
@@ -1835,21 +1860,21 @@ rectify_client_ciphers(STACK_OF(SSL_CIPHER) **ciphers)
tor_assert(CLIENT_CIPHER_STACK);
log_debug(LD_NET, "List was: %s", CLIENT_CIPHER_LIST);
- for (j = 0; j < sk_SSL_CIPHER_num(*ciphers); ++j) {
- SSL_CIPHER *cipher = sk_SSL_CIPHER_value(*ciphers, j);
+ for (j = 0; j < sk_SSL_CIPHER_num(ciphers); ++j) {
+ SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, j);
log_debug(LD_NET, "Cipher %d: %lx %s", j, cipher->id, cipher->name);
}
/* Then copy as many ciphers as we can from the good list, inserting
* dummies as needed. Let j be an index into list of ciphers we have
- * (*ciphers) and let i be an index into the ciphers we want
+ * (ciphers) and let i be an index into the ciphers we want
* (CLIENT_INFO_CIPHER_LIST). We are building a list of ciphers in
* CLIENT_CIPHER_STACK.
*/
for (i = j = 0; i < N_CLIENT_CIPHERS; ) {
SSL_CIPHER *cipher = NULL;
- if (j < sk_SSL_CIPHER_num(*ciphers))
- cipher = sk_SSL_CIPHER_value(*ciphers, j);
+ if (j < sk_SSL_CIPHER_num(ciphers))
+ cipher = sk_SSL_CIPHER_value(ciphers, j);
if (cipher && ((cipher->id >> 24) & 0xff) != 3) {
/* Skip over non-v3 ciphers entirely. (This should no longer be
* needed, thanks to saying !SSLv2 above.) */
@@ -1886,12 +1911,10 @@ rectify_client_ciphers(STACK_OF(SSL_CIPHER) **ciphers)
smartlist_free(unsupported);
}
- sk_SSL_CIPHER_free(*ciphers);
- *ciphers = sk_SSL_CIPHER_dup(CLIENT_CIPHER_STACK);
- tor_assert(*ciphers);
+ set_ssl_ciphers_to_list(ssl, CLIENT_CIPHER_STACK);
#else
- (void)ciphers;
+ (void)ciphers;
#endif
}
@@ -1935,7 +1958,7 @@ tor_tls_new(int sock, int isServer)
goto err;
}
if (!isServer)
- rectify_client_ciphers(&result->ssl->cipher_list);
+ rectify_client_ciphers(result->ssl);
result->socket = sock;
bio = BIO_new_socket(sock, BIO_NOCLOSE);
if (! bio) {
More information about the tor-commits
mailing list