From: Fabian Keil Date: Tue, 6 Oct 2020 11:28:14 +0000 (+0200) Subject: Add a cipher-list directive to specify the ciphers used X-Git-Tag: v_3_0_29~46 X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=commitdiff_plain;h=0fc07e07a74872fb3347dc762372ba7c843d5a52 Add a cipher-list directive to specify the ciphers used ... in the TLS handshake. The get_ciphersuites_from_string() function in the MbedTLS code is based on code contributed by Václav Švec. --- diff --git a/loadcfg.c b/loadcfg.c index ad15c644..d9014bc4 100644 --- a/loadcfg.c +++ b/loadcfg.c @@ -138,6 +138,7 @@ static struct file_list *current_configfile = NULL; #define hash_ca_key_file 1184187891U /* "ca-key-file" */ #define hash_ca_password 1184543320U /* "ca-password" */ #define hash_certificate_directory 1367994217U /* "certificate-directory" */ +#define hash_cipher_list 1225729316U /* "cipher-list" */ #define hash_client_header_order 2701453514U /* "client-header-order" */ #define hash_client_specific_tag 3353703383U /* "client-specific-tag" */ #define hash_client_tag_lifetime 647957580U /* "client-tag-lifetime" */ @@ -281,6 +282,7 @@ static void unload_configfile (void * data) freez(config->ca_cert_file); freez(config->ca_key_file); freez(config->certificate_directory); + freez(config->cipher_list); freez(config->trusted_cas_file); #endif @@ -1796,6 +1798,15 @@ struct configuration_spec * load_config(void) break; +/* ************************************************************************* + * cipher-list list-of-ciphers + * *************************************************************************/ + case hash_cipher_list: + freez(config->cipher_list); + config->cipher_list = strdup_or_die(arg); + + break; + /* ************************************************************************* * trusted CAs file name trusted-cas-file * *************************************************************************/ diff --git a/openssl.c b/openssl.c index 37b80696..2c065cc5 100644 --- a/openssl.c +++ b/openssl.c @@ -837,6 +837,18 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } + if (csp->config->cipher_list != NULL) + { + if (!SSL_set_cipher_list(ssl, csp->config->cipher_list)) + { + log_ssl_errors(LOG_LEVEL_ERROR, + "Setting the cipher list '%s' for the client connection failed", + csp->config->cipher_list); + ret = -1; + goto exit; + } + } + /* * Handshake with client */ @@ -1061,6 +1073,18 @@ extern int create_server_ssl_connection(struct client_state *csp) goto exit; } + if (csp->config->cipher_list != NULL) + { + if (!SSL_set_cipher_list(ssl, csp->config->cipher_list)) + { + log_ssl_errors(LOG_LEVEL_ERROR, + "Setting the cipher list '%s' for the server connection failed", + csp->config->cipher_list); + ret = -1; + goto exit; + } + } + /* * Set the hostname to check against the received server certificate */ diff --git a/project.h b/project.h index 94453834..ec3c1559 100644 --- a/project.h +++ b/project.h @@ -311,6 +311,7 @@ typedef struct { mbedtls_x509_crt server_cert; mbedtls_x509_crt ca_cert; mbedtls_pk_context prim_key; + int *ciphersuites_list; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; @@ -1588,6 +1589,9 @@ struct configuration_spec /** Directory for saving certificates and keys for each webpage **/ char *certificate_directory; + /** Cipher list to use **/ + char *cipher_list; + /** Filename of trusted CAs certificates **/ char * trusted_cas_file; #endif diff --git a/ssl.c b/ssl.c index 7334fb9c..46b8fd4b 100644 --- a/ssl.c +++ b/ssl.c @@ -5,7 +5,7 @@ * Purpose : File with TLS/SSL extension. Contains methods for * creating, using and closing TLS/SSL connections. * - * Copyright : Written by and Copyright (c) 2017 Vaclav Svec. FIT CVUT. + * Copyright : Written by and Copyright (c) 2017-2020 Vaclav Svec. FIT CVUT. * Copyright (C) 2018-2020 by Fabian Keil * * This program is free software; you can redistribute it @@ -94,6 +94,7 @@ static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uin static void free_client_ssl_structures(struct client_state *csp); static void free_server_ssl_structures(struct client_state *csp); static int seed_rng(struct client_state *csp); +static int *get_ciphersuites_from_string(const char *ciphersuites_string); /********************************************************************* * @@ -421,6 +422,22 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } + if (csp->config->cipher_list != NULL) + { + ssl_attr->mbedtls_attr.ciphersuites_list = + get_ciphersuites_from_string(csp->config->cipher_list); + if (ssl_attr->mbedtls_attr.ciphersuites_list == NULL) + { + log_error(LOG_LEVEL_ERROR, + "Setting the cipher list '%s' for the client connection failed", + csp->config->cipher_list); + ret = -1; + goto exit; + } + mbedtls_ssl_conf_ciphersuites(&(ssl_attr->mbedtls_attr.conf), + ssl_attr->mbedtls_attr.ciphersuites_list); + } + ret = mbedtls_ssl_setup(&(ssl_attr->mbedtls_attr.ssl), &(ssl_attr->mbedtls_attr.conf)); if (ret != 0) @@ -544,6 +561,7 @@ static void free_client_ssl_structures(struct client_state *csp) mbedtls_x509_crt_free(&(ssl_attr->mbedtls_attr.server_cert)); mbedtls_pk_free(&(ssl_attr->mbedtls_attr.prim_key)); mbedtls_ssl_free(&(ssl_attr->mbedtls_attr.ssl)); + freez(ssl_attr->mbedtls_attr.ciphersuites_list); mbedtls_ssl_config_free(&(ssl_attr->mbedtls_attr.conf)); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free(&(ssl_attr->mbedtls_attr.cache)); @@ -653,6 +671,22 @@ extern int create_server_ssl_connection(struct client_state *csp) mbedtls_ssl_conf_rng(&(ssl_attr->mbedtls_attr.conf), mbedtls_ctr_drbg_random, &ctr_drbg); + if (csp->config->cipher_list != NULL) + { + ssl_attr->mbedtls_attr.ciphersuites_list = + get_ciphersuites_from_string(csp->config->cipher_list); + if (ssl_attr->mbedtls_attr.ciphersuites_list == NULL) + { + log_error(LOG_LEVEL_ERROR, + "Setting the cipher list '%s' for the server connection failed", + csp->config->cipher_list); + ret = -1; + goto exit; + } + mbedtls_ssl_conf_ciphersuites(&(ssl_attr->mbedtls_attr.conf), + ssl_attr->mbedtls_attr.ciphersuites_list); + } + ret = mbedtls_ssl_setup(&(ssl_attr->mbedtls_attr.ssl), &(ssl_attr->mbedtls_attr.conf)); if (ret != 0) @@ -803,6 +837,7 @@ static void free_server_ssl_structures(struct client_state *csp) mbedtls_x509_crt_free(&(ssl_attr->mbedtls_attr.ca_cert)); mbedtls_ssl_free(&(ssl_attr->mbedtls_attr.ssl)); + freez(ssl_attr->mbedtls_attr.ciphersuites_list); mbedtls_ssl_config_free(&(ssl_attr->mbedtls_attr.conf)); } @@ -1860,3 +1895,73 @@ extern void ssl_release(void) mbedtls_entropy_free(&entropy); } } + + +/********************************************************************* + * + * Function : get_ciphersuites_from_string + * + * Description : Converts a string of ciphersuite names to + * an array of ciphersuite ids. + * + * Parameters : + * 1 : ciphersuites_string = String containing allowed + * ciphersuites. + * + * Returns : Array of ciphersuite ids + * + *********************************************************************/ +static int *get_ciphersuites_from_string(const char *parameter_string) +{ + char *ciphersuites_index; + char *item_end; + char *ciphersuites_string; + int *ciphersuite_ids; + size_t count = 2; + int index = 0; + const char separator = ':'; + size_t parameter_len = strlen(parameter_string); + + ciphersuites_string = zalloc_or_die(parameter_len + 1); + strncpy(ciphersuites_string, parameter_string, parameter_len); + ciphersuites_index = ciphersuites_string; + + while (*ciphersuites_index) + { + if (*ciphersuites_index++ == separator) + { + ++count; + } + } + + ciphersuite_ids = zalloc_or_die(count * sizeof(int)); + + ciphersuites_index = ciphersuites_string; + do + { + item_end = strchr(ciphersuites_index, separator); + if (item_end != NULL) + { + *item_end = '\0'; + } + + ciphersuite_ids[index] = + mbedtls_ssl_get_ciphersuite_id(ciphersuites_index); + if (ciphersuite_ids[index] == 0) + { + log_error(LOG_LEVEL_ERROR, + "Failed to get ciphersuite id for %s", ciphersuites_index); + freez(ciphersuite_ids); + freez(ciphersuites_string); + return NULL; + } + ciphersuites_index = item_end + 1; + index++; + } while (item_end != NULL); + + ciphersuite_ids[index] = 0; + freez(ciphersuites_string); + + return ciphersuite_ids; + +}