Add a client-body-tagger action
[privoxy.git] / ssl.c
diff --git a/ssl.c b/ssl.c
index 46b8fd4..afd9af4 100644 (file)
--- 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-2020 Vaclav Svec. FIT CVUT.
- *                Copyright (C) 2018-2020 by Fabian Keil <fk@fabiankeil.de>
+ *                Copyright (C) 2018-2021 by Fabian Keil <fk@fabiankeil.de>
  *
  *                This program is free software; you can redistribute it
  *                and/or modify it under the terms of the GNU General
@@ -88,7 +89,7 @@ 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);
@@ -325,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;
@@ -479,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:
@@ -754,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
@@ -1257,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
@@ -1273,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;
@@ -1310,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? */
@@ -1692,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
@@ -1707,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];
 
@@ -1731,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);
@@ -1758,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
  *
  *********************************************************************/
@@ -1770,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;
@@ -1872,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
@@ -1895,6 +1948,7 @@ extern void ssl_release(void)
       mbedtls_entropy_free(&entropy);
    }
 }
+#endif /* def FEATURE_GRACEFUL_TERMINATION */
 
 
 /*********************************************************************
@@ -1923,7 +1977,7 @@ static int *get_ciphersuites_from_string(const char *parameter_string)
    size_t parameter_len = strlen(parameter_string);
 
    ciphersuites_string = zalloc_or_die(parameter_len + 1);
-   strncpy(ciphersuites_string, parameter_string, parameter_len);
+   strlcpy(ciphersuites_string, parameter_string, parameter_len + 1);
    ciphersuites_index = ciphersuites_string;
 
    while (*ciphersuites_index)