[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