mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
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.
This commit is contained in:
+39
-16
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user