X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=ssl.c;h=58bd222cd76e2d30747a893b041ecea9e718a054;hp=6eb5945673d6c4a5adb99f488a700ed36c271d30;hb=f2be4cfb0e98db4cf6fcf33f3f1efadabe399887;hpb=f9b953ed3f2bc2de510352e56dfbf91efd19ac7e diff --git a/ssl.c b/ssl.c index 6eb59456..58bd222c 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 @@ -88,12 +88,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); /********************************************************************* * @@ -105,7 +106,7 @@ static int seed_rng(struct client_state *csp); * or has not yet been sent by the remote end. * * Parameters : - * 1 : ssl = SSL context to test + * 1 : ssl_attr = SSL context to test * * Returns : 0 => No data are pending * >0 => Pending data length @@ -131,7 +132,7 @@ extern size_t is_ssl_pending(struct ssl_attr *ssl_attr) * connection context. * * Parameters : - * 1 : ssl = SSL context to send data to + * 1 : ssl_attr = SSL context to send data to * 2 : buf = Pointer to data to be sent * 3 : len = Length of data to be sent to the SSL context * @@ -170,7 +171,8 @@ extern int ssl_send_data(struct ssl_attr *ssl_attr, const unsigned char *buf, si send_len = (int)max_fragment_size; } - log_error(LOG_LEVEL_WRITING, "TLS: %N", send_len, buf+pos); + log_error(LOG_LEVEL_WRITING, "TLS on socket %d: %N", + ssl_attr->mbedtls_attr.socket_fd.fd, send_len, buf+pos); /* * Sending one part of the buffer @@ -186,7 +188,8 @@ extern int ssl_send_data(struct ssl_attr *ssl_attr, const unsigned char *buf, si mbedtls_strerror(ret, err_buf, sizeof(err_buf)); log_error(LOG_LEVEL_ERROR, - "Sending data over TLS/SSL failed: %s", err_buf); + "Sending data on socket %d over TLS/SSL failed: %s", + ssl_attr->mbedtls_attr.socket_fd.fd, err_buf); return -1; } } @@ -206,7 +209,7 @@ extern int ssl_send_data(struct ssl_attr *ssl_attr, const unsigned char *buf, si * it into buffer. * * Parameters : - * 1 : ssl = SSL context to receive data from + * 1 : ssl_attr = SSL context to receive data from * 2 : buf = Pointer to buffer where data will be written * 3 : max_length = Maximum number of bytes to read * @@ -235,51 +238,26 @@ extern int ssl_recv_data(struct ssl_attr *ssl_attr, unsigned char *buf, size_t m if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - log_error(LOG_LEVEL_CONNECT, - "The peer notified us that the connection is going to be closed"); + log_error(LOG_LEVEL_CONNECT, "The peer notified us that " + "the connection on socket %d is going to be closed", + ssl_attr->mbedtls_attr.socket_fd.fd); return 0; } mbedtls_strerror(ret, err_buf, sizeof(err_buf)); log_error(LOG_LEVEL_ERROR, - "Receiving data over TLS/SSL failed: %s", err_buf); + "Receiving data on socket %d over TLS/SSL failed: %s", + ssl_attr->mbedtls_attr.socket_fd.fd, err_buf); return -1; } - log_error(LOG_LEVEL_RECEIVED, "TLS: %N", ret, buf); + log_error(LOG_LEVEL_RECEIVED, "TLS from socket %d: %N", + ssl_attr->mbedtls_attr.socket_fd.fd, ret, buf); return ret; } -/********************************************************************* - * - * Function : ssl_debug_callback - * - * Description : Debug callback function for mbedtls library. - * Prints info into log file. - * - * Parameters : - * 1 : ctx = File to save log in - * 2 : level = Debug level - * 3 : file = File calling debug message - * 4 : line = Line calling debug message - * 5 : str = Debug message - * - * Returns : N/A - * - *********************************************************************/ -static void ssl_debug_callback(void *ctx, int level, const char *file, int line, const char *str) -{ - /* - ((void)level); - fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str); - fflush((FILE *)ctx); - log_error(LOG_LEVEL_INFO, "SSL debug message: %s:%04d: %s", file, line, str); - */ -} - - /********************************************************************* * * Function : create_client_ssl_connection @@ -347,11 +325,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; @@ -422,8 +400,6 @@ extern int create_client_ssl_connection(struct client_state *csp) mbedtls_ssl_conf_rng(&(ssl_attr->mbedtls_attr.conf), mbedtls_ctr_drbg_random, &ctr_drbg); - mbedtls_ssl_conf_dbg(&(ssl_attr->mbedtls_attr.conf), - ssl_debug_callback, stdout); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache(&(ssl_attr->mbedtls_attr.conf), @@ -446,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) @@ -569,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)); @@ -677,8 +670,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); - mbedtls_ssl_conf_dbg(&(ssl_attr->mbedtls_attr.conf), - ssl_debug_callback, stdout); + + 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)); @@ -830,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)); } @@ -1249,7 +1257,7 @@ exit: /********************************************************************* * - * Function : generate_webpage_certificate + * Function : generate_host_certificate * * Description : Creates certificate file in presetted directory. * If certificate already exists, no other certificate @@ -1265,7 +1273,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; @@ -1302,6 +1310,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? */ @@ -1723,9 +1740,16 @@ 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); + if (encoded_text == NULL) + { + log_error(LOG_LEVEL_ERROR, + "Failed to HTML-encode the certificate information"); + return -1; + } strlcpy(last->info_buf, encoded_text, sizeof(last->info_buf)); freez(encoded_text); } @@ -1835,7 +1859,7 @@ static int seed_rng(struct client_state *csp) * *********************************************************************/ extern int ssl_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) + const unsigned char *src, size_t slen) { return mbedtls_base64_encode(dst, dlen, olen, src, slen); } @@ -1858,7 +1882,16 @@ 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'; + } } @@ -1881,3 +1914,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; + +}