X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=ssl_common.c;h=18817137f1e38265ffc4ec3e8828fa7818341e04;hp=20c1b24fc5310de0030c104e49733840fee971c0;hb=4cedd5b95a23a92715dcc666bc46f84981f8788f;hpb=07d3ffdfb75d55d07fa8fc9e79f7829d9e8e476f diff --git a/ssl_common.c b/ssl_common.c index 20c1b24f..18817137 100644 --- a/ssl_common.c +++ b/ssl_common.c @@ -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 + * 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 @@ -31,6 +31,7 @@ #include #include +#include #include "config.h" #include "project.h" #include "miscutil.h" @@ -289,8 +290,8 @@ extern void free_certificate_chain(struct client_state *csp) /* Cleaning buffers */ memset(csp->server_certs_chain.info_buf, 0, sizeof(csp->server_certs_chain.info_buf)); - memset(csp->server_certs_chain.file_buf, 0, - sizeof(csp->server_certs_chain.file_buf)); + freez(csp->server_certs_chain.file_buf); + csp->server_certs_chain.next = NULL; /* Freeing memory in whole linked list */ @@ -298,6 +299,11 @@ extern void free_certificate_chain(struct client_state *csp) { struct certs_chain *cert_for_free = cert; cert = cert->next; + + /* Cleaning buffers */ + memset(cert_for_free->info_buf, 0, sizeof(cert_for_free->info_buf)); + freez(cert_for_free->file_buf); + freez(cert_for_free); } } @@ -323,19 +329,20 @@ 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" "\n" "Server certificate verification failed\n" "

Server certificate verification failed

\n" "

Privoxy was unable " - "to securely connnect to the destination server.

" + "to securely connect to the destination server.

" "

Reason: "; - const char message_end[] = "\r\n\r\n"; + const char message_end[] = "\n"; char reason[INVALID_CERT_INFO_BUF_SIZE]; memset(reason, 0, sizeof(reason)); @@ -403,12 +410,33 @@ extern void ssl_send_certificate_error(struct client_state *csp) } strlcat(message, message_end, message_len); + if (0 == strcmpic(csp->http->gpc, "HEAD")) + { + /* Cut off body */ + char *header_end = strstr(message, "\r\n\r\n"); + if (header_end != NULL) + { + header_end[3] = '\0'; + } + } + /* * 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 +503,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 @@ -647,42 +675,48 @@ extern int get_certificate_valid_to_date(char *buffer, size_t buffer_size, const /********************************************************************* * - * Function : host_is_ip_address + * Function : enforce_sane_certificate_state * - * Description : Checks whether or not a host is specified by - * IP address. Does not actually validate the - * address. + * Description : Makes sure the certificate state is sane. * * Parameters : - * 1 : host = The host name to check + * 1 : certificate = Path to the potentionally existing certifcate. + * 2 : key = Path to the potentionally existing key. * - * Returns : 1 => Yes - * 0 => No + * Returns : -1 => Error + * 0 => Certificate state is sane * *********************************************************************/ -extern int host_is_ip_address(const char *host) +extern int enforce_sane_certificate_state(const char *certificate, const char *key) { - const char *p; + const int certificate_exists = file_exists(certificate); + const int key_exists = file_exists(key); - if (NULL != strstr(host, ":")) + if (!certificate_exists && key_exists) { - /* Assume an IPv6 address. */ - return 1; - } + 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); - for (p = host; *p; p++) + return -1; + } + } + if (certificate_exists && !key_exists) { - if ((*p != '.') && !privoxy_isdigit(*p)) + 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)) { - /* Not a dot or digit so it can't be an IPv4 address. */ - return 0; + log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E", certificate); + + return -1; } } - /* - * Host only consists of dots and digits so - * assume that is an IPv4 address. - */ - return 1; + return 0; }