X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=ssl.c;h=afd9af450c193689b22b7cdf87c0be559f513782;hp=7334fb9cf9b9afc8a8d9191cc4e9b80ff2d6fd76;hb=bb852452cc898205f0893d667e091773deaa9e30;hpb=f48596786c693b205581714236296ca2a17d3e54 diff --git a/ssl.c b/ssl.c index 7334fb9c..afd9af45 100644 --- a/ssl.c +++ b/ssl.c @@ -3,10 +3,11 @@ * File : $Source: /cvsroot/ijbswa/current/ssl.c,v $ * * Purpose : File with TLS/SSL extension. Contains methods for - * creating, using and closing TLS/SSL connections. + * creating, using and closing TLS/SSL connections + * using mbedTLS. * - * Copyright : Written by and Copyright (c) 2017 Vaclav Svec. FIT CVUT. - * Copyright (C) 2018-2020 by Fabian Keil + * Copyright : Written by and Copyright (c) 2017-2020 Vaclav Svec. FIT CVUT. + * Copyright (C) 2018-2021 by Fabian Keil * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -88,12 +89,13 @@ static mbedtls_ctr_drbg_context ctr_drbg; static mbedtls_entropy_context entropy; static int rng_seeded; -static int generate_webpage_certificate(struct client_state *csp); +static int generate_host_certificate(struct client_state *csp); static int host_to_hash(struct client_state *csp); static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); 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); /********************************************************************* * @@ -324,11 +326,11 @@ extern int create_client_ssl_connection(struct client_state *csp) */ privoxy_mutex_lock(&certificate_mutex); - ret = generate_webpage_certificate(csp); + ret = generate_host_certificate(csp); if (ret < 0) { log_error(LOG_LEVEL_ERROR, - "Generate_webpage_certificate failed: %d", ret); + "generate_host_certificate failed: %d", ret); privoxy_mutex_unlock(&certificate_mutex); ret = -1; goto exit; @@ -421,6 +423,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) @@ -462,7 +480,10 @@ extern int create_client_ssl_connection(struct client_state *csp) } } - log_error(LOG_LEVEL_CONNECT, "Client successfully connected over TLS/SSL"); + log_error(LOG_LEVEL_CONNECT, "Client successfully connected over %s (%s).", + mbedtls_ssl_get_version(&(ssl_attr->mbedtls_attr.ssl)), + mbedtls_ssl_get_ciphersuite(&(ssl_attr->mbedtls_attr.ssl))); + csp->ssl_with_client_is_opened = 1; exit: @@ -544,6 +565,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 +675,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) @@ -720,7 +758,9 @@ extern int create_server_ssl_connection(struct client_state *csp) } } - log_error(LOG_LEVEL_CONNECT, "Server successfully connected over TLS/SSL"); + log_error(LOG_LEVEL_CONNECT, "Server successfully connected over %s (%s).", + mbedtls_ssl_get_version(&(ssl_attr->mbedtls_attr.ssl)), + mbedtls_ssl_get_ciphersuite(&(ssl_attr->mbedtls_attr.ssl))); /* * Server certificate chain is valid, so we can clean @@ -803,6 +843,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)); } @@ -1222,7 +1263,7 @@ exit: /********************************************************************* * - * Function : generate_webpage_certificate + * Function : generate_host_certificate * * Description : Creates certificate file in presetted directory. * If certificate already exists, no other certificate @@ -1238,7 +1279,7 @@ exit: * >0 => Length of created certificate. * *********************************************************************/ -static int generate_webpage_certificate(struct client_state *csp) +static int generate_host_certificate(struct client_state *csp) { mbedtls_x509_crt issuer_cert; mbedtls_pk_context loaded_issuer_key, loaded_subject_key; @@ -1275,6 +1316,15 @@ static int generate_webpage_certificate(struct client_state *csp) return -1; } + if (enforce_sane_certificate_state(cert_opt.output_file, + cert_opt.subject_key)) + { + freez(cert_opt.output_file); + freez(cert_opt.subject_key); + + return -1; + } + if (file_exists(cert_opt.output_file) == 1) { /* The file exists, but is it valid? */ @@ -1657,6 +1707,7 @@ static int ssl_verify_callback(void *csp_void, mbedtls_x509_crt *crt, struct certs_chain *last = &(csp->server_certs_chain); size_t olen = 0; int ret = 0; + size_t pem_buffer_length; /* * Searching for last item in certificates linked list @@ -1672,14 +1723,33 @@ static int ssl_verify_callback(void *csp_void, mbedtls_x509_crt *crt, last->next = malloc_or_die(sizeof(struct certs_chain)); last->next->next = NULL; memset(last->next->info_buf, 0, sizeof(last->next->info_buf)); - memset(last->next->file_buf, 0, sizeof(last->next->file_buf)); + last->next->file_buf = NULL; + + ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT, crt->raw.p, + crt->raw.len, NULL, 0, &olen); + if (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL != ret) + { + log_error(LOG_LEVEL_ERROR, + "Failed to figure out the required X509 PEM certificate buffer size"); + return -1; + } + pem_buffer_length = olen; + + last->file_buf = malloc(pem_buffer_length); + if (last->file_buf == NULL) + { + log_error(LOG_LEVEL_ERROR, + "Failed to allocate %lu bytes to store the X509 PEM certificate", + pem_buffer_length); + return -1; + } /* * Saving certificate file into buffer */ if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT, crt->raw.p, crt->raw.len, (unsigned char *)last->file_buf, - sizeof(last->file_buf)-1, &olen)) != 0) + pem_buffer_length, &olen)) != 0) { char err_buf[ERROR_BUF_SIZE]; @@ -1696,6 +1766,7 @@ static int ssl_verify_callback(void *csp_void, mbedtls_x509_crt *crt, { char buf[CERT_INFO_BUF_SIZE]; char *encoded_text; +#define CERT_INFO_PREFIX "" mbedtls_x509_crt_info(buf, sizeof(buf), CERT_INFO_PREFIX, crt); encoded_text = html_encode(buf); @@ -1723,7 +1794,7 @@ static int ssl_verify_callback(void *csp_void, mbedtls_x509_crt *crt, * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * - * Returns : 1 => Error while creating hash + * Returns : -1 => Error while creating hash * 0 => Hash created successfully * *********************************************************************/ @@ -1735,8 +1806,15 @@ static int host_to_hash(struct client_state *csp) #error mbedTLS needs to be compiled with md5 support #else memset(csp->http->hash_of_host, 0, sizeof(csp->http->hash_of_host)); - mbedtls_md5((unsigned char *)csp->http->host, strlen(csp->http->host), - csp->http->hash_of_host); + ret = mbedtls_md5_ret((unsigned char *)csp->http->host, + strlen(csp->http->host), csp->http->hash_of_host); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Failed to generate md5 hash of host %s: %d", + csp->http->host, ret); + return -1; + } /* Converting hash into string with hex */ size_t i = 0; @@ -1837,10 +1915,20 @@ extern int ssl_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, *********************************************************************/ extern void ssl_crt_verify_info(char *buf, size_t size, struct client_state *csp) { - mbedtls_x509_crt_verify_info(buf, size, " ", csp->server_cert_verification_result); + char *last_byte; + + mbedtls_x509_crt_verify_info(buf, size, "", + csp->server_cert_verification_result); + last_byte = buf + strlen(buf)-1; + if (*last_byte == '\n') + { + /* Overwrite trailing new line character */ + *last_byte = '\0'; + } } +#ifdef FEATURE_GRACEFUL_TERMINATION /********************************************************************* * * Function : ssl_release @@ -1860,3 +1948,74 @@ extern void ssl_release(void) mbedtls_entropy_free(&entropy); } } +#endif /* def FEATURE_GRACEFUL_TERMINATION */ + + +/********************************************************************* + * + * 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); + strlcpy(ciphersuites_string, parameter_string, parameter_len + 1); + 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; + +}