Polish ChangeLog entries for 3.0.30 stable
[privoxy.git] / ssl_common.c
index 20c1b24..e46747e 100644 (file)
@@ -7,7 +7,7 @@
  *                not depend on particular TLS/SSL library.
  *
  * Copyright   :  Written by and Copyright (c) 2017 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
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #include <ctype.h>
+#include <unistd.h>
 #include "config.h"
 #include "project.h"
 #include "miscutil.h"
@@ -323,17 +324,18 @@ extern void ssl_send_certificate_error(struct client_state *csp)
    size_t message_len = 0;
    int ret = 0;
    struct certs_chain *cert = NULL;
+   const size_t head_length = 63;
 
    /* Header of message with certificate information */
    const char message_begin[] =
-      "HTTP/1.1 200 OK\r\n"
+      "HTTP/1.1 403 Certificate validation failed\r\n"
       "Content-Type: text/html\r\n"
       "Connection: close\r\n\r\n"
       "<!DOCTYPE html>\n"
       "<html><head><title>Server certificate verification failed</title></head>\n"
       "<body><h1>Server certificate verification failed</h1>\n"
       "<p><a href=\"https://" CGI_SITE_2_HOST "/\">Privoxy</a> was unable "
-      "to securely connnect to the destination server.</p>"
+      "to securely connect to the destination server.</p>"
       "<p>Reason: ";
    const char message_end[] = "</body></html>\r\n\r\n";
    char reason[INVALID_CERT_INFO_BUF_SIZE];
@@ -406,9 +408,20 @@ extern void ssl_send_certificate_error(struct client_state *csp)
    /*
     * Sending final message to client
     */
-   ssl_send_data(ssl_attr, (const unsigned char *)message, strlen(message));
+   (void)ssl_send_data(ssl_attr, (const unsigned char *)message, strlen(message));
 
    free_certificate_chain(csp);
+
+   log_error(LOG_LEVEL_CRUNCH, "Certificate error: %s: https://%s%s",
+      reason, csp->http->hostport, csp->http->path);
+   log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" 403 %lu",
+      csp->ip_addr_str, csp->http->gpc, csp->http->hostport, csp->http->path,
+      csp->http->version, message_len-head_length);
+
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+   csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
+   csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
+#endif
 }
 
 
@@ -475,12 +488,12 @@ extern char *make_certs_path(const char *conf_dir, const char *file_name,
       + strlen(file_name) + strlen(suffix) + 2;
 
    /* Setting delimiter and editing path length */
-#if defined(_WIN32) || defined(__OS2__)
+#if defined(_WIN32)
    char delim[] = "\\";
    path_size += 1;
-#else /* ifndef _WIN32 || __OS2__ */
+#else /* ifndef _WIN32 */
    char delim[] = "/";
-#endif /* ifndef _WIN32 || __OS2__ */
+#endif /* ifndef _WIN32 */
 
    /*
     * Building up path from many parts
@@ -686,3 +699,52 @@ extern int host_is_ip_address(const char *host)
    return 1;
 
 }
+
+
+/*********************************************************************
+ *
+ * Function    :  enforce_sane_certificate_state
+ *
+ * Description :  Makes sure the certificate state is sane.
+ *
+ * Parameters  :
+ *          1  :  certificate = Path to the potentionally existing certifcate.
+ *          2  :  key = Path to the potentionally existing key.
+ *
+ * Returns     :   -1 => Error
+ *                 0 => Certificate state is sane
+ *
+ *********************************************************************/
+extern int enforce_sane_certificate_state(const char *certificate, const char *key)
+{
+   const int certificate_exists = file_exists(certificate);
+   const int key_exists = file_exists(key);
+
+   if (!certificate_exists && key_exists)
+   {
+      log_error(LOG_LEVEL_ERROR,
+         "A website key already exists but there's no matching certificate. "
+         "Removing %s before creating a new key and certificate.", key);
+      if (unlink(key))
+      {
+         log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E", key);
+
+         return -1;
+      }
+   }
+   if (certificate_exists && !key_exists)
+   {
+      log_error(LOG_LEVEL_ERROR,
+         "A certificate exists but there's no matching key. "
+         "Removing %s before creating a new key and certificate.", certificate);
+      if (unlink(certificate))
+      {
+         log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E", certificate);
+
+         return -1;
+      }
+   }
+
+   return 0;
+
+}