From 416501a4667681f61c8d9d9cb9809a26d165b619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:14:00 +0200 Subject: [PATCH 01/83] Created ssl connection with server. --- GNUmakefile.in | 15 ++- jcc.c | 93 +++++++++++++---- jcc.h | 2 + project.h | 37 +++++++ ssl.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++++ ssl.h | 43 ++++++++ 6 files changed, 431 insertions(+), 26 deletions(-) create mode 100644 ssl.c create mode 100644 ssl.h diff --git a/GNUmakefile.in b/GNUmakefile.in index 9c496f3b..7980f9fe 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -231,6 +231,11 @@ W32_HDRS = @WIN_ONLY@w32log.h w32taskbar.h win32.h w32res.h w32svrapi.h W32_LIB = @WIN_ONLY@-lwsock32 -lcomctl32 W32_INIS = @WIN_ONLY@config.txt trust.txt +SSL_SRC = ssl.c +SSL_OBJS = $(SSL_SRC:.c=.o) +SSL_HDRS = $(SSL_SRC:.c=.h) project.h +SSL_LIB = mbedtls/library/libmbedx509.a mbedtls/library/libmbedtls.a mbedtls/library/libmbedcrypto.a + PCRS_SRC = @STATIC_PCRS_ONLY@pcrs.c PCRS_OBJS = @STATIC_PCRS_ONLY@$(PCRS_SRC:.c=.@OBJEXT@) PCRS_HDRS = @STATIC_PCRS_ONLY@$(PCRS_SRC:.c=.h) @@ -255,11 +260,10 @@ SOCKET_LIB = @SOCKET_LIB@ # PThreads library, if needed. PTHREAD_LIB = @PTHREAD_ONLY@@PTHREAD_LIB@ -SRCS = $(C_SRC) $(CLIENT_TAG_SRC) $(FUZZ_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC) -OBJS = $(C_OBJS) $(CLIENT_TAG_OBJS) $(FUZZ_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS) -HDRS = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS) -LIBS = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB) - +SRCS = $(C_SRC) $(CLIENT_TAG_SRC) $(FUZZ_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC) $(SSL_SRC) +OBJS = $(C_OBJS) $(CLIENT_TAG_OBJS) $(FUZZ_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS) $(SSL_OBJS) +HDRS = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS) $(SSL_HDRS) +LIBS = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB) $(SSL_LIB) ############################################################################# # Compiler switches @@ -276,6 +280,7 @@ SPECIAL_CFLAGS = @SPECIAL_CFLAGS@ OTHER_CFLAGS = CFLAGS = @CFLAGS@ @CPPFLAGS@ $(OTHER_CFLAGS) $(SPECIAL_CFLAGS) -Wall \ + -Imbedtls/include \ @STATIC_PCRE_ONLY@ -Ipcre LDFLAGS = @LDFLAGS@ $(DEBUG_CFLAGS) $(SPECIAL_CFLAGS) diff --git a/jcc.c b/jcc.c index 34327f28..b41e2823 100644 --- a/jcc.c +++ b/jcc.c @@ -112,6 +112,7 @@ #include "project.h" #include "list.h" #include "jcc.h" +#include "ssl.h" #include "filters.h" #include "loaders.h" #include "parsers.h" @@ -190,6 +191,8 @@ privoxy_mutex_t log_mutex; privoxy_mutex_t log_init_mutex; privoxy_mutex_t connection_reuse_mutex; +privoxy_mutex_t rng_mutex; + #ifdef FEATURE_EXTERNAL_FILTERS privoxy_mutex_t external_filter_mutex; #endif @@ -941,8 +944,6 @@ static void build_request_line(struct client_state *csp, const struct forward_sp { struct http_request *http = csp->http; - assert(http->ssl == 0); - /* * Downgrade http version from 1.1 to 1.0 * if +downgrade action applies. @@ -2830,6 +2831,7 @@ static void chat(struct client_state *csp) struct http_request *http; /* Skeleton for HTTP response, if we should intercept the request */ struct http_response *rsp; + int ret = 0; http = csp->http; @@ -2862,31 +2864,49 @@ static void chat(struct client_state *csp) * Note that the path and/or the HTTP version may * have been altered by now. * - * connect = Open a socket to the host:port of the server - * and short-circuit server and client socket. + * SSL proxy = Open a socket to the host:port of the server + * and create SSL/TLS connection with server and + * with client. Then behave like mediator between + * client and server over SSL/TLS. * - * pass = Pass the request unchanged if forwarding a CONNECT - * request to a parent proxy. Note that we'll be sending - * the CFAIL message ourselves if connecting to the parent - * fails, but we won't send a CSUCCEED message if it works, - * since that would result in a double message (ours and the - * parent's). After sending the request to the parent, we simply - * tunnel. + * SSL proxy = Pass the request unchanged if forwarding a CONNECT + * with request to a parent proxy. Note that we'll be sending + * forwarding the CFAIL message ourselves if connecting to the parent + * fails, but we won't send a CSUCCEED message if it works, + * since that would result in a double message (ours and the + * parent's). After sending the request to the parent, we + * must parse answer and send it to client. If connection + * with server is established, we do SSL/TLS proxy. Otherwise + * we send parent response to client and close connections. * * here's the matrix: * SSL * 0 1 * +--------+--------+ * | | | - * 0 | create | connect| - * | w/path | | + * 0 | create | SSL | + * | w/path | proxy | * Forwarding +--------+--------+ - * | | | - * 1 | create | pass | - * | w/url | | + * | | SSL | + * 1 | create | proxy | + * | w/url |+forward| * +--------+--------+ * */ + + /* + * Presetting SSL client and server flags + */ + if (http->ssl) + { + http->client_ssl = 1; + http->server_ssl = 1; + } + else + { + http->client_ssl = 0; + http->server_ssl = 0; + } if (http->ssl && connect_port_is_forbidden(csp)) { @@ -2898,13 +2918,12 @@ static void chat(struct client_state *csp) csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport); csp->action->flags |= ACTION_BLOCK; http->ssl = 0; + http->client_ssl = 0; + http->server_ssl = 0; } - if (http->ssl == 0) - { - freez(csp->headers->first->str); - build_request_line(csp, fwd, &csp->headers->first->str); - } + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); /* * We have a request. Check if one of the crunchers wants it. @@ -2964,6 +2983,9 @@ static void chat(struct client_state *csp) } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + /* + * Connecting to destination server + */ csp->server_connection.sfd = forwarded_connect(fwd, http, csp); if (csp->server_connection.sfd == JB_INVALID_SOCKET) @@ -3005,6 +3027,33 @@ static void chat(struct client_state *csp) return; } + + /* + * Creating SSL/TLS connections with destinantion server or parent + * proxy. If forwarding is enabled, we must send client request to + * parent proxy and receive, parse and resend parent proxy answer. + */ + if (http->ssl) + { + /* + * Parent proxy is not used, we can just create SSL/TLS connection + * with destination server + */ + + ret = create_server_ssl_connection(csp); + + if (ret != 0) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + return; + } + log_error(LOG_LEVEL_INFO, "SSL CONNECTION CREATED SUCCESSFULLY"); + } + #ifdef FEATURE_CONNECTION_KEEP_ALIVE save_connection_destination(csp->server_connection.sfd, http, fwd, &csp->server_connection); @@ -3582,6 +3631,8 @@ static void initialize_mutexes(void) /* * Prepare global mutex semaphores */ + privoxy_mutex_init(&rng_mutex); + privoxy_mutex_init(&log_mutex); privoxy_mutex_init(&log_init_mutex); privoxy_mutex_init(&connection_reuse_mutex); diff --git a/jcc.h b/jcc.h index 866c2a7b..e0535bb1 100644 --- a/jcc.h +++ b/jcc.h @@ -102,6 +102,8 @@ extern privoxy_mutex_t resolver_mutex; extern privoxy_mutex_t rand_mutex; #endif /* ndef HAVE_RANDOM */ +extern privoxy_mutex_t rng_mutex; + #endif /* FEATURE_PTHREAD */ /* Functions */ diff --git a/project.h b/project.h index 779c5c71..5d018351 100644 --- a/project.h +++ b/project.h @@ -44,6 +44,15 @@ /* Needed for pcre choice */ #include "config.h" +/* Mbedtls incldues */ +#include "mbedtls/net_sockets.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + /* Need for struct sockaddr_storage */ #ifdef HAVE_RFC2553 # ifndef _WIN32 @@ -259,6 +268,21 @@ struct map struct map_entry *last; }; +/* + * Srtuct of atributes necessary for SSL/TLS connection + */ +typedef struct { + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_net_context socket_fd; + mbedtls_x509_crt server_cert; + mbedtls_x509_crt ca_cert; + mbedtls_pk_context prim_key; + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_context cache; +#endif +} mbedtls_connection_attr; /** * A HTTP request. This includes the method (GET, POST) and @@ -291,6 +315,9 @@ struct http_request char **dvec; /**< List of pointers to the strings in dbuffer. */ int dcount; /**< How many parts to this domain? (length of dvec) */ #endif /* ndef FEATURE_EXTENDED_HOST_PATTERNS */ + + int client_ssl; + int server_ssl; }; /** @@ -947,6 +974,9 @@ struct client_state /** An I/O buffer used for buffering data read from the server */ /* XXX: should be renamed to server_iob */ struct iob iob[1]; + + /* attributes for connection to server */ + mbedtls_connection_attr mbedtls_server_attr; /** An I/O buffer used for buffering data read from the client */ struct iob client_iob[1]; @@ -1010,6 +1040,13 @@ struct client_state * or NULL. Currently only used for socks errors. */ char *error_message; + + /* + * Flag if SSL connection with server opened. + * Thanks to this flag, we can call function to close connection + * and we don't have to care about more details. + */ + int ssl_with_server_is_opened; }; /** diff --git a/ssl.c b/ssl.c new file mode 100644 index 00000000..e1f9cd02 --- /dev/null +++ b/ssl.c @@ -0,0 +1,267 @@ +const char ssl_rcs[] = "$Id: ssl.c,v 1.0 2018/11/03 21:00:00 vaclavsvec Exp $"; +/********************************************************************* + * + * File : $Source: /cvsroot/ijbswa/current/ssl.c,v $ + * + * Purpose : File with SSL/TLS extension. Contains methods for + * creating, using and closing SSL/TLS connections. + * + * Copyright : Written by Vaclav Svec. FIT CVUT. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * The GNU General Public License should be included with + * this file. If not, you can view it at + * http://www.gnu.org/copyleft/gpl.html + * or write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + *********************************************************************/ + +#include + +#include "mbedtls/error.h" + +#include "project.h" +#include "errlog.h" +#include "jcc.h" +#include "ssl.h" + + +/* + * Macros for ssl.c + */ +#define ERROR_BUF_SIZE 1024 /* Size of buffer for error messages */ + +static void free_server_ssl_structures(struct client_state *csp); +static int seed_rng(struct client_state *csp); + + +/********************************************************************* + * + * 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_server_ssl_connection + * + * Description : Creates SSL/TLS secured connection with server. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on success, negative value if connection wasn't created + * successfully. + * + **********************************************************************/ +extern int create_server_ssl_connection(struct client_state *csp) +{ + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, ERROR_BUF_SIZE); + + int auth_mode = MBEDTLS_SSL_VERIFY_NONE; + + /* + * Initializing mbedtls structures for SSL/TLS connection + */ + mbedtls_net_init(&(csp->mbedtls_server_attr.socket_fd)); + mbedtls_ssl_init(&(csp->mbedtls_server_attr.ssl)); + mbedtls_ssl_config_init(&(csp->mbedtls_server_attr.conf)); + mbedtls_x509_crt_init( &(csp->mbedtls_server_attr.ca_cert)); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init(&(csp->mbedtls_server_attr.cache)); +#endif + + /* + * Setting socket fd in mbedtls_net_context structure. This structure + * can't be setted by mbedtls functions, because we already have created + * TCP connection when starting this function. + */ + csp->mbedtls_server_attr.socket_fd.fd = csp->server_connection.sfd; + + /* + * Seed the RNG + */ + ret = seed_rng(csp); + if (ret != 0) + { + ret = -1; + goto exit; + } + + /* + * Set SSL/TLS options + */ + ret = mbedtls_ssl_config_defaults(&(csp->mbedtls_server_attr.conf), + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_ssl_config_defaults failed: %s", + err_buf); + ret = -1; + goto exit; + } + + mbedtls_ssl_conf_authmode(&(csp->mbedtls_server_attr.conf), auth_mode); + mbedtls_ssl_conf_ca_chain(&(csp->mbedtls_server_attr.conf), + &(csp->mbedtls_server_attr.ca_cert), NULL); + + mbedtls_ssl_conf_rng(&(csp->mbedtls_server_attr.conf), + mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&(csp->mbedtls_server_attr.conf), + ssl_debug_callback, stdout); + + ret = mbedtls_ssl_setup(&(csp->mbedtls_server_attr.ssl), + &(csp->mbedtls_server_attr.conf)); + if ( ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_ssl_setup failed: %s", err_buf); + ret = -1; + goto exit; + } + + mbedtls_ssl_set_bio(&(csp->mbedtls_server_attr.ssl), + &(csp->mbedtls_server_attr.socket_fd), mbedtls_net_send, + mbedtls_net_recv, NULL); + + /* + * Handshake with server + */ + log_error(LOG_LEVEL_CONNECT, + "Performing the SSL/TLS handshake with server"); + + while ((ret = mbedtls_ssl_handshake(&(csp->mbedtls_server_attr.ssl))) != 0) + { + if (ret != MBEDTLS_ERR_SSL_WANT_READ + && ret != MBEDTLS_ERR_SSL_WANT_WRITE) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "mbedtls_ssl_handshake with server failed: %s", err_buf); + + ret = -1; + goto exit; + } + } + + log_error(LOG_LEVEL_CONNECT, "Server successfully connected over SSL/TLS"); + + csp->ssl_with_server_is_opened = 1; + +exit: + /* Freeing structures if connection wasn't created successfully */ + if (ret < 0) + { + free_server_ssl_structures(csp); + } + + return ret; +} + + +/********************************************************************* + * + * Function : free_server_ssl_structures + * + * Description : Frees structures used for SSL communication with server + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +static void free_server_ssl_structures(struct client_state *csp) +{ + /* + * We can't use function mbedtls_net_free, because this function + * inter alia close TCP connection on setted fd. Instead of this + * function, we change fd to -1, which is the same what does + * rest of mbedtls_net_free function. + */ + csp->mbedtls_server_attr.socket_fd.fd = -1; + + mbedtls_x509_crt_free(&(csp->mbedtls_server_attr.ca_cert)); + mbedtls_ssl_free(&(csp->mbedtls_server_attr.ssl)); + mbedtls_ssl_config_free(&(csp->mbedtls_server_attr.conf)); +} + + +/********************************************************************* + * + * Function : seed_rng + * + * Description : Seeding the RNG for all SSL uses + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : -1 => RNG wasn't seed successfully + * 0 => RNG is seeded successfully + * + *********************************************************************/ +static int seed_rng(struct client_state *csp) { + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, ERROR_BUF_SIZE); + + if (rng_seeded == 0) + { + privoxy_mutex_lock(&rng_mutex); + if (rng_seeded == 0) + { + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, + &entropy, NULL, 0); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "mbedtls_ctr_drbg_seed failed: %s", err_buf); + privoxy_mutex_unlock(&rng_mutex); + return -1; + } + rng_seeded = 1; + } + privoxy_mutex_unlock(&rng_mutex); + } + return 0; +} diff --git a/ssl.h b/ssl.h new file mode 100644 index 00000000..075ddbe0 --- /dev/null +++ b/ssl.h @@ -0,0 +1,43 @@ +#ifndef SSL_H_INCLUDED +#define SSL_H_INCLUDED +#define SSL_H_VERSION "$Id: ssl.h,v 1.0 2018/11/03 21:00:00 vaclavsvec Exp $" +/********************************************************************* +* +* File : $Source: /cvsroot/ijbswa/current/ssl.h,v $ +* +* Purpose : File with SSL/TLS extension. Contains methods for +* creating, using and closing SSL/TLS connections. +* +* Copyright : Written by Vaclav Svec. FIT CVUT. +* +* This program is free software; you can redistribute it +* and/or modify it under the terms of the GNU General +* Public License as published by the Free Software +* Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will +* be useful, but WITHOUT ANY WARRANTY; without even the +* implied warranty of MERCHANTABILITY or FITNESS FOR A +* PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* The GNU General Public License should be included with +* this file. If not, you can view it at +* http://www.gnu.org/copyleft/gpl.html +* or write to the Free Software Foundation, Inc., 59 +* Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*********************************************************************/ + +#include "project.h" + +/* Variables for one common RNG for all SSL use */ +static mbedtls_ctr_drbg_context ctr_drbg; +static mbedtls_entropy_context entropy; +static int rng_seeded; + +/* Function to create SSL/TLS connections */ +extern int create_server_ssl_connection(struct client_state *csp); + +#endif /* ndef SSL_H_INCLUDED */ -- 2.26.2 From a9a26b007eaa59e5a63f08f53ebe45880ac484cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:16:10 +0200 Subject: [PATCH 02/83] Created ssl connection with client. --- CA/cacert.crt | 37 ++++++ CA/webpagesCerts/privoxy.crt | 26 ++++ CA/webpagesCerts/privoxy.key | 27 ++++ jcc.c | 26 +++- project.h | 10 +- ssl.c | 232 +++++++++++++++++++++++++++++++++++ ssl.h | 3 +- 7 files changed, 351 insertions(+), 10 deletions(-) create mode 100644 CA/cacert.crt create mode 100644 CA/webpagesCerts/privoxy.crt create mode 100644 CA/webpagesCerts/privoxy.key diff --git a/CA/cacert.crt b/CA/cacert.crt new file mode 100644 index 00000000..20b83f01 --- /dev/null +++ b/CA/cacert.crt @@ -0,0 +1,37 @@ +Bag Attributes + localKeyID: 01 00 00 00 +subject=/emailAddress=http://www.privoxy.org/O=Privoxy/CN=Privoxy Root +issuer=/emailAddress=http://www.privoxy.org/O=Privoxy/CN=Privoxy Root +-----BEGIN CERTIFICATE----- +MIIFwzCCA6ugAwIBAgIQQ+ZGTxpoWqpDjOj1BV4AtTANBgkqhkiG9w0BAQsFADBQ +MSUwIwYJKoZIhvcNAQkBFhZodHRwOi8vd3d3LnByaXZveHkub3JnMRAwDgYDVQQK +EwdQcml2b3h5MRUwEwYDVQQDEwxQcml2b3h5IFJvb3QwHhcNMTcwNDIyMTEwMzE2 +WhcNMzcwNDIyMTEwMzE1WjBQMSUwIwYJKoZIhvcNAQkBFhZodHRwOi8vd3d3LnBy +aXZveHkub3JnMRAwDgYDVQQKEwdQcml2b3h5MRUwEwYDVQQDEwxQcml2b3h5IFJv +b3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDYn0UgXA42PysYnIX5 +t8gPtXxqtOpZsfwyz2OVlI14qgAk+5nWSq2G70k73I3Zq4F+e3YhjeOP9cQKESP3 +RqaFAH9FCyfH06WzejtOO+7F/7kYcJbtWvfiY2X92DBZc7T7CIJ+97AbGQv6RR3H +gn3e9PnzlJibt4w6O+jcWDj+tmRLQ3C949t+3zURPALHfyrCEBxxwSZNKbuB5R2S +mrA92tA8eprn0ICFO1qtMo0wMENrR6oA/emGSSBg5kPLjaHF6qdbUhrqqfjTxRUY +XDbvJZ06qsOMGZ9BWSutvnkJeFofXCTREFOyKAeUf3b+gmW+/vT8/hsl7P120fta +WCVWrC1tJ5H9lbdn814KNuH+48IBtv4PF93RtKY5iC5nhJR41WIlQ0JzVESfJU4m +Xf/nQz9Z2UYXcEybXsFw10Wkf9UATykm0NByFj1+4Fq8C4k8Zro0SzERWrHOcOR5 +AYJf50xfjla6EG02terkiP6PGGcDzv3QwHUd4AXBYOKayj12RYwgZ5239jqvSMtM +2FSF59f2FYkQOU6MKBj6fjVrOgXtuOtlanjskn+rGQNxE1sKsulkecWmLFx8J9wO +lCVQtq8+Fm2nRx/vH38bzWSAtm/IopMB+aARnDa/r9nTln4MhLgLKeUpcWgJNIKO +/qN8WIBYWnILK+EdAL9B1NusrwIDAQABo4GYMIGVMA8GA1UdEwEB/wQFMAMBAf8w +gYEGA1UdAQR6MHiAENPVzdWQWPQWYpUbhrMu1WKhUjBQMSUwIwYJKoZIhvcNAQkB +FhZodHRwOi8vd3d3LnByaXZveHkub3JnMRAwDgYDVQQKEwdQcml2b3h5MRUwEwYD +VQQDEwxQcml2b3h5IFJvb3SCEEPmRk8aaFqqQ4zo9QVeALUwDQYJKoZIhvcNAQEL +BQADggIBAIHLesyN186WXzNWvrqmhzyQZQ9OCEUCite/TFgY3OA5IADyrPo+Pa7v +yNnLMjNXloIjf/NB8FFpHCPNWSQQ4Mt4wyAxUyoA3Fk6XPeajIU/kslQROKWr++m +eFQBo0NlK34JK8+aItfsWa8lJ5ILSbnf5/Sv7Zpf18qUBTE0YBxNeGkGWwE1vO8s +Gu/LvlRlhY3UD1StiCnkjudOjQf3m8Yh9v2PtXjZ+od83Jc4pvrnIXvnmlPFnZDq +XrbQBS5O1OBDIzX5g4CP1X1iwG9XRKVEbUW2D7ziT5Nc//DEqsk5pm4qYw1oVDcq +gOw89fNdBJ1+rEpN4uBA2B9mL2h0utu9xrPfqws4CGHX4GSrfrRGDcSo/OkcnyVO +JuoKQ1JzShskswdnOD1EUq0W1U1JinMVIP3vYorvEW6rU0EnnWRy5qXOoDsSBePp +nw2+Uv4nDRRerCudzyE6+jyRIaEkJBQrD22FyfmtR2oTTr04fA67c2yGQwtOtdXL +UCZIrVngFHSpcAq/JUpcS5J/xxrbswmY+GlimlkBPaehrPZ0bnjEuplz28ok2zue +o4X0A+d9nx5IEbyIfopQoB9A5j8WucEStEGlT+1DvuGXee3iYMYX9RhPNk2kH+/y +jwViE6pvvMBEGb4Liupg8KuP79kMdJf52MSurnQbSyiia7fdEmOQ +-----END CERTIFICATE----- diff --git a/CA/webpagesCerts/privoxy.crt b/CA/webpagesCerts/privoxy.crt new file mode 100644 index 00000000..cb8b4c6c --- /dev/null +++ b/CA/webpagesCerts/privoxy.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEZzCCAk8CCQCJvYh0qfKN4jANBgkqhkiG9w0BAQsFADBQMSUwIwYJKoZIhvcN +AQkBFhZodHRwOi8vd3d3LnByaXZveHkub3JnMRAwDgYDVQQKEwdQcml2b3h5MRUw +EwYDVQQDEwxQcml2b3h5IFJvb3QwHhcNMTgxMTE5MDcyODAyWhcNMjMxMTE4MDcy +ODAyWjCBmjELMAkGA1UEBhMCREUxFDASBgNVBAgMC0RldXRzY2hsYW5kMQ8wDQYD +VQQHDAZCZXJsaW4xGDAWBgNVBAoMD3d3dy5wcml2b3h5Lm9yZzEYMBYGA1UECwwP +d3d3LnByaXZveHkub3JnMRgwFgYDVQQDDA93d3cucHJpdm94eS5vcmcxFjAUBgkq +hkiG9w0BCQEWB3ByaXZveHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQD2DR0rtZ8i9CiJy08cQn6iRa0jxIP8fBpi5qEyz0p0Erd5dJjj9ZAj/R1AKs+z +09wu86AWDLy7tah3j8G+ujeEdC1TR5wUmYESHxxD73zwnxg1y+nBP0mGF+82cPBz +AbHrw/HvzGFzsbWX804XEYKIpCHwuT5z/7ka3PnLK15f99ZlZOPYp5g/n2uIiIeJ +uNE0MTV61MkxwWzjmqVCHs804MiNbkpXQvmgKXZQdyAeZIH0ABcr1GZ3PD5ynHpr +JgAhqTibPywRboSbHsJzn8pEASUAP8J8Bu7O0G85WagSPYLelXFfjDbrT16fVndl +9z0E2nEN76YKtPdPEHzTuSIZAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAClP56oa +ktwN+l2fIc9VWDZ+Gk0g3oxj1TTgUVTb5BCyyhKIlKkjBGbanpIBQnnspxGZS05f +u5A75kJRvQOB+0od5xawE8Sf7gorB/THNlMvBmEseWpiBMJK0Gp5++vESXdNm+YI +Cl+Wi9xN3ok0WmMhuZjjXlj0Gy0riwspj7ezk1FOPa9h8H/ouPPbntTWmUjA7WuE +DI8yEExAEutQrWQKM6TBcjww/u5NeV4sfKd9P13O7q8GrfzyZsLLcPXYKcRCMWKh +eVUJ1x51Qi23b8LZn2IijDly42cciJYmCCdKviMjCbWPj5EaiVGzexoem7n4nVei +EO67loXFBjgBDacsIgR8C8HMekReGMSZ1aZKcECJUHo2So2LAWXj/Q1Evm9AvR+L +Jjjk0Q1vRPprBkpbjeTJwyOA2gwNgmJTigSeDnysNLfm9AUmEqp+eVCZxU8XEaEe +p40E58RhHvz6b37MOyKcpEiHfzVbO91JqWM3rLcXkkSpfdFxljIwrQf9qLq0BEHV +lw7s6u6kAbwJAPY0/bYP0trF3p3GtldrBA24jjPD2+YLj2riGmcN7H4yY/tmqKop +Ej21QR5RE7G7gv2gjXodOKw9pQaZaVUCnXDD2cryW41PikR17M4OQfu82dRP5I/d +cjjGCP7Bt4AAIf6ANecMKoyj5zmUpmudrcHF +-----END CERTIFICATE----- diff --git a/CA/webpagesCerts/privoxy.key b/CA/webpagesCerts/privoxy.key new file mode 100644 index 00000000..659a3131 --- /dev/null +++ b/CA/webpagesCerts/privoxy.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA9g0dK7WfIvQoictPHEJ+okWtI8SD/HwaYuahMs9KdBK3eXSY +4/WQI/0dQCrPs9PcLvOgFgy8u7Wod4/Bvro3hHQtU0ecFJmBEh8cQ+988J8YNcvp +wT9JhhfvNnDwcwGx68Px78xhc7G1l/NOFxGCiKQh8Lk+c/+5Gtz5yyteX/fWZWTj +2KeYP59riIiHibjRNDE1etTJMcFs45qlQh7PNODIjW5KV0L5oCl2UHcgHmSB9AAX +K9Rmdzw+cpx6ayYAIak4mz8sEW6Emx7Cc5/KRAElAD/CfAbuztBvOVmoEj2C3pVx +X4w2609en1Z3Zfc9BNpxDe+mCrT3TxB807kiGQIDAQABAoIBAQC4EPlokHcbC/Ij +mw90gZ4AQQWUQ1fFkwWeRRAEVaRKDxJobrxNlI+fDKRMM3qr+Wq3SRPSSvcJqYz8 +3HNA/ke3871QlrqBgpBXASUBAXDDBRF0dTZKldCn2tHeNUD7mCIE0NH15Txl82R4 +5s/dXAD9vWOSlNHOr1hHa1YHEkuImASprUeCpmL1T8kxD68HsvwPjjikUtBQ6nQv +r/9HTZDvJMmBrsnYYR1UxcWqWUq38j79AgZ+rmZQBO1XnLr8WHbvhZgscs8tG/cS +ZkX395ki9LNe/X/gnbpmOpvym0Jzlaasvn/Y/A9u5hvz9ZWRheiNfe3GNRU45BmQ +XvEo+qGdAoGBAP2CsOiRDmNEsucIbg8xwa2w3wgI2a97h8vj5qCIsrSQ0845D1Eh +Q6e2w1gden0JXTNCXnfD4sApYKKPCve5fU7Gtit9DEgqDBP/BL98AuCTmzhqDygz +yAclDsgZPiv5SxqPWk5tFfyYnBCqi16YLN+6XyXYRz4SikrpFzR883FfAoGBAPh3 +q7WlBisbkMbEyK75sGhze31pUNoFHqH0Iuj28wjWLfxJBIWehMErUOUhrBaNOEVT +MXRgUiklJh6VRRrR7m+4PGlIz/1ZZHmxh4Bs+I/ihsbfYcJ2QAxjDkdxhuHwysuB +8+0hckXbmQpjYQsOB40GW6I+I3OBC1tnSCBLeUeHAoGBAIMvsFCJUAK6uEGqMRoX +y3wQfTnxKoUOzdUK2HvWgXPDRnf/OxfmuNX/U9MzXgF6aQpvm+cqLRr3zpQQpcJP +8LJlTjvu9/4YFCv82f4lNG/2smpdJ/7L3QUlfiK6PVwQI3dZG4heFvSiHJDbUEfh +Q8d68GXrJ+LNQVdGi8WTq37NAoGBAJesRa9ei4NpElmj6nWVijBYvntx/J76HRbz +9xOLHBS62dt1n0MJ3zQkAv+8LFaf4ke/XyMRYVYojTqCGGsk145vQsFqZzzagtEe +o/6rhpgeyfNAjWat1K87EI5gKNxnpwPP0l1g22b1hFipDaY37DgUN3+0uuNZVNt5 +ErhUGjalAoGAPOXVZASlWyRakPzRyUBllSihNVq4YZXxvGo2Xm17I29H3zFthObE +1xdb2JnC+4kSzCTibgJAt3/I8dTUYFd3zasj7gTiFPZFInnDsKkseHNMCgXIbbSR +RZqtM057KcmgkNMSGgYuN4NG9os1dP5X2qRv2vKfQJ59SKBpiRl2Mmg= +-----END RSA PRIVATE KEY----- diff --git a/jcc.c b/jcc.c index b41e2823..407dbbcd 100644 --- a/jcc.c +++ b/jcc.c @@ -3051,7 +3051,7 @@ static void chat(struct client_state *csp) } return; } - log_error(LOG_LEVEL_INFO, "SSL CONNECTION CREATED SUCCESSFULLY"); + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); } #ifdef FEATURE_CONNECTION_KEEP_ALIVE @@ -3084,16 +3084,30 @@ static void chat(struct client_state *csp) else { /* - * We're running an SSL tunnel and we're not forwarding, - * so just ditch the client headers, send the "connect succeeded" - * message to the client, flush the rest, and get out of the way. + * Creating an SSL proxy. If forwarding is disabled, we must send + * CSUCCEED mesage to client. Then SSL/TLS connection with client + * is created. */ list_remove_all(csp->headers); - if (write_socket_delayed(csp->cfd, CSUCCEED, - strlen(CSUCCEED), get_write_delay(csp))) + + if (fwd->forward_host == NULL) { + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + return; + } + } + + ret = create_client_ssl_connection(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Can't open secure connection with client"); return; } + + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); clear_iob(csp->client_iob); } diff --git a/project.h b/project.h index 5d018351..b4ffd454 100644 --- a/project.h +++ b/project.h @@ -976,7 +976,10 @@ struct client_state struct iob iob[1]; /* attributes for connection to server */ - mbedtls_connection_attr mbedtls_server_attr; + mbedtls_connection_attr mbedtls_server_attr; + + /* attributes for connection to client */ + mbedtls_connection_attr mbedtls_client_attr; /** An I/O buffer used for buffering data read from the client */ struct iob client_iob[1]; @@ -1042,11 +1045,12 @@ struct client_state char *error_message; /* - * Flag if SSL connection with server opened. - * Thanks to this flag, we can call function to close connection + * Flags if SSL connection with server or client is opened. + * Thanks to this flags, we can call function to close connections * and we don't have to care about more details. */ int ssl_with_server_is_opened; + int ssl_with_client_is_opened; }; /** diff --git a/ssl.c b/ssl.c index e1f9cd02..3310728e 100644 --- a/ssl.c +++ b/ssl.c @@ -33,6 +33,7 @@ const char ssl_rcs[] = "$Id: ssl.c,v 1.0 2018/11/03 21:00:00 vaclavsvec Exp $"; #include "mbedtls/error.h" #include "project.h" +#include "miscutil.h" #include "errlog.h" #include "jcc.h" #include "ssl.h" @@ -43,6 +44,7 @@ const char ssl_rcs[] = "$Id: ssl.c,v 1.0 2018/11/03 21:00:00 vaclavsvec Exp $"; */ #define ERROR_BUF_SIZE 1024 /* Size of buffer for error messages */ +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); @@ -73,6 +75,236 @@ static void ssl_debug_callback(void *ctx, int level, const char *file, int line, } +/********************************************************************* + * + * Function : create_client_ssl_connection + * + * Description : Creates SSL/TLS secured connection with client + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on success, negative value if connection wasn't created + * successfully. + * + *********************************************************************/ +extern int create_client_ssl_connection(struct client_state *csp) +{ + /* Paths to certificates file and key file */ + char *key_file = NULL; + char *ca_file = NULL; + char *cert_file = NULL; + + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, ERROR_BUF_SIZE); + + /* + * Initializing mbedtls structures for SSL/TLS connection + */ + mbedtls_net_init(&(csp->mbedtls_client_attr.socket_fd)); + mbedtls_ssl_init(&(csp->mbedtls_client_attr.ssl)); + mbedtls_ssl_config_init(&(csp->mbedtls_client_attr.conf)); + mbedtls_x509_crt_init(&(csp->mbedtls_client_attr.server_cert)); + mbedtls_pk_init(&(csp->mbedtls_client_attr.prim_key)); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init(&(csp->mbedtls_client_attr.cache)); +#endif + + /* + * Preparing paths to certificates files and key file + */ + size_t size = strlen(basedir) + 1; + ca_file = (char *)malloc(size + 14); + memset(ca_file, 0, size + 14); + strlcpy(ca_file, basedir, size + 14); + strlcat(ca_file, "/CA/cacert.crt", size + 14); + + cert_file = (char *)malloc(size + 29); + memset(cert_file, 0, size + 29); + strlcpy(cert_file, basedir, size + 29); + strlcat(cert_file, "/CA/webpagesCerts/privoxy.crt", size + 29); + + key_file = (char *)malloc(size + 29); + memset(key_file, 0, size + 29); + strlcpy(key_file, basedir, size + 29); + strlcat(key_file, "/CA/webpagesCerts/privoxy.key", size + 29); + + /* + * Seed the RNG + */ + ret = seed_rng(csp); + if (ret != 0) + { + ret = -1; + goto exit; + } + + /* + * Loading CA file, webpage certificate and key files + */ + ret = mbedtls_x509_crt_parse_file(&(csp->mbedtls_client_attr.server_cert), + cert_file); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Loading webpage certificate %s failed: %s", cert_file, err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_x509_crt_parse_file(&(csp->mbedtls_client_attr.server_cert), + ca_file); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Loading CA certificate %s failed: %s", ca_file, err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_pk_parse_keyfile(&(csp->mbedtls_client_attr.prim_key), + key_file, NULL); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Loading and parsing webpage certificat private key %s failed: %s", + key_file, err_buf); + ret = -1; + goto exit; + } + + /* + * Setting SSL parameters + */ + ret = mbedtls_ssl_config_defaults(&(csp->mbedtls_client_attr.conf), + MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "mbedtls_ssl_config_defaults failed: %s", err_buf); + ret = -1; + goto exit; + } + + mbedtls_ssl_conf_rng(&(csp->mbedtls_client_attr.conf), + mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&(csp->mbedtls_client_attr.conf), + ssl_debug_callback, stdout); + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_conf_session_cache(&(csp->mbedtls_client_attr.conf), + &(csp->mbedtls_client_attr.cache), mbedtls_ssl_cache_get, + mbedtls_ssl_cache_set); +#endif + + /* + * Setting certificates + */ + ret = mbedtls_ssl_conf_own_cert(&(csp->mbedtls_client_attr.conf), + &(csp->mbedtls_client_attr.server_cert), + &(csp->mbedtls_client_attr.prim_key)); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "mbedtls_ssl_conf_own_cert failed: %s", err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_ssl_setup(&(csp->mbedtls_client_attr.ssl), + &(csp->mbedtls_client_attr.conf)); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_ssl_setup failed: %s", err_buf); + ret = -1; + goto exit; + } + + mbedtls_ssl_set_bio(&(csp->mbedtls_client_attr.ssl), + &(csp->mbedtls_client_attr.socket_fd), mbedtls_net_send, + mbedtls_net_recv, NULL); + mbedtls_ssl_session_reset(&(csp->mbedtls_client_attr.ssl)); + + /* + * Setting socket fd in mbedtls_net_context structure. This structure + * can't be setted by mbedtls functions, because we already have created + * TCP connection when starting this function. + */ + csp->mbedtls_client_attr.socket_fd.fd = csp->cfd; + + /* + * Handshake with client + */ + log_error(LOG_LEVEL_CONNECT, + "Performing the SSL/TLS handshake with client"); + while ((ret = mbedtls_ssl_handshake(&(csp->mbedtls_client_attr.ssl))) != 0) + { + if (ret != MBEDTLS_ERR_SSL_WANT_READ + && ret != MBEDTLS_ERR_SSL_WANT_WRITE) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "medtls_ssl_handshake with client failed: %s : %d", err_buf, ret); + ret = -1; + goto exit; + } + } + + log_error(LOG_LEVEL_CONNECT, "Client successfully connected over SSL/TLS"); + csp->ssl_with_client_is_opened = 1; + +exit: + + /* Freeing structures if connection wasn't created successfully */ + if (ret < 0) + { + free_client_ssl_structures(csp); + } + return ret; +} + + +/********************************************************************** + * + * Function : free_client_ssl_structures + * + * Description : Frees structures used for SSL communication with client + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +static void free_client_ssl_structures(struct client_state *csp) +{ + /* + * We can't use function mbedtls_net_free, because this function + * inter alia close TCP connection on setted fd. Instead of this + * function, we change fd to -1, which is the same what does + * rest of mbedtls_net_free function. + */ + csp->mbedtls_client_attr.socket_fd.fd = -1; + + /* Freeing mbedtls structures */ + mbedtls_x509_crt_free(&(csp->mbedtls_client_attr.server_cert)); + mbedtls_pk_free(&(csp->mbedtls_client_attr.prim_key)); + mbedtls_ssl_free(&(csp->mbedtls_client_attr.ssl)); + mbedtls_ssl_config_free(&(csp->mbedtls_client_attr.conf)); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_free(&(csp->mbedtls_client_attr.cache)); +#endif +} + + /********************************************************************** * * Function : create_server_ssl_connection diff --git a/ssl.h b/ssl.h index 075ddbe0..9e13ec58 100644 --- a/ssl.h +++ b/ssl.h @@ -37,7 +37,8 @@ static mbedtls_ctr_drbg_context ctr_drbg; static mbedtls_entropy_context entropy; static int rng_seeded; -/* Function to create SSL/TLS connections */ +/* Functions for opening and closing SSL/TLS connections */ +extern int create_client_ssl_connection(struct client_state *csp); extern int create_server_ssl_connection(struct client_state *csp); #endif /* ndef SSL_H_INCLUDED */ -- 2.26.2 From e1ec5ada48d3eb12c8476a465b26bc037df4846f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:17:20 +0200 Subject: [PATCH 03/83] Added client and server ssl connection closing. --- jcc.c | 2 + ssl.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ssl.h | 5 +++ 3 files changed, 140 insertions(+) diff --git a/jcc.c b/jcc.c index 407dbbcd..5fc98c36 100644 --- a/jcc.c +++ b/jcc.c @@ -3095,6 +3095,7 @@ static void chat(struct client_state *csp) if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) { log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); return; } } @@ -3104,6 +3105,7 @@ static void chat(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "Can't open secure connection with client"); + close_client_and_server_ssl_connections(csp); return; } diff --git a/ssl.c b/ssl.c index 3310728e..6aeb8e08 100644 --- a/ssl.c +++ b/ssl.c @@ -49,6 +49,46 @@ static void free_server_ssl_structures(struct client_state *csp); static int seed_rng(struct client_state *csp); +/********************************************************************* +* +* Function : client_use_ssl +* +* Description : Tests if client in current client state structure should use +* SSL connection or standard connection. +* +* Parameters : +* 1 : csp = Current client state (buffers, headers, etc...) +* +* Returns : If client should use SSL/TLS connection, 1 is returned. +* Otherwise 0 is returned. +* +*********************************************************************/ +extern int client_use_ssl(struct client_state *csp) +{ + return csp->http->client_ssl; +} + + +/********************************************************************* +* +* Function : server_use_ssl +* +* Description : Tests if server in current client state structure should use +* SSL connection or standard connection. +* +* Parameters : +* 1 : csp = Current client state (buffers, headers, etc...) +* +* Returns : If server should use SSL/TLS connection, 1 is returned. +* Otherwise 0 is returned. +* +*********************************************************************/ +extern int server_use_ssl(struct client_state *csp) +{ + return csp->http->server_ssl; +} + + /********************************************************************* * * Function : ssl_debug_callback @@ -272,6 +312,40 @@ exit: } +/********************************************************************* +* +* Function : close_client_ssl_connection +* +* Description : Closes SSL/TLS connection with client. This function +* checks if this connection is already created. +* +* Parameters : +* 1 : csp = Current client state (buffers, headers, etc...) +* +* Returns : N/A +* +*********************************************************************/ +static void close_client_ssl_connection(struct client_state *csp) +{ + int ret = 0; + + if (csp->ssl_with_client_is_opened == 0) + { + return; + } + + /* + * Notifying the peer that the connection is being closed. + */ + do { + ret = mbedtls_ssl_close_notify(&(csp->mbedtls_client_attr.ssl)); + } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + free_client_ssl_structures(csp); + csp->ssl_with_client_is_opened = 0; +} + + /********************************************************************** * * Function : free_client_ssl_structures @@ -428,6 +502,40 @@ exit: } +/* +* +* Function : close_server_ssl_connection +* +* Description : Closes SSL/TLS connection with server. This function +* checks if this connection is already opened. +* +* Parameters : +* 1 : csp = Current client state (buffers, headers, etc...) +* +* Returns : N/A +* +*/ +static void close_server_ssl_connection(struct client_state *csp) +{ + int ret = 0; + + if (csp->ssl_with_server_is_opened == 0) + { + return; + } + + /* + * Notifying the peer that the connection is being closed. + */ + do { + ret = mbedtls_ssl_close_notify(&(csp->mbedtls_server_attr.ssl)); + } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + free_server_ssl_structures(csp); + csp->ssl_with_server_is_opened = 0; +} + + /********************************************************************* * * Function : free_server_ssl_structures @@ -456,6 +564,31 @@ static void free_server_ssl_structures(struct client_state *csp) } +/* +* Function : close_client_and_server_ssl_connections +* +* Description : Checks if client or server should use secured connection over +* SSL and if so, closes all of them. +* +* Parameters : +* 1 : csp = Current client state (buffers, headers, etc...) +* +* Returns : N/A +* +*/ +extern void close_client_and_server_ssl_connections(struct client_state *csp) +{ + if (client_use_ssl(csp) == 1) + { + close_client_ssl_connection(csp); + } + if (server_use_ssl(csp) == 1) + { + close_server_ssl_connection(csp); + } +} + + /********************************************************************* * * Function : seed_rng diff --git a/ssl.h b/ssl.h index 9e13ec58..baa58e72 100644 --- a/ssl.h +++ b/ssl.h @@ -37,8 +37,13 @@ static mbedtls_ctr_drbg_context ctr_drbg; static mbedtls_entropy_context entropy; static int rng_seeded; +/* Boolean functions to get informations about SSL/TLS connections */ +extern int client_use_ssl(struct client_state *csp); +extern int server_use_ssl(struct client_state *csp); + /* Functions for opening and closing SSL/TLS connections */ extern int create_client_ssl_connection(struct client_state *csp); extern int create_server_ssl_connection(struct client_state *csp); +extern void close_client_and_server_ssl_connections(struct client_state *csp); #endif /* ndef SSL_H_INCLUDED */ -- 2.26.2 From 71ecdf584bafe2be0d34f5380921d369492d8717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:19:02 +0200 Subject: [PATCH 04/83] Created functions for sending and receiving data over ssl connection. --- ssl.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- ssl.h | 8 ++- 2 files changed, 180 insertions(+), 2 deletions(-) diff --git a/ssl.c b/ssl.c index 6aeb8e08..0983bea6 100644 --- a/ssl.c +++ b/ssl.c @@ -1,4 +1,3 @@ -const char ssl_rcs[] = "$Id: ssl.c,v 1.0 2018/11/03 21:00:00 vaclavsvec Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/ssl.c,v $ @@ -89,6 +88,179 @@ extern int server_use_ssl(struct client_state *csp) } +/********************************************************************* +* +* Function : is_ssl_pending +* +* Description : Tests if there are some waitting data on ssl connection +* +* Parameters : +* 1 : ssl = SSL context to test +* +* Returns : 0 => No data are pending +* >0 => Pending data length +* +*********************************************************************/ +extern size_t is_ssl_pending(mbedtls_ssl_context * ssl) +{ + if (ssl == NULL) + { + return 0; + } + + return mbedtls_ssl_get_bytes_avail(ssl); +} + + +/********************************************************************* +* +* Function : ssl_send_data +* +* Description : Sends the content of buf (for n bytes) to given SSL +* connection context. +* +* Parameters : +* 1 : ssl = 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 +* +* Returns : Length of sent data or negative value on error. +* +*********************************************************************/ +extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len) +{ + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, ERROR_BUF_SIZE); + size_t max_fragment_size = 0; /* Maximal length of data in one SSL fragment*/ + int send_len = 0; /* length of one data part to send */ + int pos = 0; /* Position of unsent part in buffer */ + + if (len == 0) + { + return 0; + } + + /* Getting maximal length of data sent in one fragment */ + max_fragment_size = mbedtls_ssl_get_max_frag_len(ssl); + + /* + * Whole buffer must by sent in many fragments, because each fragment + * has its maximal length. + */ + while (pos < len) + { + /* Compute length of data, that can be send in next fragment */ + if ((pos + max_fragment_size) > len) + { + send_len = len - pos; + } + else + { + send_len = max_fragment_size; + } + + /* + * Sending one part of the buffer + */ + while ((ret = mbedtls_ssl_write(ssl, + (const unsigned char *)(buf + pos), + send_len)) < 0) + { + if (ret != MBEDTLS_ERR_SSL_WANT_READ + && ret != MBEDTLS_ERR_SSL_WANT_WRITE) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Sending data over SSL/TLS failed: %s", err_buf); + return -1; + } + } + /* Adding count of sent bytes to position in buffer */ + pos = pos + send_len; + } + + return len; +} + + +/********************************************************************* +* +* Function : ssl_recv_data +* +* Description : Receives data from given SSL context and puts them into buffer. +* +* Parameters : +* 1 : ssl = SSL context to receive data from +* 2 : buf = Pointer to buffer where data will be written +* 3 : len = Maximum number of bytes to read +* +* Returns : Number of bytes read, 0 for EOF, or negative +* value on error. +* +*********************************************************************/ +extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int maxLen) +{ + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, ERROR_BUF_SIZE); + memset(buf, 0, maxLen); + + /* + * Receiving data from SSL context into buffer + */ + do + { + ret = mbedtls_ssl_read(ssl, buf, maxLen); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ + || ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (ret < 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Receiving data over SSL/TLS failed: %s", err_buf); + } + + return ret; +} + + +/********************************************************************* +* +* Function : ssl_flush_socket +* +* Description : Send any pending "buffered" content with given SSL connection. +* Alternative to function flush_socket. +* +* Parameters : +* 1 : ssl = SSL context to send buffer to +* 2 : iob = The I/O buffer to flush, usually csp->iob. +* +* Returns : On success, the number of bytes send are returned (zero +* indicates nothing was sent). On error, -1 is returned. +* +*********************************************************************/ +extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob) +{ + /* Computing length of buffer part to send*/ + long len = iob->eod - iob->cur; + + if (len <= 0) + { + return(0); + } + + /* Sending data to given SSl context */ + if (ssl_send_data(ssl, (const unsigned char *)iob->cur, (size_t)len) < 0) + { + return -1; + } + iob->eod = iob->cur = iob->buf; + return(len); +} + + /********************************************************************* * * Function : ssl_debug_callback diff --git a/ssl.h b/ssl.h index baa58e72..f80d3567 100644 --- a/ssl.h +++ b/ssl.h @@ -1,6 +1,6 @@ #ifndef SSL_H_INCLUDED #define SSL_H_INCLUDED -#define SSL_H_VERSION "$Id: ssl.h,v 1.0 2018/11/03 21:00:00 vaclavsvec Exp $" +#define SSL_H_VERSION /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/ssl.h,v $ @@ -40,6 +40,12 @@ static int rng_seeded; /* Boolean functions to get informations about SSL/TLS connections */ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); +extern size_t is_ssl_pending(mbedtls_ssl_context *ssl); + +/* Functions for sending and receiving data over SSL/TLS connections */ +extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len); +extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int maxLen); +extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob); /* Functions for opening and closing SSL/TLS connections */ extern int create_client_ssl_connection(struct client_state *csp); -- 2.26.2 From 4e3ea9c23e9d243e286759674d049e87bbcfc9b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:25:08 +0200 Subject: [PATCH 05/83] Added client request forwarding to server over ssl. NOT implemented for POLL. --- jcc.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 25 deletions(-) diff --git a/jcc.c b/jcc.c index 5fc98c36..039bd2f8 100644 --- a/jcc.c +++ b/jcc.c @@ -2004,7 +2004,7 @@ static void handle_established_connection(struct client_state *csp) { char *hdr; char *p; - int n; + int n = 0; #ifdef HAVE_POLL struct pollfd poll_fds[2]; #else @@ -2019,6 +2019,7 @@ static void handle_established_connection(struct client_state *csp) long len = 0; /* for buffer sizes (and negative error codes) */ int buffer_and_filter_content = 0; unsigned int write_delay; + int ret = 0; /* Skeleton for HTTP response, if we should intercept the request */ struct http_response *rsp; @@ -2124,6 +2125,25 @@ static void handle_established_connection(struct client_state *csp) } #endif /* FEATURE_CONNECTION_KEEP_ALIVE */ + /* + * Test if some data from client or destination server are pending + * on SSL/TLS. We must work with them preferably. SSL/TLS data can + * be pending because of maximal fragment size. + */ + int read_ssl_server = 0; + int read_ssl_client = 0; + + if (client_use_ssl(csp)) + { + read_ssl_client = is_ssl_pending(&(csp->mbedtls_client_attr.ssl)); + } + + if (server_use_ssl(csp)) + { + read_ssl_server = is_ssl_pending(&(csp->mbedtls_server_attr.ssl)); + } + + #ifdef HAVE_POLL poll_fds[0].fd = csp->cfd; #ifdef FEATURE_CONNECTION_KEEP_ALIVE @@ -2148,7 +2168,29 @@ static void handle_established_connection(struct client_state *csp) #else timeout.tv_sec = csp->config->socket_timeout; timeout.tv_usec = 0; - n = select((int)maxfd+1, &rfds, NULL, NULL, &timeout); + + if (!read_ssl_server && !read_ssl_client) + { + n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout); + } + else + { + /* + * Set FD if some data are pending on SSL/TLS connections + */ + FD_ZERO(&rfds); + if (read_ssl_client) + { + FD_SET(csp->cfd, &rfds); + n++; + } + + if (read_ssl_server) + { + FD_SET(csp->server_connection.sfd, &rfds); + n++; + } + } #endif /* def HAVE_POLL */ if (n == 0) @@ -2241,38 +2283,71 @@ static void handle_established_connection(struct client_state *csp) assert(max_bytes_to_read <= csp->receive_buffer_size); #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - len = read_socket(csp->cfd, csp->receive_buffer, max_bytes_to_read); - - if (len <= 0) + /* + * Reading data from standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) { - /* XXX: not sure if this is necessary. */ - mark_server_socket_tainted(csp); - break; /* "game over, man" */ + /* + * Receiving HTTP request from client over SSL/TLS and sending + * it to server over SSL/TLS. + */ + len = ssl_recv_data(&(csp->mbedtls_client_attr.ssl), + (unsigned char *) csp->receive_buffer, max_bytes_to_read); + + if (len <= 0) + { + mark_server_socket_tainted(csp); + break; + } + + ret = ssl_send_data(&(csp->mbedtls_server_attr.ssl), + (unsigned char *) csp->receive_buffer, len); + + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, + "Send request over SSL/TLS to: %s failed", http->host); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } } + else + { + len = read_socket(csp->cfd, csp->receive_buffer, max_bytes_to_read); + + if (len <= 0) + { + /* XXX: not sure if this is necessary. */ + mark_server_socket_tainted(csp); + break; /* "game over, man" */ + } #ifdef FEATURE_CONNECTION_KEEP_ALIVE - if (csp->expected_client_content_length != 0) - { - assert(len <= max_bytes_to_read); - csp->expected_client_content_length -= (unsigned)len; - log_error(LOG_LEVEL_CONNECT, - "Expected client content length set to %llu " - "after reading %d bytes.", - csp->expected_client_content_length, len); - if (csp->expected_client_content_length == 0) + if (csp->expected_client_content_length != 0) { + assert(len <= max_bytes_to_read); + csp->expected_client_content_length -= (unsigned)len; log_error(LOG_LEVEL_CONNECT, - "Done reading from the client."); - csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; + "Expected client content length set to %llu " + "after reading %d bytes.", + csp->expected_client_content_length, len); + if (csp->expected_client_content_length == 0) + { + log_error(LOG_LEVEL_CONNECT, + "Done reading from the client."); + csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; + } } - } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - if (write_socket(csp->server_connection.sfd, csp->receive_buffer, (size_t)len)) - { - log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); - mark_server_socket_tainted(csp); - return; + if (write_socket(csp->server_connection.sfd, csp->receive_buffer, (size_t)len)) + { + log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); + mark_server_socket_tainted(csp); + return; + } } continue; } @@ -2771,9 +2846,12 @@ static void handle_established_connection(struct client_state *csp) continue; } mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; /* huh? we should never get here */ } + close_client_and_server_ssl_connections(csp); + if (csp->content_length == 0) { /* -- 2.26.2 From 0da47907753bb5d3e82f0c197749403308997ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:27:13 +0200 Subject: [PATCH 06/83] Added server response header forwarding to client over ssl. --- jcc.c | 164 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 43 deletions(-) diff --git a/jcc.c b/jcc.c index 039bd2f8..e075b3ec 100644 --- a/jcc.c +++ b/jcc.c @@ -2380,29 +2380,30 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "The server still wants to talk, but the client hung up on us."); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; #endif /* def _WIN32 */ } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - len = read_socket(csp->server_connection.sfd, csp->receive_buffer, (int)csp->receive_buffer_size); + /* + * Reading data from standard or secured connection (HTTP/HTTPS) + */ + if (server_use_ssl(csp)) + { + len = ssl_recv_data(&(csp->mbedtls_server_attr.ssl), + (unsigned char *)csp->receive_buffer, (int)csp->receive_buffer_size); + } + else + { + len = read_socket(csp->server_connection.sfd, csp->receive_buffer, (int)csp->receive_buffer_size); + } if (len < 0) { log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host); - if (http->ssl && (csp->fwd == NULL)) - { - /* - * Just hang up. We already confirmed the client's CONNECT - * request with status code 200 and unencrypted content is - * no longer welcome. - */ - log_error(LOG_LEVEL_ERROR, - "CONNECT already confirmed. Unable to tell the client about the problem."); - return; - } - else if (byte_count) + if (byte_count) { /* * Just hang up. We already transmitted the original headers @@ -2414,6 +2415,7 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. " "Unable to tell the client about the problem."); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } /* @@ -2479,7 +2481,7 @@ static void handle_established_connection(struct client_state *csp) if (len == 0) { - if (server_body || http->ssl) + if (server_body) { /* * If we have been buffering up the document, @@ -2565,7 +2567,7 @@ static void handle_established_connection(struct client_state *csp) * of the server document, just write it to the client, * unless we need to buffer the body for later content-filtering */ - if (server_body || http->ssl) + if (server_body) { if (buffer_and_filter_content) { @@ -2646,6 +2648,7 @@ static void handle_established_connection(struct client_state *csp) rsp = cgi_error_memory(); send_crunch_response(csp, rsp); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } @@ -2663,10 +2666,24 @@ static void handle_established_connection(struct client_state *csp) "Applying the MS IIS5 hack didn't help."); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd); - write_socket_delayed(csp->cfd, - INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) + { + ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE)); + } + else + { + write_socket_delayed(csp->cfd, + INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + } mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } else @@ -2712,11 +2729,12 @@ static void handle_established_connection(struct client_state *csp) } free_http_request(http); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } assert(csp->headers->first->str); - assert(!http->ssl); + if (strncmpic(csp->headers->first->str, "HTTP", 4) && strncmpic(csp->headers->first->str, "ICY", 3)) { @@ -2733,10 +2751,25 @@ static void handle_established_connection(struct client_state *csp) csp->headers->first->str); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd); - write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if(client_use_ssl(csp)) + { + ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE)); + } + else + { + write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + } + free_http_request(http); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } @@ -2748,10 +2781,24 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd); - write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) + { + ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE)); + } + else + { + write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + } free_http_request(http); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } hdr = list_to_text(csp->headers); @@ -2786,37 +2833,55 @@ static void handle_established_connection(struct client_state *csp) */ freez(hdr); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } /* Buffer and pcrs filter this if appropriate. */ + buffer_and_filter_content = content_requires_filtering(csp); - if (!http->ssl) /* We talk plaintext */ - { - buffer_and_filter_content = content_requires_filtering(csp); - } - /* - * Only write if we're not buffering for content modification - */ if (!buffer_and_filter_content) { /* * Write the server's (modified) header to * the client (along with anything else that - * may be in the buffer) + * may be in the buffer) Use standard or secured + * connection. */ + if (client_use_ssl(csp)) + { + if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)hdr, strlen(hdr)) < 0) + || (len = ssl_flush_socket(&(csp->mbedtls_client_attr.ssl), + csp->iob) < 0)) + { + log_error(LOG_LEVEL_CONNECT, "Write header to client failed"); - if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) - || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)) + /* + * The write failed, so don't bother mentioning it + * to the client... it probably can't hear us anyway. + */ + freez(hdr); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } + } + else { - log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); + if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) + || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)) + { + log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); - /* - * The write failed, so don't bother mentioning it - * to the client... it probably can't hear us anyway. - */ - freez(hdr); - mark_server_socket_tainted(csp); - return; + /* + * The write failed, so don't bother mentioning it + * to the client... it probably can't hear us anyway. + */ + freez(hdr); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } } } @@ -2837,9 +2902,22 @@ static void handle_established_connection(struct client_state *csp) "Applying the MS IIS5 hack didn't help."); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd); - write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) + { + ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE)); + } + else + { + write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); + } mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } } -- 2.26.2 From 76e15d53b3cbbc7c862ff2ce8cab9936452b6010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:28:06 +0200 Subject: [PATCH 07/83] Added server response body forwarding to client over ssl. --- jcc.c | 120 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/jcc.c b/jcc.c index e075b3ec..22946742 100644 --- a/jcc.c +++ b/jcc.c @@ -2528,16 +2528,40 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); } - if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) - || write_socket_delayed(csp->cfd, - ((p != NULL) ? p : csp->iob->cur), - (size_t)csp->content_length, write_delay)) + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) { - log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); - freez(hdr); - freez(p); - mark_server_socket_tainted(csp); - return; + if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)hdr, strlen(hdr)) < 0) + || (ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)((p != NULL) ? p : csp->iob->cur), + (size_t)csp->content_length) < 0)) + { + log_error(LOG_LEVEL_ERROR, "write modified content to " + "client over SSL/TLS failed"); + freez(hdr); + freez(p); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } + } + else + { + if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) + || write_socket_delayed(csp->cfd, + ((p != NULL) ? p : csp->iob->cur), + (size_t)csp->content_length, write_delay)) + { + log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); + freez(hdr); + freez(p); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } } freez(hdr); @@ -2563,9 +2587,9 @@ static void handle_established_connection(struct client_state *csp) } /* - * If this is an SSL connection or we're in the body - * of the server document, just write it to the client, - * unless we need to buffer the body for later content-filtering + * If we're in the body of the server document, just write it to + * the client, unless we need to buffer the body for later + * content-filtering. */ if (server_body) { @@ -2595,20 +2619,44 @@ static void handle_established_connection(struct client_state *csp) rsp = cgi_error_memory(); send_crunch_response(csp, rsp); mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); return; } hdrlen = strlen(hdr); - if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay) - || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0) - || write_socket_delayed(csp->cfd, csp->receive_buffer, - (size_t)len, write_delay)) + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) { - log_error(LOG_LEVEL_CONNECT, - "Flush header and buffers to client failed: %E"); - freez(hdr); - mark_server_socket_tainted(csp); - return; + if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)hdr, hdrlen) < 0) + || ((flushed = ssl_flush_socket(&(csp->mbedtls_client_attr.ssl), + csp->iob)) < 0) + || (ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)csp->receive_buffer, (size_t)len) < 0)) + { + log_error(LOG_LEVEL_CONNECT, + "Flush header and buffers to client failed"); + freez(hdr); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } + } + else + { + if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay) + || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0) + || write_socket_delayed(csp->cfd, csp->receive_buffer, + (size_t)len, write_delay)) + { + log_error(LOG_LEVEL_CONNECT, + "Flush header and buffers to client failed: %E"); + freez(hdr); + mark_server_socket_tainted(csp); + return; + } } /* @@ -2624,12 +2672,32 @@ static void handle_established_connection(struct client_state *csp) } else { - if (write_socket_delayed(csp->cfd, csp->receive_buffer, - (size_t)len, write_delay)) + /* + * Sending data with standard or secured connection (HTTP/HTTPS) + */ + if (client_use_ssl(csp)) { - log_error(LOG_LEVEL_ERROR, "write to client failed: %E"); - mark_server_socket_tainted(csp); - return; + ret = ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)csp->receive_buffer, len); + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, + "Sending data to client failed"); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } + } + else + { + if (write_socket_delayed(csp->cfd, csp->receive_buffer, + (size_t)len, write_delay)) + { + log_error(LOG_LEVEL_ERROR, "write to client failed: %E"); + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } } } byte_count += (unsigned long long)len; -- 2.26.2 From afdae725cc2970a1c4353dadbc2c07e17008d981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:29:04 +0200 Subject: [PATCH 08/83] Added ssl_tunnel possibility. --- jcc.c | 76 +++++++++++++++++++++++++++++++++++++++---------------- project.h | 3 +++ 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/jcc.c b/jcc.c index 22946742..417ba99d 100644 --- a/jcc.c +++ b/jcc.c @@ -2019,6 +2019,7 @@ static void handle_established_connection(struct client_state *csp) long len = 0; /* for buffer sizes (and negative error codes) */ int buffer_and_filter_content = 0; unsigned int write_delay; + const struct forward_spec *fwd = csp->use_fwd; int ret = 0; /* Skeleton for HTTP response, if we should intercept the request */ @@ -2403,7 +2404,18 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host); - if (byte_count) + if ((http->ssl && (fwd->forward_host == NULL)) && csp->use_ssl_tunnel) + { + /* + * Just hang up. We already confirmed the client's CONNECT + * request with status code 200 and unencrypted content is + * no longer welcome. + */ + log_error(LOG_LEVEL_ERROR, + "CONNECT already confirmed. Unable to tell the client about the problem."); + return; + } + else if (byte_count) { /* * Just hang up. We already transmitted the original headers @@ -2481,7 +2493,7 @@ static void handle_established_connection(struct client_state *csp) if (len == 0) { - if (server_body) + if (server_body || (http->ssl && csp->use_ssl_tunnel)) { /* * If we have been buffering up the document, @@ -2591,7 +2603,7 @@ static void handle_established_connection(struct client_state *csp) * the client, unless we need to buffer the body for later * content-filtering. */ - if (server_body) + if (server_body || (http->ssl && csp->use_ssl_tunnel)) { if (buffer_and_filter_content) { @@ -3058,6 +3070,7 @@ static void chat(struct client_state *csp) int ret = 0; http = csp->http; + csp->use_ssl_tunnel = 1; if (receive_client_request(csp) != JB_ERR_OK) { @@ -3076,6 +3089,7 @@ static void chat(struct client_state *csp) /* Never get here - LOG_LEVEL_FATAL causes program exit */ return; } + csp->use_fwd = fwd; /* * build the http request to send to the server @@ -3121,7 +3135,7 @@ static void chat(struct client_state *csp) /* * Presetting SSL client and server flags */ - if (http->ssl) + if (http->ssl && !csp->use_ssl_tunnel) { http->client_ssl = 1; http->server_ssl = 1; @@ -3257,7 +3271,7 @@ static void chat(struct client_state *csp) * proxy. If forwarding is enabled, we must send client request to * parent proxy and receive, parse and resend parent proxy answer. */ - if (http->ssl) + if (http->ssl && !csp->use_ssl_tunnel) { /* * Parent proxy is not used, we can just create SSL/TLS connection @@ -3293,7 +3307,7 @@ static void chat(struct client_state *csp) /* Client headers have been sent optimistically */ assert(csp->headers->last == NULL); } - else if (fwd->forward_host || (http->ssl == 0)) + else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) { if (send_http_request(csp)) { @@ -3308,32 +3322,50 @@ static void chat(struct client_state *csp) else { /* - * Creating an SSL proxy. If forwarding is disabled, we must send - * CSUCCEED mesage to client. Then SSL/TLS connection with client - * is created. + * Using old solution with SSL tunnel or new solution with SSL proxy */ list_remove_all(csp->headers); - - if (fwd->forward_host == NULL) + if (csp->use_ssl_tunnel) { + /* + * We're running an SSL tunnel and we're not forwarding, + * so just ditch the client headers, send the "connect succeeded" + * message to the client, flush the rest, and get out of the way. + */ if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) { - log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); return; } } - - ret = create_client_ssl_connection(csp); - if (ret != 0) + else { - log_error(LOG_LEVEL_ERROR, - "Can't open secure connection with client"); - close_client_and_server_ssl_connections(csp); - return; - } + /* + * Creating an SSL proxy. If forwarding is disabled, we must send + * CSUCCEED mesage to client. Then SSL/TLS connection with client + * is created. + */ - log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); + if (fwd->forward_host == NULL) + { + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); + return; + } + } + + ret = create_client_ssl_connection(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Can't open secure connection with client"); + close_client_and_server_ssl_connections(csp); + return; + } + + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); + } clear_iob(csp->client_iob); } diff --git a/project.h b/project.h index b4ffd454..ec1bbe5a 100644 --- a/project.h +++ b/project.h @@ -1051,6 +1051,9 @@ struct client_state */ int ssl_with_server_is_opened; int ssl_with_client_is_opened; + + int use_ssl_tunnel; + struct forward_spec * use_fwd; }; /** -- 2.26.2 From 79aaa335085ea2ff8e20b51cdd7f81a5f6436d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:30:16 +0200 Subject: [PATCH 09/83] Added forwarding for ssl. --- jcc.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++------ project.h | 2 +- ssl.c | 59 +++++++++++++++++++++++++++ ssl.h | 1 + 4 files changed, 168 insertions(+), 13 deletions(-) diff --git a/jcc.c b/jcc.c index 417ba99d..4ac900b8 100644 --- a/jcc.c +++ b/jcc.c @@ -3070,7 +3070,7 @@ static void chat(struct client_state *csp) int ret = 0; http = csp->http; - csp->use_ssl_tunnel = 1; + csp->use_ssl_tunnel = 0; if (receive_client_request(csp) != JB_ERR_OK) { @@ -3273,23 +3273,118 @@ static void chat(struct client_state *csp) */ if (http->ssl && !csp->use_ssl_tunnel) { - /* - * Parent proxy is not used, we can just create SSL/TLS connection - * with destination server - */ + if (fwd->forward_host != NULL) + { + char server_response[BUFFER_SIZE]; + int ret = 0; + int len = 0; + char *hdr = list_to_text(csp->headers); + memset(server_response, 0, sizeof(server_response)); - ret = create_server_ssl_connection(csp); + if (hdr == NULL) + { + log_error(LOG_LEVEL_FATAL, + "Out of memory parsing client header"); + } + list_remove_all(csp->headers); - if (ret != 0) + /* + * Sending client's CONNECT request to the parent proxy + */ + ret = write_socket(csp->server_connection.sfd, hdr, strlen(hdr)); + + freez(hdr); + + if (ret != 0) + { + log_error(LOG_LEVEL_CONNECT, + "Sending request headers to: %s failed", http->hostport); + mark_server_socket_tainted(csp); + return; + } + + /* Waitting for parent proxy server response */ + len = read_socket(csp->server_connection.sfd, server_response, + sizeof(server_response) - 1); + + if (len <= 0) + { + log_error(LOG_LEVEL_ERROR, "No response from parent proxy " + "server on socket %d.", csp->server_connection.sfd); + + rsp = error_response(csp, "no-server-data"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + mark_server_socket_tainted(csp); + return; + } + + /* + * Test if connection with destination server was established + * successfully by parent proxy. Then we can send response to + * the client and continue or stop. + */ + if (!tunnel_established_successfully(server_response, len)) + { + log_error(LOG_LEVEL_ERROR, "Forwarder hasn't established " + "connection with destination server."); + + write_socket(csp->cfd, server_response, len); + mark_server_socket_tainted(csp); + return; + } + + /* + * Parent proxy has established connection with destination server. + * Now we must create SSL/TLS connection with parent proxy. + */ + ret = create_server_ssl_connection(csp); + + if (ret != 0) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + return; + } + + /* + * SSL/TLS connection with parent proxy is established, we can + * inform client about success. + */ + ret = write_socket(csp->cfd, server_response, len); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Sending parent proxy response to client failed"); + mark_server_socket_tainted(csp); + return; + } + } + else { - rsp = error_response(csp, "connect-failed"); - if (rsp) + /* + * Parent proxy is not used, we can just create SSL/TLS connection + * with destination server + */ + + ret = create_server_ssl_connection(csp); + + if (ret != 0) { - send_crunch_response(csp, rsp); + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + return; } - return; + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); } - log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); } #ifdef FEATURE_CONNECTION_KEEP_ALIVE diff --git a/project.h b/project.h index ec1bbe5a..30970850 100644 --- a/project.h +++ b/project.h @@ -1053,7 +1053,7 @@ struct client_state int ssl_with_client_is_opened; int use_ssl_tunnel; - struct forward_spec * use_fwd; + const struct forward_spec * use_fwd; }; /** diff --git a/ssl.c b/ssl.c index 0983bea6..8cc71c89 100644 --- a/ssl.c +++ b/ssl.c @@ -761,6 +761,65 @@ extern void close_client_and_server_ssl_connections(struct client_state *csp) } +/********************************************************************* +* +* Function : tunnel_established_successfully +* +* Description : Check if parent proxy server response contains +* informations about successfully created connection with +* destination server. (HTTP/... 2xx ...) +* +* Parameters : +* 1 : server_response = Buffer with parent proxy server response +* 2 : response_len = Length of server_response +* +* Returns : 1 => Connection created successfully +* 0 => Connection wasn't created successfully +* +*********************************************************************/ +extern int tunnel_established_successfully(const char * server_response, unsigned int response_len) { + unsigned int pos = 0; + + if (server_response == NULL) + { + return 0; + } + + /* Tests if "HTTP/" string is at the begin of received response */ + if (strncmp(server_response, "HTTP/", 5) != 0) + { + return 0; + } + + for (pos = 0; pos < response_len; pos++) + { + if (server_response[pos] == ' ') + { + break; + } + } + + /* + * response_len -3 because of buffer end, response structure and 200 code. + * There must be at least 3 chars after space. + * End of buffer: ... 2xx'\0' + * pos = | + */ + if (pos >= (response_len - 3)) + { + return 0; + } + + /* Test HTTP status code */ + if (server_response[pos + 1] != '2') + { + return 0; + } + + return 1; +} + + /********************************************************************* * * Function : seed_rng diff --git a/ssl.h b/ssl.h index f80d3567..a5d805eb 100644 --- a/ssl.h +++ b/ssl.h @@ -41,6 +41,7 @@ static int rng_seeded; extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); extern size_t is_ssl_pending(mbedtls_ssl_context *ssl); +extern int tunnel_established_successfully(const char * response, unsigned int response_len); /* Functions for sending and receiving data over SSL/TLS connections */ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len); -- 2.26.2 From 2c3c31979d8ec1e32f4ca1670e44d2a0a35c787d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:31:07 +0200 Subject: [PATCH 10/83] Freeing random number generator seed structures. --- jcc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jcc.c b/jcc.c index 4ac900b8..6d9f15b5 100644 --- a/jcc.c +++ b/jcc.c @@ -5036,6 +5036,11 @@ static void listen_loop(void) /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */ /* Clean up. Aim: free all memory (no leaks) */ + if (rng_seeded == 1) { + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + } + #ifdef FEATURE_GRACEFUL_TERMINATION log_error(LOG_LEVEL_ERROR, "Graceful termination requested"); -- 2.26.2 From c3d558aaadd841872a138c64d2e6da94db95af5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:32:05 +0200 Subject: [PATCH 11/83] Added ssl connection when poll function is used. --- jcc.c | 75 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/jcc.c b/jcc.c index 6d9f15b5..cc44df8c 100644 --- a/jcc.c +++ b/jcc.c @@ -2145,37 +2145,50 @@ static void handle_established_connection(struct client_state *csp) } + if (!read_ssl_server && !read_ssl_client) + { #ifdef HAVE_POLL - poll_fds[0].fd = csp->cfd; + poll_fds[0].fd = csp->cfd; #ifdef FEATURE_CONNECTION_KEEP_ALIVE - if (!watch_client_socket) - { - /* - * Ignore incoming data, but still watch out - * for disconnects etc. These flags are always - * implied anyway but explicitly setting them - * doesn't hurt. - */ - poll_fds[0].events = POLLERR|POLLHUP; - } - else + if (!watch_client_socket) + { + /* + * Ignore incoming data, but still watch out + * for disconnects etc. These flags are always + * implied anyway but explicitly setting them + * doesn't hurt. + */ + poll_fds[0].events = POLLERR | POLLHUP; + } + else #endif - { - poll_fds[0].events = POLLIN; - } - poll_fds[1].fd = csp->server_connection.sfd; - poll_fds[1].events = POLLIN; - n = poll(poll_fds, 2, csp->config->socket_timeout * 1000); + { + poll_fds[0].events = POLLIN; + } + poll_fds[1].fd = csp->server_connection.sfd; + poll_fds[1].events = POLLIN; + n = poll(poll_fds, 2, csp->config->socket_timeout * 1000); #else - timeout.tv_sec = csp->config->socket_timeout; - timeout.tv_usec = 0; - - if (!read_ssl_server && !read_ssl_client) - { + timeout.tv_sec = csp->config->socket_timeout; + timeout.tv_usec = 0; n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout); - } - else +#endif /* def HAVE_POLL */ + } + else { +#ifdef HAVE_POLL + if (read_ssl_client) + { + poll_fds[0].revents = POLLIN; + n++; + } + + if (read_ssl_server) + { + poll_fds[1].revents = POLLIN; + n++; + } +#else /* * Set FD if some data are pending on SSL/TLS connections */ @@ -2191,8 +2204,8 @@ static void handle_established_connection(struct client_state *csp) FD_SET(csp->server_connection.sfd, &rfds); n++; } - } #endif /* def HAVE_POLL */ + } if (n == 0) { @@ -2285,14 +2298,14 @@ static void handle_established_connection(struct client_state *csp) #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ /* - * Reading data from standard or secured connection (HTTP/HTTPS) - */ + * Reading data from standard or secured connection (HTTP/HTTPS) + */ if (client_use_ssl(csp)) { /* - * Receiving HTTP request from client over SSL/TLS and sending - * it to server over SSL/TLS. - */ + * Receiving HTTP request from client over SSL/TLS and sending + * it to server over SSL/TLS. + */ len = ssl_recv_data(&(csp->mbedtls_client_attr.ssl), (unsigned char *) csp->receive_buffer, max_bytes_to_read); -- 2.26.2 From 8b10127360a7605455744d757ade3f7f397aca4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:35:14 +0200 Subject: [PATCH 12/83] Unified comments indenting. --- ssl.c | 320 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 160 insertions(+), 160 deletions(-) diff --git a/ssl.c b/ssl.c index 8cc71c89..4e1b3e2a 100644 --- a/ssl.c +++ b/ssl.c @@ -49,19 +49,19 @@ static int seed_rng(struct client_state *csp); /********************************************************************* -* -* Function : client_use_ssl -* -* Description : Tests if client in current client state structure should use -* SSL connection or standard connection. -* -* Parameters : -* 1 : csp = Current client state (buffers, headers, etc...) -* -* Returns : If client should use SSL/TLS connection, 1 is returned. -* Otherwise 0 is returned. -* -*********************************************************************/ + * + * Function : client_use_ssl + * + * Description : Tests if client in current client state structure should use + * SSL connection or standard connection. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : If client should use SSL/TLS connection, 1 is returned. + * Otherwise 0 is returned. + * + *********************************************************************/ extern int client_use_ssl(struct client_state *csp) { return csp->http->client_ssl; @@ -69,19 +69,19 @@ extern int client_use_ssl(struct client_state *csp) /********************************************************************* -* -* Function : server_use_ssl -* -* Description : Tests if server in current client state structure should use -* SSL connection or standard connection. -* -* Parameters : -* 1 : csp = Current client state (buffers, headers, etc...) -* -* Returns : If server should use SSL/TLS connection, 1 is returned. -* Otherwise 0 is returned. -* -*********************************************************************/ + * + * Function : server_use_ssl + * + * Description : Tests if server in current client state structure should use + * SSL connection or standard connection. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : If server should use SSL/TLS connection, 1 is returned. + * Otherwise 0 is returned. + * + *********************************************************************/ extern int server_use_ssl(struct client_state *csp) { return csp->http->server_ssl; @@ -89,18 +89,18 @@ extern int server_use_ssl(struct client_state *csp) /********************************************************************* -* -* Function : is_ssl_pending -* -* Description : Tests if there are some waitting data on ssl connection -* -* Parameters : -* 1 : ssl = SSL context to test -* -* Returns : 0 => No data are pending -* >0 => Pending data length -* -*********************************************************************/ + * + * Function : is_ssl_pending + * + * Description : Tests if there are some waitting data on ssl connection + * + * Parameters : + * 1 : ssl = SSL context to test + * + * Returns : 0 => No data are pending + * >0 => Pending data length + * + *********************************************************************/ extern size_t is_ssl_pending(mbedtls_ssl_context * ssl) { if (ssl == NULL) @@ -113,20 +113,20 @@ extern size_t is_ssl_pending(mbedtls_ssl_context * ssl) /********************************************************************* -* -* Function : ssl_send_data -* -* Description : Sends the content of buf (for n bytes) to given SSL -* connection context. -* -* Parameters : -* 1 : ssl = 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 -* -* Returns : Length of sent data or negative value on error. -* -*********************************************************************/ + * + * Function : ssl_send_data + * + * Description : Sends the content of buf (for n bytes) to given SSL + * connection context. + * + * Parameters : + * 1 : ssl = 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 + * + * Returns : Length of sent data or negative value on error. + * + *********************************************************************/ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len) { int ret = 0; @@ -145,9 +145,9 @@ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, i max_fragment_size = mbedtls_ssl_get_max_frag_len(ssl); /* - * Whole buffer must by sent in many fragments, because each fragment - * has its maximal length. - */ + * Whole buffer must by sent in many fragments, because each fragment + * has its maximal length. + */ while (pos < len) { /* Compute length of data, that can be send in next fragment */ @@ -161,8 +161,8 @@ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, i } /* - * Sending one part of the buffer - */ + * Sending one part of the buffer + */ while ((ret = mbedtls_ssl_write(ssl, (const unsigned char *)(buf + pos), send_len)) < 0) @@ -185,20 +185,20 @@ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, i /********************************************************************* -* -* Function : ssl_recv_data -* -* Description : Receives data from given SSL context and puts them into buffer. -* -* Parameters : -* 1 : ssl = SSL context to receive data from -* 2 : buf = Pointer to buffer where data will be written -* 3 : len = Maximum number of bytes to read -* -* Returns : Number of bytes read, 0 for EOF, or negative -* value on error. -* -*********************************************************************/ + * + * Function : ssl_recv_data + * + * Description : Receives data from given SSL context and puts them into buffer. + * + * Parameters : + * 1 : ssl = SSL context to receive data from + * 2 : buf = Pointer to buffer where data will be written + * 3 : len = Maximum number of bytes to read + * + * Returns : Number of bytes read, 0 for EOF, or negative + * value on error. + * + *********************************************************************/ extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int maxLen) { int ret = 0; @@ -207,8 +207,8 @@ extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int max memset(buf, 0, maxLen); /* - * Receiving data from SSL context into buffer - */ + * Receiving data from SSL context into buffer + */ do { ret = mbedtls_ssl_read(ssl, buf, maxLen); @@ -227,20 +227,20 @@ extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int max /********************************************************************* -* -* Function : ssl_flush_socket -* -* Description : Send any pending "buffered" content with given SSL connection. -* Alternative to function flush_socket. -* -* Parameters : -* 1 : ssl = SSL context to send buffer to -* 2 : iob = The I/O buffer to flush, usually csp->iob. -* -* Returns : On success, the number of bytes send are returned (zero -* indicates nothing was sent). On error, -1 is returned. -* -*********************************************************************/ + * + * Function : ssl_flush_socket + * + * Description : Send any pending "buffered" content with given SSL connection. + * Alternative to function flush_socket. + * + * Parameters : + * 1 : ssl = SSL context to send buffer to + * 2 : iob = The I/O buffer to flush, usually csp->iob. + * + * Returns : On success, the number of bytes send are returned (zero + * indicates nothing was sent). On error, -1 is returned. + * + *********************************************************************/ extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob) { /* Computing length of buffer part to send*/ @@ -485,18 +485,18 @@ exit: /********************************************************************* -* -* Function : close_client_ssl_connection -* -* Description : Closes SSL/TLS connection with client. This function -* checks if this connection is already created. -* -* Parameters : -* 1 : csp = Current client state (buffers, headers, etc...) -* -* Returns : N/A -* -*********************************************************************/ + * + * Function : close_client_ssl_connection + * + * Description : Closes SSL/TLS connection with client. This function + * checks if this connection is already created. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ static void close_client_ssl_connection(struct client_state *csp) { int ret = 0; @@ -507,8 +507,8 @@ static void close_client_ssl_connection(struct client_state *csp) } /* - * Notifying the peer that the connection is being closed. - */ + * Notifying the peer that the connection is being closed. + */ do { ret = mbedtls_ssl_close_notify(&(csp->mbedtls_client_attr.ssl)); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); @@ -533,11 +533,11 @@ static void close_client_ssl_connection(struct client_state *csp) static void free_client_ssl_structures(struct client_state *csp) { /* - * We can't use function mbedtls_net_free, because this function - * inter alia close TCP connection on setted fd. Instead of this - * function, we change fd to -1, which is the same what does - * rest of mbedtls_net_free function. - */ + * We can't use function mbedtls_net_free, because this function + * inter alia close TCP connection on setted fd. Instead of this + * function, we change fd to -1, which is the same what does + * rest of mbedtls_net_free function. + */ csp->mbedtls_client_attr.socket_fd.fd = -1; /* Freeing mbedtls structures */ @@ -584,10 +584,10 @@ extern int create_server_ssl_connection(struct client_state *csp) #endif /* - * Setting socket fd in mbedtls_net_context structure. This structure - * can't be setted by mbedtls functions, because we already have created - * TCP connection when starting this function. - */ + * Setting socket fd in mbedtls_net_context structure. This structure + * can't be setted by mbedtls functions, because we already have created + * TCP connection when starting this function. + */ csp->mbedtls_server_attr.socket_fd.fd = csp->server_connection.sfd; /* @@ -675,18 +675,18 @@ exit: /* -* -* Function : close_server_ssl_connection -* -* Description : Closes SSL/TLS connection with server. This function -* checks if this connection is already opened. -* -* Parameters : -* 1 : csp = Current client state (buffers, headers, etc...) -* -* Returns : N/A -* -*/ + * + * Function : close_server_ssl_connection + * + * Description : Closes SSL/TLS connection with server. This function + * checks if this connection is already opened. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + */ static void close_server_ssl_connection(struct client_state *csp) { int ret = 0; @@ -697,8 +697,8 @@ static void close_server_ssl_connection(struct client_state *csp) } /* - * Notifying the peer that the connection is being closed. - */ + * Notifying the peer that the connection is being closed. + */ do { ret = mbedtls_ssl_close_notify(&(csp->mbedtls_server_attr.ssl)); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); @@ -723,11 +723,11 @@ static void close_server_ssl_connection(struct client_state *csp) static void free_server_ssl_structures(struct client_state *csp) { /* - * We can't use function mbedtls_net_free, because this function - * inter alia close TCP connection on setted fd. Instead of this - * function, we change fd to -1, which is the same what does - * rest of mbedtls_net_free function. - */ + * We can't use function mbedtls_net_free, because this function + * inter alia close TCP connection on setted fd. Instead of this + * function, we change fd to -1, which is the same what does + * rest of mbedtls_net_free function. + */ csp->mbedtls_server_attr.socket_fd.fd = -1; mbedtls_x509_crt_free(&(csp->mbedtls_server_attr.ca_cert)); @@ -737,17 +737,17 @@ static void free_server_ssl_structures(struct client_state *csp) /* -* Function : close_client_and_server_ssl_connections -* -* Description : Checks if client or server should use secured connection over -* SSL and if so, closes all of them. -* -* Parameters : -* 1 : csp = Current client state (buffers, headers, etc...) -* -* Returns : N/A -* -*/ + * Function : close_client_and_server_ssl_connections + * + * Description : Checks if client or server should use secured connection over + * SSL and if so, closes all of them. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + */ extern void close_client_and_server_ssl_connections(struct client_state *csp) { if (client_use_ssl(csp) == 1) @@ -762,21 +762,21 @@ extern void close_client_and_server_ssl_connections(struct client_state *csp) /********************************************************************* -* -* Function : tunnel_established_successfully -* -* Description : Check if parent proxy server response contains -* informations about successfully created connection with -* destination server. (HTTP/... 2xx ...) -* -* Parameters : -* 1 : server_response = Buffer with parent proxy server response -* 2 : response_len = Length of server_response -* -* Returns : 1 => Connection created successfully -* 0 => Connection wasn't created successfully -* -*********************************************************************/ + * + * Function : tunnel_established_successfully + * + * Description : Check if parent proxy server response contains + * informations about successfully created connection with + * destination server. (HTTP/... 2xx ...) + * + * Parameters : + * 1 : server_response = Buffer with parent proxy server response + * 2 : response_len = Length of server_response + * + * Returns : 1 => Connection created successfully + * 0 => Connection wasn't created successfully + * + *********************************************************************/ extern int tunnel_established_successfully(const char * server_response, unsigned int response_len) { unsigned int pos = 0; @@ -800,11 +800,11 @@ extern int tunnel_established_successfully(const char * server_response, unsigne } /* - * response_len -3 because of buffer end, response structure and 200 code. - * There must be at least 3 chars after space. - * End of buffer: ... 2xx'\0' - * pos = | - */ + * response_len -3 because of buffer end, response structure and 200 code. + * There must be at least 3 chars after space. + * End of buffer: ... 2xx'\0' + * pos = | + */ if (pos >= (response_len - 3)) { return 0; -- 2.26.2 From b222cf12227e84d0e6b3ee24458a89a646470f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:36:33 +0200 Subject: [PATCH 13/83] Server cerificate verification. --- CA/trustedCAs.pem | 4045 +++++++++++++++++++++++++++++++++++++++++++++ project.h | 24 + ssl.c | 137 +- ssl.h | 10 + 4 files changed, 4212 insertions(+), 4 deletions(-) create mode 100644 CA/trustedCAs.pem diff --git a/CA/trustedCAs.pem b/CA/trustedCAs.pem new file mode 100644 index 00000000..5579b5d1 --- /dev/null +++ b/CA/trustedCAs.pem @@ -0,0 +1,4045 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Wed Jan 18 04:12:05 2017 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.27. +## SHA256: dffa79e6aa993f558e82884abf7bb54bf440ab66ee91d82a27a627f6f2a4ace4 +## + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz +0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j +Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn +RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O ++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq +/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE +Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM +lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 +yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ +eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW +FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ +7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ +Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM +8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi +FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi +yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c +J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw +sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + + + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 +EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc +cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw +EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj +055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f +j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 +xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa +t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +AddTrust Low-Value Services Root +================================ +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU +cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw +CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO +ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 +54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr +oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 +Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui +GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w +HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT +RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw +HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt +ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph +iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr +mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj +ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +AddTrust External Root +====================== +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD +VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw +NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU +cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 ++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw +Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo +aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy +2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 +7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL +VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk +VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl +j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 +e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u +G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +AddTrust Public Services Root +============================= +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU +cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ +BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l +dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu +nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i +d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG +Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw +HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G +A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G +A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 +JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL ++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 +Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H +EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +AddTrust Qualified Certificates Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU +cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx +CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ +IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx +64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 +KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o +L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR +wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU +MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE +BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y +azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG +GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze +RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB +iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +GeoTrust Global CA +================== +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw +MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo +BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet +8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc +T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU +vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk +DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q +zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 +d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 +mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p +XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm +Mw== +-----END CERTIFICATE----- + +GeoTrust Global CA 2 +==================== +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw +MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ +NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k +LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA +Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b +HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH +K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 +srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh +ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL +OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC +x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF +H4z1Ir+rzoPz4iIprn2DQKi6bA== +-----END CERTIFICATE----- + +GeoTrust Universal CA +===================== +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 +MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu +Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t +JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e +RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs +7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d +8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V +qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga +Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB +Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu +KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 +ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 +XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 +qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL +oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK +xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF +KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 +DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK +xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU +p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI +P/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +======================= +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 +MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg +SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 +DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 +j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q +JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a +QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 +WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP +20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn +ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC +SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG +8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 ++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ +4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ +mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq +A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg +Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP +pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d +FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp +gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm +X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +Visa eCommerce Root +=================== +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG +EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug +QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 +WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm +VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL +F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b +RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 +TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI +/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs +GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc +CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW +YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz +zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu +YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +Certum Root CA +============== +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK +ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla +Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u +by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x +wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL +kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ +89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K +Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P +NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ +GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg +GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ +0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS +qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +Comodo Secure Services root +=========================== +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw +MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu +Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi +BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP +9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc +rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC +oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V +p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E +FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj +YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm +aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm +4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL +DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw +pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H +RR3B7Hzs/Sk= +-----END CERTIFICATE----- + +Comodo Trusted Services root +============================ +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw +MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h +bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw +IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 +3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y +/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 +juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS +ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud +DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp +ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl +cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw +uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA +BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l +R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O +9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +UTN USERFirst Hardware Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd +BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx +OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 +eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz +ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI +wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd +tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 +i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf +Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw +gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF +UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF +BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW +XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 +lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn +iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 +nfhmqA== +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx +NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp +cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn +MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU +xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH +NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW +DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV +d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud +EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v +cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P +AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh +bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD +VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi +fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD +L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN +UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n +ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 +erfutGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +================================== +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx +NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt +YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg +MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw +ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J +1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O +by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl +6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c +8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ +BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j +aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B +Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj +aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y +ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA +PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y +gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ +PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 +IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes +t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj +YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH +AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw +Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg +U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 +LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh +cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT +dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC +AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh +3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm +vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk +fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 +fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ +EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl +1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ +lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro +g14= +-----END CERTIFICATE----- + +Taiwan GRCA +=========== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG +EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X +DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv +dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN +w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 +BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O +1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO +htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov +J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 +Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t +B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB +O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 +lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV +HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 +09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj +Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 +Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU +D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz +DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk +Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk +7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ +CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy ++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS +-----END CERTIFICATE----- + +Swisscom Root CA 1 +================== +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG +EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy +dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4 +MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln +aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM +MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF +NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe +AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC +b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn +7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN +cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp +WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5 +haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY +MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw +HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j +BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9 +MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn +jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ +MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H +VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl +vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl +OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3 +1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq +nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy +x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW +NY6E0F/6MBr1mmz0DlP5OlvRHA== +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +Certplus Class 2 Primary CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE +BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN +OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy +dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR +5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ +Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO +YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e +e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME +CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ +YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t +L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD +P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R +TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ +7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW +//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +DST ACES CA X6 +============== +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT +MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha +MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE +CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI +DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa +pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow +GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy +MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu +Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy +dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU +CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 +5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t +Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs +vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 +oKfN5XozNmr6mis= +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X +DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 +aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 +N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm ++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH +6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu +MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h +qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 +FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs +ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc +celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X +CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB +tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P +4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F +kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L +3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx +/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa +DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP +e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu +WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ +DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub +DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ +cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN +b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 +nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge +RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt +tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI +hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K +Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN +NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa +Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG +1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 +MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg +SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv +KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT +FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs +oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ +1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc +q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K +aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p +afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF +AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE +uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 +jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH +z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +============================================================ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln +biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh +dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz +j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD +Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ +Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r +fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv +Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG +SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ +X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE +KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC +Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE +ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +WellsSecure Public Root Certificate Authority +============================================= +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM +F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw +NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl +bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD +VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 +iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 +i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 +bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB +K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB +AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu +cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm +lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB +i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww +GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI +K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 +bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj +qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es +E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ +tylv2G0xffX8oRAHh84vWdw+WNs= +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Security Communication EV RootCA1 +================================= +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE +BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl +Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO +/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX +WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z +ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 +bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK +9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm +iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG +Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW +mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW +T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GA CA +=============================== +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE +BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG +A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH +bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD +VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw +IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 +IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 +Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg +Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD +d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ +/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R +LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm +MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 ++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY +okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE +BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL +EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 +MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz +dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT +GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG +d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N +oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc +QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ +PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb +MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG +IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD +VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 +LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A +dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA +4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg +AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA +egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 +Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO +PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv +c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h +cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw +IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT +WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV +MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER +MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp +Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal +HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT +nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE +aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK +yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB +S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +Deutsche Telekom Root CA 2 +========================== +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT +RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG +A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 +MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G +A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS +b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 +bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI +KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY +AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK +Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV +jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV +HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr +E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy +zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 +rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G +dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 +============================================================================================================================= +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH +DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q +aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry +b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV +BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg +S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 +MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl +IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF +n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl +IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft +dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl +cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO +Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 +xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR +6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd +BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 +N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT +y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh +LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M +dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +CNNIC ROOT +========== +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE +ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw +OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD +o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz +VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT +VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or +czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK +y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC +wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S +lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 +Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM +O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 +BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 +G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m +mxE= +-----END CERTIFICATE----- + +ApplicationCA - Japanese Government +=================================== +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT +SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw +MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl +cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 +fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN +wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE +jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu +nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU +WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV +BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD +vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs +o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g +/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD +io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW +dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +============================================= +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz +NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo +YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT +LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j +K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE +c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C +IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu +dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr +2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 +cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE +Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s +t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +=========================== +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC +VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu +IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg +Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV +MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG +b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt +IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS +LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 +8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU +mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN +G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K +rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w +ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD +VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG +A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At +P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC ++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY +7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW +vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ +KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK +A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC +8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm +er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC +VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 +b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz +ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU +cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo +b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 +Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz +rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw +HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u +Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD +A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx +AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G2 +================================== +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC +TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l +ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ +5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn +vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj +CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil +e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR +OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI +CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65 +48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi +trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737 +qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB +AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC +ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA +A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz ++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj +f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN +kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk +CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF +URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb +CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h +oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV +IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm +66+KAQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +ACEDICOM Root +============= +-----BEGIN CERTIFICATE----- +MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD +T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4 +MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG +A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk +WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD +YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew +MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb +m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk +HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT +xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2 +3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9 +2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq +TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz +4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU +9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv +bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg +aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP +eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk +zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1 +ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI +KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq +nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE +I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp +MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o +tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA== +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +Certinomis - Autorité Racine +============================ +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg +LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG +A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw +JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa +wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly +Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw +2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N +jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q +c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC +lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb +xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g +530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna +4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x +WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva +R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 +nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B +CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv +JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE +qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b +WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE +wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ +vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ +Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 +dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu +c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv +bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 +aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 +fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm +N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN +Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T +tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX +e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA +2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs +HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib +D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +StartCom Certification Authority G2 +=================================== +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE +ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O +o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG +4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi +Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul +Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs +O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H +vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L +nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS +FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa +z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ +KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk +J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ +JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG +/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc +nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld +blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc +l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm +7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm +obp573PYtlNXLfbQ4ddI +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +EE Certification Centre Root CA +=============================== +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy +dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw +MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB +UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy +ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM +TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 +rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw +93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN +P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ +MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF +BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj +xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM +lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU +3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM +dcGWxZ0= +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 2007 +================================================= +-----BEGIN CERTIFICATE----- +MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP +MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg +QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X +DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl +a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN +BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp +bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N +YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv +KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya +KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT +rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC +AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s +Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I +aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO +Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb +BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK +poRq0Tl9 +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +================================= +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +PSCProcert +========== +-----BEGIN CERTIFICATE----- +MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk +ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ +MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz +dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl +cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw +IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw +MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w +DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD +ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp +Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC +wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA +3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh +RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO +EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2 +0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH +0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU +td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw +Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp +r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/ +AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz +Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId +xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp +ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH +EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h +Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k +ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG +9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG +MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG +LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52 +ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy +YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v +Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o +dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq +T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN +g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q +uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1 +n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn +FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo +5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq +3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5 +poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y +eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km +-----END CERTIFICATE----- + +China Internet Network Information Center EV Certificates Root +============================================================== +-----BEGIN CERTIFICATE----- +MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D +aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg +Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG +A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM +PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl +cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y +jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV +98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H +klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23 +KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC +7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD +glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5 +0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM +7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws +ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0 +5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8= +-----END CERTIFICATE----- + +Swisscom Root CA 2 +================== +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG +EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy +dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2 +MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln +aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM +LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo +ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ +wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH +Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a +SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS +NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab +mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY +Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3 +qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw +HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O +BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu +MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO +v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ +82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz +o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs +a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx +OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW +mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o ++sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC +rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX +5OfNeOI5wSsSnqaeG8XmDtkx2Q== +-----END CERTIFICATE----- + +Swisscom Root EV CA 2 +===================== +-----BEGIN CERTIFICATE----- +MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE +BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl +cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN +MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT +HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg +Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz +o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy +Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti +GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li +qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH +Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG +alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa +m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox +bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi +xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED +MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB +bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL +j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU +wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7 +XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH +59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/ +23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq +J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA +HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi +uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW +l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc= +-----END CERTIFICATE----- + +CA Disig Root R1 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy +3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8 +u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2 +m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk +CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa +YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6 +vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL +LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX +ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is +XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ +04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR +xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B +LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM +CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb +VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85 +YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS +ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix +lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N +UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ +a7+h89n07eLw4+1knj0vllJPgFOL +-----END CERTIFICATE----- + +CA Disig Root R2 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +========= +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +====================== +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +===================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +=========================== +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +=========================== +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +======================= +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +======================= +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +======================== +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE----- + +WoSign +====== +-----BEGIN CERTIFICATE----- +MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG +EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g +QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ +BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO +CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX +2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5 +KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR ++ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez +EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk +lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2 +8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY +yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C +AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R +8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1 +LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq +T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj +y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC +2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes +5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/ +EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh +mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx +kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi +kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w== +-----END CERTIFICATE----- + +WoSign China +============ +-----BEGIN CERTIFICATE----- +MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG +EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv +geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD +VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k +8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5 +uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85 +dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5 +Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy +b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc +76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m ++Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6 +yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX +GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA +A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6 +yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY +r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115 +j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A +kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97 +qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y +jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB +ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv +T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO +kI26oQ== +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + + +USERTrust ECC Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl +OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV +MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF +JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G3 +================================== +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC +TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l +ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y +olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t +x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy +EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K +Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur +mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5 +1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp +07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo +FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE +41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu +yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq +KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1 +v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA +8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b +8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r +mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq +1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI +JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV +tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk= +-----END CERTIFICATE----- + +Staat der Nederlanden EV Root CA +================================ +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M +MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl +cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk +SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW +O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r +0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 +Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV +XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr +08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV +0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd +74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx +fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa +ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu +c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq +5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN +b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN +f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi +5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 +WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK +DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy +eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +============================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +================================= +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +========================================== +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +============ +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 +==================================================== +-----BEGIN CERTIFICATE----- +MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN +BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp +bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg +RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw +ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w +SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE +n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp +ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537 +jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m +ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP +9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV +4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH +HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo +BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq +URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl +lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8 +B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU= +-----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6 +==================================================== +-----BEGIN CERTIFICATE----- +MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQGEwJUUjEPMA0G +A1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls +acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5 +MDQxMFoXDTIzMTIxNjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBL +BgNVBAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSf +aSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlm +aWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCdsGjW6L0UlqMACprx9MfMkU1xeHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a +2uqsxgbPJQ1BgfbBOCK9+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EED +wnS3/faAz1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0pu5Fb +HH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6plVxiSvgNZ1GpryHV ++DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMBAAGjQjBAMB0GA1UdDgQWBBTdVRcT +9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQsFAAOCAQEAb1gNl0OqFlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3R +fdCaqaXKGDsCQC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy +o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKIDgI6tflEATseW +hvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm9ocJV612ph1jmv3XZch4gyt1 +O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsGtAuYSyher4hYyw== +-----END CERTIFICATE----- + +Certinomis - Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg +LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx +EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD +ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos +P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo +d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap +z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00 +8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x +RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE +6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t +FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV +PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH +i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj +YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I +6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV +WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw +Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX +lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ +y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9 +Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng +DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi +I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM +cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr +hkIGuUE= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +Certification Authority of WoSign G2 +==================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG +EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g +QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx +CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai +XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du +W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9 +5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK +v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI +hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY +P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3 +TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu ++sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+ +7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg= +-----END CERTIFICATE----- + +CA WoSign ECC Root +================== +-----BEGIN CERTIFICATE----- +MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD +TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v +dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK +ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU +t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw +QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R +MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0 +Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu +a/GRspBl9JrmkO5K +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +Certplus Root CA G1 +=================== +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV +BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe +Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD +ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN +r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx +Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj +BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv +LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2 +z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc +4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd +4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj +jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+ +ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G +A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY +lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh +66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG +YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/ +2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F +6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX +CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe +tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC +VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/ ++mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+ +qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= +-----END CERTIFICATE----- + +Certplus Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT +AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x +NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0 +cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN +Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud +IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV +HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl +vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw== +-----END CERTIFICATE----- + +OpenTrust Root CA G1 +==================== +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx +MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM +CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa +Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87 +ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO +YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9 +xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO +9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq +3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi +n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9 +URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr +TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px +N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E +PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv +uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK +n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh +X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80 +nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm +GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/ +bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o +4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA +OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx +-----END CERTIFICATE----- + +OpenTrust Root CA G2 +==================== +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy +MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM +CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+ +Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz +4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV +eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt +UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz +3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj +3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz +9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0 +0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT +y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59 +M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz +Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI +mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG +S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp +EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ +6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr +gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo +SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0 +YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm +u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK +-----END CERTIFICATE----- + +OpenTrust Root CA G3 +==================== +-----BEGIN CERTIFICATE----- +MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X +DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w +ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B +ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf +BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM +BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta +3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +LuxTrust Global Root 2 +====================== +-----BEGIN CERTIFICATE----- +MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG +A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh +bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW +MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm +Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2 +xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC +wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm +1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm +FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF +wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/ +a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U +ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ +MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB +/zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5 +Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT ++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ +FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN +H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW +7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu +ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA +VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR +TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt +/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc +7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I +iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr +-----END CERTIFICATE----- diff --git a/project.h b/project.h index 30970850..fde9eaad 100644 --- a/project.h +++ b/project.h @@ -53,6 +53,12 @@ #include "mbedtls/ssl_cache.h" #endif +/* + * Macros for SSL structures + */ +#define CERT_INFO_BUF_SIZE 4096 +#define CERT_FILE_BUF_SIZE 16384 + /* Need for struct sockaddr_storage */ #ifdef HAVE_RFC2553 # ifndef _WIN32 @@ -320,6 +326,15 @@ struct http_request int server_ssl; }; +/* + * Struct for linked list containing certificates + */ +typedef struct certs_chain { + char text_buf[CERT_INFO_BUF_SIZE]; /* text info about properties of certificate */ + char file_buf[CERT_FILE_BUF_SIZE]; /* buffer for whole certificate - format to save in file */ + struct certs_chain *next; /* next certificate in chain of trust */ +}certs_chain_t; + /** * Reasons for generating a http_response instead of delivering * the requested resource. Mostly ordered the way they are checked @@ -1044,6 +1059,9 @@ struct client_state */ char *error_message; + /* Result of server certificate verification */ + uint32_t server_cert_verification_result; + /* * Flags if SSL connection with server or client is opened. * Thanks to this flags, we can call function to close connections @@ -1054,6 +1072,12 @@ struct client_state int use_ssl_tunnel; const struct forward_spec * use_fwd; + + /* + * Server certificate chain of trust including strings with certificates + * informations and string with whole certificate file + */ + struct certs_chain server_certs_chain; }; /** diff --git a/ssl.c b/ssl.c index 4e1b3e2a..33976eee 100644 --- a/ssl.c +++ b/ssl.c @@ -43,6 +43,8 @@ */ #define ERROR_BUF_SIZE 1024 /* Size of buffer for error messages */ +static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); +static void free_certificate_chain(struct client_state *csp); 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); @@ -570,7 +572,18 @@ extern int create_server_ssl_connection(struct client_state *csp) char err_buf[ERROR_BUF_SIZE]; memset(err_buf, 0, ERROR_BUF_SIZE); - int auth_mode = MBEDTLS_SSL_VERIFY_NONE; + char *trusted_cas_file = NULL; + csp->server_cert_verification_result = SSL_CERT_NOT_VERIFIED; + csp->server_certs_chain.next = NULL; + + int auth_mode = MBEDTLS_SSL_VERIFY_REQUIRED; + + /* Setting path to file with trusted CAs */ + size_t size = strlen(basedir) + 1; + trusted_cas_file = (char *)malloc(size + 18); + memset(trusted_cas_file, 0, size + 18); + strlcpy(trusted_cas_file, basedir, size + 18); + strlcat(trusted_cas_file, "/CA/trustedCAs.pem", size + 18); /* * Initializing mbedtls structures for SSL/TLS connection @@ -599,6 +612,20 @@ extern int create_server_ssl_connection(struct client_state *csp) ret = -1; goto exit; } + + /* + * Loading file with trusted CAs + */ + ret = mbedtls_x509_crt_parse_file(&(csp->mbedtls_server_attr.ca_cert), + trusted_cas_file); + if (ret < 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "Loading trusted CAs file %s failed: %s", + trusted_cas_file, err_buf); + ret = -1; + goto exit; + } /* * Set SSL/TLS options @@ -616,10 +643,18 @@ extern int create_server_ssl_connection(struct client_state *csp) goto exit; } + /* + * Setting how strict should certificate verification be and other + * parameters for certificate verification + */ mbedtls_ssl_conf_authmode(&(csp->mbedtls_server_attr.conf), auth_mode); mbedtls_ssl_conf_ca_chain(&(csp->mbedtls_server_attr.conf), &(csp->mbedtls_server_attr.ca_cert), NULL); + /* Setting callback function for certificates verification */ + mbedtls_ssl_conf_verify(&(csp->mbedtls_server_attr.conf), + ssl_verify_callback, (void *)csp); + mbedtls_ssl_conf_rng(&(csp->mbedtls_server_attr.conf), mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_dbg(&(csp->mbedtls_server_attr.conf), @@ -635,6 +670,20 @@ extern int create_server_ssl_connection(struct client_state *csp) goto exit; } + /* + * Set the hostname to check against the received server certificate + */ + ret = mbedtls_ssl_set_hostname(&(csp->mbedtls_server_attr.ssl), + csp->http->host); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_ssl_set_hostname failed: %s", + err_buf); + ret = -1; + goto exit; + } + mbedtls_ssl_set_bio(&(csp->mbedtls_server_attr.ssl), &(csp->mbedtls_server_attr.socket_fd), mbedtls_net_send, mbedtls_net_recv, NULL); @@ -651,17 +700,36 @@ extern int create_server_ssl_connection(struct client_state *csp) && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { mbedtls_strerror(ret, err_buf, sizeof(err_buf)); - log_error(LOG_LEVEL_ERROR, - "mbedtls_ssl_handshake with server failed: %s", err_buf); - ret = -1; + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) + { + log_error(LOG_LEVEL_ERROR, + "Server cerificate verification failed: %s", err_buf); + csp->server_cert_verification_result = + mbedtls_ssl_get_verify_result(&(csp->mbedtls_server_attr.ssl)); + + ret = -1; + } + else + { + log_error(LOG_LEVEL_ERROR, + "mbedtls_ssl_handshake with server failed: %s", err_buf); + ret = -1; + } goto exit; } } log_error(LOG_LEVEL_CONNECT, "Server successfully connected over SSL/TLS"); + /* + * Server certificate chain is valid, so we can clean + * chain, because we will not send it to client. + */ + free_certificate_chain(csp); + csp->ssl_with_server_is_opened = 1; + csp->server_cert_verification_result = mbedtls_ssl_get_verify_result(&(csp->mbedtls_server_attr.ssl)); exit: /* Freeing structures if connection wasn't created successfully */ @@ -820,6 +888,67 @@ extern int tunnel_established_successfully(const char * server_response, unsigne } +/*======================Certificates======================*/ + +/********************************************************************* + * + * Function : ssl_verify_callback + * + * Description : This is callback function for certificates verification. + * It's called for all certificates in server certificate + * trusted chain. + * + * Parameters : + * 1 : csp_void = Current client state (buffers, headers, etc...) + * 2 : crt = certificate from trusted chain + * 3 : depth = depth in trusted chain + * 4 : flags = certificate flags + * + * Returns : 0 on success and negative value on error + * + *********************************************************************/ +static int ssl_verify_callback(void *csp_void, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ + return 0; +} + + +/********************************************************************* + * + * Function : free_certificate_chain + * + * Description : Frees certificates linked list. This linked list is used + * to save informations about certificates in trusted chain. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +static void free_certificate_chain(struct client_state *csp) { + struct certs_chain * cert = csp->server_certs_chain.next; + + /* Cleaning buffers */ + memset(csp->server_certs_chain.text_buf, 0, + sizeof(csp->server_certs_chain.text_buf)); + memset(csp->server_certs_chain.text_buf, 0, + sizeof(csp->server_certs_chain.file_buf)); + csp->server_certs_chain.next = NULL; + + /* Freeing memory in whole linked list */ + if (cert != NULL) + { + do + { + struct certs_chain *cert_for_free = cert; + cert = cert->next; + freez(cert_for_free); + } while (cert != NULL); + } +} + + /********************************************************************* * * Function : seed_rng diff --git a/ssl.h b/ssl.h index a5d805eb..62ec84a5 100644 --- a/ssl.h +++ b/ssl.h @@ -32,6 +32,16 @@ #include "project.h" +/* + * Values for flag determining certificate validity. + * These values are compatible with return value of function + * mbedtls_ssl_get_verify_result. There is not value for invalid + * certificate, this value is setted by function + * mbedtls_ssl_get_verify_result. + */ +#define SSL_CERT_VALID 0 +#define SSL_CERT_NOT_VERIFIED 0xFFFFFFFF + /* Variables for one common RNG for all SSL use */ static mbedtls_ctr_drbg_context ctr_drbg; static mbedtls_entropy_context entropy; -- 2.26.2 From ac400b7385022f2a0f8a3dc13458f6f30cb55583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:52:32 +0200 Subject: [PATCH 14/83] Added functions to generate and save key for host name. Added malloc output check. --- project.h | 9 ++ ssl.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 259 insertions(+), 2 deletions(-) diff --git a/project.h b/project.h index fde9eaad..2a589be5 100644 --- a/project.h +++ b/project.h @@ -326,6 +326,15 @@ struct http_request int server_ssl; }; +/* + * Propeties of key for generating + */ +typedef struct { + mbedtls_pk_type_t type; /* type of key to generate */ + int rsa_keysize; /* length of key in bits */ + char *key_file_path; /* filename of the key file */ +} key_options; + /* * Struct for linked list containing certificates */ diff --git a/ssl.c b/ssl.c index 33976eee..6bd0920b 100644 --- a/ssl.c +++ b/ssl.c @@ -42,7 +42,12 @@ * Macros for ssl.c */ #define ERROR_BUF_SIZE 1024 /* Size of buffer for error messages */ +#define PRIVATE_KEY_BUF_SIZE 16000 /* Size of buffer to save private key. Value 16000 is taken from mbed TLS library examples. */ +#define RSA_KEY_PUBLIC_EXPONENT 65537 /* Public exponent for RSA private key generating */ +#define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ +#define KEY_FILE_TYPE ".pem" +static int file_exists(const char * path); static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); static void free_certificate_chain(struct client_state *csp); static void free_client_ssl_structures(struct client_state *csp); @@ -330,16 +335,23 @@ extern int create_client_ssl_connection(struct client_state *csp) */ size_t size = strlen(basedir) + 1; ca_file = (char *)malloc(size + 14); + cert_file = (char *)malloc(size + 29); + key_file = (char *)malloc(size + 29); + + if (ca_file == NULL || cert_file == NULL || key_file == NULL) + { + log_error(LOG_LEVEL_ERROR, "create_client_ssl_connection failed: malloc fail"); + return NULL; + } + memset(ca_file, 0, size + 14); strlcpy(ca_file, basedir, size + 14); strlcat(ca_file, "/CA/cacert.crt", size + 14); - cert_file = (char *)malloc(size + 29); memset(cert_file, 0, size + 29); strlcpy(cert_file, basedir, size + 29); strlcat(cert_file, "/CA/webpagesCerts/privoxy.crt", size + 29); - key_file = (char *)malloc(size + 29); memset(key_file, 0, size + 29); strlcpy(key_file, basedir, size + 29); strlcat(key_file, "/CA/webpagesCerts/privoxy.key", size + 29); @@ -581,6 +593,11 @@ extern int create_server_ssl_connection(struct client_state *csp) /* Setting path to file with trusted CAs */ size_t size = strlen(basedir) + 1; trusted_cas_file = (char *)malloc(size + 18); + if (trusted_cas_file == NULL) + { + log_error(LOG_LEVEL_ERROR, "create_server_ssl_connection failed: malloc fail"); + return NULL; + } memset(trusted_cas_file, 0, size + 18); strlcpy(trusted_cas_file, basedir, size + 18); strlcat(trusted_cas_file, "/CA/trustedCAs.pem", size + 18); @@ -890,6 +907,211 @@ extern int tunnel_established_successfully(const char * server_response, unsigne /*======================Certificates======================*/ +/* + * Function : write_private_key + * + * Description : Writes private key into file and copies saved content into + * given pointer to string. If fuction returns 0 for success, + * this copy must be freed by caller. + * + * Parameters : + * 1 : key = key to write into file + * 2 : ret_buf = pointer to string with created key file content + * 3 : key_file_path = path where to save key file + * + * Returns : Length of written private key on success or negative value + * on error + * + */ +static int write_private_key(mbedtls_pk_context *key, unsigned char ** ret_buf, const char * key_file_path) +{ + size_t len = 0; /* Length of created key */ + FILE *f = NULL; /* File to save certificate */ + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, sizeof(err_buf)); + + /* Initializing buffer for key file content */ + *ret_buf = (unsigned char *)malloc((PRIVATE_KEY_BUF_SIZE + 1) * sizeof(unsigned char)); + if (*ret_buf == NULL) { + log_error(LOG_LEVEL_ERROR, + "Creating buffer for private key failed: malloc fail"); + ret = -1; + goto exit; + } + memset(*ret_buf, 0, PRIVATE_KEY_BUF_SIZE + 1); + + /* + * Writing private key into PEM string + */ + if ((ret = mbedtls_pk_write_key_pem(key, *ret_buf, PRIVATE_KEY_BUF_SIZE)) != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Writing private key into PEM string failed: %s", err_buf); + ret = -1; + goto exit; + } + len = strlen((char *)*ret_buf); + + /* + * Saving key into file + */ + if ((f = fopen(key_file_path, "wb")) == NULL) + { + log_error(LOG_LEVEL_ERROR, "Opening file %s to save private key failed", + key_file_path); + ret = -1; + goto exit; + } + + if (fwrite(*ret_buf, 1, len, f) != len) + { + fclose(f); + log_error(LOG_LEVEL_ERROR, "Writing private key into file %s failed", + key_file_path); + ret = -1; + goto exit; + } + + fclose(f); + +exit: + if (ret < 0) + { + freez(*ret_buf); + *ret_buf = NULL; + return ret; + } + return len; +} + + +/********************************************************************* + * + * Function : generate_key + * + * Description : Tests if private key for host saved in csp already exists. + * If this file doesn't exists, new key is generated and saved + * in file. Generated key is also copied into given parameter + * key_buf, which must be then freed by caller. If file with key + * exists, key_buf contain NULL and no private key is generated. + * + * Parameters : + * 1 : key_buf = buffer to save new generated key + * 2 : csp = Current client state (buffers, headers, etc...) + * + * Returns : -1 => Error while generating private key + * 0 => Key already exists + * >0 => Length of generated private key + * + *********************************************************************/ +extern int generate_key(unsigned char ** key_buf, struct client_state *csp) +{ + mbedtls_pk_context key; + key_options key_opt; + key_opt.key_file_path = NULL; + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, sizeof(err_buf)); + + /* + * Initializing structures for key generating + */ + mbedtls_pk_init(&key); + + /* + * Preparing path for key file and other properties for generating key + */ + key_opt.type = MBEDTLS_PK_RSA; + key_opt.rsa_keysize = RSA_KEYSIZE; + + size_t size = strlen(basedir) + strlen((char *)csp->http->host) + 1; + char *key_file = (char *)malloc(size + 22); + if (key_file == NULL) + { + log_error(LOG_LEVEL_ERROR, "generate_key failed: malloc fail"); + return NULL; + } + memset(key_file, 0, size + 22); + strlcpy(key_file, basedir, size + 22); + strlcat(key_file, "/CA/webpagesCerts/", size + 22); + strlcat(key_file, (char *)csp->http->host, size + 22); + strlcat(key_file, ".pem", size + 22); + key_opt.key_file_path = key_file; + + if (key_opt.key_file_path == NULL) + { + ret = -1; + goto exit; + } + + /* + * Test if key already exists. If so, we don't have to create it again. + */ + if (file_exists(key_opt.key_file_path) == 1) + { + ret = 0; + goto exit; + } + + /* + * Seed the RNG + */ + ret = seed_rng(csp); + if (ret != 0) + { + ret = -1; + goto exit; + } + + /* + * Setting atributes of private key and generating it + */ + if ((ret = mbedtls_pk_setup(&key, + mbedtls_pk_info_from_type(key_opt.type))) != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_pk_setup failed: %s", err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(key), mbedtls_ctr_drbg_random, + &ctr_drbg, key_opt.rsa_keysize, RSA_KEY_PUBLIC_EXPONENT); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "Key generating failed: %s", err_buf); + ret = -1; + goto exit; + } + + /* + * Exporting private key into file + */ + if ((ret = write_private_key(&key, key_buf, key_opt.key_file_path)) < 0) + { + log_error(LOG_LEVEL_ERROR, " Writing private key into file failed"); + ret = -1; + goto exit; + } + +exit: + /* + * Freeing used variables + */ + if (key_opt.key_file_path != NULL) + { + freez(key_opt.key_file_path); + } + + mbedtls_pk_free(&key); + + return ret; +} + + /********************************************************************* * * Function : ssl_verify_callback @@ -949,6 +1171,32 @@ static void free_certificate_chain(struct client_state *csp) { } +/********************************************************************* + * + * Function : file_exists + * + * Description : Tests if file exists and is readable. + * + * Parameters : + * 1 : path = Path to tested file. + * + * Returns : 1 => File exists and is readable. + * 0 => File doesn't exist or is not readable. + * + *********************************************************************/ +static int file_exists(const char * path) +{ + FILE * f; + if ((f = fopen(path, "r")) != NULL) + { + fclose(f); + return 1; + } + + return 0; +} + + /********************************************************************* * * Function : seed_rng -- 2.26.2 From 4e1f3d79a2a52427f600ff02999b1b1d1b823fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:54:24 +0200 Subject: [PATCH 15/83] Added function for creating absolute path of files from given parameters. --- ssl.c | 141 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 39 deletions(-) diff --git a/ssl.c b/ssl.c index 6bd0920b..c2f6ced8 100644 --- a/ssl.c +++ b/ssl.c @@ -46,7 +46,9 @@ #define RSA_KEY_PUBLIC_EXPONENT 65537 /* Public exponent for RSA private key generating */ #define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ #define KEY_FILE_TYPE ".pem" +#define CERT_FILE_TYPE ".crt" +static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); static int file_exists(const char * path); static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); static void free_certificate_chain(struct client_state *csp); @@ -333,29 +335,16 @@ extern int create_client_ssl_connection(struct client_state *csp) /* * Preparing paths to certificates files and key file */ - size_t size = strlen(basedir) + 1; - ca_file = (char *)malloc(size + 14); - cert_file = (char *)malloc(size + 29); - key_file = (char *)malloc(size + 29); + ca_file = make_certs_path("CA", "cacert", CERT_FILE_TYPE); + cert_file = make_certs_path("CA/webpagesCerts", "privoxy", CERT_FILE_TYPE); + key_file = make_certs_path("CA/webpagesCerts", "privoxy", ".key"); if (ca_file == NULL || cert_file == NULL || key_file == NULL) { - log_error(LOG_LEVEL_ERROR, "create_client_ssl_connection failed: malloc fail"); - return NULL; + ret = -1; + goto exit; } - memset(ca_file, 0, size + 14); - strlcpy(ca_file, basedir, size + 14); - strlcat(ca_file, "/CA/cacert.crt", size + 14); - - memset(cert_file, 0, size + 29); - strlcpy(cert_file, basedir, size + 29); - strlcat(cert_file, "/CA/webpagesCerts/privoxy.crt", size + 29); - - memset(key_file, 0, size + 29); - strlcpy(key_file, basedir, size + 29); - strlcat(key_file, "/CA/webpagesCerts/privoxy.key", size + 29); - /* * Seed the RNG */ @@ -591,16 +580,12 @@ extern int create_server_ssl_connection(struct client_state *csp) int auth_mode = MBEDTLS_SSL_VERIFY_REQUIRED; /* Setting path to file with trusted CAs */ - size_t size = strlen(basedir) + 1; - trusted_cas_file = (char *)malloc(size + 18); + trusted_cas_file = make_certs_path("CA", "trustedCAs", KEY_FILE_TYPE); if (trusted_cas_file == NULL) { - log_error(LOG_LEVEL_ERROR, "create_server_ssl_connection failed: malloc fail"); - return NULL; + ret = -1; + goto exit; } - memset(trusted_cas_file, 0, size + 18); - strlcpy(trusted_cas_file, basedir, size + 18); - strlcat(trusted_cas_file, "/CA/trustedCAs.pem", size + 18); /* * Initializing mbedtls structures for SSL/TLS connection @@ -1026,20 +1011,8 @@ extern int generate_key(unsigned char ** key_buf, struct client_state *csp) key_opt.type = MBEDTLS_PK_RSA; key_opt.rsa_keysize = RSA_KEYSIZE; - size_t size = strlen(basedir) + strlen((char *)csp->http->host) + 1; - char *key_file = (char *)malloc(size + 22); - if (key_file == NULL) - { - log_error(LOG_LEVEL_ERROR, "generate_key failed: malloc fail"); - return NULL; - } - memset(key_file, 0, size + 22); - strlcpy(key_file, basedir, size + 22); - strlcat(key_file, "/CA/webpagesCerts/", size + 22); - strlcat(key_file, (char *)csp->http->host, size + 22); - strlcat(key_file, ".pem", size + 22); - key_opt.key_file_path = key_file; - + key_opt.key_file_path = make_certs_path("CA/webpagesCerts", + (char *)csp->http->host, KEY_FILE_TYPE); if (key_opt.key_file_path == NULL) { ret = -1; @@ -1112,6 +1085,96 @@ exit: } +/********************************************************************* + * + * Function : make_certs_path + * + * Description : Creates path to file from three pieces. This fuction takes + * this parameters and put them in one new mallocated + * char * in correct order. Returned variable must be freed + * by caller. This function is mainly used for creating paths + * of certificates and keys files. + * + * Parameters : + * 1 : conf_dir = Name/path of directory where is the file. + * '.' can be used for current directory. + * 2 : file_name = Name of file in conf_dir without suffix. + * 3 : suffix = Suffix of given file_name. + * + * Returns : path => Path was built up successfully + * NULL => Path can't be built up + * + *********************************************************************/ +static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix) +{ + /* Test if all given parameters are valid */ + if (conf_dir == NULL || *conf_dir == '\0' || file_name == NULL + || *file_name == '\0' || suffix == NULL || *suffix == '\0') + { + log_error(LOG_LEVEL_ERROR, + "make_certs_path failed: bad input parameters"); + return NULL; + } + + char * path = NULL; + size_t path_size = strlen(conf_dir) + + strlen(file_name) + strlen(suffix) + 2; + + /* Setting delimiter and editing path length */ +#if defined(_WIN32) || defined(__OS2__) + char delim[] = "\\"; + path_size += 1; +#else /* ifndef _WIN32 || __OS2__ */ + char delim[] = "/"; +#endif /* ifndef _WIN32 || __OS2__ */ + + /* + * Biuilding up path from many parts + */ +#if defined(unix) + if (*conf_dir != '/' && basedir && *basedir) + { + /* + * Replacing conf_dir with basedir. This new variable contains + * absolute path to cwd. + */ + path_size += strlen(basedir) + 2; + path = (char *)malloc(path_size); + if (path == NULL) + { + log_error(LOG_LEVEL_ERROR, "make_certs_path failed: malloc fail"); + return NULL; + } + memset(path, 0, path_size); + + strlcpy(path, basedir, path_size); + strlcat(path, delim, path_size); + strlcat(path, conf_dir, path_size); + strlcat(path, delim, path_size); + strlcat(path, file_name, path_size); + strlcat(path, suffix, path_size); + } + else +#endif /* defined unix */ + { + path = (char *)malloc(path_size); + if (path == NULL) + { + log_error(LOG_LEVEL_ERROR, "make_certs_path failed: malloc fail"); + return NULL; + } + memset(path, 0, path_size); + + strlcpy(path, conf_dir, path_size); + strlcat(path, delim, path_size); + strlcat(path, file_name, path_size); + strlcat(path, suffix, path_size); + } + + return path; +} + + /********************************************************************* * * Function : ssl_verify_callback -- 2.26.2 From 6cf171fd1379551ebdab61d0341d3cc44b753b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:55:12 +0200 Subject: [PATCH 16/83] Freeing alocated paths to files. --- ssl.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ssl.c b/ssl.c index c2f6ced8..ef5de8b6 100644 --- a/ssl.c +++ b/ssl.c @@ -477,6 +477,21 @@ extern int create_client_ssl_connection(struct client_state *csp) csp->ssl_with_client_is_opened = 1; exit: + /* + * Freeing allocated paths to files + */ + if (ca_file != NULL) + { + freez(ca_file); + } + if (cert_file != NULL) + { + freez(cert_file); + } + if (key_file != NULL) + { + freez(key_file); + } /* Freeing structures if connection wasn't created successfully */ if (ret < 0) @@ -734,6 +749,14 @@ extern int create_server_ssl_connection(struct client_state *csp) csp->server_cert_verification_result = mbedtls_ssl_get_verify_result(&(csp->mbedtls_server_attr.ssl)); exit: + /* + * Freeing allocated paths to files + */ + if (trusted_cas_file != NULL) + { + freez(trusted_cas_file); + } + /* Freeing structures if connection wasn't created successfully */ if (ret < 0) { -- 2.26.2 From 6985c9159c5b11ad646eea450a5f4c39eca96907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:55:47 +0200 Subject: [PATCH 17/83] Generating certificate for requested webpage. Without saving as a file. --- CA/cakey.pem | 51 ++++++++ project.h | 20 +++ ssl.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 417 insertions(+) create mode 100644 CA/cakey.pem diff --git a/CA/cakey.pem b/CA/cakey.pem new file mode 100644 index 00000000..12884968 --- /dev/null +++ b/CA/cakey.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJJwIBAAKCAgEA2J9FIFwONj8rGJyF+bfID7V8arTqWbH8Ms9jlZSNeKoAJPuZ +1kqthu9JO9yN2auBfnt2IY3jj/XEChEj90amhQB/RQsnx9Ols3o7Tjvuxf+5GHCW +7Vr34mNl/dgwWXO0+wiCfvewGxkL+kUdx4J93vT585SYm7eMOjvo3Fg4/rZkS0Nw +vePbft81ETwCx38qwhAcccEmTSm7geUdkpqwPdrQPHqa59CAhTtarTKNMDBDa0eq +AP3phkkgYOZDy42hxeqnW1Ia6qn408UVGFw27yWdOqrDjBmfQVkrrb55CXhaH1wk +0RBTsigHlH92/oJlvv70/P4bJez9dtH7WlglVqwtbSeR/ZW3Z/NeCjbh/uPCAbb+ +Dxfd0bSmOYguZ4SUeNViJUNCc1REnyVOJl3/50M/WdlGF3BMm17BcNdFpH/VAE8p +JtDQchY9fuBavAuJPGa6NEsxEVqxznDkeQGCX+dMX45WuhBtNrXq5Ij+jxhnA879 +0MB1HeAFwWDimso9dkWMIGedt/Y6r0jLTNhUhefX9hWJEDlOjCgY+n41azoF7bjr +ZWp47JJ/qxkDcRNbCrLpZHnFpixcfCfcDpQlULavPhZtp0cf7x9/G81kgLZvyKKT +AfmgEZw2v6/Z05Z+DIS4CynlKXFoCTSCjv6jfFiAWFpyCyvhHQC/QdTbrK8CAwEA +AQKCAgBTukPqvQoVN5c9vQofukROphQ/3kuSfbQAI57XKwL/d530rXcJl/W4aPbC +d34wexTjQW8oiwJBG3o5deST6C/myolms2gd2ZV7aKxRkeK5jx0I8EO13Gphi4/Z +bN1LRejW+rQNxUjBQI4bnuliuvJR4hhWaMIPtgMyYwOfX04wTWk4mgmSq+akBDwr +vClK2ME7HyUPZtuaCZ5bF6a1iqrCTbgdGDqVjUaPuKBUv2xJCu6UIa/5ECtZ5xvn +uDjODaFQsWEccADNYQM3Pz7nGoV1K/G4wlYw6ZpflMrILg30dhtHccMdN5VSEBzV +7eqdduNCzqL8wm7V2uMhMQpZIibTwkTfO2jxFVac/Q7pwHbE4mo7L/F5KSeZQrTc +tZvS0EOezJUokep2R0UBqHpLb0zWOvUD3zkDroHK4lj9FuDxxChPuyKZj/xpBYGe +5YwSM/vFO8L+EcD4H+5prJrKeY1xVv5U7gQdIz5rhAir342Kp3MJXx29Ny41HMon +62J0Q7bo7SOKM9zbSc9clZhLv6FLvIZ79HxDeDQx2Gnb69Hygqw0aCPfcXYby0sW +Bot47vg+8HfKJle5v/sltssEe6QbBMH7VRw3JQm5ATXtvUS8513M8WjQO6ZIc88t +UvxeeRS4Lm9wX6eqDYloD940FlgqY4njmjnIfE4TWoj5dZ6ZsQKCAQEA8LXA8sfg +XTbQAIW1pDEsqEk+xqOgnUGt2JcL3Z+et3JAw8JvsWpDOe28cJKSwaHpy4JUyrKa +vSsqFvX4wLxHkY8YhnFDUfK7moSd6r4VmWoZUFZ579xLcVTgWpWO0bKho+X+l2Ac +tVWE/KdkcTAYDUwS36gj2P/Pa+DuDSQ9pVnyNM5+Nq/n3WvD8c/euvAAiivSc1Ja +aLZtn7tsRI3zdvGDGUts/utVdppA+db6+bZtio3MgG4CKsjs8vCTj5hS3iKZNdHf +uZ2/nYCR43zd3AwIvgW9IjV14+UNPmrhksDggVSzsIWJzD5PDNzj7wE6ViqVxh64 +joq7omhV7/FOhwKCAQEA5mHRahPk/K09Sg1o9qfqBTsJcBvsd23MifxTfSzxKiBh +CYyoVHBdcSYSyU81cgT6wFGNXevGmd7WtwPGwYh1AK+OgvOwp854/OnMe4oeMYsW +1+5WC5Uw8oDxQA1gFQfqHqg4rYqZHiLvS8/LpQa5XtP8xIioZcgIZce9gzLSMTyb +CUmr8IWGiYvhhFmdy+0aO2E/WFr97YqwCRdN1O/qcNvPl03+P36e03ddbp+gbjhO +hjTmoRDld4l0z1hfOqxvdgtYMM5EeQ4QolCH4V7RFn6B9bwdX0I5D/lRKMNJeqqs +yOhHzv4plSPZc3N2CdclcSBbhn8OHSo9bLo5mD/SmQKCAQArzngR9ww/CpWqMqtO ++WAONF5HWkoFtIlF7J9NMxp4ekONHNqk6BjZ9wkfV517vdLFpa92wDBnEu7zBMrD +kMBZnjgxZ3V/+XPo+A+hQ/y8UdHPjB1e6LGWK4M1GRjH0wGVyWqe8+/llG3CaVhf +PQhziw+4QmpbuJpwIJxSKfFKIWdx8s6Hd1X0NwOPA2yeisUeYEFJmYg4nFKxCjP2 ++fqAAA4C0XZBomSIVCRVE6nTPj8LQykfimW8kZqF0ACa1nbmVFebstlLd4kCyf5C +71uVC1+f7X1xN1eAJRRW8q6gvZdeEiMtke/1CrXqOl0FBy0tt0xQpRCjaF4jfWd+ +ZmULAoIBAHHIfhVWHhJtvYeFeAHajMpojhDAudmCcTL1XIbGW5XiyApfXgPWO1BW +7ZBffpYBv5acsKVifYQhewqI4vFS4/aivlAO64D1iOvgzQ12+dKeT3n2TKkL1lDv +PjfUY0//yLG7g8KyYU1xE57t0jZ/S656JK0skX8zfHJIZGEYCJgoxqmfqTvxtrDY +VVl4qWa+g+Yv8YlB54gapzbWO6qfk7qJ1c10x820S91FZu/sBuBpDt9Z4U5Legm/ +6eE+VEo2QBadI8F3HnprZ+vCulmk6r+hW65yak9R9bzd9ieby/65rPzNPCoPfZob +Spqqu/HAQM3OnWWf+uiMpCm/EBMR8oECggEAdPdBPHxKqIsAfdQ2WgDuDhZogAX3 +ddlun2PgJ3JbaqAVG1IJjaeJkZj0+VI5I2hK3j1KFI4D8AVO0sLFMaJUFu3kNOJv +a//L03K+BvKkalptixEUt9gpbAAaMo4OKaHnkpy5npulXmGMHYzVKieIKdBcz0Ny +hpBeF+jSkROqN/m9rlzxBi6ZnUTGkNTeTwtR3Bma5AOGQdyiiAqisOVTRLlvN7Rd +J3eTnc3XKBkOOyKzbVCfuZs5y9hrOgsTVkkn97dws25yJspd7Xp1OTcugaQ3Hce8 +9135Rq2WO7gcCQgsFvcVpIekRVh+82eYKDVngzLW9/kPNBSXeXa/NViSeg== +-----END RSA PRIVATE KEY----- diff --git a/project.h b/project.h index 2a589be5..4018b3e6 100644 --- a/project.h +++ b/project.h @@ -58,6 +58,7 @@ */ #define CERT_INFO_BUF_SIZE 4096 #define CERT_FILE_BUF_SIZE 16384 +#define ISSUER_NAME_BUF_SIZE 2048 /* Need for struct sockaddr_storage */ #ifdef HAVE_RFC2553 @@ -326,6 +327,25 @@ struct http_request int server_ssl; }; +/* + * Properties of cert for generating + */ +typedef struct { + char *issuer_crt; /* filename of the issuer certificate */ + char *subject_key; /* filename of the subject key file */ + char *issuer_key; /* filename of the issuer key file */ + const char *subject_pwd; /* password for the subject key file */ + const char *issuer_pwd; /* password for the issuer key file */ + char *output_file; /* where to store the constructed key file */ + const char *subject_name; /* subject name for certificate */ + char issuer_name[ISSUER_NAME_BUF_SIZE]; /* issuer name for certificate */ + const char *not_before; /* validity period not before */ + const char *not_after; /* validity period not after */ + const char *serial; /* serial number string */ + int is_ca; /* is a CA certificate */ + int max_pathlen; /* maximum CA path length */ +} cert_options; + /* * Propeties of key for generating */ diff --git a/ssl.c b/ssl.c index ef5de8b6..504b46e8 100644 --- a/ssl.c +++ b/ssl.c @@ -42,12 +42,22 @@ * Macros for ssl.c */ #define ERROR_BUF_SIZE 1024 /* Size of buffer for error messages */ +#define CERTIFICATE_BUF_SIZE 16384 /* Size of buffer to save certificate. Value 4096 is mbedtls library buffer size for certificate in DER form */ #define PRIVATE_KEY_BUF_SIZE 16000 /* Size of buffer to save private key. Value 16000 is taken from mbed TLS library examples. */ #define RSA_KEY_PUBLIC_EXPONENT 65537 /* Public exponent for RSA private key generating */ #define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ +#define GENERATED_CERT_VALID_FROM "20100101000000" /* Date and time, which will be setted in generated certificates as parameter valid from */ +#define GENERATED_CERT_VALID_TO "20401231235959" /* Date and time, which will be setted in generated certificates as parameter valid to */ +#define CERT_SIGNATURE_ALGORITHM MBEDTLS_MD_SHA256 /* The MD algorithm to use for the signature */ +#define CERT_PARAM_COMMON_NAME "CN=" +#define CERT_PARAM_ORGANIZATION ",O=" +#define CERT_PARAM_ORG_UNIT ",OU=" +#define CERT_PARAM_COUNTRY ",C=CZ" #define KEY_FILE_TYPE ".pem" #define CERT_FILE_TYPE ".crt" +#define CERT_SUBJECT_PASSWORD "" +extern int generate_webpage_certificate(struct client_state * csp); static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); static int file_exists(const char * path); static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags); @@ -345,6 +355,18 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } + /* + * Generating certificate for requested host. + */ + ret = generate_webpage_certificate(csp); + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, + "Generate_webpage_certificate failed: %d", ret); + ret = -1; + goto exit; + } + /* * Seed the RNG */ @@ -1108,6 +1130,330 @@ exit: } +/********************************************************************* + * + * Function : generate_webpage_certificate + * + * Description : Creates certificate. Subject of certificate is named + * by csp->http->host from parameter. This function also + * call generating of private key for new certificate. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : -1 => Error while creating certificate. + * 0 => Certificate alreaday exist. + * >0 => Length of created certificate. + * + *********************************************************************/ +extern int generate_webpage_certificate(struct client_state * csp) +{ + mbedtls_x509_crt issuer_cert; + mbedtls_pk_context loaded_issuer_key, loaded_subject_key; + mbedtls_pk_context *issuer_key = &loaded_issuer_key; + mbedtls_pk_context *subject_key = &loaded_subject_key; + mbedtls_x509write_cert cert; + mbedtls_mpi serial; + + unsigned char * key_buf = NULL; /* Buffer for created key */ + + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + memset(err_buf, 0, sizeof(err_buf)); + cert_options cert_opt; + + /* Paths to keys and certificates needed to create certificate */ + cert_opt.issuer_key = NULL; + cert_opt.subject_key = NULL; + cert_opt.issuer_crt = NULL; + + /* + * Create key for requested host + */ + int subject_key_len = generate_key(&key_buf, csp); + if (subject_key_len < 0) + { + log_error(LOG_LEVEL_ERROR, "Key generating failed"); + return -1; + } + + + /* + * Initializing structures for certificate generating + */ + mbedtls_x509write_crt_init(&cert); + mbedtls_x509write_crt_set_md_alg(&cert, CERT_SIGNATURE_ALGORITHM); + mbedtls_pk_init(&loaded_issuer_key); + mbedtls_pk_init(&loaded_subject_key); + mbedtls_mpi_init(&serial); + mbedtls_x509_crt_init(&issuer_cert); + + /* + * Presetting parameters for certificate. We must compute total length + * of parameters. + */ + int cert_params_len = strlen(CERT_PARAM_COMMON_NAME) + + strlen(CERT_PARAM_ORGANIZATION) + strlen(CERT_PARAM_COUNTRY) + + strlen(CERT_PARAM_ORG_UNIT) + + 3 * strlen(csp->http->host) + 1; + char cert_params[cert_params_len]; + memset(cert_params, 0, cert_params_len); + + /* + * Temporarily fixed serial number + */ + char serial_num_text[2] = "1"; + serial_num_text[1] = 0; + + /* + * Praparing parameters for certificate + */ + strlcpy(cert_params, CERT_PARAM_COMMON_NAME, cert_params_len); + strlcat(cert_params, csp->http->host, cert_params_len); + strlcat(cert_params, CERT_PARAM_ORGANIZATION, cert_params_len); + strlcat(cert_params, csp->http->host, cert_params_len); + strlcat(cert_params, CERT_PARAM_ORG_UNIT, cert_params_len); + strlcat(cert_params, csp->http->host, cert_params_len); + strlcat(cert_params, CERT_PARAM_COUNTRY, cert_params_len); + + cert_opt.issuer_crt = make_certs_path("CA", "cacert", CERT_FILE_TYPE); + cert_opt.issuer_key = make_certs_path("CA", "cakey", KEY_FILE_TYPE); + cert_opt.subject_key = make_certs_path("CA/webpagesCerts", + (const char *)csp->http->host, KEY_FILE_TYPE); + + if (cert_opt.issuer_crt == NULL || cert_opt.issuer_key == NULL + || cert_opt.subject_key == NULL) + { + ret = -1; + goto exit; + } + + cert_opt.subject_pwd = CERT_SUBJECT_PASSWORD; + cert_opt.issuer_pwd = "abc"; + cert_opt.subject_name = cert_params; + cert_opt.not_before = GENERATED_CERT_VALID_FROM; + cert_opt.not_after = GENERATED_CERT_VALID_TO; + cert_opt.serial = serial_num_text; + cert_opt.is_ca = 0; + cert_opt.max_pathlen = -1; + + /* + * Seed the PRNG + */ + ret = seed_rng(csp); + if (ret != 0) + { + ret = -1; + goto exit; + } + + /* + * Parse serial to MPI + */ + ret = mbedtls_mpi_read_string(&serial, 10, cert_opt.serial); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "mbedtls_mpi_read_string failed: %s", err_buf); + ret = -1; + goto exit; + } + + /* + * Loading certificates + */ + ret = mbedtls_x509_crt_parse_file(&issuer_cert, cert_opt.issuer_crt); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "Loading issuer certificate %s failed: %s", + cert_opt.issuer_crt, err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_x509_dn_gets(cert_opt.issuer_name, + sizeof(cert_opt.issuer_name), &issuer_cert.subject); + if (ret < 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_x509_dn_gets failed: %s", err_buf); + ret = -1; + goto exit; + } + + /* + * Loading keys from file or from buffer + */ + if (key_buf != NULL && subject_key_len > 0) + { + /* Key was created in this function and is stored in buffer */ + ret = mbedtls_pk_parse_key(&loaded_subject_key, key_buf, + (size_t)(subject_key_len + 1), (unsigned const char *) + cert_opt.subject_pwd, strlen(cert_opt.subject_pwd)); + } + else + { + /* Key was't created in this function, because it already existed */ + ret = mbedtls_pk_parse_keyfile(&loaded_subject_key, + cert_opt.subject_key, cert_opt.subject_pwd); + } + + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "Parsing subject key %s failed: %s", + cert_opt.subject_key, err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_pk_parse_keyfile(&loaded_issuer_key, cert_opt.issuer_key, + cert_opt.issuer_pwd); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "Parsing issuer key failed: %s", err_buf); + ret = -1; + goto exit; + } + + /* + * Check if key and issuer certificate match + */ + if (!mbedtls_pk_can_do(&issuer_cert.pk, MBEDTLS_PK_RSA) || + mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa(issuer_cert.pk)->N, + &mbedtls_pk_rsa(*issuer_key)->N) != 0 || + mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa(issuer_cert.pk)->E, + &mbedtls_pk_rsa(*issuer_key)->E) != 0) + { + log_error(LOG_LEVEL_ERROR, + "Issuer key doesn't match issuer certificate"); + ret = -1; + goto exit; + } + + + mbedtls_x509write_crt_set_subject_key(&cert, subject_key); + mbedtls_x509write_crt_set_issuer_key(&cert, issuer_key); + + /* + * Setting parameters of signed certificate + */ + ret = mbedtls_x509write_crt_set_subject_name(&cert, cert_opt.subject_name); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Setting subject name in signed certificate failed: %s", err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_x509write_crt_set_issuer_name(&cert, cert_opt.issuer_name); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Setting issuer name in signed certificate failed: %s", err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_x509write_crt_set_serial(&cert, &serial); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Setting serial number in signed certificate failed: %s", err_buf); + ret = -1; + goto exit; + } + + ret = mbedtls_x509write_crt_set_validity(&cert, cert_opt.not_before, + cert_opt.not_after); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Setting validity in signed certificate failed: %s", err_buf); + ret = -1; + goto exit; + } + + /* + * Setting the basicConstraints extension for certificate + */ + ret = mbedtls_x509write_crt_set_basic_constraints(&cert, cert_opt.is_ca, + cert_opt.max_pathlen); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "Setting the basicConstraints extension " + "in signed certificate failed: %s", err_buf); + ret = -1; + goto exit; + } + +#if defined(MBEDTLS_SHA1_C) + /* Setting the subjectKeyIdentifier extension for certificate */ + ret = mbedtls_x509write_crt_set_subject_key_identifier(&cert); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_x509write_crt_set_subject_key_" + "identifier failed: %s", err_buf); + ret = -1; + goto exit; + } + + /* Setting the authorityKeyIdentifier extension for certificate */ + ret = mbedtls_x509write_crt_set_authority_key_identifier(&cert); + if (ret != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, "mbedtls_x509write_crt_set_authority_key_" + "identifier failed: %s", err_buf); + ret = -1; + goto exit; + } +#endif /* MBEDTLS_SHA1_C */ + +exit: + /* + * Freeing used structures + */ + mbedtls_x509write_crt_free(&cert); + mbedtls_pk_free(&loaded_subject_key); + mbedtls_pk_free(&loaded_issuer_key); + mbedtls_mpi_free(&serial); + mbedtls_x509_crt_free(&issuer_cert); + + if (cert_opt.issuer_crt != NULL) + { + freez(cert_opt.issuer_crt); + } + + if (cert_opt.issuer_key != NULL) + { + freez(cert_opt.issuer_key); + } + + if (cert_opt.subject_key != NULL) + { + freez(cert_opt.subject_key); + } + + if (key_buf != NULL) + { + freez(key_buf); + } + + return ret; +} + + /********************************************************************* * * Function : make_certs_path -- 2.26.2 From e377409856a67900dd0cd470f863d57e9989f7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:56:51 +0200 Subject: [PATCH 18/83] Saving generated certificate for requested webpage as a file. --- ssl.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/ssl.c b/ssl.c index 504b46e8..7242a64d 100644 --- a/ssl.c +++ b/ssl.c @@ -937,6 +937,71 @@ extern int tunnel_established_successfully(const char * server_response, unsigne /*======================Certificates======================*/ +/********************************************************************* + * Function : write_certificate + * + * Description : Writes certificate into file. + * + * Parameters : + * 1 : crt = certificate to write into file + * 2 : output_file = path to save certificate file + * 3 : f_rng = mbedtls_ctr_drbg_random + * 4 : p_rng = mbedtls_ctr_drbg_context + * + * Returns : Length of written certificate on success or negative value + * on error + * + *********************************************************************/ +static int write_certificate(mbedtls_x509write_cert *crt, const char *output_file, int(*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + FILE *f = NULL; + size_t len = 0; + unsigned char cert_buf[CERTIFICATE_BUF_SIZE + 1]; /* Buffer for certificate in PEM format + terminating NULL */ + int ret = 0; + char err_buf[ERROR_BUF_SIZE]; + + memset(err_buf, 0, sizeof(err_buf)); + memset(cert_buf, 0, sizeof(cert_buf)); + + /* + * Writing certificate into PEM string. If buffer is too small, fuction + * returns specific error and no buffer overflow can happen. + */ + if ((ret = mbedtls_x509write_crt_pem(crt, cert_buf, + sizeof(cert_buf) - 1, f_rng, p_rng)) != 0) + { + mbedtls_strerror(ret, err_buf, sizeof(err_buf)); + log_error(LOG_LEVEL_ERROR, + "Writing certificate into buffer failed: %s", err_buf); + return -1; + } + + len = strlen((char *)cert_buf); + + /* + * Saving certificate into file + */ + if ((f = fopen(output_file, "w")) == NULL) + { + log_error(LOG_LEVEL_ERROR, "Opening file %s to save certificate failed", + output_file); + return -1; + } + + if (fwrite(cert_buf, 1, len, f) != len) + { + log_error(LOG_LEVEL_ERROR, + "Writing certificate into file %s failed", output_file); + fclose(f); + return -1; + } + + fclose(f); + + return len; +} + + /* * Function : write_private_key * @@ -1134,7 +1199,9 @@ exit: * * Function : generate_webpage_certificate * - * Description : Creates certificate. Subject of certificate is named + * Description : Creates certificate file in presetted directory. + * If certificate already exists, no other certificate + * will be created. Subject of certificate is named * by csp->http->host from parameter. This function also * call generating of private key for new certificate. * @@ -1166,6 +1233,7 @@ extern int generate_webpage_certificate(struct client_state * csp) cert_opt.issuer_key = NULL; cert_opt.subject_key = NULL; cert_opt.issuer_crt = NULL; + cert_opt.output_file = NULL; /* * Create key for requested host @@ -1220,9 +1288,11 @@ extern int generate_webpage_certificate(struct client_state * csp) cert_opt.issuer_key = make_certs_path("CA", "cakey", KEY_FILE_TYPE); cert_opt.subject_key = make_certs_path("CA/webpagesCerts", (const char *)csp->http->host, KEY_FILE_TYPE); + cert_opt.output_file = make_certs_path("CA/webpagesCerts", + (const char *)csp->http->host, CERT_FILE_TYPE); - if (cert_opt.issuer_crt == NULL || cert_opt.issuer_key == NULL - || cert_opt.subject_key == NULL) + if (cert_opt.issuer_crt == NULL || cert_opt.issuer_key == NULL + || cert_opt.subject_key == NULL || cert_opt.output_file == NULL) { ret = -1; goto exit; @@ -1237,6 +1307,15 @@ extern int generate_webpage_certificate(struct client_state * csp) cert_opt.is_ca = 0; cert_opt.max_pathlen = -1; + /* + * Test if certificate exists and private key was already created + */ + if (file_exists(cert_opt.output_file) == 1 && subject_key_len == 0) + { + ret = 0; + goto exit; + } + /* * Seed the PRNG */ @@ -1420,6 +1499,17 @@ extern int generate_webpage_certificate(struct client_state * csp) } #endif /* MBEDTLS_SHA1_C */ + /* + * Writing certificate into file + */ + ret = write_certificate(&cert, cert_opt.output_file, + mbedtls_ctr_drbg_random, &ctr_drbg); + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, "Writing certificate into file failed"); + goto exit; + } + exit: /* * Freeing used structures @@ -1445,6 +1535,11 @@ exit: freez(cert_opt.subject_key); } + if (cert_opt.output_file != NULL) + { + freez(cert_opt.output_file); + } + if (key_buf != NULL) { freez(key_buf); -- 2.26.2 From f7ec923e533061e410245bab483b5ded8e96eb03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:57:25 +0200 Subject: [PATCH 19/83] Generating hash of host. --- project.h | 3 +++ ssl.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/project.h b/project.h index 4018b3e6..affe3007 100644 --- a/project.h +++ b/project.h @@ -59,6 +59,7 @@ #define CERT_INFO_BUF_SIZE 4096 #define CERT_FILE_BUF_SIZE 16384 #define ISSUER_NAME_BUF_SIZE 2048 +#define HASH_OF_HOST_BUF_SIZE 16 /* Need for struct sockaddr_storage */ #ifdef HAVE_RFC2553 @@ -325,6 +326,8 @@ struct http_request int client_ssl; int server_ssl; + unsigned char hash_of_host_hex[(HASH_OF_HOST_BUF_SIZE * 2) + 1]; /**< chars for hash in hex string and one for '\0' */ + unsigned char hash_of_host[HASH_OF_HOST_BUF_SIZE + 1]; /**< chars for bytes of hash and one for '\0' */ }; /* diff --git a/ssl.c b/ssl.c index 7242a64d..55cf0046 100644 --- a/ssl.c +++ b/ssl.c @@ -29,6 +29,7 @@ #include +#include "mbedtls/md5.h" #include "mbedtls/error.h" #include "project.h" @@ -60,6 +61,7 @@ extern int generate_webpage_certificate(struct client_state * csp); static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); static int file_exists(const char * path); +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_certificate_chain(struct client_state *csp); static void free_client_ssl_structures(struct client_state *csp); @@ -342,6 +344,17 @@ extern int create_client_ssl_connection(struct client_state *csp) mbedtls_ssl_cache_init(&(csp->mbedtls_client_attr.cache)); #endif + /* + * Preparing hash of host for creating certificates + */ + ret = host_to_hash(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, "Generating hash of host failed: %d", ret); + ret = -1; + goto exit; + } + /* * Preparing paths to certificates files and key file */ @@ -1724,6 +1737,50 @@ static int file_exists(const char * path) } +/********************************************************************* + * + * Function : host_to_hash + * + * Description : Creates MD5 hash from host name. Host name is loaded from + * structure csp and saved again into it. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 1 => Error while creating hash + * 0 => Hash created successfully + * + *********************************************************************/ +static int host_to_hash(struct client_state * csp) +{ + int ret = 0; + +#if !defined(MBEDTLS_MD5_C) + log_error(LOG_LEVEL_ERROR, "MBEDTLS_MD5_C is not defined. Can't create" + "MD5 hash for certificate and key name."); + return -1; +#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); + + /* Converting hash into string with hex */ + size_t i = 0; + for (; i < 16; i++) + { + if ((ret = sprintf((char *)csp->http->hash_of_host_hex + 2 * i, "%02x", + csp->http->hash_of_host[i])) < 0) + { + log_error(LOG_LEVEL_ERROR, "Sprintf return value: %d", ret); + return -1; + } + } + + return 0; +#endif /* MBEDTLS_MD5_C */ +} + + /********************************************************************* * * Function : seed_rng -- 2.26.2 From 9e8c3f2c48241c83782362cc6e9f36d89aa21037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:58:02 +0200 Subject: [PATCH 20/83] Dynamically generated serial number of certificate from hash of host. --- ssl.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/ssl.c b/ssl.c index 55cf0046..0b431453 100644 --- a/ssl.c +++ b/ssl.c @@ -50,6 +50,7 @@ #define GENERATED_CERT_VALID_FROM "20100101000000" /* Date and time, which will be setted in generated certificates as parameter valid from */ #define GENERATED_CERT_VALID_TO "20401231235959" /* Date and time, which will be setted in generated certificates as parameter valid to */ #define CERT_SIGNATURE_ALGORITHM MBEDTLS_MD_SHA256 /* The MD algorithm to use for the signature */ +#define CERT_SERIAL_NUM_LENGTH 8 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */ #define CERT_PARAM_COMMON_NAME "CN=" #define CERT_PARAM_ORGANIZATION ",O=" #define CERT_PARAM_ORG_UNIT ",OU=" @@ -64,6 +65,7 @@ static int file_exists(const char * path); 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_certificate_chain(struct client_state *csp); +static unsigned long get_certificate_serial(struct client_state *csp); 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); @@ -1281,10 +1283,25 @@ extern int generate_webpage_certificate(struct client_state * csp) memset(cert_params, 0, cert_params_len); /* - * Temporarily fixed serial number + * Converting unsigned long serial number to char * serial number. + * We must compute length of serial number in string + terminating null. */ - char serial_num_text[2] = "1"; - serial_num_text[1] = 0; + unsigned long certificate_serial = get_certificate_serial(csp); + size_t serial_num_size = snprintf(NULL, 0, "%lu", certificate_serial) + 1; + if (serial_num_size <= 0) + { + serial_num_size = 1; + } + + char serial_num_text[serial_num_size]; /* Buffer for serial number */ + ret = snprintf(serial_num_text, serial_num_size, "%lu", certificate_serial); + if (ret < 0 || ret >= serial_num_size) + { + log_error(LOG_LEVEL_ERROR, + "Converting certificate serial number into string failed"); + ret = -1; + goto exit; + } /* * Praparing parameters for certificate @@ -1652,6 +1669,54 @@ static char * make_certs_path(const char * conf_dir, const char * file_name, con } +/********************************************************************* + * + * Function : get_certificate_serial + * + * Description : Computes serial number for new certificate from host + * name hash. This hash must be already saved in csp + * structure. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Serial number for new certificate + * + *********************************************************************/ +static unsigned long get_certificate_serial(struct client_state *csp) { + unsigned long exp = 1; + unsigned long serial = 0; + const size_t MD5_DIGEST_LENGTH = 32; + /* 21 should be enough for 64 bits number */ + const size_t PARAMETERS_BUF_LEN = MD5_DIGEST_LENGTH + 21; + char parameters_concat[PARAMETERS_BUF_LEN]; + unsigned char serial_buf[MD5_DIGEST_LENGTH]; + time_t now = time(NULL); + snprintf(parameters_concat, PARAMETERS_BUF_LEN, "%s%lu", + csp->http->hash_of_host, now); + + mbedtls_md5((unsigned char *)parameters_concat, PARAMETERS_BUF_LEN, + serial_buf); + + int i = CERT_SERIAL_NUM_LENGTH; + /* Length of hash is 16 bytes, we must avoid to read next chars*/ + if (i > 16) + { + i = 16; + } + if (i < 2) { + i = 2; + } + + for (i--; i >= 0; i--) + { + serial += exp * (int)serial_buf[i]; + exp *= 256; + } + return serial; +} + + /********************************************************************* * * Function : ssl_verify_callback -- 2.26.2 From e68fd5139b103e13ee765f07cc8a0974048a4adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:58:42 +0200 Subject: [PATCH 21/83] Saving certificate with hash of host in name and sending it to the client. --- ssl.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ssl.c b/ssl.c index 0b431453..be69a493 100644 --- a/ssl.c +++ b/ssl.c @@ -361,8 +361,10 @@ extern int create_client_ssl_connection(struct client_state *csp) * Preparing paths to certificates files and key file */ ca_file = make_certs_path("CA", "cacert", CERT_FILE_TYPE); - cert_file = make_certs_path("CA/webpagesCerts", "privoxy", CERT_FILE_TYPE); - key_file = make_certs_path("CA/webpagesCerts", "privoxy", ".key"); + cert_file = make_certs_path("CA/webpagesCerts", + (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); + key_file = make_certs_path("CA/webpagesCerts", + (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); if (ca_file == NULL || cert_file == NULL || key_file == NULL) { @@ -1137,7 +1139,7 @@ extern int generate_key(unsigned char ** key_buf, struct client_state *csp) key_opt.rsa_keysize = RSA_KEYSIZE; key_opt.key_file_path = make_certs_path("CA/webpagesCerts", - (char *)csp->http->host, KEY_FILE_TYPE); + (char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); if (key_opt.key_file_path == NULL) { ret = -1; @@ -1317,9 +1319,9 @@ extern int generate_webpage_certificate(struct client_state * csp) cert_opt.issuer_crt = make_certs_path("CA", "cacert", CERT_FILE_TYPE); cert_opt.issuer_key = make_certs_path("CA", "cakey", KEY_FILE_TYPE); cert_opt.subject_key = make_certs_path("CA/webpagesCerts", - (const char *)csp->http->host, KEY_FILE_TYPE); + (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); cert_opt.output_file = make_certs_path("CA/webpagesCerts", - (const char *)csp->http->host, CERT_FILE_TYPE); + (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); if (cert_opt.issuer_crt == NULL || cert_opt.issuer_key == NULL || cert_opt.subject_key == NULL || cert_opt.output_file == NULL) -- 2.26.2 From 409bac4bcecea15b653d84f00e5e6f61cd579c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:59:16 +0200 Subject: [PATCH 22/83] Added mutexes for generating certificates parallelly. --- jcc.c | 15 +++++++++++++++ jcc.h | 5 +++++ ssl.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/jcc.c b/jcc.c index cc44df8c..436ab6ca 100644 --- a/jcc.c +++ b/jcc.c @@ -191,6 +191,11 @@ privoxy_mutex_t log_mutex; privoxy_mutex_t log_init_mutex; privoxy_mutex_t connection_reuse_mutex; +#ifdef LIMIT_MUTEX_NUMBER + privoxy_mutex_t certificates_mutexes[32]; +#else + privoxy_mutex_t certificates_mutexes[65536]; +#endif /* LIMIT_MUTEX_NUMBER */ privoxy_mutex_t rng_mutex; #ifdef FEATURE_EXTERNAL_FILTERS @@ -4011,6 +4016,16 @@ static void initialize_mutexes(void) /* * Prepare global mutex semaphores */ +#ifdef LIMIT_MUTEX_NUMBER + int i = 0; + for (i = 0; i < 32; i++) +#else + int i = 0; + for (i = 0; i < 65536; i++) +#endif /* LIMIT_MUTEX_NUMBER */ + { + privoxy_mutex_init(&(certificates_mutexes[i])); + } privoxy_mutex_init(&rng_mutex); privoxy_mutex_init(&log_mutex); diff --git a/jcc.h b/jcc.h index e0535bb1..2df07553 100644 --- a/jcc.h +++ b/jcc.h @@ -102,6 +102,11 @@ extern privoxy_mutex_t resolver_mutex; extern privoxy_mutex_t rand_mutex; #endif /* ndef HAVE_RANDOM */ +#ifdef LIMIT_MUTEX_NUMBER + extern privoxy_mutex_t certificates_mutexes[32]; +#else + extern privoxy_mutex_t certificates_mutexes[65536]; +#endif /* LIMIT_MUTEX_NUMBER */ extern privoxy_mutex_t rng_mutex; #endif /* FEATURE_PTHREAD */ diff --git a/ssl.c b/ssl.c index be69a493..95b38f5b 100644 --- a/ssl.c +++ b/ssl.c @@ -51,6 +51,7 @@ #define GENERATED_CERT_VALID_TO "20401231235959" /* Date and time, which will be setted in generated certificates as parameter valid to */ #define CERT_SIGNATURE_ALGORITHM MBEDTLS_MD_SHA256 /* The MD algorithm to use for the signature */ #define CERT_SERIAL_NUM_LENGTH 8 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */ +#define LIMIT_MUTEX_NUMBER /* If this macro is defined, mutexes count for generating private keys is changed from 65536 to 32 */ #define CERT_PARAM_COMMON_NAME "CN=" #define CERT_PARAM_ORGANIZATION ",O=" #define CERT_PARAM_ORG_UNIT ",OU=" @@ -65,6 +66,7 @@ static int file_exists(const char * path); 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_certificate_chain(struct client_state *csp); +static unsigned int get_certificate_mutex_id(struct client_state *csp); static unsigned long get_certificate_serial(struct client_state *csp); static void free_client_ssl_structures(struct client_state *csp); static void free_server_ssl_structures(struct client_state *csp); @@ -373,16 +375,22 @@ extern int create_client_ssl_connection(struct client_state *csp) } /* - * Generating certificate for requested host. + * Generating certificate for requested host. Mutex to prevent + * certificate and key inconsistence must be locked. */ + unsigned int cert_mutex_id = get_certificate_mutex_id(csp); + privoxy_mutex_lock(&(certificates_mutexes[cert_mutex_id])); + ret = generate_webpage_certificate(csp); if (ret < 0) { log_error(LOG_LEVEL_ERROR, "Generate_webpage_certificate failed: %d", ret); + privoxy_mutex_unlock(&(certificates_mutexes[cert_mutex_id])); ret = -1; goto exit; } + privoxy_mutex_unlock(&(certificates_mutexes[cert_mutex_id])); /* * Seed the RNG @@ -1671,6 +1679,29 @@ static char * make_certs_path(const char * conf_dir, const char * file_name, con } +/********************************************************************* + * + * Function : get_certificate_mutex_id + * + * Description : Computes mutex id from host name hash. This hash must + * be already saved in csp structure + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Mutex id for given host name + * + *********************************************************************/ +static unsigned int get_certificate_mutex_id(struct client_state *csp) { +#ifdef LIMIT_MUTEX_NUMBER + return (unsigned int)(csp->http->hash_of_host[0] % 32); +#else + return (unsigned int)(csp->http->hash_of_host[1] + + 256 * (int)csp->http->hash_of_host[0]); +#endif /* LIMIT_MUTEX_NUMBER */ +} + + /********************************************************************* * * Function : get_certificate_serial -- 2.26.2 From ec620d467a7667f09888c4cd457d96e4c5b7cbe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 20:59:54 +0200 Subject: [PATCH 23/83] Sending information about invalid server certificate to user. --- jcc.c | 29 +++++++++++++++++++++++++-- ssl.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ssl.h | 1 + 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/jcc.c b/jcc.c index 436ab6ca..e8c18dd5 100644 --- a/jcc.c +++ b/jcc.c @@ -3360,7 +3360,14 @@ static void chat(struct client_state *csp) */ ret = create_server_ssl_connection(csp); - if (ret != 0) + /* + * If SLL/TLS connection wasn't created and invalid certificate + * wasn't detected, we can interrupt this fuction. Otherwise, we + * must inform client about invalid server certificate. + */ + if (ret != 0 + && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED + || csp->server_cert_verification_result == SSL_CERT_VALID)) { rsp = error_response(csp, "connect-failed"); if (rsp) @@ -3392,7 +3399,14 @@ static void chat(struct client_state *csp) ret = create_server_ssl_connection(csp); - if (ret != 0) + /* + * If SLL/TLS connection wasn't created and invalid certificate + * wasn't detected, we can interrupt this fuction. Otherwise, we + * must inform client about invalid server certificate. + */ + if (ret != 0 + && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED + || csp->server_cert_verification_result == SSL_CERT_VALID)) { rsp = error_response(csp, "connect-failed"); if (rsp) @@ -3477,6 +3491,17 @@ static void chat(struct client_state *csp) return; } + /* + * If server certificate is invalid, we must inform client and then + * close connection with client. + */ + if (csp->server_cert_verification_result != SSL_CERT_VALID) + { + ssl_send_certificate_error(csp); + close_client_and_server_ssl_connections(csp); + return; + } + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); } clear_iob(csp->client_iob); diff --git a/ssl.c b/ssl.c index 95b38f5b..e300b83a 100644 --- a/ssl.c +++ b/ssl.c @@ -28,6 +28,7 @@ *********************************************************************/ #include +#include #include "mbedtls/md5.h" #include "mbedtls/error.h" @@ -52,6 +53,7 @@ #define CERT_SIGNATURE_ALGORITHM MBEDTLS_MD_SHA256 /* The MD algorithm to use for the signature */ #define CERT_SERIAL_NUM_LENGTH 8 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */ #define LIMIT_MUTEX_NUMBER /* If this macro is defined, mutexes count for generating private keys is changed from 65536 to 32 */ +#define INVALID_CERT_INFO_BUF_SIZE 2048 /* Size of buffer for message with information about reason of certificate invalidity. Data after the end of buffer be not be saved */ #define CERT_PARAM_COMMON_NAME "CN=" #define CERT_PARAM_ORGANIZATION ",O=" #define CERT_PARAM_ORG_UNIT ",OU=" @@ -1750,6 +1752,68 @@ static unsigned long get_certificate_serial(struct client_state *csp) { } +/********************************************************************* + * + * Function : ssl_send_certificate_error + * + * Description : Sends info about invalid server certificate to client. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +extern void ssl_send_certificate_error(struct client_state *csp) +{ + size_t message_len = 0; + + /* Header of message with certificate informations */ + const char message_begin[] = + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n\r\n" + "

Invalid server certificate

Reason: "; + const char message_end[] = "\r\n\r\n"; + char reason[INVALID_CERT_INFO_BUF_SIZE]; + memset(reason, 0, sizeof(reason)); + + /* Get verification message from verification return code */ + mbedtls_x509_crt_verify_info(reason, sizeof(reason), " ", + csp->server_cert_verification_result); + + /* + * Computing total lenght of message with all certificates inside + */ + message_len = strlen(message_begin) + strlen(message_end) + + strlen(reason) + strlen("

") + 1; + + /* + * Joining all blocks in one long message + */ + char message[message_len]; + memset(message, 0, message_len); + + strlcpy(message, message_begin, message_len); + strlcat(message, reason, message_len); + strlcat(message, "

", message_len); + strlcat(message, message_end, message_len); + + /* + * Sending final message to client + */ + ssl_send_data(&(csp->mbedtls_client_attr.ssl), + (const unsigned char *)message, strlen(message)); + /* + * Waiting before closing connection. Some browsers don't show received + * message if there isn't this delay. + */ + sleep(1); + + free_certificate_chain(csp); +} + + /********************************************************************* * * Function : ssl_verify_callback diff --git a/ssl.h b/ssl.h index 62ec84a5..a56f0205 100644 --- a/ssl.h +++ b/ssl.h @@ -57,6 +57,7 @@ extern int tunnel_established_successfully(const char * response, unsigned int r extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len); extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int maxLen); extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob); +extern void ssl_send_certificate_error(struct client_state *csp); /* Functions for opening and closing SSL/TLS connections */ extern int create_client_ssl_connection(struct client_state *csp); -- 2.26.2 From 20206237d20e20c9239da545475bb2e1f5cf22a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:00:45 +0200 Subject: [PATCH 24/83] Sending more information about invalid server certificate including whole certificate file to download. --- ssl.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 16 deletions(-) diff --git a/ssl.c b/ssl.c index e300b83a..8cfdd9ad 100644 --- a/ssl.c +++ b/ssl.c @@ -31,6 +31,8 @@ #include #include "mbedtls/md5.h" +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" #include "mbedtls/error.h" #include "project.h" @@ -40,6 +42,12 @@ #include "ssl.h" +/* Macros for searching begin and end of certificates + * Necessary to convert structure mbedtls_x509_crt to crt file + */ +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + /* * Macros for ssl.c */ @@ -61,6 +69,7 @@ #define KEY_FILE_TYPE ".pem" #define CERT_FILE_TYPE ".crt" #define CERT_SUBJECT_PASSWORD "" +#define CERT_INFO_PREFIX "" extern int generate_webpage_certificate(struct client_state * csp); static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); @@ -1757,6 +1766,8 @@ static unsigned long get_certificate_serial(struct client_state *csp) { * Function : ssl_send_certificate_error * * Description : Sends info about invalid server certificate to client. + * Sent message is including all trusted chain certificates, + * that can be downloaded in web browser. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) @@ -1767,6 +1778,8 @@ static unsigned long get_certificate_serial(struct client_state *csp) { extern void ssl_send_certificate_error(struct client_state *csp) { size_t message_len = 0; + int ret = 0; + struct certs_chain *cert = NULL; /* Header of message with certificate informations */ const char message_begin[] = @@ -1788,6 +1801,17 @@ extern void ssl_send_certificate_error(struct client_state *csp) message_len = strlen(message_begin) + strlen(message_end) + strlen(reason) + strlen("

") + 1; + cert = &(csp->server_certs_chain); + while (cert->next != NULL) + { + size_t base64_len = 4 * ((strlen(cert->file_buf) + 2) / 3) + 1; + + message_len += strlen(cert->text_buf) + strlen("
\n")
+         + base64_len + strlen("Download certificate");
+      cert = cert->next;
+   }
+
    /*
     * Joining all blocks in one long message
     */
@@ -1797,6 +1821,39 @@ extern void ssl_send_certificate_error(struct client_state *csp)
    strlcpy(message, message_begin, message_len);
    strlcat(message, reason, message_len);
    strlcat(message, "

", message_len); + + cert = &(csp->server_certs_chain); + while (cert->next != NULL) + { + size_t olen = 0; + size_t base64_len = 4 * ((strlen(cert->file_buf) + 2) / 3) + 1; /* +1 for terminating null*/ + char base64_buf[base64_len]; + memset(base64_buf, 0, base64_len); + + /* Encoding certificate into base64 code */ + ret = mbedtls_base64_encode((unsigned char*)base64_buf, + base64_len, &olen, (const unsigned char*)cert->file_buf, + strlen(cert->file_buf)); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Encoding to base64 failed, buffer is to small"); + } + + strlcat(message, "
", message_len);
+      strlcat(message, cert->text_buf, message_len);
+      strlcat(message, "
\n", message_len); + + if (ret == 0) + { + strlcat(message, "Download certificate", message_len); + } + + cert = cert->next; + } strlcat(message, message_end, message_len); /* @@ -1815,24 +1872,73 @@ extern void ssl_send_certificate_error(struct client_state *csp) /********************************************************************* - * - * Function : ssl_verify_callback - * - * Description : This is callback function for certificates verification. - * It's called for all certificates in server certificate - * trusted chain. - * - * Parameters : - * 1 : csp_void = Current client state (buffers, headers, etc...) - * 2 : crt = certificate from trusted chain - * 3 : depth = depth in trusted chain - * 4 : flags = certificate flags - * - * Returns : 0 on success and negative value on error - * - *********************************************************************/ + * + * Function : ssl_verify_callback + * + * Description : This is callback function for certificates verification. + * It's called for all certificates in server certificate + * trusted chain and it's preparing information about this + * certificates. Prepared informations can be used to inform + * user about invalid certificate. + * + * Parameters : + * 1 : csp_void = Current client state (buffers, headers, etc...) + * 2 : crt = certificate from trusted chain + * 3 : depth = depth in trusted chain + * 4 : flags = certificate flags + * + * Returns : 0 on success and negative value on error + * + *********************************************************************/ static int ssl_verify_callback(void *csp_void, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { + struct client_state * csp = (struct client_state *)csp_void; + struct certs_chain * last = &(csp->server_certs_chain); + size_t olen = 0; + int ret = 0; + + /* + * Searching for last item in certificates linked list + */ + while (last->next != NULL) + { + last = last->next; + } + + /* + * Preparing next item in linked list for next certificate + * If malloc fails, we are continuing withnout this certificate + */ + last->next = (struct certs_chain *)malloc(sizeof(struct certs_chain)); + if (last->next != NULL) + { + last->next->next = NULL; + memset(last->next->text_buf, 0, sizeof(last->next->text_buf)); + memset(last->next->file_buf, 0, sizeof(last->next->file_buf)); + + /* + * 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) + { + return(ret); + } + + /* + * Saving certificate information into buffer + */ + mbedtls_x509_crt_info(last->text_buf, sizeof(last->text_buf) - 1, + CERT_INFO_PREFIX, crt); + } + else + { + log_error(LOG_LEVEL_ERROR, + "Malloc memory for server cecertificate informations failed"); + return -1; + } + return 0; } -- 2.26.2 From 40ddc8dedc86187f30e47bee0f47c044ec91a8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:04:30 +0200 Subject: [PATCH 25/83] Disabling ssl filters - tunnel. --- actionlist.h | 1 + jcc.c | 8 ++++++++ project.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/actionlist.h b/actionlist.h index 01d4d371..afd86209 100644 --- a/actionlist.h +++ b/actionlist.h @@ -73,6 +73,7 @@ DEFINE_ACTION_STRING ("delay-response", ACTION_DELAY_RESPONSE, DEFINE_CGI_PARAM_NO_RADIO("delay-response", ACTION_DELAY_RESPONSE, ACTION_STRING_DELAY_RESPONSE, "100") DEFINE_CGI_PARAM_RADIO ("deanimate-gifs", ACTION_DEANIMATE, ACTION_STRING_DEANIMATE, "last", 1) DEFINE_ACTION_BOOL ("downgrade-http-version", ACTION_DOWNGRADE) +DEFINE_ACTION_BOOL ("disable-ssl-filtering", ACTION_DISABLE_HTTPS_FILTER) #ifdef FEATURE_EXTERNAL_FILTERS DEFINE_ACTION_MULTI ("external-filter", ACTION_MULTI_EXTERNAL_FILTER) #endif diff --git a/jcc.c b/jcc.c index e8c18dd5..ed37d7a6 100644 --- a/jcc.c +++ b/jcc.c @@ -3109,6 +3109,14 @@ static void chat(struct client_state *csp) } csp->use_fwd = fwd; + /* + * Setting flags to use old solution with SSL tunnel. + */ + if (http->ssl && csp->action->flags & ACTION_DISABLE_HTTPS_FILTER) + { + csp->use_ssl_tunnel = 1; + } + /* * build the http request to send to the server * we have to do one of the following: diff --git a/project.h b/project.h index affe3007..9adc3ba6 100644 --- a/project.h +++ b/project.h @@ -577,6 +577,8 @@ struct iob #define ACTION_LIMIT_COOKIE_LIFETIME 0x08000000UL /** Action bitmap: Delay writes */ #define ACTION_DELAY_RESPONSE 0x10000000UL +/** Action bitmap: Turn https filtering off */ +#define ACTION_DISABLE_HTTPS_FILTER 0x20000000UL /** Action string index: How to deanimate GIFs */ -- 2.26.2 From 32da859739d112b3152f2bce26c8aa787b6987ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:09:26 +0200 Subject: [PATCH 26/83] Disabling certificates check. --- actionlist.h | 1 + jcc.c | 9 ++++++++- project.h | 5 +++++ ssl.c | 5 +++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/actionlist.h b/actionlist.h index afd86209..84fd21b6 100644 --- a/actionlist.h +++ b/actionlist.h @@ -108,6 +108,7 @@ DEFINE_CGI_PARAM_RADIO ("hide-referrer", ACTION_HIDE_REFERER, DEFINE_CGI_PARAM_CUSTOM ("hide-referrer", ACTION_HIDE_REFERER, ACTION_STRING_REFERER, "http://www.privoxy.org/") DEFINE_ACTION_STRING ("hide-user-agent", ACTION_HIDE_USER_AGENT, ACTION_STRING_USER_AGENT) DEFINE_CGI_PARAM_NO_RADIO("hide-user-agent", ACTION_HIDE_USER_AGENT, ACTION_STRING_USER_AGENT, "Privoxy " VERSION) +DEFINE_ACTION_BOOL ("ignore-certificate-errors", ACTION_IGNORE_CERTIFICATE_ERRORS) DEFINE_ACTION_STRING ("limit-connect", ACTION_LIMIT_CONNECT, ACTION_STRING_LIMIT_CONNECT) DEFINE_CGI_PARAM_NO_RADIO("limit-connect", ACTION_LIMIT_CONNECT, ACTION_STRING_LIMIT_CONNECT, "443") DEFINE_ACTION_STRING ("limit-cookie-lifetime", ACTION_LIMIT_COOKIE_LIFETIME, ACTION_STRING_LIMIT_COOKIE_LIFETIME) diff --git a/jcc.c b/jcc.c index ed37d7a6..b2a30a8d 100644 --- a/jcc.c +++ b/jcc.c @@ -3089,6 +3089,7 @@ static void chat(struct client_state *csp) http = csp->http; csp->use_ssl_tunnel = 0; + csp->dont_verify_certificate = 0; if (receive_client_request(csp) != JB_ERR_OK) { @@ -3110,13 +3111,19 @@ static void chat(struct client_state *csp) csp->use_fwd = fwd; /* - * Setting flags to use old solution with SSL tunnel. + * Setting flags to use old solution with SSL tunel and to disable + * certificates verification. */ if (http->ssl && csp->action->flags & ACTION_DISABLE_HTTPS_FILTER) { csp->use_ssl_tunnel = 1; } + if (http->ssl && csp->action->flags & ACTION_IGNORE_CERTIFICATE_ERRORS) + { + csp->dont_verify_certificate = 1; + } + /* * build the http request to send to the server * we have to do one of the following: diff --git a/project.h b/project.h index 9adc3ba6..58a3d82d 100644 --- a/project.h +++ b/project.h @@ -579,6 +579,8 @@ struct iob #define ACTION_DELAY_RESPONSE 0x10000000UL /** Action bitmap: Turn https filtering off */ #define ACTION_DISABLE_HTTPS_FILTER 0x20000000UL +/** Action bitmap: Turn certificates verification off */ +#define ACTION_IGNORE_CERTIFICATE_ERRORS 0x40000000UL /** Action string index: How to deanimate GIFs */ @@ -1096,6 +1098,9 @@ struct client_state /* Result of server certificate verification */ uint32_t server_cert_verification_result; + /* Flag for certificate validity checking */ + int dont_verify_certificate; + /* * Flags if SSL connection with server or client is opened. * Thanks to this flags, we can call function to close connections diff --git a/ssl.c b/ssl.c index 8cfdd9ad..fb8947cb 100644 --- a/ssl.c +++ b/ssl.c @@ -722,6 +722,11 @@ extern int create_server_ssl_connection(struct client_state *csp) * Setting how strict should certificate verification be and other * parameters for certificate verification */ + if (csp->dont_verify_certificate) + { + auth_mode = MBEDTLS_SSL_VERIFY_NONE; + } + mbedtls_ssl_conf_authmode(&(csp->mbedtls_server_attr.conf), auth_mode); mbedtls_ssl_conf_ca_chain(&(csp->mbedtls_server_attr.conf), &(csp->mbedtls_server_attr.ca_cert), NULL); -- 2.26.2 From e9c5d7492f2ef4a21eac7bc11bd8e1586c8c2978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:10:34 +0200 Subject: [PATCH 27/83] Loading configuration for certificates. --- config | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ loadcfg.c | 126 ++++++++++++++++++++++++++++++++++++++++++++ project.h | 18 +++++++ 3 files changed, 296 insertions(+) diff --git a/config b/config index e568a2cd..d465ec19 100644 --- a/config +++ b/config @@ -16,6 +16,7 @@ # 5. FORWARDING # # 6. MISCELLANEOUS # # 7. WINDOWS GUI OPTIONS # +# 8. SSL # # # ##################################################################### # @@ -2462,3 +2463,154 @@ socket-timeout 300 # # # +# 8. SSL +# ======= +# +# This section of the config file controls parameters for SSL +# connections. +# +# +# 8.1. ca-password +# ================= +# +# Specifies: +# +# Password for CA key file. +# +# Type of value: +# +# Text +# +# Default value: +# +# Empty string: "" +# +# Effect if unset: +# +# Default value is used (see above). +# +# Examples: +# +# ca-password abcd +# +# +# 8.2. ca-dir +# ============ +# +# Specifies: +# +# Path to directory with CA key, CA certificate and trusted +# CAs file. +# +# Type of value: +# +# Path name +# +# Default value: +# +# ./CA +# +# Effect if unset: +# +# Default value is used (see above). +# +# Examples: +# +# ca-dir ./MY_CA +# +# +# 8.3. ca-cert-file +# ================== +# +# Specifies: +# +# File name of CA certificate. In ".crt" format. +# +# Type of value: +# +# File name, relative to ca-dir. +# +# Default value: +# +# cacert.crt +# +# Effect if unset: +# +# Default value is used (see above). +# +# Examples: +# +# ca-cert-file root.crt +# +# +# 8.4. ca-key-file +# ================= +# +# Specifies: +# +# File name of CA key. In ".pem" format. +# +# Type of value: +# +# File name, relative to ca-dir. +# +# Default value: +# +# cakey.pem +# +# Effect if unset: +# +# Default value is used (see above). +# +# Examples: +# +# ca-key-file root.pem +# +# +# 8.5. certs-dir +# =============== +# +# Specifies: +# +# Path to directory for saving generated keys and certificates. +# +# Type of value: +# +# Path name +# +# Default value: +# +# ./certs +# +# Effect if unset: +# +# Default value is used (see above). +# +# Examples: +# +# certs-dir ./generated_certs +# +# +# 8.6. trusted-cas-file +# ====================== +# +# Specifies: +# +# File name with trusted CAs. In ".pem" format. +# +# Type of value: +# +# File name, relative to ca-dir. +# +# Default value: +# +# trustedCAs.pem +# +# Effect if unset: +# +# Default value is used (see above). +# +# Examples: +# +# trusted-cas-file trusted_cas_file.pem +# diff --git a/loadcfg.c b/loadcfg.c index eac9206a..c1d9f388 100644 --- a/loadcfg.c +++ b/loadcfg.c @@ -135,6 +135,11 @@ static struct file_list *current_configfile = NULL; #define hash_admin_address 4112573064U /* "admin-address" */ #define hash_allow_cgi_request_crunching 258915987U /* "allow-cgi-request-crunching" */ #define hash_buffer_limit 1881726070U /* "buffer-limit */ +#define hash_ca_cert_file 1622923720U /* "ca-cert-file" */ +#define hash_ca_dir 378764U /* "ca-dir" */ +#define hash_ca_key_file 1184187891U /* "ca-key-file" */ +#define hash_ca_password 1184543320U /* "ca-password" */ +#define hash_certs_dir 48786889U /* "certs-dir" */ #define hash_client_header_order 2701453514U /* "client-header-order" */ #define hash_client_specific_tag 3353703383U /* "client-specific-tag" */ #define hash_client_tag_lifetime 647957580U /* "client-tag-lifetime" */ @@ -179,6 +184,7 @@ static struct file_list *current_configfile = NULL; #define hash_toggle 447966U /* "toggle" */ #define hash_trust_info_url 430331967U /* "trust-info-url" */ #define hash_trust_x_forwarded_for 2971537414U /* "trust-x-forwarded-for" */ +#define hash_trusted_cas_file 2679803024U /* "trusted-cas-files" */ #define hash_trusted_cgi_referrer 4270883427U /* "trusted-cgi-referrer" */ #define hash_trustfile 56494766U /* "trustfile" */ #define hash_usermanual 1416668518U /* "user-manual" */ @@ -271,6 +277,13 @@ static void unload_configfile (void * data) freez(config->usermanual); freez(config->trusted_cgi_referrer); + freez(config->ca_password); + freez(config->ca_dir); + freez(config->ca_cert_file); + freez(config->ca_key_file); + freez(config->certs_dir); + freez(config->trusted_cas_file); + #ifdef FEATURE_TRUST freez(config->trustfile); list_remove_all(config->trust_info); @@ -568,6 +581,11 @@ struct configuration_spec * load_config(void) unsigned long linenum = 0; int i; char *logfile = NULL; + char *ca_cert_file = NULL; + char *ca_key_file = NULL; + char *ca_dir = NULL; + char *trusted_cas_file = NULL; + char *certs_dir = NULL; if (!check_file_changed(current_configfile, configfile, &fs)) { @@ -612,6 +630,12 @@ struct configuration_spec * load_config(void) config->usermanual = strdup_or_die(USER_MANUAL_URL); config->proxy_args = strdup_or_die(""); config->forwarded_connect_retries = 0; + config->ca_password = strdup_or_die(""); + ca_cert_file = strdup_or_die("cacert.crt"); + ca_key_file = strdup_or_die("cakey.pem"); + ca_dir = strdup_or_die("./CA"); + trusted_cas_file = strdup_or_die("trustedCAs.pem"); + certs_dir = strdup_or_die("./certs"); #ifdef FEATURE_CLIENT_TAGS config->client_tag_lifetime = 60; #endif @@ -1683,6 +1707,85 @@ struct configuration_spec * load_config(void) config->usermanual = strdup_or_die(arg); break; + /* ************************************************************************* + * SSL config + * *************************************************************************/ + + /* ************************************************************************* + * ca private key file password + * *************************************************************************/ + case hash_ca_password: + freez(config->ca_password); + config->ca_password = strdup(arg); + break; + + /* ************************************************************************* + * ca dir directory-name + * *************************************************************************/ + case hash_ca_dir: + ca_dir = make_path(NULL, arg); + + if (NULL == ca_dir) + { + log_error(LOG_LEVEL_FATAL, "Out of memory while creating ca dir path"); + } + + break; + + /* ************************************************************************* + * ca cert file ca-cert-file + * In ca dir by default + * *************************************************************************/ + case hash_ca_cert_file: + ca_cert_file = make_path(config->ca_dir, arg); + + if (NULL == ca_cert_file) + { + log_error(LOG_LEVEL_FATAL, "Out of memory while creating ca certificate file path"); + } + + break; + + /* ************************************************************************* + * ca key file ca-key-file + * In ca dir by default + * *************************************************************************/ + case hash_ca_key_file: + ca_key_file = make_path(config->ca_dir, arg); + + if (NULL == ca_key_file) + { + log_error(LOG_LEVEL_FATAL, "Out of memory while creating ca key file path"); + } + + break; + + /* ************************************************************************* + * certificates of each server dir certs-dir + * *************************************************************************/ + case hash_certs_dir: + certs_dir = make_path(NULL, arg); + + if (NULL == certs_dir) + { + log_error(LOG_LEVEL_FATAL, "Out of memory while creating certs dir path"); + } + + break; + + /* ************************************************************************* + * trusted CAs file name trusted-cas-file + * *************************************************************************/ + case hash_trusted_cas_file: + trusted_cas_file = make_path(config->ca_dir, arg); + + if (NULL == trusted_cas_file) + { + log_error(LOG_LEVEL_FATAL, "Out of memory while creating trusted CAs file path"); + } + + break; + /* ************************************************************************* * Win32 Console options: * *************************************************************************/ @@ -1858,6 +1961,29 @@ struct configuration_spec * load_config(void) } } + /* + * Setting SSL parameters from loaded values into structures + */ + freez(config->ca_dir); + config->ca_dir = make_path(NULL, ca_dir); + freez(ca_dir); + + freez(config->ca_cert_file); + config->ca_cert_file = make_path(config->ca_dir, ca_cert_file); + freez(ca_cert_file); + + freez(config->ca_key_file); + config->ca_key_file = make_path(config->ca_dir, ca_key_file); + freez(ca_key_file); + + freez(config->trusted_cas_file); + config->trusted_cas_file = make_path(config->ca_dir, trusted_cas_file); + freez(trusted_cas_file); + + freez(config->certs_dir); + config->certs_dir = make_path(NULL, certs_dir); + freez(certs_dir); + #ifdef FEATURE_CONNECTION_KEEP_ALIVE if (config->default_server_timeout > config->keep_alive_timeout) { diff --git a/project.h b/project.h index 58a3d82d..8bdc68e7 100644 --- a/project.h +++ b/project.h @@ -1531,6 +1531,24 @@ struct configuration_spec /** Nonzero if we need to bind() to the new port. */ int need_bind; + + /** Password for proxy ca file **/ + char * ca_password; + + /** Directory with files of ca **/ + char * ca_dir; + + /** Filename of ca certificate **/ + char * ca_cert_file; + + /** Filename of ca key **/ + char * ca_key_file; + + /** Directory for saving certificates and keys for each webpage **/ + char * certs_dir; + + /** Filename of trusted CAs certificates **/ + char * trusted_cas_file; }; /** Calculates the number of elements in an array, using sizeof. */ -- 2.26.2 From 576bda4f5f896bb0f1f9a216df850fa7834090c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:11:38 +0200 Subject: [PATCH 28/83] Using configuration for certificates. --- CA/webpagesCerts/privoxy.crt | 26 ------------------ CA/webpagesCerts/privoxy.key | 27 ------------------- config | 14 ++++++++-- ssl.c | 52 +++++++++--------------------------- 4 files changed, 24 insertions(+), 95 deletions(-) delete mode 100644 CA/webpagesCerts/privoxy.crt delete mode 100644 CA/webpagesCerts/privoxy.key diff --git a/CA/webpagesCerts/privoxy.crt b/CA/webpagesCerts/privoxy.crt deleted file mode 100644 index cb8b4c6c..00000000 --- a/CA/webpagesCerts/privoxy.crt +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEZzCCAk8CCQCJvYh0qfKN4jANBgkqhkiG9w0BAQsFADBQMSUwIwYJKoZIhvcN -AQkBFhZodHRwOi8vd3d3LnByaXZveHkub3JnMRAwDgYDVQQKEwdQcml2b3h5MRUw -EwYDVQQDEwxQcml2b3h5IFJvb3QwHhcNMTgxMTE5MDcyODAyWhcNMjMxMTE4MDcy -ODAyWjCBmjELMAkGA1UEBhMCREUxFDASBgNVBAgMC0RldXRzY2hsYW5kMQ8wDQYD -VQQHDAZCZXJsaW4xGDAWBgNVBAoMD3d3dy5wcml2b3h5Lm9yZzEYMBYGA1UECwwP -d3d3LnByaXZveHkub3JnMRgwFgYDVQQDDA93d3cucHJpdm94eS5vcmcxFjAUBgkq -hkiG9w0BCQEWB3ByaXZveHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQD2DR0rtZ8i9CiJy08cQn6iRa0jxIP8fBpi5qEyz0p0Erd5dJjj9ZAj/R1AKs+z -09wu86AWDLy7tah3j8G+ujeEdC1TR5wUmYESHxxD73zwnxg1y+nBP0mGF+82cPBz -AbHrw/HvzGFzsbWX804XEYKIpCHwuT5z/7ka3PnLK15f99ZlZOPYp5g/n2uIiIeJ -uNE0MTV61MkxwWzjmqVCHs804MiNbkpXQvmgKXZQdyAeZIH0ABcr1GZ3PD5ynHpr -JgAhqTibPywRboSbHsJzn8pEASUAP8J8Bu7O0G85WagSPYLelXFfjDbrT16fVndl -9z0E2nEN76YKtPdPEHzTuSIZAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAClP56oa -ktwN+l2fIc9VWDZ+Gk0g3oxj1TTgUVTb5BCyyhKIlKkjBGbanpIBQnnspxGZS05f -u5A75kJRvQOB+0od5xawE8Sf7gorB/THNlMvBmEseWpiBMJK0Gp5++vESXdNm+YI -Cl+Wi9xN3ok0WmMhuZjjXlj0Gy0riwspj7ezk1FOPa9h8H/ouPPbntTWmUjA7WuE -DI8yEExAEutQrWQKM6TBcjww/u5NeV4sfKd9P13O7q8GrfzyZsLLcPXYKcRCMWKh -eVUJ1x51Qi23b8LZn2IijDly42cciJYmCCdKviMjCbWPj5EaiVGzexoem7n4nVei -EO67loXFBjgBDacsIgR8C8HMekReGMSZ1aZKcECJUHo2So2LAWXj/Q1Evm9AvR+L -Jjjk0Q1vRPprBkpbjeTJwyOA2gwNgmJTigSeDnysNLfm9AUmEqp+eVCZxU8XEaEe -p40E58RhHvz6b37MOyKcpEiHfzVbO91JqWM3rLcXkkSpfdFxljIwrQf9qLq0BEHV -lw7s6u6kAbwJAPY0/bYP0trF3p3GtldrBA24jjPD2+YLj2riGmcN7H4yY/tmqKop -Ej21QR5RE7G7gv2gjXodOKw9pQaZaVUCnXDD2cryW41PikR17M4OQfu82dRP5I/d -cjjGCP7Bt4AAIf6ANecMKoyj5zmUpmudrcHF ------END CERTIFICATE----- diff --git a/CA/webpagesCerts/privoxy.key b/CA/webpagesCerts/privoxy.key deleted file mode 100644 index 659a3131..00000000 --- a/CA/webpagesCerts/privoxy.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA9g0dK7WfIvQoictPHEJ+okWtI8SD/HwaYuahMs9KdBK3eXSY -4/WQI/0dQCrPs9PcLvOgFgy8u7Wod4/Bvro3hHQtU0ecFJmBEh8cQ+988J8YNcvp -wT9JhhfvNnDwcwGx68Px78xhc7G1l/NOFxGCiKQh8Lk+c/+5Gtz5yyteX/fWZWTj -2KeYP59riIiHibjRNDE1etTJMcFs45qlQh7PNODIjW5KV0L5oCl2UHcgHmSB9AAX -K9Rmdzw+cpx6ayYAIak4mz8sEW6Emx7Cc5/KRAElAD/CfAbuztBvOVmoEj2C3pVx -X4w2609en1Z3Zfc9BNpxDe+mCrT3TxB807kiGQIDAQABAoIBAQC4EPlokHcbC/Ij -mw90gZ4AQQWUQ1fFkwWeRRAEVaRKDxJobrxNlI+fDKRMM3qr+Wq3SRPSSvcJqYz8 -3HNA/ke3871QlrqBgpBXASUBAXDDBRF0dTZKldCn2tHeNUD7mCIE0NH15Txl82R4 -5s/dXAD9vWOSlNHOr1hHa1YHEkuImASprUeCpmL1T8kxD68HsvwPjjikUtBQ6nQv -r/9HTZDvJMmBrsnYYR1UxcWqWUq38j79AgZ+rmZQBO1XnLr8WHbvhZgscs8tG/cS -ZkX395ki9LNe/X/gnbpmOpvym0Jzlaasvn/Y/A9u5hvz9ZWRheiNfe3GNRU45BmQ -XvEo+qGdAoGBAP2CsOiRDmNEsucIbg8xwa2w3wgI2a97h8vj5qCIsrSQ0845D1Eh -Q6e2w1gden0JXTNCXnfD4sApYKKPCve5fU7Gtit9DEgqDBP/BL98AuCTmzhqDygz -yAclDsgZPiv5SxqPWk5tFfyYnBCqi16YLN+6XyXYRz4SikrpFzR883FfAoGBAPh3 -q7WlBisbkMbEyK75sGhze31pUNoFHqH0Iuj28wjWLfxJBIWehMErUOUhrBaNOEVT -MXRgUiklJh6VRRrR7m+4PGlIz/1ZZHmxh4Bs+I/ihsbfYcJ2QAxjDkdxhuHwysuB -8+0hckXbmQpjYQsOB40GW6I+I3OBC1tnSCBLeUeHAoGBAIMvsFCJUAK6uEGqMRoX -y3wQfTnxKoUOzdUK2HvWgXPDRnf/OxfmuNX/U9MzXgF6aQpvm+cqLRr3zpQQpcJP -8LJlTjvu9/4YFCv82f4lNG/2smpdJ/7L3QUlfiK6PVwQI3dZG4heFvSiHJDbUEfh -Q8d68GXrJ+LNQVdGi8WTq37NAoGBAJesRa9ei4NpElmj6nWVijBYvntx/J76HRbz -9xOLHBS62dt1n0MJ3zQkAv+8LFaf4ke/XyMRYVYojTqCGGsk145vQsFqZzzagtEe -o/6rhpgeyfNAjWat1K87EI5gKNxnpwPP0l1g22b1hFipDaY37DgUN3+0uuNZVNt5 -ErhUGjalAoGAPOXVZASlWyRakPzRyUBllSihNVq4YZXxvGo2Xm17I29H3zFthObE -1xdb2JnC+4kSzCTibgJAt3/I8dTUYFd3zasj7gTiFPZFInnDsKkseHNMCgXIbbSR -RZqtM057KcmgkNMSGgYuN4NG9os1dP5X2qRv2vKfQJ59SKBpiRl2Mmg= ------END RSA PRIVATE KEY----- diff --git a/config b/config index d465ec19..b9158ca1 100644 --- a/config +++ b/config @@ -2491,7 +2491,9 @@ socket-timeout 300 # # Examples: # -# ca-password abcd +# ca-password abcd +# + ca-password abc # # # 8.2. ca-dir @@ -2516,7 +2518,7 @@ socket-timeout 300 # # Examples: # -# ca-dir ./MY_CA +# ca-dir ./MY_CA # # # 8.3. ca-cert-file @@ -2541,6 +2543,8 @@ socket-timeout 300 # Examples: # # ca-cert-file root.crt +# + ca-cert-file cacert.crt # # # 8.4. ca-key-file @@ -2565,6 +2569,8 @@ socket-timeout 300 # Examples: # # ca-key-file root.pem +# + ca-key-file cakey.pem # # # 8.5. certs-dir @@ -2589,6 +2595,8 @@ socket-timeout 300 # Examples: # # certs-dir ./generated_certs +# + certs-dir ./CA/webpagesCerts # # # 8.6. trusted-cas-file @@ -2613,4 +2621,6 @@ socket-timeout 300 # Examples: # # trusted-cas-file trusted_cas_file.pem +# + trusted-cas-file trustedCAs.pem # diff --git a/ssl.c b/ssl.c index fb8947cb..18a5ae55 100644 --- a/ssl.c +++ b/ssl.c @@ -373,13 +373,13 @@ extern int create_client_ssl_connection(struct client_state *csp) /* * Preparing paths to certificates files and key file */ - ca_file = make_certs_path("CA", "cacert", CERT_FILE_TYPE); - cert_file = make_certs_path("CA/webpagesCerts", + ca_file = csp->config->ca_cert_file; + cert_file = make_certs_path(csp->config->certs_dir, (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); - key_file = make_certs_path("CA/webpagesCerts", + key_file = make_certs_path(csp->config->certs_dir, (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); - if (ca_file == NULL || cert_file == NULL || key_file == NULL) + if (cert_file == NULL || key_file == NULL) { ret = -1; goto exit; @@ -538,10 +538,6 @@ exit: /* * Freeing allocated paths to files */ - if (ca_file != NULL) - { - freez(ca_file); - } if (cert_file != NULL) { freez(cert_file); @@ -653,12 +649,7 @@ extern int create_server_ssl_connection(struct client_state *csp) int auth_mode = MBEDTLS_SSL_VERIFY_REQUIRED; /* Setting path to file with trusted CAs */ - trusted_cas_file = make_certs_path("CA", "trustedCAs", KEY_FILE_TYPE); - if (trusted_cas_file == NULL) - { - ret = -1; - goto exit; - } + trusted_cas_file = csp->config->trusted_cas_file; /* * Initializing mbedtls structures for SSL/TLS connection @@ -812,14 +803,6 @@ extern int create_server_ssl_connection(struct client_state *csp) csp->server_cert_verification_result = mbedtls_ssl_get_verify_result(&(csp->mbedtls_server_attr.ssl)); exit: - /* - * Freeing allocated paths to files - */ - if (trusted_cas_file != NULL) - { - freez(trusted_cas_file); - } - /* Freeing structures if connection wasn't created successfully */ if (ret < 0) { @@ -1162,7 +1145,7 @@ extern int generate_key(unsigned char ** key_buf, struct client_state *csp) key_opt.type = MBEDTLS_PK_RSA; key_opt.rsa_keysize = RSA_KEYSIZE; - key_opt.key_file_path = make_certs_path("CA/webpagesCerts", + key_opt.key_file_path = make_certs_path(csp->config->certs_dir, (char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); if (key_opt.key_file_path == NULL) { @@ -1340,22 +1323,21 @@ extern int generate_webpage_certificate(struct client_state * csp) strlcat(cert_params, csp->http->host, cert_params_len); strlcat(cert_params, CERT_PARAM_COUNTRY, cert_params_len); - cert_opt.issuer_crt = make_certs_path("CA", "cacert", CERT_FILE_TYPE); - cert_opt.issuer_key = make_certs_path("CA", "cakey", KEY_FILE_TYPE); - cert_opt.subject_key = make_certs_path("CA/webpagesCerts", + cert_opt.issuer_crt = csp->config->ca_cert_file; + cert_opt.issuer_key = csp->config->ca_key_file; + cert_opt.subject_key = make_certs_path(csp->config->certs_dir, (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); - cert_opt.output_file = make_certs_path("CA/webpagesCerts", + cert_opt.output_file = make_certs_path(csp->config->certs_dir, (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); - if (cert_opt.issuer_crt == NULL || cert_opt.issuer_key == NULL - || cert_opt.subject_key == NULL || cert_opt.output_file == NULL) + if (cert_opt.subject_key == NULL || cert_opt.output_file == NULL) { ret = -1; goto exit; } cert_opt.subject_pwd = CERT_SUBJECT_PASSWORD; - cert_opt.issuer_pwd = "abc"; + cert_opt.issuer_pwd = csp->config->ca_password; cert_opt.subject_name = cert_params; cert_opt.not_before = GENERATED_CERT_VALID_FROM; cert_opt.not_after = GENERATED_CERT_VALID_TO; @@ -1576,16 +1558,6 @@ exit: mbedtls_mpi_free(&serial); mbedtls_x509_crt_free(&issuer_cert); - if (cert_opt.issuer_crt != NULL) - { - freez(cert_opt.issuer_crt); - } - - if (cert_opt.issuer_key != NULL) - { - freez(cert_opt.issuer_key); - } - if (cert_opt.subject_key != NULL) { freez(cert_opt.subject_key); -- 2.26.2 From b77f2d0bf93026d1d9345376e1ea304608ed93ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:15:00 +0200 Subject: [PATCH 29/83] Renaming ssl structures and added macro for Mbedtls. --- jcc.c | 48 +++++++++++------- project.h | 22 +++++++-- ssl.c | 142 +++++++++++++++++++++++++++--------------------------- ssl.h | 8 +-- 4 files changed, 124 insertions(+), 96 deletions(-) diff --git a/jcc.c b/jcc.c index b2a30a8d..3c2d2a73 100644 --- a/jcc.c +++ b/jcc.c @@ -112,7 +112,6 @@ #include "project.h" #include "list.h" #include "jcc.h" -#include "ssl.h" #include "filters.h" #include "loaders.h" #include "parsers.h" @@ -128,6 +127,10 @@ #include "client-tags.h" #endif +#ifdef FEATURE_MBEDTLS +#include "ssl.h" +#endif + int daemon_mode = 1; struct client_states clients[1]; struct file_list files[1]; @@ -2141,12 +2144,12 @@ static void handle_established_connection(struct client_state *csp) if (client_use_ssl(csp)) { - read_ssl_client = is_ssl_pending(&(csp->mbedtls_client_attr.ssl)); + read_ssl_client = is_ssl_pending(&(csp->ssl_client_attr)); } if (server_use_ssl(csp)) { - read_ssl_server = is_ssl_pending(&(csp->mbedtls_server_attr.ssl)); + read_ssl_server = is_ssl_pending(&(csp->ssl_server_attr)); } @@ -2311,7 +2314,7 @@ static void handle_established_connection(struct client_state *csp) * Receiving HTTP request from client over SSL/TLS and sending * it to server over SSL/TLS. */ - len = ssl_recv_data(&(csp->mbedtls_client_attr.ssl), + len = ssl_recv_data(&(csp->ssl_client_attr), (unsigned char *) csp->receive_buffer, max_bytes_to_read); if (len <= 0) @@ -2320,7 +2323,7 @@ static void handle_established_connection(struct client_state *csp) break; } - ret = ssl_send_data(&(csp->mbedtls_server_attr.ssl), + ret = ssl_send_data(&(csp->ssl_server_attr), (unsigned char *) csp->receive_buffer, len); if (ret < 0) @@ -2410,7 +2413,7 @@ static void handle_established_connection(struct client_state *csp) */ if (server_use_ssl(csp)) { - len = ssl_recv_data(&(csp->mbedtls_server_attr.ssl), + len = ssl_recv_data(&(csp->ssl_server_attr), (unsigned char *)csp->receive_buffer, (int)csp->receive_buffer_size); } else @@ -2563,9 +2566,9 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl), + if ((ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)hdr, strlen(hdr)) < 0) - || (ssl_send_data(&(csp->mbedtls_client_attr.ssl), + || (ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)((p != NULL) ? p : csp->iob->cur), (size_t)csp->content_length) < 0)) { @@ -2659,11 +2662,11 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl), + if ((ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)hdr, hdrlen) < 0) - || ((flushed = ssl_flush_socket(&(csp->mbedtls_client_attr.ssl), + || ((flushed = ssl_flush_socket(&(csp->ssl_client_attr), csp->iob)) < 0) - || (ssl_send_data(&(csp->mbedtls_client_attr.ssl), + || (ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)csp->receive_buffer, (size_t)len) < 0)) { log_error(LOG_LEVEL_CONNECT, @@ -2707,7 +2710,7 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - ret = ssl_send_data(&(csp->mbedtls_client_attr.ssl), + ret = ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)csp->receive_buffer, len); if (ret < 0) { @@ -2770,7 +2773,7 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - ssl_send_data(&(csp->mbedtls_client_attr.ssl), + ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, strlen(INVALID_SERVER_HEADERS_RESPONSE)); } @@ -2855,7 +2858,7 @@ static void handle_established_connection(struct client_state *csp) */ if(client_use_ssl(csp)) { - ssl_send_data(&(csp->mbedtls_client_attr.ssl), + ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, strlen(INVALID_SERVER_HEADERS_RESPONSE)); } @@ -2885,7 +2888,7 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - ssl_send_data(&(csp->mbedtls_client_attr.ssl), + ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, strlen(INVALID_SERVER_HEADERS_RESPONSE)); } @@ -2947,9 +2950,9 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl), + if ((ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)hdr, strlen(hdr)) < 0) - || (len = ssl_flush_socket(&(csp->mbedtls_client_attr.ssl), + || (len = ssl_flush_socket(&(csp->ssl_client_attr), csp->iob) < 0)) { log_error(LOG_LEVEL_CONNECT, "Write header to client failed"); @@ -3005,7 +3008,7 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - ssl_send_data(&(csp->mbedtls_client_attr.ssl), + ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, strlen(INVALID_SERVER_HEADERS_RESPONSE)); } @@ -3380,6 +3383,7 @@ static void chat(struct client_state *csp) * wasn't detected, we can interrupt this fuction. Otherwise, we * must inform client about invalid server certificate. */ +#ifdef FEATURE_MBEDTLS if (ret != 0 && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED || csp->server_cert_verification_result == SSL_CERT_VALID)) @@ -3391,6 +3395,7 @@ static void chat(struct client_state *csp) } return; } +#endif /* FEATURE_MBEDTLS */ /* * SSL/TLS connection with parent proxy is established, we can @@ -3419,6 +3424,7 @@ static void chat(struct client_state *csp) * wasn't detected, we can interrupt this fuction. Otherwise, we * must inform client about invalid server certificate. */ +#ifdef FEATURE_MBEDTLS if (ret != 0 && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED || csp->server_cert_verification_result == SSL_CERT_VALID)) @@ -3430,6 +3436,8 @@ static void chat(struct client_state *csp) } return; } +#endif /* FEATURE_MBEDTLS */ + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); } } @@ -3510,12 +3518,14 @@ static void chat(struct client_state *csp) * If server certificate is invalid, we must inform client and then * close connection with client. */ +#ifdef FEATURE_MBEDTLS if (csp->server_cert_verification_result != SSL_CERT_VALID) { ssl_send_certificate_error(csp); close_client_and_server_ssl_connections(csp); return; } +#endif /* FEATURE_MBEDTLS */ log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); } @@ -5104,10 +5114,12 @@ static void listen_loop(void) /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */ /* Clean up. Aim: free all memory (no leaks) */ +#ifdef FEATURE_MBEDTLS if (rng_seeded == 1) { mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); } +#endif #ifdef FEATURE_GRACEFUL_TERMINATION diff --git a/project.h b/project.h index 8bdc68e7..d52e0a95 100644 --- a/project.h +++ b/project.h @@ -44,6 +44,8 @@ /* Needed for pcre choice */ #include "config.h" + +#ifdef FEATURE_MBEDTLS /* Mbedtls incldues */ #include "mbedtls/net_sockets.h" #include "mbedtls/entropy.h" @@ -52,6 +54,8 @@ #if defined(MBEDTLS_SSL_CACHE_C) #include "mbedtls/ssl_cache.h" #endif +#endif /* FEATURE_MBEDTLS */ + /* * Macros for SSL structures @@ -280,6 +284,7 @@ struct map * Srtuct of atributes necessary for SSL/TLS connection */ typedef struct { +#ifdef FEATURE_MBEDTLS mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_net_context socket_fd; @@ -290,7 +295,15 @@ typedef struct { #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif -} mbedtls_connection_attr; +#endif /* FEATURE_MBEDTLS */ + +#ifdef FEATURE_LIBRESSL + int socket_fd; + struct tls *tls; + struct tls_config *config; + struct sockaddr_in server; +#endif /* FEATURE_LIBRESSL */ +} ssl_connection_attr; /** * A HTTP request. This includes the method (GET, POST) and @@ -353,7 +366,10 @@ typedef struct { * Propeties of key for generating */ typedef struct { +#ifdef FEATURE_MBEDTLS mbedtls_pk_type_t type; /* type of key to generate */ +#endif /* FEATURE_MBEDTLS */ + int rsa_keysize; /* length of key in bits */ char *key_file_path; /* filename of the key file */ } key_options; @@ -1027,10 +1043,10 @@ struct client_state struct iob iob[1]; /* attributes for connection to server */ - mbedtls_connection_attr mbedtls_server_attr; + ssl_connection_attr ssl_server_attr; /* attributes for connection to client */ - mbedtls_connection_attr mbedtls_client_attr; + ssl_connection_attr ssl_client_attr; /** An I/O buffer used for buffering data read from the client */ struct iob client_iob[1]; diff --git a/ssl.c b/ssl.c index 18a5ae55..8f510b25 100644 --- a/ssl.c +++ b/ssl.c @@ -137,14 +137,14 @@ extern int server_use_ssl(struct client_state *csp) * >0 => Pending data length * *********************************************************************/ -extern size_t is_ssl_pending(mbedtls_ssl_context * ssl) +extern size_t is_ssl_pending(ssl_connection_attr * connection) { - if (ssl == NULL) + if (&(connection->ssl) == NULL) { return 0; } - return mbedtls_ssl_get_bytes_avail(ssl); + return mbedtls_ssl_get_bytes_avail(&connection->ssl); } @@ -163,7 +163,7 @@ extern size_t is_ssl_pending(mbedtls_ssl_context * ssl) * Returns : Length of sent data or negative value on error. * *********************************************************************/ -extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len) +extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * buf, int len) { int ret = 0; char err_buf[ERROR_BUF_SIZE]; @@ -178,7 +178,7 @@ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, i } /* Getting maximal length of data sent in one fragment */ - max_fragment_size = mbedtls_ssl_get_max_frag_len(ssl); + max_fragment_size = mbedtls_ssl_get_max_frag_len(&connection->ssl); /* * Whole buffer must by sent in many fragments, because each fragment @@ -199,7 +199,7 @@ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, i /* * Sending one part of the buffer */ - while ((ret = mbedtls_ssl_write(ssl, + while ((ret = mbedtls_ssl_write(&connection->ssl, (const unsigned char *)(buf + pos), send_len)) < 0) { @@ -235,7 +235,7 @@ extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, i * value on error. * *********************************************************************/ -extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int maxLen) +extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { int ret = 0; char err_buf[ERROR_BUF_SIZE]; @@ -247,7 +247,7 @@ extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int max */ do { - ret = mbedtls_ssl_read(ssl, buf, maxLen); + ret = mbedtls_ssl_read(&connection->ssl, buf, maxLen); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); @@ -277,7 +277,7 @@ extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int max * indicates nothing was sent). On error, -1 is returned. * *********************************************************************/ -extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob) +extern long ssl_flush_socket(ssl_connection_attr * connection, struct iob *iob) { /* Computing length of buffer part to send*/ long len = iob->eod - iob->cur; @@ -288,7 +288,7 @@ extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob) } /* Sending data to given SSl context */ - if (ssl_send_data(ssl, (const unsigned char *)iob->cur, (size_t)len) < 0) + if (ssl_send_data(connection, (const unsigned char *)iob->cur, (size_t)len) < 0) { return -1; } @@ -350,13 +350,13 @@ extern int create_client_ssl_connection(struct client_state *csp) /* * Initializing mbedtls structures for SSL/TLS connection */ - mbedtls_net_init(&(csp->mbedtls_client_attr.socket_fd)); - mbedtls_ssl_init(&(csp->mbedtls_client_attr.ssl)); - mbedtls_ssl_config_init(&(csp->mbedtls_client_attr.conf)); - mbedtls_x509_crt_init(&(csp->mbedtls_client_attr.server_cert)); - mbedtls_pk_init(&(csp->mbedtls_client_attr.prim_key)); + mbedtls_net_init(&(csp->ssl_client_attr.socket_fd)); + mbedtls_ssl_init(&(csp->ssl_client_attr.ssl)); + mbedtls_ssl_config_init(&(csp->ssl_client_attr.conf)); + mbedtls_x509_crt_init(&(csp->ssl_client_attr.server_cert)); + mbedtls_pk_init(&(csp->ssl_client_attr.prim_key)); #if defined(MBEDTLS_SSL_CACHE_C) - mbedtls_ssl_cache_init(&(csp->mbedtls_client_attr.cache)); + mbedtls_ssl_cache_init(&(csp->ssl_client_attr.cache)); #endif /* @@ -416,7 +416,7 @@ extern int create_client_ssl_connection(struct client_state *csp) /* * Loading CA file, webpage certificate and key files */ - ret = mbedtls_x509_crt_parse_file(&(csp->mbedtls_client_attr.server_cert), + ret = mbedtls_x509_crt_parse_file(&(csp->ssl_client_attr.server_cert), cert_file); if (ret != 0) { @@ -427,7 +427,7 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } - ret = mbedtls_x509_crt_parse_file(&(csp->mbedtls_client_attr.server_cert), + ret = mbedtls_x509_crt_parse_file(&(csp->ssl_client_attr.server_cert), ca_file); if (ret != 0) { @@ -438,7 +438,7 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } - ret = mbedtls_pk_parse_keyfile(&(csp->mbedtls_client_attr.prim_key), + ret = mbedtls_pk_parse_keyfile(&(csp->ssl_client_attr.prim_key), key_file, NULL); if (ret != 0) { @@ -453,7 +453,7 @@ extern int create_client_ssl_connection(struct client_state *csp) /* * Setting SSL parameters */ - ret = mbedtls_ssl_config_defaults(&(csp->mbedtls_client_attr.conf), + ret = mbedtls_ssl_config_defaults(&(csp->ssl_client_attr.conf), MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) @@ -465,23 +465,23 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } - mbedtls_ssl_conf_rng(&(csp->mbedtls_client_attr.conf), + mbedtls_ssl_conf_rng(&(csp->ssl_client_attr.conf), mbedtls_ctr_drbg_random, &ctr_drbg); - mbedtls_ssl_conf_dbg(&(csp->mbedtls_client_attr.conf), + mbedtls_ssl_conf_dbg(&(csp->ssl_client_attr.conf), ssl_debug_callback, stdout); #if defined(MBEDTLS_SSL_CACHE_C) - mbedtls_ssl_conf_session_cache(&(csp->mbedtls_client_attr.conf), - &(csp->mbedtls_client_attr.cache), mbedtls_ssl_cache_get, + mbedtls_ssl_conf_session_cache(&(csp->ssl_client_attr.conf), + &(csp->ssl_client_attr.cache), mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); #endif /* * Setting certificates */ - ret = mbedtls_ssl_conf_own_cert(&(csp->mbedtls_client_attr.conf), - &(csp->mbedtls_client_attr.server_cert), - &(csp->mbedtls_client_attr.prim_key)); + ret = mbedtls_ssl_conf_own_cert(&(csp->ssl_client_attr.conf), + &(csp->ssl_client_attr.server_cert), + &(csp->ssl_client_attr.prim_key)); if (ret != 0) { mbedtls_strerror(ret, err_buf, sizeof(err_buf)); @@ -491,8 +491,8 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } - ret = mbedtls_ssl_setup(&(csp->mbedtls_client_attr.ssl), - &(csp->mbedtls_client_attr.conf)); + ret = mbedtls_ssl_setup(&(csp->ssl_client_attr.ssl), + &(csp->ssl_client_attr.conf)); if (ret != 0) { mbedtls_strerror(ret, err_buf, sizeof(err_buf)); @@ -501,24 +501,24 @@ extern int create_client_ssl_connection(struct client_state *csp) goto exit; } - mbedtls_ssl_set_bio(&(csp->mbedtls_client_attr.ssl), - &(csp->mbedtls_client_attr.socket_fd), mbedtls_net_send, + mbedtls_ssl_set_bio(&(csp->ssl_client_attr.ssl), + &(csp->ssl_client_attr.socket_fd), mbedtls_net_send, mbedtls_net_recv, NULL); - mbedtls_ssl_session_reset(&(csp->mbedtls_client_attr.ssl)); + mbedtls_ssl_session_reset(&(csp->ssl_client_attr.ssl)); /* * Setting socket fd in mbedtls_net_context structure. This structure * can't be setted by mbedtls functions, because we already have created * TCP connection when starting this function. */ - csp->mbedtls_client_attr.socket_fd.fd = csp->cfd; + csp->ssl_client_attr.socket_fd.fd = csp->cfd; /* * Handshake with client */ log_error(LOG_LEVEL_CONNECT, "Performing the SSL/TLS handshake with client"); - while ((ret = mbedtls_ssl_handshake(&(csp->mbedtls_client_attr.ssl))) != 0) + while ((ret = mbedtls_ssl_handshake(&(csp->ssl_client_attr.ssl))) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) @@ -582,7 +582,7 @@ static void close_client_ssl_connection(struct client_state *csp) * Notifying the peer that the connection is being closed. */ do { - ret = mbedtls_ssl_close_notify(&(csp->mbedtls_client_attr.ssl)); + ret = mbedtls_ssl_close_notify(&(csp->ssl_client_attr.ssl)); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); free_client_ssl_structures(csp); @@ -610,15 +610,15 @@ static void free_client_ssl_structures(struct client_state *csp) * function, we change fd to -1, which is the same what does * rest of mbedtls_net_free function. */ - csp->mbedtls_client_attr.socket_fd.fd = -1; + csp->ssl_client_attr.socket_fd.fd = -1; /* Freeing mbedtls structures */ - mbedtls_x509_crt_free(&(csp->mbedtls_client_attr.server_cert)); - mbedtls_pk_free(&(csp->mbedtls_client_attr.prim_key)); - mbedtls_ssl_free(&(csp->mbedtls_client_attr.ssl)); - mbedtls_ssl_config_free(&(csp->mbedtls_client_attr.conf)); + mbedtls_x509_crt_free(&(csp->ssl_client_attr.server_cert)); + mbedtls_pk_free(&(csp->ssl_client_attr.prim_key)); + mbedtls_ssl_free(&(csp->ssl_client_attr.ssl)); + mbedtls_ssl_config_free(&(csp->ssl_client_attr.conf)); #if defined(MBEDTLS_SSL_CACHE_C) - mbedtls_ssl_cache_free(&(csp->mbedtls_client_attr.cache)); + mbedtls_ssl_cache_free(&(csp->ssl_client_attr.cache)); #endif } @@ -654,12 +654,12 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Initializing mbedtls structures for SSL/TLS connection */ - mbedtls_net_init(&(csp->mbedtls_server_attr.socket_fd)); - mbedtls_ssl_init(&(csp->mbedtls_server_attr.ssl)); - mbedtls_ssl_config_init(&(csp->mbedtls_server_attr.conf)); - mbedtls_x509_crt_init( &(csp->mbedtls_server_attr.ca_cert)); + mbedtls_net_init(&(csp->ssl_server_attr.socket_fd)); + mbedtls_ssl_init(&(csp->ssl_server_attr.ssl)); + mbedtls_ssl_config_init(&(csp->ssl_server_attr.conf)); + mbedtls_x509_crt_init( &(csp->ssl_server_attr.ca_cert)); #if defined(MBEDTLS_SSL_CACHE_C) - mbedtls_ssl_cache_init(&(csp->mbedtls_server_attr.cache)); + mbedtls_ssl_cache_init(&(csp->ssl_server_attr.cache)); #endif /* @@ -667,7 +667,7 @@ extern int create_server_ssl_connection(struct client_state *csp) * can't be setted by mbedtls functions, because we already have created * TCP connection when starting this function. */ - csp->mbedtls_server_attr.socket_fd.fd = csp->server_connection.sfd; + csp->ssl_server_attr.socket_fd.fd = csp->server_connection.sfd; /* * Seed the RNG @@ -682,7 +682,7 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Loading file with trusted CAs */ - ret = mbedtls_x509_crt_parse_file(&(csp->mbedtls_server_attr.ca_cert), + ret = mbedtls_x509_crt_parse_file(&(csp->ssl_server_attr.ca_cert), trusted_cas_file); if (ret < 0) { @@ -696,7 +696,7 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Set SSL/TLS options */ - ret = mbedtls_ssl_config_defaults(&(csp->mbedtls_server_attr.conf), + ret = mbedtls_ssl_config_defaults(&(csp->ssl_server_attr.conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); @@ -718,21 +718,21 @@ extern int create_server_ssl_connection(struct client_state *csp) auth_mode = MBEDTLS_SSL_VERIFY_NONE; } - mbedtls_ssl_conf_authmode(&(csp->mbedtls_server_attr.conf), auth_mode); - mbedtls_ssl_conf_ca_chain(&(csp->mbedtls_server_attr.conf), - &(csp->mbedtls_server_attr.ca_cert), NULL); + mbedtls_ssl_conf_authmode(&(csp->ssl_server_attr.conf), auth_mode); + mbedtls_ssl_conf_ca_chain(&(csp->ssl_server_attr.conf), + &(csp->ssl_server_attr.ca_cert), NULL); /* Setting callback function for certificates verification */ - mbedtls_ssl_conf_verify(&(csp->mbedtls_server_attr.conf), + mbedtls_ssl_conf_verify(&(csp->ssl_server_attr.conf), ssl_verify_callback, (void *)csp); - mbedtls_ssl_conf_rng(&(csp->mbedtls_server_attr.conf), + mbedtls_ssl_conf_rng(&(csp->ssl_server_attr.conf), mbedtls_ctr_drbg_random, &ctr_drbg); - mbedtls_ssl_conf_dbg(&(csp->mbedtls_server_attr.conf), + mbedtls_ssl_conf_dbg(&(csp->ssl_server_attr.conf), ssl_debug_callback, stdout); - ret = mbedtls_ssl_setup(&(csp->mbedtls_server_attr.ssl), - &(csp->mbedtls_server_attr.conf)); + ret = mbedtls_ssl_setup(&(csp->ssl_server_attr.ssl), + &(csp->ssl_server_attr.conf)); if ( ret != 0) { mbedtls_strerror(ret, err_buf, sizeof(err_buf)); @@ -744,7 +744,7 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Set the hostname to check against the received server certificate */ - ret = mbedtls_ssl_set_hostname(&(csp->mbedtls_server_attr.ssl), + ret = mbedtls_ssl_set_hostname(&(csp->ssl_server_attr.ssl), csp->http->host); if (ret != 0) { @@ -755,8 +755,8 @@ extern int create_server_ssl_connection(struct client_state *csp) goto exit; } - mbedtls_ssl_set_bio(&(csp->mbedtls_server_attr.ssl), - &(csp->mbedtls_server_attr.socket_fd), mbedtls_net_send, + mbedtls_ssl_set_bio(&(csp->ssl_server_attr.ssl), + &(csp->ssl_server_attr.socket_fd), mbedtls_net_send, mbedtls_net_recv, NULL); /* @@ -765,7 +765,7 @@ extern int create_server_ssl_connection(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "Performing the SSL/TLS handshake with server"); - while ((ret = mbedtls_ssl_handshake(&(csp->mbedtls_server_attr.ssl))) != 0) + while ((ret = mbedtls_ssl_handshake(&(csp->ssl_server_attr.ssl))) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) @@ -777,7 +777,7 @@ extern int create_server_ssl_connection(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Server cerificate verification failed: %s", err_buf); csp->server_cert_verification_result = - mbedtls_ssl_get_verify_result(&(csp->mbedtls_server_attr.ssl)); + mbedtls_ssl_get_verify_result(&(csp->ssl_server_attr.ssl)); ret = -1; } @@ -800,7 +800,7 @@ extern int create_server_ssl_connection(struct client_state *csp) free_certificate_chain(csp); csp->ssl_with_server_is_opened = 1; - csp->server_cert_verification_result = mbedtls_ssl_get_verify_result(&(csp->mbedtls_server_attr.ssl)); + csp->server_cert_verification_result = mbedtls_ssl_get_verify_result(&(csp->ssl_server_attr.ssl)); exit: /* Freeing structures if connection wasn't created successfully */ @@ -813,7 +813,7 @@ exit: } -/* +/********************************************************************** * * Function : close_server_ssl_connection * @@ -825,7 +825,7 @@ exit: * * Returns : N/A * - */ + **********************************************************************/ static void close_server_ssl_connection(struct client_state *csp) { int ret = 0; @@ -839,7 +839,7 @@ static void close_server_ssl_connection(struct client_state *csp) * Notifying the peer that the connection is being closed. */ do { - ret = mbedtls_ssl_close_notify(&(csp->mbedtls_server_attr.ssl)); + ret = mbedtls_ssl_close_notify(&(csp->ssl_server_attr.ssl)); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); free_server_ssl_structures(csp); @@ -867,11 +867,11 @@ static void free_server_ssl_structures(struct client_state *csp) * function, we change fd to -1, which is the same what does * rest of mbedtls_net_free function. */ - csp->mbedtls_server_attr.socket_fd.fd = -1; + csp->ssl_server_attr.socket_fd.fd = -1; - mbedtls_x509_crt_free(&(csp->mbedtls_server_attr.ca_cert)); - mbedtls_ssl_free(&(csp->mbedtls_server_attr.ssl)); - mbedtls_ssl_config_free(&(csp->mbedtls_server_attr.conf)); + mbedtls_x509_crt_free(&(csp->ssl_server_attr.ca_cert)); + mbedtls_ssl_free(&(csp->ssl_server_attr.ssl)); + mbedtls_ssl_config_free(&(csp->ssl_server_attr.conf)); } @@ -1836,7 +1836,7 @@ extern void ssl_send_certificate_error(struct client_state *csp) /* * Sending final message to client */ - ssl_send_data(&(csp->mbedtls_client_attr.ssl), + ssl_send_data(&(csp->ssl_client_attr), (const unsigned char *)message, strlen(message)); /* * Waiting before closing connection. Some browsers don't show received diff --git a/ssl.h b/ssl.h index a56f0205..33d4d8f3 100644 --- a/ssl.h +++ b/ssl.h @@ -50,13 +50,13 @@ static int rng_seeded; /* Boolean functions to get informations about SSL/TLS connections */ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); -extern size_t is_ssl_pending(mbedtls_ssl_context *ssl); +extern size_t is_ssl_pending(ssl_connection_attr *connection); extern int tunnel_established_successfully(const char * response, unsigned int response_len); /* Functions for sending and receiving data over SSL/TLS connections */ -extern int ssl_send_data(mbedtls_ssl_context * ssl, const unsigned char * buf, int len); -extern int ssl_recv_data(mbedtls_ssl_context * ssl, unsigned char * buf, int maxLen); -extern long ssl_flush_socket(mbedtls_ssl_context * ssl, struct iob *iob); +extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * buf, int len); +extern int ssl_recv_data(ssl_connection_attr * connection, unsigned char * buf, int maxLen); +extern long ssl_flush_socket(ssl_connection_attr * connection, struct iob *iob); extern void ssl_send_certificate_error(struct client_state *csp); /* Functions for opening and closing SSL/TLS connections */ -- 2.26.2 From d1ffa9af094ce3d6daed453aa6eb556bdc715ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:21:12 +0200 Subject: [PATCH 30/83] Created ssl connection with server. --- jcc.c | 31 ++++-- project.h | 11 ++- ssl_libressl.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++ ssl_libressl.h | 54 +++++++++++ 4 files changed, 336 insertions(+), 11 deletions(-) create mode 100644 ssl_libressl.c create mode 100644 ssl_libressl.h diff --git a/jcc.c b/jcc.c index 3c2d2a73..0e33fb52 100644 --- a/jcc.c +++ b/jcc.c @@ -131,6 +131,11 @@ #include "ssl.h" #endif +#ifdef FEATURE_LIBRESSL +#include "ssl_libressl.h" +#endif + + int daemon_mode = 1; struct client_states clients[1]; struct file_list files[1]; @@ -2060,6 +2065,11 @@ static void handle_established_connection(struct client_state *csp) server_body = 0; +#ifdef FEATURE_LIBRESSL + csp->ssl_server_attr.is_pending = 0; + csp->ssl_client_attr.is_pending = 0; +#endif + #ifdef FEATURE_CONNECTION_KEEP_ALIVE watch_client_socket = 0 == (csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING); #endif @@ -2152,7 +2162,6 @@ static void handle_established_connection(struct client_state *csp) read_ssl_server = is_ssl_pending(&(csp->ssl_server_attr)); } - if (!read_ssl_server && !read_ssl_client) { #ifdef HAVE_POLL @@ -2181,7 +2190,7 @@ static void handle_established_connection(struct client_state *csp) timeout.tv_usec = 0; n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout); #endif /* def HAVE_POLL */ - } + } else { #ifdef HAVE_POLL @@ -3383,10 +3392,13 @@ static void chat(struct client_state *csp) * wasn't detected, we can interrupt this fuction. Otherwise, we * must inform client about invalid server certificate. */ -#ifdef FEATURE_MBEDTLS + if (ret != 0 +#ifdef FEATURE_MBEDTLS && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED - || csp->server_cert_verification_result == SSL_CERT_VALID)) + || csp->server_cert_verification_result == SSL_CERT_VALID) +#endif /* FEATURE_MBEDTLS */ + ) { rsp = error_response(csp, "connect-failed"); if (rsp) @@ -3395,7 +3407,7 @@ static void chat(struct client_state *csp) } return; } -#endif /* FEATURE_MBEDTLS */ + /* * SSL/TLS connection with parent proxy is established, we can @@ -3424,10 +3436,13 @@ static void chat(struct client_state *csp) * wasn't detected, we can interrupt this fuction. Otherwise, we * must inform client about invalid server certificate. */ -#ifdef FEATURE_MBEDTLS + if (ret != 0 +#ifdef FEATURE_MBEDTLS && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED - || csp->server_cert_verification_result == SSL_CERT_VALID)) + || csp->server_cert_verification_result == SSL_CERT_VALID) +#endif /* FEATURE_MBEDTLS */ + ) { rsp = error_response(csp, "connect-failed"); if (rsp) @@ -3436,7 +3451,7 @@ static void chat(struct client_state *csp) } return; } -#endif /* FEATURE_MBEDTLS */ + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); } diff --git a/project.h b/project.h index d52e0a95..0591129c 100644 --- a/project.h +++ b/project.h @@ -56,6 +56,10 @@ #endif #endif /* FEATURE_MBEDTLS */ +#ifdef FEATURE_LIBRESSL +#include "tls.h" +#endif /* FEATURE_LIBRESSL */ + /* * Macros for SSL structures @@ -299,9 +303,10 @@ typedef struct { #ifdef FEATURE_LIBRESSL int socket_fd; - struct tls *tls; - struct tls_config *config; - struct sockaddr_in server; + struct tls *ctx_io; + struct tls *ctx; + struct tls_config *conf; + int is_pending; #endif /* FEATURE_LIBRESSL */ } ssl_connection_attr; diff --git a/ssl_libressl.c b/ssl_libressl.c new file mode 100644 index 00000000..b221fd89 --- /dev/null +++ b/ssl_libressl.c @@ -0,0 +1,251 @@ +/********************************************************************* + * + * File : $Source: /cvsroot/ijbswa/current/ssl_libressl.c,v $ + * + * Purpose : File with SSL/TLS extension in Libressl library. + * Contains methods for creating, using and closing + * SSL/TLS connections. + * + * Copyright : Written by Vaclav Svec. FIT CVUT. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * The GNU General Public License should be included with + * this file. If not, you can view it at + * http://www.gnu.org/copyleft/gpl.html + * or write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + *********************************************************************/ + +#include "ssl_libressl.h" +#include "project.h" +#include "errlog.h" +#include "miscutil.h" +#include "string.h" +#include "tls.h" +#include "err.h" + + +extern int client_use_ssl(struct client_state *csp); +extern int server_use_ssl(struct client_state *csp); +static void close_client_ssl_connection(struct client_state *csp); +static void free_server_ssl_structures(struct client_state *csp); + +/********************************************************************** + * + * Function : create_server_ssl_connection + * + * Description : Creates SSL/TLS secured connection with server. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on success, negative value if connection wasn't created + * successfully. + * + **********************************************************************/ +extern int create_server_ssl_connection(struct client_state *csp) +{ + int ret = 0; + csp->ssl_server_attr.socket_fd = csp->server_connection.sfd; + + ret = tls_init(); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, "tls_init failed"); + ret = -1; + goto exit; + } + + csp->ssl_server_attr.ctx_io = tls_client(); + if (csp->ssl_server_attr.ctx_io == NULL) + { + log_error(LOG_LEVEL_ERROR, "tls_client failed"); + ret = 1; + goto exit; + } + + csp->ssl_server_attr.conf = tls_config_new(); + if (csp->ssl_server_attr.conf == NULL) + { + log_error(LOG_LEVEL_ERROR, "tls_config_new failed"); + ret = -1; + goto exit; + } + + tls_config_insecure_noverifycert(csp->ssl_server_attr.conf); + tls_config_insecure_noverifyname(csp->ssl_server_attr.conf); + + ret = tls_configure(csp->ssl_server_attr.ctx_io, csp->ssl_server_attr.conf); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, "tls_configure failed"); + ret = 1; + goto exit; + } + + ret = tls_connect_fds(csp->ssl_server_attr.ctx_io, + csp->ssl_server_attr.socket_fd, csp->ssl_server_attr.socket_fd, csp->http->host); + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, "tls_connect_socket failed"); + ret = 1; + goto exit; + } + + ret = tls_handshake(csp->ssl_server_attr.ctx_io); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_handshake failed"); + ret = -1; + goto exit; + } + + csp->ssl_with_server_is_opened = 1; + ret = 0; +exit: + if (ret != 0) { + free_server_ssl_structures(csp); + } + return ret; +} + + +/********************************************************************* + * + * Function : free_server_ssl_structures + * + * Description : Frees structures used for SSL communication with server + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +static void free_server_ssl_structures(struct client_state *csp) +{ + tls_free(csp->ssl_server_attr.ctx_io); + tls_config_free(csp->ssl_server_attr.conf); + csp->ssl_server_attr.socket_fd = -1; +} + + +/********************************************************************** + * + * Function : close_server_ssl_connection + * + * Description : Closes SSL/TLS connection with server. This function + * checks if this connection is already opened. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + **********************************************************************/ +static void close_server_ssl_connection(struct client_state *csp) +{ + int ret = 0; + + if (csp->ssl_with_server_is_opened == 0) + { + return; + } + + ret = tls_close(csp->ssl_server_attr.ctx_io); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_close with server failed: %s", tls_error(csp->ssl_server_attr.ctx_io)); + } + + free_server_ssl_structures(csp); + csp->ssl_with_server_is_opened = 0; +} + + + +/* + * Function : close_client_and_server_ssl_connections + * + * Description : Checks if client or server should use secured connection over + * SSL and if so, closes all of them. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + */ +extern void close_client_and_server_ssl_connections(struct client_state *csp) +{ + if (client_use_ssl(csp) == 1) + { + close_client_ssl_connection(csp); + } + if (server_use_ssl(csp) == 1) + { + close_server_ssl_connection(csp); + } +} + + + + +/********************************************************************* + * + * Function : client_use_ssl + * + * Description : Tests if client in current client state structure should use + * SSL connection or standard connection. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : If client should use SSL/TLS connection, 1 is returned. + * Otherwise 0 is returned. + * + *********************************************************************/ +extern int client_use_ssl(struct client_state *csp) +{ + return csp->http->client_ssl; +} + + +/********************************************************************* + * + * Function : server_use_ssl + * + * Description : Tests if server in current client state structure should use + * SSL connection or standard connection. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : If server should use SSL/TLS connection, 1 is returned. + * Otherwise 0 is returned. + * + *********************************************************************/ +extern int server_use_ssl(struct client_state *csp) +{ + return csp->http->server_ssl; +} + + +extern int create_client_ssl_connection(struct client_state *csp) { return 0; } +static void close_client_ssl_connection(struct client_state *csp) { return; } +extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len) { return 0; } +extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { return 0; } +extern size_t is_ssl_pending(ssl_connection_attr *connection) { return 0; } +extern int tunnel_established_successfully(const char * response, unsigned int response_len) { return 0; } +extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { return 0; } +extern void ssl_send_certificate_error(struct client_state *csp) { return; } \ No newline at end of file diff --git a/ssl_libressl.h b/ssl_libressl.h new file mode 100644 index 00000000..c792c642 --- /dev/null +++ b/ssl_libressl.h @@ -0,0 +1,54 @@ +#ifndef SSL_LIBRESSL_H_INCLUDED +#define SSL_LIBRESSL_H_INCLUDED +#define SSL_LIBRESSL_H_VERSION +/********************************************************************* +* +* File : $Source: /cvsroot/ijbswa/current/ssl_libressl.h,v $ +* +* Purpose : File with SSL/TLS extension in Libressl library. +* Contains methods for creating, using and closing SSL/TLS +* connections. +* +* Copyright : Written by Vaclav Svec. FIT CVUT. +* +* This program is free software; you can redistribute it +* and/or modify it under the terms of the GNU General +* Public License as published by the Free Software +* Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will +* be useful, but WITHOUT ANY WARRANTY; without even the +* implied warranty of MERCHANTABILITY or FITNESS FOR A +* PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* The GNU General Public License should be included with +* this file. If not, you can view it at +* http://www.gnu.org/copyleft/gpl.html +* or write to the Free Software Foundation, Inc., 59 +* Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*********************************************************************/ + +#include "project.h" + + +/* Boolean functions to get informations about SSL/TLS connections */ +extern int client_use_ssl(struct client_state *csp); +extern int server_use_ssl(struct client_state *csp); +extern size_t is_ssl_pending(ssl_connection_attr *connection); +extern int tunnel_established_successfully(const char * response, unsigned int response_len); + +/* Functions for sending and receiving data over SSL/TLS connections */ +extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len); +extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen); +extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob); +extern void ssl_send_certificate_error(struct client_state *csp); + +/* Functions for opening and closing SSL/TLS connections */ +extern int create_client_ssl_connection(struct client_state *csp); +extern int create_server_ssl_connection(struct client_state *csp); +extern void close_client_and_server_ssl_connections(struct client_state *csp); + +#endif /* ndef SSL_LIBRESSL_H_INCLUDED */ \ No newline at end of file -- 2.26.2 From 18db112ec8f5e492148ddb523dc448dd284bc157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:21:38 +0200 Subject: [PATCH 31/83] Created ssl connection with client. --- ssl_libressl.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 178 insertions(+), 4 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index b221fd89..4e2f6761 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -39,7 +39,6 @@ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); -static void close_client_ssl_connection(struct client_state *csp); static void free_server_ssl_structures(struct client_state *csp); /********************************************************************** @@ -173,6 +172,62 @@ static void close_server_ssl_connection(struct client_state *csp) } +/********************************************************************** + * + * Function : free_client_ssl_structures + * + * Description : Frees structures used for SSL communication with client + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +static void free_client_ssl_structures(struct client_state *csp) +{ + log_error(LOG_LEVEL_ERROR, "free_client_ssl_structures"); + tls_free(csp->ssl_client_attr.ctx); + tls_free(csp->ssl_client_attr.ctx_io); + tls_config_free(csp->ssl_client_attr.conf); + csp->ssl_client_attr.socket_fd = -1; +} + + +/********************************************************************* + * + * Function : close_client_ssl_connection + * + * Description : Closes SSL/TLS connection with client. This function + * checks if this connection is already created. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +static void close_client_ssl_connection(struct client_state *csp) +{ + int ret = 0; + + if (csp->ssl_with_client_is_opened == 0) + { + return; + } + + /* + * Notifying the peer that the connection is being closed. + */ + ret = tls_close(csp->ssl_client_attr.ctx_io); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_close with client failed: %s", tls_error(csp->ssl_client_attr.ctx_io)); + } + free_client_ssl_structures(csp); + + csp->ssl_with_client_is_opened = 0; +} + /* * Function : close_client_and_server_ssl_connections @@ -199,6 +254,127 @@ extern void close_client_and_server_ssl_connections(struct client_state *csp) } +/********************************************************************* + * + * Function : create_client_ssl_connection + * + * Description : Creates SSL/TLS secured connection with client + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on success, negative value if connection wasn't created + * successfully. + * + *********************************************************************/ +extern int create_client_ssl_connection(struct client_state *csp) { + int ret = 0; + unsigned int protocols = 0; + char *ciphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384"; + csp->ssl_client_attr.socket_fd = csp->cfd; + + /* + * Preparing paths to certificates files and key file + */ + char *key_file = NULL; + char *ca_file = NULL; + char *cert_file = NULL; + + size_t size = strlen(basedir) + 1; + ca_file = (char *)malloc(size + 14); + memset(ca_file, 0, size + 14); + strlcpy(ca_file, basedir, size + 14); + strlcat(ca_file, "/CA/cacert.crt", size + 14); + + cert_file = (char *)malloc(size + 29); + memset(cert_file, 0, size + 29); + strlcpy(cert_file, basedir, size + 29); + strlcat(cert_file, "/CA/webpagesCerts/privoxy.crt", size + 29); + + key_file = (char *)malloc(size + 29); + memset(key_file, 0, size + 29); + strlcpy(key_file, basedir, size + 29); + strlcat(key_file, "/CA/webpagesCerts/privoxy.pem", size + 29); + + ret = tls_init(); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_init failed"); + ret = -1; + goto exit; + } + + csp->ssl_client_attr.conf = tls_config_new(); + if (csp->ssl_client_attr.conf == NULL) { + log_error(LOG_LEVEL_ERROR, "tls_config_new failed"); + ret = -1; + goto exit; + } + + ret = tls_config_set_cert_file(csp->ssl_client_attr.conf, cert_file); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_config_set_cert_file failed"); + ret = -1; + goto exit; + } + + tls_config_set_key_file(csp->ssl_client_attr.conf, key_file); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_config_set_key_file failed"); + ret = -1; + goto exit; + } + + tls_config_set_ca_file(csp->ssl_client_attr.conf, ca_file); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_config_set_ca_file failed"); + ret = -1; + goto exit; + } + + tls_config_set_ciphers(csp->ssl_client_attr.conf, "compat"); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_config_set_ciphers failed"); + ret = -1; + goto exit; + } + + csp->ssl_client_attr.ctx = tls_server(); + if (csp->ssl_client_attr.ctx == NULL) { + log_error(LOG_LEVEL_ERROR, "tls_server failed"); + ret = -1; + goto exit; + } + tls_reset(csp->ssl_client_attr.ctx); + + ret = tls_configure(csp->ssl_client_attr.ctx, csp->ssl_client_attr.conf); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_configure failed: %s", tls_error(csp->ssl_client_attr.ctx)); + ret = -1; + goto exit; + } + + ret = tls_accept_fds(csp->ssl_client_attr.ctx, &csp->ssl_client_attr.ctx_io, csp->ssl_client_attr.socket_fd, csp->ssl_client_attr.socket_fd); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_accept_socket failed: %s", tls_error(csp->ssl_client_attr.ctx)); + ret = -1; + goto exit; + } + + ret = tls_handshake(csp->ssl_client_attr.ctx_io); + if (ret != 0) { + log_error(LOG_LEVEL_ERROR, "tls_handshake failed: %s", tls_error(csp->ssl_client_attr.ctx_io)); + ret = -1; + goto exit; + } + + csp->ssl_with_client_is_opened = 1; + ret = 0; +exit: + if (ret != 0) { + free_client_ssl_structures(csp); + } + return ret; +} /********************************************************************* @@ -241,11 +417,9 @@ extern int server_use_ssl(struct client_state *csp) } -extern int create_client_ssl_connection(struct client_state *csp) { return 0; } -static void close_client_ssl_connection(struct client_state *csp) { return; } extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len) { return 0; } extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { return 0; } extern size_t is_ssl_pending(ssl_connection_attr *connection) { return 0; } extern int tunnel_established_successfully(const char * response, unsigned int response_len) { return 0; } extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { return 0; } -extern void ssl_send_certificate_error(struct client_state *csp) { return; } \ No newline at end of file +extern void ssl_send_certificate_error(struct client_state *csp) { return; } -- 2.26.2 From 7dafaa7085091cd4636b42c8591a7653d00f82ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:23:03 +0200 Subject: [PATCH 32/83] Sending data between client and server over ssl. --- ssl_libressl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 4e2f6761..8ae4d800 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -417,9 +417,93 @@ extern int server_use_ssl(struct client_state *csp) } -extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len) { return 0; } -extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { return 0; } -extern size_t is_ssl_pending(ssl_connection_attr *connection) { return 0; } +/********************************************************************* + * + * Function : ssl_send_data + * + * Description : Sends the content of buf (for n bytes) to given SSL + * connection. + * + * Parameters : + * 1 : ssl = 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 + * + * Returns : Length of sent data or negative value on error. + * + *********************************************************************/ +extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len) { + int ret = 0; + + ret = tls_write(connection->ctx_io, (char *)buf, len); + if (ret < 0) { + log_error(LOG_LEVEL_ERROR, "tls_write failed: %s", tls_error(connection->ctx_io)); + ret = -1; + goto exit; + } + +exit: + return ret; +} + + +/********************************************************************* + * + * Function : ssl_recv_data + * + * Description : Receives data from given SSL context and puts them + * into buffer. + * + * Parameters : + * 1 : ssl = SSL context to receive data from + * 2 : buf = Pointer to buffer where data will be written + * 3 : len = Maximum number of bytes to read + * + * Returns : Number of bytes read, 0 for EOF, or negative + * value on error. + * + *********************************************************************/ +extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { + int ret = 0; + + ret = tls_read(connection->ctx_io, (char *)buf, maxLen); + if (ret == maxLen) { + connection->is_pending = 1; + } + else { + connection->is_pending = 0; + } + + if (ret < 0) { + log_error(LOG_LEVEL_ERROR, "tls_read failed: %s", tls_error(connection->ctx_io)); + ret = -1; + goto exit; + } + +exit: + return ret; +} + + +/********************************************************************* + * + * Function : is_ssl_pending + * + * Description : Returns true when last received data filled whole + * buffer. + * + * Parameters : + * 1 : ssl = SSL context to test + * + * Returns : 0 => No data are pending + * >0 => Pending data length + * + *********************************************************************/ +extern size_t is_ssl_pending(ssl_connection_attr *connection) { + return connection->is_pending; +} + + extern int tunnel_established_successfully(const char * response, unsigned int response_len) { return 0; } extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { return 0; } extern void ssl_send_certificate_error(struct client_state *csp) { return; } -- 2.26.2 From 985039c1436d956c9779d937fa39ddd3b03fd295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:24:04 +0200 Subject: [PATCH 33/83] Added check of tunnel establishion for libressl. --- ssl_libressl.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 8ae4d800..68e3a290 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -229,7 +229,7 @@ static void close_client_ssl_connection(struct client_state *csp) } -/* +/********************************************************************* * Function : close_client_and_server_ssl_connections * * Description : Checks if client or server should use secured connection over @@ -240,7 +240,7 @@ static void close_client_ssl_connection(struct client_state *csp) * * Returns : N/A * - */ + *********************************************************************/ extern void close_client_and_server_ssl_connections(struct client_state *csp) { if (client_use_ssl(csp) == 1) @@ -504,6 +504,64 @@ extern size_t is_ssl_pending(ssl_connection_attr *connection) { } -extern int tunnel_established_successfully(const char * response, unsigned int response_len) { return 0; } +/********************************************************************* + * + * Function : tunnel_established_successfully + * + * Description : Check if parent proxy server response contains + * informations about successfully created connection with + * destination server. (HTTP/... 2xx ...) + * + * Parameters : + * 1 : server_response = Buffer with parent proxy server response + * 2 : response_len = Length of server_response + * + * Returns : 1 => Connection created successfully + * 0 => Connection wasn't created successfully + * + *********************************************************************/ +extern int tunnel_established_successfully(const char * server_response, unsigned int response_len) { + unsigned int pos = 0; + + if (server_response == NULL) + { + return 0; + } + + /* Tests if "HTTP/" string is at the begin of received response */ + if (strncmp(server_response, "HTTP/", 5) != 0) + { + return 0; + } + + for (pos = 0; pos < response_len; pos++) + { + if (server_response[pos] == ' ') + { + break; + } + } + + /* + * response_len -3 because of buffer end, response structure and 200 code. + * There must be at least 3 chars after space. + * End of buffer: ... 2xx'\0' + * pos = | + */ + if (pos >= (response_len - 3)) + { + return 0; + } + + /* Test HTTP status code */ + if (server_response[pos + 1] != '2') + { + return 0; + } + + return 1; +} + + extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { return 0; } extern void ssl_send_certificate_error(struct client_state *csp) { return; } -- 2.26.2 From c5273962de1cb7eba7e1068003c03aff2e591384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:25:31 +0200 Subject: [PATCH 34/83] Creating ssl connection with server using libssl instead of libtls. --- project.h | 9 +++-- ssl_libressl.c | 96 +++++++++++++++++++++++++++++--------------------- 2 files changed, 59 insertions(+), 46 deletions(-) diff --git a/project.h b/project.h index 0591129c..c2831c54 100644 --- a/project.h +++ b/project.h @@ -57,7 +57,7 @@ #endif /* FEATURE_MBEDTLS */ #ifdef FEATURE_LIBRESSL -#include "tls.h" +#include "openssl/ssl.h" #endif /* FEATURE_LIBRESSL */ @@ -303,10 +303,9 @@ typedef struct { #ifdef FEATURE_LIBRESSL int socket_fd; - struct tls *ctx_io; - struct tls *ctx; - struct tls_config *conf; - int is_pending; + SSL_CTX * ctx; + SSL * ssl; + BIO * bio, * ssl_bio; #endif /* FEATURE_LIBRESSL */ } ssl_connection_attr; diff --git a/ssl_libressl.c b/ssl_libressl.c index 68e3a290..5a984c4f 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -35,12 +35,15 @@ #include "string.h" #include "tls.h" #include "err.h" +#include "openssl/ssl.h" +#include "openssl/x509.h" extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); static void free_server_ssl_structures(struct client_state *csp); + /********************************************************************** * * Function : create_server_ssl_connection @@ -57,65 +60,75 @@ static void free_server_ssl_structures(struct client_state *csp); extern int create_server_ssl_connection(struct client_state *csp) { int ret = 0; + const SSL_METHOD *meth; csp->ssl_server_attr.socket_fd = csp->server_connection.sfd; - ret = tls_init(); - if (ret != 0) - { - log_error(LOG_LEVEL_ERROR, "tls_init failed"); + meth = TLS_method(); + if (meth == NULL) { + log_error(LOG_LEVEL_ERROR, "Server connection: TLS_method failed"); ret = -1; goto exit; } - csp->ssl_server_attr.ctx_io = tls_client(); - if (csp->ssl_server_attr.ctx_io == NULL) - { - log_error(LOG_LEVEL_ERROR, "tls_client failed"); - ret = 1; - goto exit; - } - - csp->ssl_server_attr.conf = tls_config_new(); - if (csp->ssl_server_attr.conf == NULL) - { - log_error(LOG_LEVEL_ERROR, "tls_config_new failed"); + csp->ssl_server_attr.ctx = SSL_CTX_new(meth); + if (csp->ssl_server_attr.ctx == NULL) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_CTX_new failed"); ret = -1; goto exit; } - tls_config_insecure_noverifycert(csp->ssl_server_attr.conf); - tls_config_insecure_noverifyname(csp->ssl_server_attr.conf); + /* + * Setting how strict should certificate verification be and callback function. + */ + SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_NONE, NULL); - ret = tls_configure(csp->ssl_server_attr.ctx_io, csp->ssl_server_attr.conf); - if (ret != 0) - { - log_error(LOG_LEVEL_ERROR, "tls_configure failed"); - ret = 1; + csp->ssl_server_attr.ssl = SSL_new(csp->ssl_server_attr.ctx); + + /* + * Setting TCP socket to bio. + */ + csp->ssl_server_attr.bio = BIO_new_socket(csp->ssl_server_attr.socket_fd, BIO_NOCLOSE); + if (csp->ssl_server_attr.bio == NULL) { + log_error(LOG_LEVEL_ERROR, "Server connection: BIO_new_socket failed"); + ret = -1; goto exit; } - ret = tls_connect_fds(csp->ssl_server_attr.ctx_io, - csp->ssl_server_attr.socket_fd, csp->ssl_server_attr.socket_fd, csp->http->host); - if (ret < 0) - { - log_error(LOG_LEVEL_ERROR, "tls_connect_socket failed"); - ret = 1; + SSL_set_bio(csp->ssl_server_attr.ssl, csp->ssl_server_attr.bio, + csp->ssl_server_attr.bio); + + /* + * Handshake with server + */ + ret = SSL_connect(csp->ssl_server_attr.ssl); + if (ret <= 0) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_connect failed"); + ret = -1; goto exit; } - ret = tls_handshake(csp->ssl_server_attr.ctx_io); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_handshake failed"); - ret = -1; - goto exit; + /* + * Getting results of server certificate verification. + */ + log_error(LOG_LEVEL_INFO, "Cert verification result: %d", SSL_get_verify_result(csp->ssl_server_attr.ssl)); + X509 * peer_cert = SSL_get_peer_certificate(csp->ssl_server_attr.ssl); + if (peer_cert == NULL) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_get_peer_certificate failed"); } - + + /* + * Creating BIO to comunicate with server over ssl. + */ + csp->ssl_server_attr.ssl_bio = BIO_new(BIO_f_ssl()); + BIO_set_ssl(csp->ssl_server_attr.ssl_bio, csp->ssl_server_attr.ssl, BIO_CLOSE); + csp->ssl_with_server_is_opened = 1; ret = 0; exit: if (ret != 0) { free_server_ssl_structures(csp); } + return ret; } @@ -134,8 +147,9 @@ exit: *********************************************************************/ static void free_server_ssl_structures(struct client_state *csp) { - tls_free(csp->ssl_server_attr.ctx_io); - tls_config_free(csp->ssl_server_attr.conf); + SSL_free(csp->ssl_server_attr.ssl); + SSL_CTX_free(csp->ssl_server_attr.ctx); + csp->ssl_server_attr.socket_fd = -1; } @@ -161,10 +175,10 @@ static void close_server_ssl_connection(struct client_state *csp) { return; } - - ret = tls_close(csp->ssl_server_attr.ctx_io); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_close with server failed: %s", tls_error(csp->ssl_server_attr.ctx_io)); + + ret = SSL_shutdown(csp->ssl_server_attr.ssl); + if (ret < 0) { + log_error(LOG_LEVEL_ERROR, "SSL_shutdown with server failed"); } free_server_ssl_structures(csp); -- 2.26.2 From 271e45a92e89e9f6e22b88a4ebf2696355bf286a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:26:08 +0200 Subject: [PATCH 35/83] Creating ssl connection with client using libssl instead of libtls. --- ssl_libressl.c | 115 ++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 59 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 5a984c4f..c6d99c28 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -200,10 +200,9 @@ static void close_server_ssl_connection(struct client_state *csp) *********************************************************************/ static void free_client_ssl_structures(struct client_state *csp) { - log_error(LOG_LEVEL_ERROR, "free_client_ssl_structures"); - tls_free(csp->ssl_client_attr.ctx); - tls_free(csp->ssl_client_attr.ctx_io); - tls_config_free(csp->ssl_client_attr.conf); + SSL_free(csp->ssl_client_attr.ssl); + SSL_CTX_free(csp->ssl_client_attr.ctx); + csp->ssl_client_attr.socket_fd = -1; } @@ -233,12 +232,12 @@ static void close_client_ssl_connection(struct client_state *csp) /* * Notifying the peer that the connection is being closed. */ - ret = tls_close(csp->ssl_client_attr.ctx_io); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_close with client failed: %s", tls_error(csp->ssl_client_attr.ctx_io)); + ret = SSL_shutdown(csp->ssl_client_attr.ssl); + if (ret < 0) { + log_error(LOG_LEVEL_ERROR, "SSL_shutdown with client failed"); } + free_client_ssl_structures(csp); - csp->ssl_with_client_is_opened = 0; } @@ -283,9 +282,8 @@ extern void close_client_and_server_ssl_connections(struct client_state *csp) *********************************************************************/ extern int create_client_ssl_connection(struct client_state *csp) { int ret = 0; - unsigned int protocols = 0; - char *ciphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384"; csp->ssl_client_attr.socket_fd = csp->cfd; + const SSL_METHOD * meth; /* * Preparing paths to certificates files and key file @@ -310,76 +308,74 @@ extern int create_client_ssl_connection(struct client_state *csp) { strlcpy(key_file, basedir, size + 29); strlcat(key_file, "/CA/webpagesCerts/privoxy.pem", size + 29); - ret = tls_init(); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_init failed"); - ret = -1; - goto exit; - } - - csp->ssl_client_attr.conf = tls_config_new(); - if (csp->ssl_client_attr.conf == NULL) { - log_error(LOG_LEVEL_ERROR, "tls_config_new failed"); - ret = -1; - goto exit; - } - - ret = tls_config_set_cert_file(csp->ssl_client_attr.conf, cert_file); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_config_set_cert_file failed"); - ret = -1; - goto exit; - } - - tls_config_set_key_file(csp->ssl_client_attr.conf, key_file); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_config_set_key_file failed"); + + meth = TLS_method(); + if (meth == NULL) { + log_error(LOG_LEVEL_ERROR, "Client connection: TLS_method failed"); ret = -1; goto exit; } - - tls_config_set_ca_file(csp->ssl_client_attr.conf, ca_file); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_config_set_ca_file failed"); + csp->ssl_client_attr.ctx = SSL_CTX_new(meth); + if (csp->ssl_client_attr.ctx == NULL) { + log_error(LOG_LEVEL_ERROR, "Client connection: SSL_CTX_new failed"); ret = -1; - goto exit; + goto exit; } + - tls_config_set_ciphers(csp->ssl_client_attr.conf, "compat"); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_config_set_ciphers failed"); + /* + * Setting SSL server certificate. + */ + ret = SSL_CTX_use_certificate_file(csp->ssl_client_attr.ctx, + cert_file, SSL_FILETYPE_PEM); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Client connection: SSL_CTX_use_certificate_file: Failed to load server certificate"); ret = -1; goto exit; } - - csp->ssl_client_attr.ctx = tls_server(); - if (csp->ssl_client_attr.ctx == NULL) { - log_error(LOG_LEVEL_ERROR, "tls_server failed"); + + ret = SSL_CTX_use_PrivateKey_file(csp->ssl_client_attr.ctx, + key_file, SSL_FILETYPE_PEM); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Client connection: SSL_CTX_use_PrivateKey_file: Failed to load server private key"); ret = -1; goto exit; } - tls_reset(csp->ssl_client_attr.ctx); + + /* + * Setting how strict should client certificate verification be and callback function. + */ + SSL_CTX_set_verify(csp->ssl_client_attr.ctx, SSL_VERIFY_NONE, 0); + + csp->ssl_client_attr.ssl = SSL_new(csp->ssl_client_attr.ctx); - ret = tls_configure(csp->ssl_client_attr.ctx, csp->ssl_client_attr.conf); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_configure failed: %s", tls_error(csp->ssl_client_attr.ctx)); + /* + * Setting TCP socket to bio. + */ + csp->ssl_client_attr.bio = BIO_new_socket(csp->ssl_client_attr.socket_fd, BIO_NOCLOSE); + if (csp->ssl_client_attr.bio == NULL) { + log_error(LOG_LEVEL_ERROR, "Client connection: BIO_new_socket failed"); ret = -1; goto exit; } + + SSL_set_bio(csp->ssl_client_attr.ssl, csp->ssl_client_attr.bio, csp->ssl_client_attr.bio); - ret = tls_accept_fds(csp->ssl_client_attr.ctx, &csp->ssl_client_attr.ctx_io, csp->ssl_client_attr.socket_fd, csp->ssl_client_attr.socket_fd); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_accept_socket failed: %s", tls_error(csp->ssl_client_attr.ctx)); + /* + * Handshake with server + */ + ret = SSL_accept(csp->ssl_client_attr.ssl); + if (ret <= 0) { + log_error(LOG_LEVEL_ERROR, "Client connection: SSL_accept failed"); ret = -1; goto exit; } - ret = tls_handshake(csp->ssl_client_attr.ctx_io); - if (ret != 0) { - log_error(LOG_LEVEL_ERROR, "tls_handshake failed: %s", tls_error(csp->ssl_client_attr.ctx_io)); - ret = -1; - goto exit; - } + /* + * Creating BIO to comunicate with client over ssl. + */ + csp->ssl_client_attr.ssl_bio = BIO_new(BIO_f_ssl()); + BIO_set_ssl(csp->ssl_client_attr.ssl_bio, csp->ssl_client_attr.ssl, BIO_CLOSE); csp->ssl_with_client_is_opened = 1; ret = 0; @@ -387,6 +383,7 @@ exit: if (ret != 0) { free_client_ssl_structures(csp); } + return ret; } -- 2.26.2 From 17c5d29a4ac0433547bf33456960ff12b1597d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:27:33 +0200 Subject: [PATCH 36/83] Sending data between client and server over ssl using libssl instead of libtls. --- jcc.c | 5 ----- ssl_libressl.c | 21 ++++++++------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/jcc.c b/jcc.c index 0e33fb52..a1b2c678 100644 --- a/jcc.c +++ b/jcc.c @@ -2065,11 +2065,6 @@ static void handle_established_connection(struct client_state *csp) server_body = 0; -#ifdef FEATURE_LIBRESSL - csp->ssl_server_attr.is_pending = 0; - csp->ssl_client_attr.is_pending = 0; -#endif - #ifdef FEATURE_CONNECTION_KEEP_ALIVE watch_client_socket = 0 == (csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING); #endif diff --git a/ssl_libressl.c b/ssl_libressl.c index c6d99c28..2072578a 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -446,9 +446,10 @@ extern int server_use_ssl(struct client_state *csp) extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len) { int ret = 0; - ret = tls_write(connection->ctx_io, (char *)buf, len); + ret = BIO_write(connection->ssl_bio, buf, len); + if (ret < 0) { - log_error(LOG_LEVEL_ERROR, "tls_write failed: %s", tls_error(connection->ctx_io)); + log_error(LOG_LEVEL_ERROR, "BIO_write failed"); ret = -1; goto exit; } @@ -477,16 +478,10 @@ exit: extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { int ret = 0; - ret = tls_read(connection->ctx_io, (char *)buf, maxLen); - if (ret == maxLen) { - connection->is_pending = 1; - } - else { - connection->is_pending = 0; - } + ret = BIO_read(connection->ssl_bio, buf, maxLen); if (ret < 0) { - log_error(LOG_LEVEL_ERROR, "tls_read failed: %s", tls_error(connection->ctx_io)); + log_error(LOG_LEVEL_ERROR, "BIO_read failed"); ret = -1; goto exit; } @@ -500,8 +495,8 @@ exit: * * Function : is_ssl_pending * - * Description : Returns true when last received data filled whole - * buffer. + * Description : Returns return the number of pending characters in + * the BIO's read and write buffers. * * Parameters : * 1 : ssl = SSL context to test @@ -511,7 +506,7 @@ exit: * *********************************************************************/ extern size_t is_ssl_pending(ssl_connection_attr *connection) { - return connection->is_pending; + return BIO_pending(connection->ssl_bio); } -- 2.26.2 From b503221f5276194f73f842ece47eb37e64d39622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:28:24 +0200 Subject: [PATCH 37/83] Implemented function ssl_flush_socket. --- ssl_libressl.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 2072578a..16baf634 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -569,5 +569,38 @@ extern int tunnel_established_successfully(const char * server_response, unsigne } -extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { return 0; } +/********************************************************************* + * + * Function : ssl_flush_socket + * + * Description : Send any pending "buffered" content with given SSL connection. + * Alternative to function flush_socket. + * + * Parameters : + * 1 : ssl = SSL context to send buffer to + * 2 : iob = The I/O buffer to flush, usually csp->iob. + * + * Returns : On success, the number of bytes send are returned (zero + * indicates nothing was sent). On error, -1 is returned. + * + *********************************************************************/ +extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { + /* Computing length of buffer part to send*/ + long len = iob->eod - iob->cur; + + if (len <= 0) + { + return(0); + } + + /* Sending data to given bio */ + if (ssl_send_data(connection, (const unsigned char *)iob->cur, (size_t)len) < 0) + { + return -1; + } + iob->eod = iob->cur = iob->buf; + return(len); +} + + extern void ssl_send_certificate_error(struct client_state *csp) { return; } -- 2.26.2 From 2447ead158e1079838f00cc4c948b80afc435ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:29:25 +0200 Subject: [PATCH 38/83] Generating and saving RSA key. --- project.h | 5 +- ssl_libressl.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 132 insertions(+), 8 deletions(-) diff --git a/project.h b/project.h index c2831c54..5daac946 100644 --- a/project.h +++ b/project.h @@ -347,6 +347,7 @@ struct http_request unsigned char hash_of_host[HASH_OF_HOST_BUF_SIZE + 1]; /**< chars for bytes of hash and one for '\0' */ }; +#ifdef FEATURE_MBEDTLS /* * Properties of cert for generating */ @@ -370,13 +371,11 @@ typedef struct { * Propeties of key for generating */ typedef struct { -#ifdef FEATURE_MBEDTLS mbedtls_pk_type_t type; /* type of key to generate */ -#endif /* FEATURE_MBEDTLS */ - int rsa_keysize; /* length of key in bits */ char *key_file_path; /* filename of the key file */ } key_options; +#endif /* FEATURE_MBEDTLS */ /* * Struct for linked list containing certificates diff --git a/ssl_libressl.c b/ssl_libressl.c index 16baf634..4c78d6e6 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -32,16 +32,19 @@ #include "project.h" #include "errlog.h" #include "miscutil.h" -#include "string.h" -#include "tls.h" -#include "err.h" -#include "openssl/ssl.h" -#include "openssl/x509.h" +/* + * Macros for ssl.c + */ +#define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ +#define KEY_FILE_TYPE ".pem" + extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); static void free_server_ssl_structures(struct client_state *csp); +extern int generate_key(RSA **key_rsa, struct client_state *csp); +static int file_exists(const char * path); /********************************************************************** @@ -604,3 +607,125 @@ extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { extern void ssl_send_certificate_error(struct client_state *csp) { return; } + + +/*======================Certificates======================*/ + +/********************************************************************* + * + * Function : generate_key + * + * Description : Tests if private key for host saved in csp already exists. + * If this file doesn't exists, new key is generated and saved + * in file. Generated key is also copied into given parameter + * key_buf, which must be then freed by caller. If file with key + * exists, key_buf contain NULL and no private key is generated. + * + * Parameters : + * 1 : key_rsa = RSA struct pointer to save new generated key + * 2 : csp = Current client state (buffers, headers, etc...) + * + * Returns : -1 = Error while generating private key + * 0 = Key already exists + * 1 = Key generated successfully + * + *********************************************************************/ +extern int generate_key(RSA **key_rsa, struct client_state *csp) +{ + int ret = 0; + int rsa_keysize = RSA_KEYSIZE; + int e = RSA_F4; + BIGNUM *bne = NULL; + BIO *bio = NULL; + char *key_file_path = NULL; + + /* + * Preparing path for key file and other properties for generating key + */ + size_t size = strlen(basedir) + strlen(csp->http->host) + strlen("/CA/webpagesCerts/") + + strlen(KEY_FILE_TYPE) + 1; + key_file_path = (char *)malloc(size); + memset(key_file_path, 0, size); + strlcpy(key_file_path, basedir, size); + strlcat(key_file_path, "/CA/webpagesCerts/", size); + strlcat(key_file_path, csp->http->host, size); + strlcat(key_file_path, KEY_FILE_TYPE, size); + + /* + * Test if key already exists. If so, we don't have to create it again. + */ + if (file_exists(key_file_path) == 1) + { + *key_rsa = NULL; + ret = 0; + goto exit; + } + + bne = BN_new(); + ret = BN_set_word(bne, e); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "RSA key generating: BN_set_word failed"); + ret = -1; + goto exit; + } + + /* + * Setting atributes of private key and generating it + */ + *key_rsa = RSA_new(); + RSA_generate_key_ex(*key_rsa, rsa_keysize, bne, NULL); + bio = BIO_new_file(key_file_path, "w+"); + if (bio == NULL) { + log_error(LOG_LEVEL_ERROR, "RSA key generating: BIO_new_file failed"); + ret = -1; + goto exit; + } + + ret = PEM_write_bio_RSAPrivateKey(bio, *key_rsa, NULL, NULL, 0, NULL, NULL); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "RSA key generating: PEM_write_bio_RSAPrivateKey failed"); + ret = -1; + goto exit; + } + + ret = 1; +exit: + /* + * Freeing used variables + */ + BN_free(bne); + BIO_free_all(bio); + + if (key_file_path != NULL) + { + freez(key_file_path); + } + + return ret; +} + + +/********************************************************************* + * + * Function : file_exists + * + * Description : Tests if file exists and is readable. + * + * Parameters : + * 1 : path = Path to tested file. + * + * Returns : 1 => File exists and is readable. + * 0 => File doesn't exist or is not readable. + * + *********************************************************************/ +static int file_exists(const char * path) +{ + FILE * f; + if ((f = fopen(path, "r")) != NULL) + { + fclose(f); + return 1; + } + + return 0; +} \ No newline at end of file -- 2.26.2 From 5d0765d1b911301566349dde96e6ce18becaa9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:30:17 +0200 Subject: [PATCH 39/83] Generating webpage certificate. --- ssl_libressl.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 315 insertions(+), 3 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 4c78d6e6..64c44ea2 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -38,12 +38,23 @@ * Macros for ssl.c */ #define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ +#define GENERATED_CERT_VALID_YEARS 10 /* Count of years till expiration in generated certificates as parameter valid to */ +#define CERT_PARAM_COMMON_NAME "CN" +#define CERT_PARAM_ORGANIZATION "O" +#define CERT_PARAM_ORG_UNIT "OU" +#define CERT_PARAM_COUNTRY "C" +#define CERT_PARAM_COUNTRY_VALUE "CZ" #define KEY_FILE_TYPE ".pem" +#define CERT_FILE_TYPE ".crt" +#define CA_CERT_PASSWORD "" +#define CA_KEY_PASSWORD "" + extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); static void free_server_ssl_structures(struct client_state *csp); extern int generate_key(RSA **key_rsa, struct client_state *csp); +extern int generate_webpage_certificate(struct client_state * csp); static int file_exists(const char * path); @@ -311,6 +322,12 @@ extern int create_client_ssl_connection(struct client_state *csp) { strlcpy(key_file, basedir, size + 29); strlcat(key_file, "/CA/webpagesCerts/privoxy.pem", size + 29); + ret = generate_webpage_certificate(csp); + if (ret < 0) { + log_error(LOG_LEVEL_ERROR, "Client connection: generate_webpage_certificate failed"); + ret = -1; + goto exit; + } meth = TLS_method(); if (meth == NULL) { @@ -625,9 +642,9 @@ extern void ssl_send_certificate_error(struct client_state *csp) { return; } * 1 : key_rsa = RSA struct pointer to save new generated key * 2 : csp = Current client state (buffers, headers, etc...) * - * Returns : -1 = Error while generating private key - * 0 = Key already exists - * 1 = Key generated successfully + * Returns : -1 => Error while generating private key + * 0 => Key already exists + * 1 => Key generated successfully * *********************************************************************/ extern int generate_key(RSA **key_rsa, struct client_state *csp) @@ -705,6 +722,301 @@ exit: } +/********************************************************************* + * + * Function : generate_webpage_certificate + * + * Description : Creates certificate file in presetted directory. + * If certificate already exists, no other certificate + * will be created. Subject of certificate is named + * by csp->http->host from parameter. This function also + * call generating of private key for new certificate. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : -1 => Error while creating certificate + * 0 => Certificate alreaday exist + * 1 => Certificate created successfully + * + *********************************************************************/ +extern int generate_webpage_certificate(struct client_state * csp) +{ + int ret = 0; + RSA *key_rsa = NULL; + EVP_PKEY *subject_pkey = NULL, *issuer_pkey = NULL; + BIO * subject_key_bio = NULL, *issuer_key_bio = NULL, + *issuer_cert_bio = NULL, *subject_cert_bio = NULL; + X509 *cert_x509 = NULL, *issuer_cert = NULL; + X509_EXTENSION * extension = NULL; + ASN1_OCTET_STRING *value = NULL; + char *issuer_crt_path, *issuer_key_path, *subject_crt_path, *subject_key_path; + + /* + * Creating paths of certificates + */ + size_t size = strlen(basedir) + strlen("/CA/webpagesCerts/") + 1; + size_t file_name_size = 0; + issuer_crt_path = csp->config->ca_cert_file; + issuer_key_path = csp->config->ca_key_file; + + file_name_size = strlen(csp->http->host) + strlen(KEY_FILE_TYPE); + subject_key_path = (char *)calloc(size + file_name_size, 1); + strlcpy(subject_key_path, basedir, size + file_name_size); + strlcat(subject_key_path, "/CA/webpagesCerts/", size + file_name_size); + strlcat(subject_key_path, csp->http->host, size + file_name_size); + strlcat(subject_key_path, KEY_FILE_TYPE, size + file_name_size); + + file_name_size = strlen(csp->http->host) + strlen(CERT_FILE_TYPE); + subject_crt_path = (char *)calloc(size + file_name_size, 1); + strlcpy(subject_crt_path, basedir, size + file_name_size); + strlcat(subject_crt_path, "/CA/webpagesCerts/", size + file_name_size); + strlcat(subject_crt_path, csp->http->host, size + file_name_size); + strlcat(subject_crt_path, CERT_FILE_TYPE, size + file_name_size); + + /* + * Generating or loading subject key + */ + ret = generate_key(&key_rsa, csp); + if (ret >= 1) { + subject_pkey = EVP_PKEY_new(); + ret = EVP_PKEY_assign_RSA(subject_pkey, key_rsa); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: EVP_PKEY_assign_RSA failed"); + ret = -1; + goto exit; + } + } + else if (ret == 0) { + if (file_exists(subject_crt_path) == 1) + { + ret = 0; + goto exit; + } + + subject_key_bio = BIO_new_file(subject_key_path, "r+"); + if (subject_key_bio == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: BIO_new_file failed"); + ret = -1; + goto exit; + } + + subject_pkey = PEM_read_bio_PrivateKey(subject_key_bio, NULL, NULL, ""); + if (subject_pkey == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: PEM_read_bio_PrivateKey failed"); + ret = -1; + goto exit; + } + } + else { + log_error(LOG_LEVEL_ERROR, "Certificate generating: generate_key failed"); + ret = -1; + goto exit; + } + + /* + * Setting parameters of generated certificate + */ + cert_x509 = X509_new(); + if (cert_x509 == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_new failed"); + ret = -1; + goto exit; + } + + ret = ASN1_INTEGER_set(X509_get_serialNumber(cert_x509), 1); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: ASN1_INTEGER_set failed"); + ret = -1; + goto exit; + } + + if (X509_gmtime_adj(X509_get_notBefore(cert_x509), 0) == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_gmtime_adj failed"); + ret = -1; + goto exit; + } + if (X509_gmtime_adj(X509_get_notAfter(cert_x509), GENERATED_CERT_VALID_YEARS * 31536000L) == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_gmtime_adj failed"); + ret = -1; + goto exit; + } + ret = X509_set_version(cert_x509, 3); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_set_version failed"); + ret = -1; + goto exit; + } + + /* + * Setting public key into generated certificate + */ + ret = X509_set_pubkey(cert_x509, subject_pkey); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_set_pubkey failed"); + ret = -1; + goto exit; + } + + /* + * Setting subject name into certificate + */ + X509_NAME *subject_name = X509_get_subject_name(cert_x509); + ret = 0; + ret += X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_COUNTRY, MBSTRING_ASC, + (unsigned char *)CERT_PARAM_COUNTRY_VALUE, -1, -1, 0); + ret += X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_ORGANIZATION, MBSTRING_ASC, + (unsigned char *)csp->http->host, -1, -1, 0); + ret += X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_ORG_UNIT, MBSTRING_ASC, + (unsigned char *)csp->http->host, -1, -1, 0); + ret += X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_COMMON_NAME, MBSTRING_ASC, + (unsigned char *)csp->http->host, -1, -1, 0); + if (ret != 4) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_NAME_add_entry_by_txt failed"); + ret = -1; + goto exit; + } + ret = X509_set_subject_name(cert_x509, subject_name); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_set_subject_name failed"); + ret = -1; + goto exit; + } + + /* + * Setting subject alternative name + */ + extension = X509_EXTENSION_new(); + if (extension == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_EXTENSION_new failed"); + ret = -1; + goto exit; + } + + value = ASN1_OCTET_STRING_new(); + if (value == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: ASN1_OCTET_STRING_new failed"); + ret = -1; + goto exit; + } + + ret = ASN1_STRING_set(value, csp->http->host, strlen(csp->http->host)); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: ASN1_STRING_set failed"); + ret = -1; + goto exit; + } + + if (X509_EXTENSION_create_by_NID(&extension, NID_subject_alt_name, 0, value) == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_EXTENSION_create_by_NID failed"); + ret = -1; + goto exit; + } + + ret = X509_add_ext(cert_x509, extension, -1); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_add_ext failed"); + ret = -1; + goto exit; + } + + /* + * Loading CA key and certificate, setting issuer name + */ + issuer_key_bio = BIO_new_file(issuer_key_path, "r+"); + if (issuer_key_bio == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: BIO_new_file failed"); + ret = -1; + goto exit; + } + + issuer_pkey = PEM_read_bio_PrivateKey(issuer_key_bio, NULL, NULL, CA_KEY_PASSWORD); + if (issuer_pkey == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: PEM_read_bio_PrivateKey failed"); + ret = -1; + goto exit; + } + + issuer_cert = X509_new(); + if (issuer_cert == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_new failed"); + ret = -1; + goto exit; + } + + issuer_cert_bio = BIO_new_file(issuer_crt_path, "r+"); + if (issuer_cert_bio == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: BIO_new_file failed"); + ret = -1; + goto exit; + } + + issuer_cert = PEM_read_bio_X509(issuer_cert_bio, NULL, NULL, CA_CERT_PASSWORD); + if (issuer_cert == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: PEM_read_bio_X509 failed"); + ret = -1; + goto exit; + } + + X509_NAME *issuer_name = X509_get_subject_name(issuer_cert); + ret = X509_set_issuer_name(cert_x509, issuer_name); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_set_issuer_name failed"); + ret = -1; + goto exit; + } + + /* + * Signing and saving certificate file + */ + ret = X509_sign(cert_x509, issuer_pkey, EVP_sha256()); + if (ret == 0) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_sign failed"); + ret = -1; + goto exit; + } + + subject_cert_bio = BIO_new_file(subject_crt_path, "w"); + if (subject_cert_bio == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate generating: BIO_new_file failed"); + ret = -1; + goto exit; + } + + ret = PEM_write_bio_X509(subject_cert_bio, cert_x509); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "RSA key generating: PEM_write_bio_RSAPrivateKey failed"); + ret = -1; + goto exit; + } + + ret = 1; +exit: + /* + * Freeing used variables + */ + BIO_free_all(subject_key_bio); + BIO_free_all(issuer_key_bio); + BIO_free_all(issuer_cert_bio); + BIO_free_all(subject_cert_bio); + X509_free(cert_x509); + X509_free(issuer_cert); + EVP_PKEY_free(issuer_pkey); + EVP_PKEY_free(subject_pkey); + X509_EXTENSION_free(extension); + ASN1_OCTET_STRING_free(value); + + if (subject_crt_path != NULL) { + freez(subject_crt_path); + } + if (subject_key_path != NULL) { + freez(subject_key_path); + } + + return ret; +} + + /********************************************************************* * * Function : file_exists -- 2.26.2 From 262ebb3c03d923ad01c410bd138dce306d937665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:31:13 +0200 Subject: [PATCH 40/83] Added function for creating absolute path of files from given parameters. --- ssl_libressl.c | 170 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 129 insertions(+), 41 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 64c44ea2..353b05d6 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -56,7 +56,7 @@ static void free_server_ssl_structures(struct client_state *csp); extern int generate_key(RSA **key_rsa, struct client_state *csp); extern int generate_webpage_certificate(struct client_state * csp); static int file_exists(const char * path); - +static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); /********************************************************************** * @@ -303,25 +303,27 @@ extern int create_client_ssl_connection(struct client_state *csp) { * Preparing paths to certificates files and key file */ char *key_file = NULL; - char *ca_file = NULL; char *cert_file = NULL; - size_t size = strlen(basedir) + 1; - ca_file = (char *)malloc(size + 14); - memset(ca_file, 0, size + 14); - strlcpy(ca_file, basedir, size + 14); - strlcat(ca_file, "/CA/cacert.crt", size + 14); - - cert_file = (char *)malloc(size + 29); - memset(cert_file, 0, size + 29); - strlcpy(cert_file, basedir, size + 29); - strlcat(cert_file, "/CA/webpagesCerts/privoxy.crt", size + 29); + cert_file = make_certs_path(csp->config->certs_dir, + (const char *)csp->http->host, CERT_FILE_TYPE); + if (cert_file == NULL) + { + ret = -1; + goto exit; + } - key_file = (char *)malloc(size + 29); - memset(key_file, 0, size + 29); - strlcpy(key_file, basedir, size + 29); - strlcat(key_file, "/CA/webpagesCerts/privoxy.pem", size + 29); + key_file = make_certs_path(csp->config->certs_dir, + (const char *)csp->http->host, KEY_FILE_TYPE); + if (key_file == NULL) + { + ret = -1; + goto exit; + } + /* + * Generating webpage key and certificate + */ ret = generate_webpage_certificate(csp); if (ret < 0) { log_error(LOG_LEVEL_ERROR, "Client connection: generate_webpage_certificate failed"); @@ -341,7 +343,6 @@ extern int create_client_ssl_connection(struct client_state *csp) { ret = -1; goto exit; } - /* * Setting SSL server certificate. @@ -659,14 +660,13 @@ extern int generate_key(RSA **key_rsa, struct client_state *csp) /* * Preparing path for key file and other properties for generating key */ - size_t size = strlen(basedir) + strlen(csp->http->host) + strlen("/CA/webpagesCerts/") - + strlen(KEY_FILE_TYPE) + 1; - key_file_path = (char *)malloc(size); - memset(key_file_path, 0, size); - strlcpy(key_file_path, basedir, size); - strlcat(key_file_path, "/CA/webpagesCerts/", size); - strlcat(key_file_path, csp->http->host, size); - strlcat(key_file_path, KEY_FILE_TYPE, size); + key_file_path = make_certs_path(csp->config->certs_dir, + (char *)csp->http->host, KEY_FILE_TYPE); + if (key_file_path == NULL) + { + ret = -1; + goto exit; + } /* * Test if key already exists. If so, we don't have to create it again. @@ -750,29 +750,27 @@ extern int generate_webpage_certificate(struct client_state * csp) X509 *cert_x509 = NULL, *issuer_cert = NULL; X509_EXTENSION * extension = NULL; ASN1_OCTET_STRING *value = NULL; - char *issuer_crt_path, *issuer_key_path, *subject_crt_path, *subject_key_path; + char *issuer_crt_path = NULL, *issuer_key_path = NULL, + *subject_crt_path = NULL, *subject_key_path = NULL; /* * Creating paths of certificates */ - size_t size = strlen(basedir) + strlen("/CA/webpagesCerts/") + 1; - size_t file_name_size = 0; issuer_crt_path = csp->config->ca_cert_file; issuer_key_path = csp->config->ca_key_file; - file_name_size = strlen(csp->http->host) + strlen(KEY_FILE_TYPE); - subject_key_path = (char *)calloc(size + file_name_size, 1); - strlcpy(subject_key_path, basedir, size + file_name_size); - strlcat(subject_key_path, "/CA/webpagesCerts/", size + file_name_size); - strlcat(subject_key_path, csp->http->host, size + file_name_size); - strlcat(subject_key_path, KEY_FILE_TYPE, size + file_name_size); - - file_name_size = strlen(csp->http->host) + strlen(CERT_FILE_TYPE); - subject_crt_path = (char *)calloc(size + file_name_size, 1); - strlcpy(subject_crt_path, basedir, size + file_name_size); - strlcat(subject_crt_path, "/CA/webpagesCerts/", size + file_name_size); - strlcat(subject_crt_path, csp->http->host, size + file_name_size); - strlcat(subject_crt_path, CERT_FILE_TYPE, size + file_name_size); + subject_key_path = make_certs_path(csp->config->certs_dir, + (const char *)csp->http->host, KEY_FILE_TYPE); + if (subject_key_path == NULL) { + ret = -1; + goto exit; + } + subject_crt_path = make_certs_path(csp->config->certs_dir, + (const char *)csp->http->host, CERT_FILE_TYPE); + if (subject_crt_path == NULL) { + ret = -1; + goto exit; + } /* * Generating or loading subject key @@ -1017,6 +1015,96 @@ exit: } +/********************************************************************* + * + * Function : make_certs_path + * + * Description : Creates path to file from three pieces. This fuction takes + * this parameters and put them in one new mallocated + * char * in correct order. Returned variable must be freed + * by caller. This function is mainly used for creating paths + * of certificates and keys files. + * + * Parameters : + * 1 : conf_dir = Name/path of directory where is the file. + * '.' can be used for current directory. + * 2 : file_name = Name of file in conf_dir without suffix. + * 3 : suffix = Suffix of given file_name. + * + * Returns : path => Path was built up successfully + * NULL => Path can't be built up + * + *********************************************************************/ +static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix) +{ + /* Test if all given parameters are valid */ + if (conf_dir == NULL || *conf_dir == '\0' || file_name == NULL + || *file_name == '\0' || suffix == NULL || *suffix == '\0') + { + log_error(LOG_LEVEL_ERROR, + "make_certs_path failed: bad input parameters"); + return NULL; + } + + char * path = NULL; + size_t path_size = strlen(conf_dir) + + strlen(file_name) + strlen(suffix) + 2; + + /* Setting delimiter and editing path length */ +#if defined(_WIN32) || defined(__OS2__) + char delim[] = "\\"; + path_size += 1; +#else /* ifndef _WIN32 || __OS2__ */ + char delim[] = "/"; +#endif /* ifndef _WIN32 || __OS2__ */ + + /* + * Biuilding up path from many parts + */ +#if defined(unix) + if (*conf_dir != '/' && basedir && *basedir) + { + /* + * Replacing conf_dir with basedir. This new variable contains + * absolute path to cwd. + */ + path_size += strlen(basedir) + 2; + path = (char *)malloc(path_size); + if (path == NULL) + { + log_error(LOG_LEVEL_ERROR, "make_certs_path failed: malloc fail"); + return NULL; + } + memset(path, 0, path_size); + + strlcpy(path, basedir, path_size); + strlcat(path, delim, path_size); + strlcat(path, conf_dir, path_size); + strlcat(path, delim, path_size); + strlcat(path, file_name, path_size); + strlcat(path, suffix, path_size); + } + else +#endif /* defined unix */ + { + path = (char *)malloc(path_size); + if (path == NULL) + { + log_error(LOG_LEVEL_ERROR, "make_certs_path failed: malloc fail"); + return NULL; + } + memset(path, 0, path_size); + + strlcpy(path, conf_dir, path_size); + strlcat(path, delim, path_size); + strlcat(path, file_name, path_size); + strlcat(path, suffix, path_size); + } + + return path; +} + + /********************************************************************* * * Function : file_exists -- 2.26.2 From b04117a516a4c7f3decb84001b6b1a5fbd4420dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:31:54 +0200 Subject: [PATCH 41/83] Generating hash of host and computing serial number from it. --- ssl_libressl.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 6 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 353b05d6..e3d08d2e 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -32,6 +32,7 @@ #include "project.h" #include "errlog.h" #include "miscutil.h" +#include "openssl/md5.h" /* @@ -39,6 +40,7 @@ */ #define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ #define GENERATED_CERT_VALID_YEARS 10 /* Count of years till expiration in generated certificates as parameter valid to */ +#define CERT_SERIAL_NUM_LENGTH 8 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */ #define CERT_PARAM_COMMON_NAME "CN" #define CERT_PARAM_ORGANIZATION "O" #define CERT_PARAM_ORG_UNIT "OU" @@ -57,6 +59,8 @@ extern int generate_key(RSA **key_rsa, struct client_state *csp); extern int generate_webpage_certificate(struct client_state * csp); static int file_exists(const char * path); static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); +static unsigned long get_certificate_serial(struct client_state *csp); +static int host_to_hash(struct client_state *csp); /********************************************************************** * @@ -299,6 +303,18 @@ extern int create_client_ssl_connection(struct client_state *csp) { csp->ssl_client_attr.socket_fd = csp->cfd; const SSL_METHOD * meth; + /* + * Preparing hash of host for creating certificates + */ + ret = host_to_hash(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, "Generating hash of host failed: %d", ret); + ret = -1; + goto exit; + } + log_error(LOG_LEVEL_INFO, "Generating hash of host: %s", csp->http->hash_of_host_hex); + /* * Preparing paths to certificates files and key file */ @@ -306,7 +322,7 @@ extern int create_client_ssl_connection(struct client_state *csp) { char *cert_file = NULL; cert_file = make_certs_path(csp->config->certs_dir, - (const char *)csp->http->host, CERT_FILE_TYPE); + (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); if (cert_file == NULL) { ret = -1; @@ -314,7 +330,7 @@ extern int create_client_ssl_connection(struct client_state *csp) { } key_file = make_certs_path(csp->config->certs_dir, - (const char *)csp->http->host, KEY_FILE_TYPE); + (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); if (key_file == NULL) { ret = -1; @@ -661,7 +677,7 @@ extern int generate_key(RSA **key_rsa, struct client_state *csp) * Preparing path for key file and other properties for generating key */ key_file_path = make_certs_path(csp->config->certs_dir, - (char *)csp->http->host, KEY_FILE_TYPE); + (char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); if (key_file_path == NULL) { ret = -1; @@ -760,13 +776,13 @@ extern int generate_webpage_certificate(struct client_state * csp) issuer_key_path = csp->config->ca_key_file; subject_key_path = make_certs_path(csp->config->certs_dir, - (const char *)csp->http->host, KEY_FILE_TYPE); + (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE); if (subject_key_path == NULL) { ret = -1; goto exit; } subject_crt_path = make_certs_path(csp->config->certs_dir, - (const char *)csp->http->host, CERT_FILE_TYPE); + (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); if (subject_crt_path == NULL) { ret = -1; goto exit; @@ -822,7 +838,7 @@ extern int generate_webpage_certificate(struct client_state * csp) goto exit; } - ret = ASN1_INTEGER_set(X509_get_serialNumber(cert_x509), 1); + ret = ASN1_INTEGER_set(X509_get_serialNumber(cert_x509), get_certificate_serial(csp)); if (ret != 1) { log_error(LOG_LEVEL_ERROR, "Certificate generating: ASN1_INTEGER_set failed"); ret = -1; @@ -1105,6 +1121,54 @@ static char * make_certs_path(const char * conf_dir, const char * file_name, con } +/********************************************************************* + * + * Function : get_certificate_serial + * + * Description : Computes serial number for new certificate from host + * name hash. This hash must be already saved in csp + * structure. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Serial number for new certificate + * + *********************************************************************/ +static unsigned long get_certificate_serial(struct client_state *csp) { + unsigned long exp = 1; + unsigned long serial = 0; + /* 21 should be enough for 64 bits number */ + const size_t PARAMETERS_BUF_LEN = MD5_DIGEST_LENGTH + 21; + char parameters_concat[PARAMETERS_BUF_LEN]; + unsigned char serial_buf[MD5_DIGEST_LENGTH]; + time_t now = time(NULL); + snprintf(parameters_concat, PARAMETERS_BUF_LEN, "%s%lu", + csp->http->hash_of_host, now); + + MD5((unsigned char *)parameters_concat, PARAMETERS_BUF_LEN, + serial_buf); + + int i = CERT_SERIAL_NUM_LENGTH; + /* Length of hash is 16 bytes, we must avoid to read next chars*/ + if (i > 16) + { + i = 16; + } + if (i < 2) { + i = 2; + } + + for (i--; i >= 0; i--) + { + serial += exp * (int)serial_buf[i]; + exp *= 256; + } + + return serial; +} + + /********************************************************************* * * Function : file_exists @@ -1127,5 +1191,42 @@ static int file_exists(const char * path) return 1; } + return 0; +} + + +/********************************************************************* + * + * Function : host_to_hash + * + * Description : Creates MD5 hash from host name. Host name is loaded from + * structure csp and saved again into it. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 1 => Error while creating hash + * 0 => Hash created successfully + * + *********************************************************************/ +static int host_to_hash(struct client_state * csp) +{ + int ret = 0; + memset(csp->http->hash_of_host, 0, sizeof(csp->http->hash_of_host)); + MD5((const unsigned char *)csp->http->host, strlen(csp->http->host), + (unsigned char *)csp->http->hash_of_host); + + /* Converting hash into string with hex */ + size_t i = 0; + for (; i < 16; i++) + { + if ((ret = sprintf((char *)csp->http->hash_of_host_hex + 2 * i, "%02x", + csp->http->hash_of_host[i])) < 0) + { + log_error(LOG_LEVEL_ERROR, "Sprintf return value: %d", ret); + return -1; + } + } + return 0; } \ No newline at end of file -- 2.26.2 From 3325a1ae0360167061c58400ce82997e11113fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:32:38 +0200 Subject: [PATCH 42/83] Verifying server certificate and sending static message about invalid certificate. --- jcc.c | 15 +++-- ssl_libressl.c | 147 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 145 insertions(+), 17 deletions(-) diff --git a/jcc.c b/jcc.c index a1b2c678..c3777028 100644 --- a/jcc.c +++ b/jcc.c @@ -3392,7 +3392,9 @@ static void chat(struct client_state *csp) #ifdef FEATURE_MBEDTLS && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED || csp->server_cert_verification_result == SSL_CERT_VALID) -#endif /* FEATURE_MBEDTLS */ +#elif defined(FEATURE_LIBRESSL) + && (csp->server_cert_verification_result == X509_V_OK) +#endif ) { rsp = error_response(csp, "connect-failed"); @@ -3423,7 +3425,6 @@ static void chat(struct client_state *csp) * Parent proxy is not used, we can just create SSL/TLS connection * with destination server */ - ret = create_server_ssl_connection(csp); /* @@ -3436,7 +3437,9 @@ static void chat(struct client_state *csp) #ifdef FEATURE_MBEDTLS && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED || csp->server_cert_verification_result == SSL_CERT_VALID) -#endif /* FEATURE_MBEDTLS */ +#elif defined(FEATURE_LIBRESSL) + && (csp->server_cert_verification_result == X509_V_OK) +#endif ) { rsp = error_response(csp, "connect-failed"); @@ -3530,12 +3533,16 @@ static void chat(struct client_state *csp) */ #ifdef FEATURE_MBEDTLS if (csp->server_cert_verification_result != SSL_CERT_VALID) +#elif defined(FEATURE_LIBRESSL) + if (csp->server_cert_verification_result != X509_V_OK) +#endif +#if defined(FEATURE_MBEDTLS) || defined(FEATURE_LIBRESSL) { ssl_send_certificate_error(csp); close_client_and_server_ssl_connections(csp); return; } -#endif /* FEATURE_MBEDTLS */ +#endif log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); } diff --git a/ssl_libressl.c b/ssl_libressl.c index e3d08d2e..14c9310d 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -27,6 +27,7 @@ * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *********************************************************************/ +#include #include "ssl_libressl.h" #include "project.h" @@ -41,6 +42,7 @@ #define RSA_KEYSIZE 2048 /* Size of generated RSA keys */ #define GENERATED_CERT_VALID_YEARS 10 /* Count of years till expiration in generated certificates as parameter valid to */ #define CERT_SERIAL_NUM_LENGTH 8 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */ +#define INVALID_CERT_INFO_BUF_SIZE 2048 /* Size of buffer for message with information about reason of certificate invalidity. Data after the end of buffer be not be saved */ #define CERT_PARAM_COMMON_NAME "CN" #define CERT_PARAM_ORGANIZATION "O" #define CERT_PARAM_ORG_UNIT "OU" @@ -61,6 +63,7 @@ static int file_exists(const char * path); static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); static unsigned long get_certificate_serial(struct client_state *csp); static int host_to_hash(struct client_state *csp); +static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx); /********************************************************************** * @@ -95,10 +98,27 @@ extern int create_server_ssl_connection(struct client_state *csp) goto exit; } + /* + * Setting minimal protocol version: TLS1_VERSION, TLS1_1_VERSION, + * TLS1_2_VERSION, DTLS1_VERSION + */ + ret = SSL_CTX_set_min_proto_version(csp->ssl_server_attr.ctx, 0); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_CTX_set_min_proto_version failed"); + ret = -1; + goto exit; + } + /* * Setting how strict should certificate verification be and callback function. */ - SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_NONE, NULL); + SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_PEER, ssl_verify_callback); + ret = SSL_CTX_load_verify_locations(csp->ssl_server_attr.ctx, csp->config->trusted_cas_file, NULL); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_CTX_load_verify_locations: Failed to load trusted CAs"); + ret = -1; + goto exit; + } csp->ssl_server_attr.ssl = SSL_new(csp->ssl_server_attr.ctx); @@ -114,26 +134,25 @@ extern int create_server_ssl_connection(struct client_state *csp) SSL_set_bio(csp->ssl_server_attr.ssl, csp->ssl_server_attr.bio, csp->ssl_server_attr.bio); + SSL_set_connect_state(csp->ssl_server_attr.ssl); /* * Handshake with server */ ret = SSL_connect(csp->ssl_server_attr.ssl); + csp->server_cert_verification_result = SSL_get_verify_result(csp->ssl_server_attr.ssl); + if (ret <= 0) { + X509 * peer_cert = SSL_get_peer_certificate(csp->ssl_server_attr.ssl); + if (peer_cert == NULL) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_get_peer_certificate failed"); + } + log_error(LOG_LEVEL_INFO, "Cert verification result: %d, %d => host: %s", ret, csp->server_cert_verification_result, csp->http->host); log_error(LOG_LEVEL_ERROR, "Server connection: SSL_connect failed"); ret = -1; goto exit; } - /* - * Getting results of server certificate verification. - */ - log_error(LOG_LEVEL_INFO, "Cert verification result: %d", SSL_get_verify_result(csp->ssl_server_attr.ssl)); - X509 * peer_cert = SSL_get_peer_certificate(csp->ssl_server_attr.ssl); - if (peer_cert == NULL) { - log_error(LOG_LEVEL_ERROR, "Server connection: SSL_get_peer_certificate failed"); - } - /* * Creating BIO to comunicate with server over ssl. */ @@ -313,7 +332,6 @@ extern int create_client_ssl_connection(struct client_state *csp) { ret = -1; goto exit; } - log_error(LOG_LEVEL_INFO, "Generating hash of host: %s", csp->http->hash_of_host_hex); /* * Preparing paths to certificates files and key file @@ -640,8 +658,6 @@ extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { } -extern void ssl_send_certificate_error(struct client_state *csp) { return; } - /*======================Certificates======================*/ @@ -1169,6 +1185,111 @@ static unsigned long get_certificate_serial(struct client_state *csp) { } +/********************************************************************* + * + * Function : ssl_send_certificate_error + * + * Description : Sends info about invalid server certificate to client. + * Sent message is including all trusted chain certificates, + * that can be downloaded in web browser. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : N/A + * + *********************************************************************/ +extern void ssl_send_certificate_error(struct client_state *csp) +{ + size_t message_len = 0; + int ret = 0; + struct certs_chain *cert = NULL; + + log_error(LOG_LEVEL_ERROR, "posilam error"); + + /* Header of message with certificate informations */ + const char message_begin[] = + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n\r\n" + "

Invalid server certificate

Reason: "; + const char message_end[] = "\r\n\r\n"; + char reason[INVALID_CERT_INFO_BUF_SIZE]; + memset(reason, 0, sizeof(reason)); + + /* + * Computing total lenght of message with all certificates inside + */ + message_len = strlen(message_begin) + strlen(message_end); + + /* + * Joining all blocks in one long message + */ + char message[message_len]; + memset(message, 0, message_len); + + strlcpy(message, message_begin, message_len); + strlcat(message, message_end, message_len); + + /* + * Sending final message to client + */ + ssl_send_data(&(csp->ssl_client_attr), + (const unsigned char *)message, strlen(message)); + + /* + * Waiting before closing connection. Some browsers don't show received + * message if there isn't this delay. + */ + sleep(1); +} + + +/********************************************************************* + * + * Function : ssl_verify_callback + * + * Description : This is callback function for certificates verification. + * It's called for all certificates in server certificate + * trusted chain and it's preparing information about this + * certificates. Prepared informations can be used to inform + * user about invalid certificate. + * + * Parameters : + * 1 : ok = Result of cert verification + * 2 : ctx = Certificate from chain + * + * Returns : 1 on success and 0 on error + * + *********************************************************************/ +int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + X509 *err_cert; + char *s, buf[256]; + int err, depth; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + log_error(LOG_LEVEL_INFO, "depth=%d", depth); + if (err_cert != NULL) { + s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof buf); + log_error(LOG_LEVEL_INFO, "Cert name: %s", buf); + } + else { + log_error(LOG_LEVEL_ERROR, "Can't get failing cert file"); + } + + if (ok == 0) { + log_error(LOG_LEVEL_ERROR, "Certificate verification error string: %s\n", X509_verify_cert_error_string(ctx->error)); + } + + log_error(LOG_LEVEL_INFO, "Cert verification returns: %d", ok); + return ok; +} + + /********************************************************************* * * Function : file_exists -- 2.26.2 From 02cd906962126f254c8a2a5dd0d6d4b840f889a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:33:54 +0200 Subject: [PATCH 43/83] Edited configuration files to build Privoxy with selected ssl library (mbedtls or libressl). --- GNUmakefile.in | 24 +++++++++++++++--------- acconfig.h | 7 +++++++ configure.in | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/GNUmakefile.in b/GNUmakefile.in index 7980f9fe..a2d88de4 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -231,10 +231,15 @@ W32_HDRS = @WIN_ONLY@w32log.h w32taskbar.h win32.h w32res.h w32svrapi.h W32_LIB = @WIN_ONLY@-lwsock32 -lcomctl32 W32_INIS = @WIN_ONLY@config.txt trust.txt -SSL_SRC = ssl.c -SSL_OBJS = $(SSL_SRC:.c=.o) -SSL_HDRS = $(SSL_SRC:.c=.h) project.h -SSL_LIB = mbedtls/library/libmbedx509.a mbedtls/library/libmbedtls.a mbedtls/library/libmbedcrypto.a +SSL_MBEDTLS_SRC = @USAGE_MBEDTLS@ssl.c +SSL_MBEDTLS_OBJS = @USAGE_MBEDTLS@$(SSL_MBEDTLS_SRC:.c=.o) +SSL_MBEDTLS_HDRS = @USAGE_MBEDTLS@$(SSL_MBEDTLS_SRC:.c=.h) project.h +SSL_MBEDTLS_LIB = @USAGE_MBEDTLS@mbedtls/library/libmbedx509.a mbedtls/library/libmbedtls.a mbedtls/library/libmbedcrypto.a + +SSL_LIBRE_SRC = @USAGE_LIBRESSL@ssl_libressl.c +SSL_LIBRE_OBJS = @USAGE_LIBRESSL@$(SSL_LIBRE_SRC:.c=.o) +SSL_LIBRE_HDRS = @USAGE_LIBRESSL@$(SSL_LIBRE_SRC:.c=.h) project.h +SSL_LIBRE_LIB = @USAGE_LIBRESSL@libressl/tls/.libs/libtls.a libressl/ssl/.libs/libssl.a libressl/crypto/.libs/libcrypto.a PCRS_SRC = @STATIC_PCRS_ONLY@pcrs.c PCRS_OBJS = @STATIC_PCRS_ONLY@$(PCRS_SRC:.c=.@OBJEXT@) @@ -260,10 +265,10 @@ SOCKET_LIB = @SOCKET_LIB@ # PThreads library, if needed. PTHREAD_LIB = @PTHREAD_ONLY@@PTHREAD_LIB@ -SRCS = $(C_SRC) $(CLIENT_TAG_SRC) $(FUZZ_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC) $(SSL_SRC) -OBJS = $(C_OBJS) $(CLIENT_TAG_OBJS) $(FUZZ_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS) $(SSL_OBJS) -HDRS = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS) $(SSL_HDRS) -LIBS = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB) $(SSL_LIB) +SRCS = $(C_SRC) $(CLIENT_TAG_SRC) $(FUZZ_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC) $(SSL_MBEDTLS_SRC) $(SSL_LIBRE_SRC) +OBJS = $(C_OBJS) $(CLIENT_TAG_OBJS) $(FUZZ_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS) $(SSL_MBEDTLS_OBJS) $(SSL_LIBRE_OBJS) +HDRS = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS) $(SSL_MBEDTLS_HDRS) $(SSL_LIBRE_HDRS) +LIBS = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB) $(SSL_MBEDTLS_LIB) $(SSL_LIBRE_LIB) ############################################################################# # Compiler switches @@ -280,7 +285,8 @@ SPECIAL_CFLAGS = @SPECIAL_CFLAGS@ OTHER_CFLAGS = CFLAGS = @CFLAGS@ @CPPFLAGS@ $(OTHER_CFLAGS) $(SPECIAL_CFLAGS) -Wall \ - -Imbedtls/include \ + @USAGE_LIBRESSL@ -Ilibressl/include \ + @USAGE_MBEDTLS@ -Imbedtls/include \ @STATIC_PCRE_ONLY@ -Ipcre LDFLAGS = @LDFLAGS@ $(DEBUG_CFLAGS) $(SPECIAL_CFLAGS) diff --git a/acconfig.h b/acconfig.h index ab59de81..5cdd1290 100644 --- a/acconfig.h +++ b/acconfig.h @@ -127,6 +127,13 @@ */ #undef FEATURE_EXTENDED_HOST_PATTERNS + +/* Allow Privoxy to use libressl for SSL comunication and filtering. */ +#undef FEATURE_LIBRESSL + +/* Allow Privoxy to use mbedtls for SSL comunication and filtering. */ +#undef FEATURE_MBEDTLS + /* * Allow filtering with scripts and programs. */ diff --git a/configure.in b/configure.in index 64658751..da4a264e 100644 --- a/configure.in +++ b/configure.in @@ -1082,6 +1082,40 @@ if test $enableval2 = yes; then fi fi +dnl ================================================================= +dnl SSL libraries +dnl ================================================================= + +AC_ARG_ENABLE(libressl, +[ --disable-libressl Set Privoxy not to use libressl for SSL comunication and filtering. Libressl is defaultly enabled.], +[disablelibressl=yes], +[disablelibressl=no]) + +AC_ARG_ENABLE(mbedtls, +[ --enable-mbedtls Allow Privoxy to use mbedtls for SSL comunication and filtering.], +[enablembedtls=$enableval], +[enablembedtls=no]) + +if test $enablembedtls = yes; then + echo Enabling mbedtls. + AC_DEFINE(FEATURE_MBEDTLS) + USAGE_MBEDTLS= + USAGE_LIBRESSL=# +else + if test $disablelibressl = no; then + echo Enabling libressl. + AC_DEFINE(FEATURE_LIBRESSL) + USAGE_MBEDTLS=# + USAGE_LIBRESSL= + fi +fi + +AC_SUBST(USAGE_MBEDTLS) +AC_SUBST(USAGE_LIBRESSL) + +dnl ================================================================= +dnl END of SSL libraries +dnl ================================================================= # If we have libpcre and either we also have pcreposix or # we don't need pcreposix, then link pcre dynamically; else -- 2.26.2 From 3cfac52dcb8a3b17af90ff9721ca39478a504520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:34:48 +0200 Subject: [PATCH 44/83] Setting subjectAltName (SAN) into generated certificates in correct form. Fixed certificate version value to V3. --- ssl_libressl.c | 199 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 164 insertions(+), 35 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 14c9310d..8d744d0e 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -34,6 +34,7 @@ #include "errlog.h" #include "miscutil.h" #include "openssl/md5.h" +#include "openssl/x509v3.h" /* @@ -64,6 +65,8 @@ static char * make_certs_path(const char * conf_dir, const char * file_name, con static unsigned long get_certificate_serial(struct client_state *csp); static int host_to_hash(struct client_state *csp); static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx); +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit, ASN1_VALUE *ext_struc); + /********************************************************************** * @@ -754,6 +757,74 @@ exit: } +/********************************************************************* + * + * Function : set_certificate_extensions + * + * Description : Sets extensions of given certificate. It's used to set + * subject alternative name (SAN). + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : cert + * + * Returns : 1 => Extensions set successfully + * 0 => Extensions setting error + *********************************************************************/ +extern int set_certificate_extensions(struct client_state * csp, X509 *cert) { + int ret = 0; + X509V3_CTX ctx2; + X509_EXTENSION * extension = NULL; + STACK_OF(CONF_VALUE) *nval = NULL; + STACK_OF(X509_EXTENSION) **sk = NULL; + + const X509V3_EXT_METHOD *method; + ASN1_VALUE *ext_struc = NULL; + + X509V3_set_ctx(&ctx2, cert, cert, NULL, NULL, 0); + sk = &cert->cert_info->extensions; + X509V3_add_value("DNS.1", csp->http->host, &nval); + + method = X509V3_EXT_get_nid(NID_subject_alt_name); + if (method == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate extensions setting: X509V3_EXT_get_nid failed"); + ret = -1; + goto exit; + } + + ext_struc = method->v2i(method, &ctx2, nval); + if (!ext_struc) { + log_error(LOG_LEVEL_ERROR, "Certificate extensions setting: v2i failed"); + ret = -1; + goto exit; + } + + extension = do_ext_i2d(method, NID_subject_alt_name, 0, ext_struc); + + if (X509v3_add_ext(sk, extension, -1) == NULL) { + log_error(LOG_LEVEL_ERROR, "Certificate extensions setting: X509v3_add_ext failed"); + ret = -1; + goto exit; + } + +exit: + if (method->it) { + ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); + } + else { + method->ext_free(ext_struc); + } + + X509_EXTENSION_free(extension); + + if (ret == -1) { + return 0; + } + + return 1; +} + + /********************************************************************* * * Function : generate_webpage_certificate @@ -780,8 +851,6 @@ extern int generate_webpage_certificate(struct client_state * csp) BIO * subject_key_bio = NULL, *issuer_key_bio = NULL, *issuer_cert_bio = NULL, *subject_cert_bio = NULL; X509 *cert_x509 = NULL, *issuer_cert = NULL; - X509_EXTENSION * extension = NULL; - ASN1_OCTET_STRING *value = NULL; char *issuer_crt_path = NULL, *issuer_key_path = NULL, *subject_crt_path = NULL, *subject_key_path = NULL; @@ -871,7 +940,7 @@ extern int generate_webpage_certificate(struct client_state * csp) ret = -1; goto exit; } - ret = X509_set_version(cert_x509, 3); + ret = X509_set_version(cert_x509, 2); if (ret != 1) { log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_set_version failed"); ret = -1; @@ -916,36 +985,9 @@ extern int generate_webpage_certificate(struct client_state * csp) /* * Setting subject alternative name */ - extension = X509_EXTENSION_new(); - if (extension == NULL) { - log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_EXTENSION_new failed"); - ret = -1; - goto exit; - } - - value = ASN1_OCTET_STRING_new(); - if (value == NULL) { - log_error(LOG_LEVEL_ERROR, "Certificate generating: ASN1_OCTET_STRING_new failed"); - ret = -1; - goto exit; - } - - ret = ASN1_STRING_set(value, csp->http->host, strlen(csp->http->host)); + ret = set_certificate_extensions(csp, cert_x509); if (ret != 1) { - log_error(LOG_LEVEL_ERROR, "Certificate generating: ASN1_STRING_set failed"); - ret = -1; - goto exit; - } - - if (X509_EXTENSION_create_by_NID(&extension, NID_subject_alt_name, 0, value) == NULL) { - log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_EXTENSION_create_by_NID failed"); - ret = -1; - goto exit; - } - - ret = X509_add_ext(cert_x509, extension, -1); - if (ret != 1) { - log_error(LOG_LEVEL_ERROR, "Certificate generating: X509_add_ext failed"); + log_error(LOG_LEVEL_ERROR, "Certificate generating: set_certificate_extensions failed"); ret = -1; goto exit; } @@ -1033,8 +1075,6 @@ exit: X509_free(issuer_cert); EVP_PKEY_free(issuer_pkey); EVP_PKEY_free(subject_pkey); - X509_EXTENSION_free(extension); - ASN1_OCTET_STRING_free(value); if (subject_crt_path != NULL) { freez(subject_crt_path); @@ -1350,4 +1390,93 @@ static int host_to_hash(struct client_state * csp) } return 0; -} \ No newline at end of file +} + + +/********************************************************************* + * + * Function : do_ext_i2d + * + * Description : Creates X509_EXTENSION from given parameters, which can + * can be setted as a certificate extension. + * + * Parameters : + * 1 : method = Current client state (buffers, headers, etc...) + * 2 : ext_nid = Certificate extension NID + * 3 : crit = 1 -> critical + * 0 -> not critical + * 4 : ext_struct = value to be setted into extension + * + * Returns : extension => Created extension + * NULL => Function failed + * + *********************************************************************/ +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, + int ext_nid, int crit, ASN1_VALUE *ext_struc) +{ + unsigned char *ext_der = NULL; + int ext_len; + ASN1_OCTET_STRING *ext_oct = NULL; + X509_EXTENSION *ext; + int ret = 0; + + /* + * Convert internal representation to DER + */ + if (method->it) + { + ext_der = NULL; + ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); + if (ext_len < 0) + { + log_error(LOG_LEVEL_ERROR, "do_ext_i2d: ASN1_item_i2d failed"); + ret = -1; + goto exit; + } + } + else + { + unsigned char *p; + ext_len = method->i2d(ext_struc, NULL); + + ext_der = calloc(ext_len, 1); + if (ext_der == NULL) + { + log_error(LOG_LEVEL_ERROR, "do_ext_i2d: calloc failed"); + ret = -1; + goto exit; + } + p = ext_der; + method->i2d(ext_struc, &p); + } + + /* + * Putting value into octet string + */ + if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL) + { + log_error(LOG_LEVEL_ERROR, "do_ext_i2d: ASN1_OCTET_STRING_new failed"); + ret = -1; + goto exit; + } + ext_oct->data = ext_der; + ext_der = NULL; + ext_oct->length = ext_len; + + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); + if (ext == NULL) + { + log_error(LOG_LEVEL_ERROR, "do_ext_i2d: X509_EXTENSION_create_by_NID failed"); + ret = -1; + goto exit; + } + +exit: + if (ret == -1) + { + freez(ext_der); + } + + ASN1_OCTET_STRING_free(ext_oct); + return ext; +} -- 2.26.2 From 920630653005e4a272cdc060a2a0694bbd826a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:36:03 +0200 Subject: [PATCH 45/83] Setting hostname for handshake (SNI) and server certificate verification purpose. --- ssl_libressl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ssl_libressl.c b/ssl_libressl.c index 8d744d0e..c02d816d 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -85,6 +85,7 @@ extern int create_server_ssl_connection(struct client_state *csp) { int ret = 0; const SSL_METHOD *meth; + X509_VERIFY_PARAM *param = NULL; csp->ssl_server_attr.socket_fd = csp->server_connection.sfd; meth = TLS_method(); @@ -125,6 +126,25 @@ extern int create_server_ssl_connection(struct client_state *csp) csp->ssl_server_attr.ssl = SSL_new(csp->ssl_server_attr.ctx); + /* + * Setting hostname for handshake and server certificate verification + */ + ret = SSL_set_tlsext_host_name(csp->ssl_server_attr.ssl, csp->http->host); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Server connection: SSL_set_tlsext_host_name failed"); + ret = -1; + goto exit; + } + + param = SSL_get0_param(csp->ssl_server_attr.ssl); + X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + ret = X509_VERIFY_PARAM_set1_host(param, csp->http->host, strlen(csp->http->host)); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "Server connection: X509_VERIFY_PARAM_set1_host failed"); + ret = -1; + goto exit; + } + /* * Setting TCP socket to bio. */ -- 2.26.2 From 24b1fbd699f05fd3d7cfc6fc1c4ad698e4f200a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:37:02 +0200 Subject: [PATCH 46/83] Added function to create string with basic information about given certificate. --- project.h | 5 ++ ssl_libressl.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) diff --git a/project.h b/project.h index 5daac946..5d8195ee 100644 --- a/project.h +++ b/project.h @@ -381,9 +381,14 @@ typedef struct { * Struct for linked list containing certificates */ typedef struct certs_chain { +#ifdef FEATURE_MBEDTLS char text_buf[CERT_INFO_BUF_SIZE]; /* text info about properties of certificate */ char file_buf[CERT_FILE_BUF_SIZE]; /* buffer for whole certificate - format to save in file */ struct certs_chain *next; /* next certificate in chain of trust */ +#endif +#ifdef FEATURE_LIBRESSL + STACK_OF(X509) *chain; +#endif }certs_chain_t; /** diff --git a/ssl_libressl.c b/ssl_libressl.c index c02d816d..57e9263a 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -44,6 +44,7 @@ #define GENERATED_CERT_VALID_YEARS 10 /* Count of years till expiration in generated certificates as parameter valid to */ #define CERT_SERIAL_NUM_LENGTH 8 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */ #define INVALID_CERT_INFO_BUF_SIZE 2048 /* Size of buffer for message with information about reason of certificate invalidity. Data after the end of buffer be not be saved */ +#define INVALID_CERT_INFO_KEY_SIZE 20 /* Size of buffer for getting information about server certificate key size */ #define CERT_PARAM_COMMON_NAME "CN" #define CERT_PARAM_ORGANIZATION "O" #define CERT_PARAM_ORG_UNIT "OU" @@ -66,6 +67,7 @@ static unsigned long get_certificate_serial(struct client_state *csp); static int host_to_hash(struct client_state *csp); static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx); static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit, ASN1_VALUE *ext_struc); +static char* generate_cert_info(X509* cert); /********************************************************************** @@ -1305,6 +1307,218 @@ extern void ssl_send_certificate_error(struct client_state *csp) } +/********************************************************************* + * + * Function : generate_cert_info + * + * Description : Creates string with basic information about given + * certificate. String is dynamically allocated and + * must be freed by caller. + * + * Parameters : + * 1 : cert = Certificate + * + * Returns : String with certificate information. + * + *********************************************************************/ +static char* generate_cert_info(X509* cert) { + int ret = 0; + char* message = NULL; + size_t message_len = 0; + char** subject_alt_names = NULL; + char version_buf[2]; + const char* sign_algo_buf = NULL; + int rc; + int key_size = -1; + char key_size_buf[INVALID_CERT_INFO_KEY_SIZE + 1]; + size_t subject_alt_names_len = 0; + + char* subject_info = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + char* issuer_info = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); + ASN1_TIME *not_before = X509_get_notBefore(cert); + ASN1_TIME *not_after = X509_get_notAfter(cert); + int ca_status = X509_check_ca(cert); + int version = ((int)X509_get_version(cert)) + 1; + version_buf[0] = (char)(version + (int)'0'); + version_buf[1] = 0; + BUF_MEM* not_before_buf = NULL; + BUF_MEM* not_after_buf = NULL; + + /* + * Getting serial number. + */ + ASN1_INTEGER* serial = X509_get_serialNumber(cert); + BIGNUM* bn_serial = ASN1_INTEGER_to_BN(serial, NULL); + char* serial_buf; + if (bn_serial != NULL) { + serial_buf = BN_bn2hex(bn_serial); + } + + if (bn_serial == NULL || serial_buf == NULL) { + log_error(LOG_LEVEL_INFO, "generate_cert_info: getting certificate serial failed"); + } + + /* + * Getting alternative names. + */ + STACK_OF(GENERAL_NAME)* san_names = NULL; + san_names = X509_get_ext_d2i((X509 *)cert, NID_subject_alt_name, NULL, NULL); + int alt_names_count = 0; + if (san_names != NULL) { + int san_names_nb = sk_GENERAL_NAME_num(san_names); + subject_alt_names = (char**)calloc(san_names_nb, sizeof(char*)); + + for (int i = 0; i < san_names_nb; i++) { + const GENERAL_NAME* current_name = sk_GENERAL_NAME_value(san_names, i); + + if (current_name->type == GEN_DNS) { + if (subject_alt_names_len > 0) { + subject_alt_names_len += strlen(", "); + } + subject_alt_names[alt_names_count] = (char *)ASN1_STRING_get0_data(current_name->d.dNSName); + subject_alt_names_len += strlen(subject_alt_names[alt_names_count]); + alt_names_count++; + } + } + } + else { + log_error(LOG_LEVEL_INFO, "generate_cert_info: getting certificate subject alternative name failed"); + } + + /* + * Getting signature algorithm + */ + int pkey_nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); + if (pkey_nid != NID_undef) { + sign_algo_buf = OBJ_nid2ln(pkey_nid); + } + + if (pkey_nid == NID_undef || sign_algo_buf == NULL) { + log_error(LOG_LEVEL_INFO, "generate_cert_info: getting signature algorithm failed"); + } + + /* + * Getting expiration dates + */ + BIO* not_before_bio = BIO_new(BIO_s_mem()); + rc = ASN1_TIME_print(not_before_bio, not_before); + if (rc == 1) { + ret = BIO_get_mem_ptr(not_before_bio, ¬_before_buf); + } + + if (rc != 1 || ret != 1) { + log_error(LOG_LEVEL_INFO, "generate_cert_info: getting certificate sign date failed"); + } + + BIO* not_after_bio = BIO_new(BIO_s_mem()); + rc = ASN1_TIME_print(not_after_bio, not_after); + if (rc == 1) { + ret = BIO_get_mem_ptr(not_after_bio, ¬_after_buf); + } + + if (rc != 1 || ret != 1) { + log_error(LOG_LEVEL_INFO, "generate_cert_info: getting certificate expiration date failed"); + } + + /* + * Getting key size + */ + RSA* rsa_key = NULL; + EVP_PKEY* public_key = X509_get0_pubkey(cert); + if (public_key != NULL) { + rsa_key = EVP_PKEY_get0_RSA(public_key); + if (rsa_key != NULL) { + key_size = RSA_bits(rsa_key); + } + } + if (key_size != -1) { + ret = snprintf(key_size_buf, INVALID_CERT_INFO_KEY_SIZE, "%d", key_size); + if (ret <= 0 || ret > INVALID_CERT_INFO_KEY_SIZE) { + key_size = -1; + } + else { + key_size_buf[ret + 1] = '\0'; + } + } + else { + log_error(LOG_LEVEL_INFO, "generate_cert_info: getting certificate key size failed"); + } + + /* + * Preparing buffer for certificate information string and filling it + */ + if (ca_status == 0) { + message_len += strlen("\nis CA certificate : false"); + } + else { + message_len += strlen("\nis CA certificate : true"); + } + message_len += strlen(issuer_info) + strlen(subject_info) + subject_alt_names_len + + strlen(serial_buf) + strlen(sign_algo_buf) + not_before_buf->length + not_after_buf->length + + strlen(version_buf) + strlen(key_size_buf) + + strlen("cert. version : \nserial number : \nissuer name : \nsubject name : ") + + strlen("\nissued on : \nexpires on : \nsigned using : \nkey size : bits") + + strlen("\nsubject alt name : ") + 1; + + message = (char*)calloc(message_len, 1); + strlcpy(message, "cert. version : ", message_len); + strlcat(message, version_buf, message_len); + strlcat(message, "\nserial number : ", message_len); + strlcat(message, serial_buf, message_len); + strlcat(message, "\nissuer name : ", message_len); + strlcat(message, issuer_info, message_len); + strlcat(message, "\nsubject name : ", message_len); + strlcat(message, subject_info, message_len); + strlcat(message, "\nissued on : ", message_len); + strlcat(message, not_before_buf->data, message_len); + strlcat(message, "\nexpires on : ", message_len); + strlcat(message, not_after_buf->data, message_len); + + if (sign_algo_buf != NULL) { + strlcat(message, "\nsigned using : ", message_len); + strlcat(message, sign_algo_buf, message_len); + } + + if (key_size != -1) { + strlcat(message, "\nkey size : ", message_len); + strlcat(message, key_size_buf, message_len); + strlcat(message, " bits", message_len); + } + + if (ca_status == 0) { + strlcat(message, "\nis CA certificate : false", message_len); + } + else { + strlcat(message, "\nis CA certificate : true", message_len); + } + + strlcat(message, "\nsubject alt name : ", message_len); + for (int i = 0; i < alt_names_count; i++) + { + strlcat(message, subject_alt_names[i], message_len); + if (i != alt_names_count - 1) { + strlcat(message, ", ", message_len); + } + } + + /* + * Freeing used structures + */ + BN_clear_free(bn_serial); + freez(serial_buf); + freez(issuer_info); + freez(subject_info); + + BIO_free_all(not_before_bio); + BIO_free_all(not_after_bio); + + freez(subject_alt_names); + version_buf[0] = '\0'; + + return message; +} + + /********************************************************************* * * Function : ssl_verify_callback -- 2.26.2 From 6962d3c5a4d5cd3ab45ecdaafac12e43d2e6c7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:37:47 +0200 Subject: [PATCH 47/83] Setted callback for certificate verification. It keeps server certificate chain, when certificate verification is not successful. --- ssl_libressl.c | 65 +++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 41 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 57e9263a..46beb278 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -65,7 +65,7 @@ static int file_exists(const char * path); static char * make_certs_path(const char * conf_dir, const char * file_name, const char * suffix); static unsigned long get_certificate_serial(struct client_state *csp); static int host_to_hash(struct client_state *csp); -static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx); +static int ssl_cert_verify_callback(X509_STORE_CTX * ctx, void * arg); static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit, ASN1_VALUE *ext_struc); static char* generate_cert_info(X509* cert); @@ -118,7 +118,9 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Setting how strict should certificate verification be and callback function. */ - SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_PEER, ssl_verify_callback); + SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_PEER, NULL); + SSL_CTX_set_cert_verify_callback(csp->ssl_server_attr.ctx, ssl_cert_verify_callback, &(csp->server_certs_chain.chain)); + ret = SSL_CTX_load_verify_locations(csp->ssl_server_attr.ctx, csp->config->trusted_cas_file, NULL); if (ret != 1) { log_error(LOG_LEVEL_ERROR, "Server connection: SSL_CTX_load_verify_locations: Failed to load trusted CAs"); @@ -166,13 +168,7 @@ extern int create_server_ssl_connection(struct client_state *csp) */ ret = SSL_connect(csp->ssl_server_attr.ssl); csp->server_cert_verification_result = SSL_get_verify_result(csp->ssl_server_attr.ssl); - if (ret <= 0) { - X509 * peer_cert = SSL_get_peer_certificate(csp->ssl_server_attr.ssl); - if (peer_cert == NULL) { - log_error(LOG_LEVEL_ERROR, "Server connection: SSL_get_peer_certificate failed"); - } - log_error(LOG_LEVEL_INFO, "Cert verification result: %d, %d => host: %s", ret, csp->server_cert_verification_result, csp->http->host); log_error(LOG_LEVEL_ERROR, "Server connection: SSL_connect failed"); ret = -1; goto exit; @@ -187,7 +183,7 @@ extern int create_server_ssl_connection(struct client_state *csp) csp->ssl_with_server_is_opened = 1; ret = 0; exit: - if (ret != 0) { + if (ret == -1) { free_server_ssl_structures(csp); } @@ -423,7 +419,7 @@ extern int create_client_ssl_connection(struct client_state *csp) { } /* - * Setting how strict should client certificate verification be and callback function. + * Setting how strict should client certificate verification be. */ SSL_CTX_set_verify(csp->ssl_client_attr.ctx, SSL_VERIFY_NONE, 0); @@ -1521,46 +1517,33 @@ static char* generate_cert_info(X509* cert) { /********************************************************************* * - * Function : ssl_verify_callback + * Function : ssl_cert_verify_callback * - * Description : This is callback function for certificates verification. - * It's called for all certificates in server certificate - * trusted chain and it's preparing information about this - * certificates. Prepared informations can be used to inform - * user about invalid certificate. + * Description : Callback function for certificates verification. + * It's called for server certificate and it's checking + * validity of it. Invalid certificate is shallow + * copied (reference count is increased) to be kept for + * future treatment and setted to given argument. * * Parameters : - * 1 : ok = Result of cert verification - * 2 : ctx = Certificate from chain + * 1 : ctx = Server certificate + * 2 : arg = pointer to STACK_OF(X509) where should be + * invalid certificate placed * - * Returns : 1 on success and 0 on error + * Returns : 1 => Indicates certificate verification success + * 0 => Indicates certificate verification failure * *********************************************************************/ -int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) -{ - X509 *err_cert; - char *s, buf[256]; - int err, depth; - - err_cert = X509_STORE_CTX_get_current_cert(ctx); - err = X509_STORE_CTX_get_error(ctx); - depth = X509_STORE_CTX_get_error_depth(ctx); +static int ssl_cert_verify_callback(X509_STORE_CTX * ctx, void * arg) { + int result = 0; + STACK_OF(X509) ** untrusted_chain = (STACK_OF(X509) **) (arg); - log_error(LOG_LEVEL_INFO, "depth=%d", depth); - if (err_cert != NULL) { - s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof buf); - log_error(LOG_LEVEL_INFO, "Cert name: %s", buf); - } - else { - log_error(LOG_LEVEL_ERROR, "Can't get failing cert file"); + result = X509_verify_cert(ctx); + if (result != 1) { + *untrusted_chain = X509_chain_up_ref(X509_STORE_CTX_get0_untrusted(ctx)); } - if (ok == 0) { - log_error(LOG_LEVEL_ERROR, "Certificate verification error string: %s\n", X509_verify_cert_error_string(ctx->error)); - } - - log_error(LOG_LEVEL_INFO, "Cert verification returns: %d", ok); - return ok; + return result; } -- 2.26.2 From 357ab9745d772e30abc989cf89a1aecef0cc8203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:38:26 +0200 Subject: [PATCH 48/83] Sending response to client with information about invalid server certificate and with link to download it. --- ssl_libressl.c | 85 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 9 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index 46beb278..f859abe0 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -1260,10 +1260,9 @@ static unsigned long get_certificate_serial(struct client_state *csp) { extern void ssl_send_certificate_error(struct client_state *csp) { size_t message_len = 0; + char *message = NULL; + int certs_count = 0; int ret = 0; - struct certs_chain *cert = NULL; - - log_error(LOG_LEVEL_ERROR, "posilam error"); /* Header of message with certificate informations */ const char message_begin[] = @@ -1272,21 +1271,75 @@ extern void ssl_send_certificate_error(struct client_state *csp) "Connection: close\r\n\r\n" "

Invalid server certificate

Reason: "; const char message_end[] = "\r\n\r\n"; - char reason[INVALID_CERT_INFO_BUF_SIZE]; - memset(reason, 0, sizeof(reason)); + + /* Get verification message from verification return code */ + const char* reason = X509_verify_cert_error_string(csp->server_cert_verification_result); /* * Computing total lenght of message with all certificates inside */ - message_len = strlen(message_begin) + strlen(message_end); + message_len = strlen(message_begin) + strlen(message_end) + + strlen(reason) + strlen("

") + 1; + + certs_count = sk_X509_num(csp->server_certs_chain.chain); + BUF_MEM** cert_buffs = (BUF_MEM**)calloc(certs_count, sizeof(BUF_MEM*)); + BIO** cert_bios = (BIO**)calloc(certs_count, sizeof(BIO*)); + X509** certs = (X509**)calloc(certs_count, sizeof(X509*)); + char** certs_info = (char**)calloc(certs_count, sizeof(char*)); + + for (int i = 0; i < certs_count; i++) + { + cert_bios[i] = BIO_new(BIO_s_mem()); + certs[i] = sk_X509_value(csp->server_certs_chain.chain, i); + + ret = PEM_write_bio_X509(cert_bios[i], certs[i]); + if (ret != 1) { + log_error(LOG_LEVEL_ERROR, "ssl_send_certificate_error: PEM_write_bio_X509 failed"); + goto exit; + } + + ret = BIO_get_mem_ptr(cert_bios[i], &(cert_buffs[i])); + if (ret != 1) { + cert_buffs[i] = NULL; + log_error(LOG_LEVEL_ERROR, "ssl_send_certificate_error: can't get client certificate data"); + } + else { + message_len += 4 * ((cert_buffs[i]->length + 2) / 3) + 1; + message_len += strlen("
") + strlen("Download certificate

"); + } + + certs_info[i] = generate_cert_info(certs[i]); + message_len += strlen(certs_info[i]); + } /* * Joining all blocks in one long message */ - char message[message_len]; - memset(message, 0, message_len); - + message = (char*)calloc(message_len, 1); strlcpy(message, message_begin, message_len); + strlcat(message, reason, message_len); + strlcat(message, "

", message_len); + + for (int i = 0; i < certs_count; i++) { + char* base64_buf = NULL; + strlcat(message, "
", message_len);
+      strlcat(message, certs_info[i], message_len);
+      strlcat(message, "
", message_len); + + if (cert_buffs[i] != NULL) { + size_t cert_len = 4 * ((cert_buffs[i]->length + 2) / 3) + 1; + base64_buf = (char*)calloc(cert_len, 1); + EVP_EncodeBlock((unsigned char*)base64_buf, + (const unsigned char*)cert_buffs[i]->data, cert_buffs[i]->length); + + strlcat(message, "Download certificate

", message_len); + } + + freez(base64_buf); + } strlcat(message, message_end, message_len); /* @@ -1300,6 +1353,20 @@ extern void ssl_send_certificate_error(struct client_state *csp) * message if there isn't this delay. */ sleep(1); + +exit: + sk_X509_pop_free(csp->server_certs_chain.chain, X509_free); + + for (int i = 0; i < certs_count; i++) { + freez(certs_info[i]); + BIO_free_all(cert_bios[i]); + } + + freez(cert_buffs); + freez(cert_bios); + freez(certs); + freez(certs_info); + freez(message); } -- 2.26.2 From 16c8209924d2f67d7809af2b2cded4606af0c128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:39:20 +0200 Subject: [PATCH 49/83] Added allocation result check into generate_cert_info and ssl_send_certificate_error functions. --- ssl_libressl.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index f859abe0..b0f8621f 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -1286,6 +1286,10 @@ extern void ssl_send_certificate_error(struct client_state *csp) BIO** cert_bios = (BIO**)calloc(certs_count, sizeof(BIO*)); X509** certs = (X509**)calloc(certs_count, sizeof(X509*)); char** certs_info = (char**)calloc(certs_count, sizeof(char*)); + if (cert_buffs == NULL || cert_bios == NULL || certs == NULL || certs_info == NULL) { + log_error(LOG_LEVEL_ERROR, "ssl_send_certificate_error: calloc failed"); + goto exit; + } for (int i = 0; i < certs_count; i++) { @@ -1310,6 +1314,10 @@ extern void ssl_send_certificate_error(struct client_state *csp) } certs_info[i] = generate_cert_info(certs[i]); + if (certs_info[i] == NULL) { + log_error(LOG_LEVEL_ERROR, "ssl_send_certificate_error: generate_cert_info failed"); + goto exit; + } message_len += strlen(certs_info[i]); } @@ -1317,6 +1325,10 @@ extern void ssl_send_certificate_error(struct client_state *csp) * Joining all blocks in one long message */ message = (char*)calloc(message_len, 1); + if (message == NULL) { + log_error(LOG_LEVEL_ERROR, "ssl_send_certificate_error: calloc failed"); + goto exit; + } strlcpy(message, message_begin, message_len); strlcat(message, reason, message_len); strlcat(message, "

", message_len); @@ -1330,6 +1342,10 @@ extern void ssl_send_certificate_error(struct client_state *csp) if (cert_buffs[i] != NULL) { size_t cert_len = 4 * ((cert_buffs[i]->length + 2) / 3) + 1; base64_buf = (char*)calloc(cert_len, 1); + if (base64_buf == NULL) { + log_error(LOG_LEVEL_ERROR, "ssl_send_certificate_error: calloc failed"); + goto exit; + } EVP_EncodeBlock((unsigned char*)base64_buf, (const unsigned char*)cert_buffs[i]->data, cert_buffs[i]->length); @@ -1357,9 +1373,11 @@ extern void ssl_send_certificate_error(struct client_state *csp) exit: sk_X509_pop_free(csp->server_certs_chain.chain, X509_free); - for (int i = 0; i < certs_count; i++) { - freez(certs_info[i]); - BIO_free_all(cert_bios[i]); + if (certs_info != NULL) { + for (int i = 0; i < certs_count; i++) { + freez(certs_info[i]); + BIO_free_all(cert_bios[i]); + } } freez(cert_buffs); @@ -1395,6 +1413,8 @@ static char* generate_cert_info(X509* cert) { int key_size = -1; char key_size_buf[INVALID_CERT_INFO_KEY_SIZE + 1]; size_t subject_alt_names_len = 0; + BIO* not_after_bio = NULL; + BIO* not_before_bio = NULL; char* subject_info = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); char* issuer_info = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); @@ -1430,6 +1450,10 @@ static char* generate_cert_info(X509* cert) { if (san_names != NULL) { int san_names_nb = sk_GENERAL_NAME_num(san_names); subject_alt_names = (char**)calloc(san_names_nb, sizeof(char*)); + if (subject_alt_names == NULL) { + log_error(LOG_LEVEL_ERROR, "generate_cert_info: calloc failed"); + goto exit; + } for (int i = 0; i < san_names_nb; i++) { const GENERAL_NAME* current_name = sk_GENERAL_NAME_value(san_names, i); @@ -1463,7 +1487,11 @@ static char* generate_cert_info(X509* cert) { /* * Getting expiration dates */ - BIO* not_before_bio = BIO_new(BIO_s_mem()); + not_before_bio = BIO_new(BIO_s_mem()); + if (not_before_bio == NULL) { + log_error(LOG_LEVEL_ERROR, "generate_cert_info: BIO_new failed"); + goto exit; + } rc = ASN1_TIME_print(not_before_bio, not_before); if (rc == 1) { ret = BIO_get_mem_ptr(not_before_bio, ¬_before_buf); @@ -1473,7 +1501,11 @@ static char* generate_cert_info(X509* cert) { log_error(LOG_LEVEL_INFO, "generate_cert_info: getting certificate sign date failed"); } - BIO* not_after_bio = BIO_new(BIO_s_mem()); + not_after_bio = BIO_new(BIO_s_mem()); + if (not_after_bio == NULL) { + log_error(LOG_LEVEL_ERROR, "generate_cert_info: BIO_new failed"); + goto exit; + } rc = ASN1_TIME_print(not_after_bio, not_after); if (rc == 1) { ret = BIO_get_mem_ptr(not_after_bio, ¬_after_buf); @@ -1524,6 +1556,10 @@ static char* generate_cert_info(X509* cert) { + strlen("\nsubject alt name : ") + 1; message = (char*)calloc(message_len, 1); + if (message == NULL) { + log_error(LOG_LEVEL_ERROR, "generate_cert_info: calloc failed"); + goto exit; + } strlcpy(message, "cert. version : ", message_len); strlcat(message, version_buf, message_len); strlcat(message, "\nserial number : ", message_len); @@ -1564,6 +1600,7 @@ static char* generate_cert_info(X509* cert) { } } +exit: /* * Freeing used structures */ -- 2.26.2 From 782e2989f1b0edb6f58acb94aa0ec63719fe5b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:46:44 +0200 Subject: [PATCH 50/83] Added possibility to disable server certificate verification. --- ssl_libressl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index b0f8621f..77136a37 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -118,7 +118,15 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Setting how strict should certificate verification be and callback function. */ - SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_PEER, NULL); + if (csp->dont_verify_certificate) + { + SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_NONE, NULL); + csp->server_cert_verification_result = X509_V_OK; + } + else + { + SSL_CTX_set_verify(csp->ssl_server_attr.ctx, SSL_VERIFY_PEER, NULL); + } SSL_CTX_set_cert_verify_callback(csp->ssl_server_attr.ctx, ssl_cert_verify_callback, &(csp->server_certs_chain.chain)); ret = SSL_CTX_load_verify_locations(csp->ssl_server_attr.ctx, csp->config->trusted_cas_file, NULL); @@ -167,7 +175,10 @@ extern int create_server_ssl_connection(struct client_state *csp) * Handshake with server */ ret = SSL_connect(csp->ssl_server_attr.ssl); - csp->server_cert_verification_result = SSL_get_verify_result(csp->ssl_server_attr.ssl); + if (!csp->dont_verify_certificate) + { + csp->server_cert_verification_result = SSL_get_verify_result(csp->ssl_server_attr.ssl); + } if (ret <= 0) { log_error(LOG_LEVEL_ERROR, "Server connection: SSL_connect failed"); ret = -1; -- 2.26.2 From e06dd5a90778bb9bc57ebd0aabbdd8a9acdb9dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:49:31 +0200 Subject: [PATCH 51/83] Processing of client requests was excluded from chat function to new function process_http_header. --- jcc.c | 107 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 40 deletions(-) diff --git a/jcc.c b/jcc.c index c3777028..f26ac57a 100644 --- a/jcc.c +++ b/jcc.c @@ -3064,56 +3064,43 @@ static void handle_established_connection(struct client_state *csp) /********************************************************************* * - * Function : chat - * - * Description : Once a connection from the client has been accepted, - * this function is called (via serve()) to handle the - * main business of the communication. This function - * returns after dealing with a single request. It can - * be called multiple times with the same client socket - * if the client is keeping the connection alive. + * Function : process_http_header * - * The decision whether or not a client connection will - * be kept alive is up to the caller which also must - * close the client socket when done. - * - * FIXME: chat is nearly thousand lines long. - * Ridiculous. + * Description : This function can be called to receive client's + * request including header, parse it and set some + * variables according to loaded data. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * - * Returns : Nothing. + * Returns : 0 on success, 1 on fail * *********************************************************************/ -static void chat(struct client_state *csp) -{ +static int process_http_header(struct client_state *csp) { const struct forward_spec *fwd; struct http_request *http; - /* Skeleton for HTTP response, if we should intercept the request */ - struct http_response *rsp; - int ret = 0; http = csp->http; - csp->use_ssl_tunnel = 0; - csp->dont_verify_certificate = 0; + http->client_ssl = 0; + http->server_ssl = 0; if (receive_client_request(csp) != JB_ERR_OK) { - return; + return 1; } + if (parse_client_request(csp) != JB_ERR_OK) { - return; + return 1; } - /* decide how to route the HTTP request */ + ///* decide how to route the HTTP request */ fwd = forward_url(csp, http); if (NULL == fwd) { log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!"); /* Never get here - LOG_LEVEL_FATAL causes program exit */ - return; + return 1; } csp->use_fwd = fwd; @@ -3131,6 +3118,60 @@ static void chat(struct client_state *csp) csp->dont_verify_certificate = 1; } + /* + * Presetting SSL client and server flags + */ + if (http->ssl && !csp->use_ssl_tunnel) + { + http->client_ssl = 1; + http->server_ssl = 1; + } + + return 0; +} + + +/********************************************************************* + * + * Function : chat + * + * Description : Once a connection from the client has been accepted, + * this function is called (via serve()) to handle the + * main business of the communication. This function + * returns after dealing with a single request. It can + * be called multiple times with the same client socket + * if the client is keeping the connection alive. + * + * The decision whether or not a client connection will + * be kept alive is up to the caller which also must + * close the client socket when done. + * + * FIXME: chat is nearly thousand lines long. + * Ridiculous. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Nothing. + * + *********************************************************************/ +static void chat(struct client_state *csp) +{ + const struct forward_spec *fwd; + struct http_request *http; + /* Skeleton for HTTP response, if we should intercept the request */ + struct http_response *rsp; + int ret = 0; + + http = csp->http; + csp->dont_verify_certificate = 0; + + ret = process_http_header(csp); + if (ret != 0) { + return; + } + fwd = csp->use_fwd; + /* * build the http request to send to the server * we have to do one of the following: @@ -3171,20 +3212,6 @@ static void chat(struct client_state *csp) * +--------+--------+ * */ - - /* - * Presetting SSL client and server flags - */ - if (http->ssl && !csp->use_ssl_tunnel) - { - http->client_ssl = 1; - http->server_ssl = 1; - } - else - { - http->client_ssl = 0; - http->server_ssl = 0; - } if (http->ssl && connect_port_is_forbidden(csp)) { -- 2.26.2 From 251ef8e4169d34caaaa6ce4c08159400c0c3eca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:50:09 +0200 Subject: [PATCH 52/83] Created functions to send or receive data over tcp or ssl connection according to given parameters. These functions can be used regardless of connection type (tcp/ssl). --- jbsockets.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++ jbsockets.h | 11 +++ ssl.c | 52 +++++++++++ ssl.h | 1 + ssl_libressl.c | 52 +++++++++++ ssl_libressl.h | 1 + 6 files changed, 355 insertions(+) diff --git a/jbsockets.c b/jbsockets.c index 625d830e..a64a23d5 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -91,6 +91,13 @@ #endif /* def __GLIBC__ */ #endif /* HAVE_POLL */ +#ifdef FEATURE_LIBRESSL +#include "ssl_libressl.h" +#endif +#ifdef FEATURE_MBEDTLS +#include "ssl.h" +#endif + #include "project.h" /* For mutex semaphores only */ @@ -100,6 +107,7 @@ #include "filters.h" #include "errlog.h" #include "miscutil.h" +#include "parsers.h" /* Mac OSX doesn't define AI_NUMERICSESRV */ #ifndef AI_NUMERICSERV @@ -1714,3 +1722,233 @@ void mark_socket_for_close_on_execute(jb_socket fd) tab-width: 3 end: */ + + + +/*======================Sending and receiving data over tcp/ssl======================*/ + +/********************************************************************* + * + * Function : recv_data + * + * Description : Receives data from tcp or ssl connection and puts + * them into buffer. Source of data will be choosen + * according to given src variable and variables + * csp->http->[client|server]_ssl. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : src = Value from communication_side enum + * 3 : buf = Pointer to buffer where data will be written + * 4 : len = Maximum number of bytes to read + * + * Returns : Number of bytes read, 0 for EOF, or negative + * value on error. + * + *********************************************************************/ +extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int maxLen) { + if (src == CLIENT) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->client_ssl == 1) + { + return ssl_recv_data(&(csp->ssl_client_attr), buf, maxLen); + } + else +#endif + { + return read_socket(csp->cfd, (char*)buf, maxLen); + } + } + else if (src == SERVER) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->server_ssl == 1) + { + return ssl_recv_data(&(csp->ssl_server_attr), buf, maxLen); + } + else +#endif + { + return read_socket(csp->server_connection.sfd, (char*)buf, maxLen); + } + } + + return -1; +} + + +/********************************************************************* + * + * Function : send_data_delayed + * + * Description : Writes the contents of buf (for n bytes) to + * tcp or ssl connection, optionally delaying the + * operation. Destination of data will be choosen + * according to given dest variable and variables + * csp->http->[client|server]_ssl. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : dest = Value from communication_side enum + * 3 : buf = Pointer to buffer where data will be written + * 4 : len = Maximum number of bytes to read + * 5 : delay = Delay in milliseconds. + * + * Returns : 0 on success (entire buffer sent). + * nonzero on error. + * + *********************************************************************/ +extern int send_data_delayed(struct client_state *csp, int dest, const char *buf, int len, int delay) { + if (dest == CLIENT) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->client_ssl == 1) + { + return ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char*)buf, len, delay); + } + else +#endif + { + return write_socket_delayed(csp->cfd, buf, len, delay); + } + } + else if (dest == SERVER) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->server_ssl == 1) { + return ssl_send_data_delayed(&(csp->ssl_server_attr), (const unsigned char*)buf, len, delay); + } + else +#endif + { + return write_socket_delayed(csp->server_connection.sfd, buf, len, delay); + } + } + + return -1; +} + + +/********************************************************************* + * + * Function : send_data + * + * Description : Writes the contents of buf (for n bytes) to + * tcp or ssl connection. Destination of data will + * be choosen according to given dest variable and + * variables csp->http->[client|server]_ssl. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : dest = Value from communication_side enum + * 3 : buf = Pointer to buffer where data will be written + * 4 : len = Maximum number of bytes to read + * + * Returns : 0 on success (entire buffer sent). + * nonzero on error. + * + *********************************************************************/ +extern int send_data(struct client_state *csp, int dest, const char *buf, int len) { + return send_data_delayed(csp, dest, buf, len, 0); +} + + +/********************************************************************* + * + * Function : flush_socket + * + * Description : Sends any pending "buffered" content. Flushed source + * will be choosen according to given dest variable and + * variables csp->http->[client|server]_ssl. + * + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : dest = Value from communication_side enum + * 3 : iob = The I/O buffer to flush, usually csp->iob + * 4 : delay = Delay in milliseconds + * + * Returns : On success, the number of bytes send are returned (zero + * indicates nothing was sent). On error, -1 is returned. + * + *********************************************************************/ +extern int flush_socket(struct client_state *csp, int dest, struct iob *iob, unsigned int delay) { + if (dest == CLIENT) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->client_ssl == 1) + { + return ssl_flush_socket(&(csp->ssl_client_attr), iob); + } + else +#endif + { + return flush_iob(csp->cfd, iob, delay); + } + + } + else if (dest == SERVER) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->server_ssl == 1) { + return ssl_flush_socket(&(csp->ssl_server_attr), iob); + } + else +#endif + { + return flush_iob(csp->server_connection.sfd, iob, delay); + } + } + return -1; +} + + +/********************************************************************* + * + * Function : data_is_available_tcp_ssl + * + * Description : Checks whether some data are available from + * specified connection. Checked source will be choosen + * according to given dest variable and variables + * csp->http->[client|server]_ssl. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : src = Value from communication_side enum + * 3 : seconds_to_wait = number of seconds after which + * we give up. (only for tcp connection) + * + * Returns : Positive value if data arrived in time, + * 0 otherwise. + * + *********************************************************************/ +extern int data_is_available_tcp_ssl(struct client_state *csp, int src, int seconds_to_wait) { + if (src == CLIENT) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->client_ssl == 1) + { + return is_ssl_pending(&(csp->ssl_client_attr)); + } + else +#endif + { + return data_is_available(csp->cfd, seconds_to_wait); + } + } + else if (src == SERVER) + { +#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS + if (csp->http->server_ssl == 1) + { + return is_ssl_pending(&(csp->ssl_server_attr)); + } + else +#endif + { + return data_is_available(csp->server_connection.sfd, seconds_to_wait); + } + } + return 0; +} diff --git a/jbsockets.h b/jbsockets.h index 2a7756a1..c45d5d68 100644 --- a/jbsockets.h +++ b/jbsockets.h @@ -41,6 +41,11 @@ struct client_state; +enum communication_side { + CLIENT = 0, + SERVER = 1 +}; + extern jb_socket connect_to(const char *host, int portnum, struct client_state *csp); extern int write_socket(jb_socket fd, const char *buf, size_t n); extern int write_socket_delayed(jb_socket fd, const char *buf, size_t len, unsigned int delay); @@ -61,6 +66,12 @@ extern int socket_is_still_alive(jb_socket sfd); extern void mark_socket_for_close_on_execute(jb_socket fd); #endif +extern int send_data_delayed(struct client_state *csp, int destination, const char *buf, int len, int delay); +extern int recv_data(struct client_state *csp, int source, unsigned char *buf, int maxLen); +extern int send_data(struct client_state *csp, int destination, const char *buf, int len); +extern int flush_socket(struct client_state *csp, int destination, struct iob *iob, unsigned int delay); +extern int data_is_available_tcp_ssl(struct client_state *csp, int source, int seconds_to_wait); + /* * Solaris workaround * XXX: still necessary? diff --git a/ssl.c b/ssl.c index 8f510b25..bb9fcf1b 100644 --- a/ssl.c +++ b/ssl.c @@ -220,6 +220,58 @@ extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * } +/********************************************************************* + * + * Function : ssl_send_data_delayed + * + * Description : Sends the contents of buf (for n bytes) to given SSL + * connection, optionally delaying the operation. + * + * Parameters : + * 1 : ssl = 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 + * 4 : delay = Delay in milliseconds. + * + * Returns : 0 on success (entire buffer sent). + * nonzero on error. + * + *********************************************************************/ +extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay) { + size_t i = 0; + + if (delay == 0) + { + return ssl_send_data(connection, buf, len); + } + + while (i < len) + { + size_t write_length; + enum { MAX_WRITE_LENGTH = 10 }; + + if ((i + MAX_WRITE_LENGTH) > len) + { + write_length = len - i; + } + else + { + write_length = MAX_WRITE_LENGTH; + } + + privoxy_millisleep(delay); + + if (ssl_send_data(connection, buf + i, write_length) < 0) + { + return -1; + } + i += write_length; + } + + return i; +} + + /********************************************************************* * * Function : ssl_recv_data diff --git a/ssl.h b/ssl.h index 33d4d8f3..1638fa54 100644 --- a/ssl.h +++ b/ssl.h @@ -55,6 +55,7 @@ extern int tunnel_established_successfully(const char * response, unsigned int r /* Functions for sending and receiving data over SSL/TLS connections */ extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * buf, int len); +extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay); extern int ssl_recv_data(ssl_connection_attr * connection, unsigned char * buf, int maxLen); extern long ssl_flush_socket(ssl_connection_attr * connection, struct iob *iob); extern void ssl_send_certificate_error(struct client_state *csp); diff --git a/ssl_libressl.c b/ssl_libressl.c index 77136a37..8320533c 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -546,6 +546,58 @@ exit: } +/********************************************************************* + * + * Function : ssl_send_data_delayed + * + * Description : Sends the contents of buf (for n bytes) to given SSL + * connection, optionally delaying the operation. + * + * Parameters : + * 1 : ssl = 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 + * 4 : delay = Delay in milliseconds. + * + * Returns : 0 on success (entire buffer sent). + * nonzero on error. + * + *********************************************************************/ +extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay) { + size_t i = 0; + + if (delay == 0) + { + return ssl_send_data(connection, buf, len); + } + + while (i < len) + { + size_t write_length; + enum { MAX_WRITE_LENGTH = 10 }; + + if ((i + MAX_WRITE_LENGTH) > len) + { + write_length = len - i; + } + else + { + write_length = MAX_WRITE_LENGTH; + } + + privoxy_millisleep(delay); + + if (ssl_send_data(connection, buf + i, write_length) < 0) + { + return -1; + } + i += write_length; + } + + return i; +} + + /********************************************************************* * * Function : ssl_recv_data diff --git a/ssl_libressl.h b/ssl_libressl.h index c792c642..a8660a1d 100644 --- a/ssl_libressl.h +++ b/ssl_libressl.h @@ -42,6 +42,7 @@ extern int tunnel_established_successfully(const char * response, unsigned int r /* Functions for sending and receiving data over SSL/TLS connections */ extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len); +extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay); extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen); extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob); extern void ssl_send_certificate_error(struct client_state *csp); -- 2.26.2 From 073a90d1723f99338a45af135dbdfa1236e7999f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:53:31 +0200 Subject: [PATCH 53/83] Edited functions which are receiving client requests, to be able read data from tcp or ssl connection. --- jcc.c | 35 +++++++++++++++++++++-------------- parsers.c | 2 -- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/jcc.c b/jcc.c index f26ac57a..b914d4b9 100644 --- a/jcc.c +++ b/jcc.c @@ -575,7 +575,7 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, csp->http->cmd); - write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER), + send_data_delayed(csp, CLIENT, CHEADER, strlen(CHEADER), get_write_delay(csp)); destroy_list(headers); @@ -604,7 +604,7 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct csp->ip_addr_str, csp->http->cmd, req); freez(req); - write_socket_delayed(csp->cfd, MISSING_DESTINATION_RESPONSE, + send_data_delayed(csp, CLIENT, MISSING_DESTINATION_RESPONSE, strlen(MISSING_DESTINATION_RESPONSE), get_write_delay(csp)); destroy_list(headers); @@ -1342,15 +1342,15 @@ static char *get_request_line(struct client_state *csp) #ifdef FUZZ 0 == (csp->flags & CSP_FLAG_FUZZED_INPUT) && #endif - !data_is_available(csp->cfd, csp->config->socket_timeout) - ) + !data_is_available_tcp_ssl(csp, CLIENT, csp->config->socket_timeout) + ) { if (socket_is_still_alive(csp->cfd)) { log_error(LOG_LEVEL_CONNECT, "No request line on socket %d received in time. Timeout: %d.", csp->cfd, csp->config->socket_timeout); - write_socket_delayed(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE, + send_data_delayed(csp, CLIENT, CLIENT_CONNECTION_TIMEOUT_RESPONSE, strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE), get_write_delay(csp)); } @@ -1363,8 +1363,7 @@ static char *get_request_line(struct client_state *csp) return NULL; } - len = read_socket(csp->cfd, buf, sizeof(buf) - 1); - + len = recv_data(csp, CLIENT, (unsigned char*)buf, sizeof(buf) - 1); if (len <= 0) return NULL; /* @@ -1723,8 +1722,9 @@ static jb_err receive_client_request(struct client_state *csp) freez(req); if (JB_ERR_OK != err) { - write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER), + send_data_delayed(csp, CLIENT, CHEADER, strlen(CHEADER), get_write_delay(csp)); + /* XXX: Use correct size */ log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str); log_error(LOG_LEVEL_ERROR, @@ -1753,7 +1753,7 @@ static jb_err receive_client_request(struct client_state *csp) * We didn't receive a complete header * line yet, get the rest of it. */ - if (!data_is_available(csp->cfd, csp->config->socket_timeout)) + if (!data_is_available_tcp_ssl(csp, CLIENT, csp->config->socket_timeout)) { log_error(LOG_LEVEL_ERROR, "Stopped grabbing the client headers."); @@ -1761,7 +1761,7 @@ static jb_err receive_client_request(struct client_state *csp) return JB_ERR_PARSE; } - len = read_socket(csp->cfd, buf, sizeof(buf) - 1); + len = recv_data(csp, CLIENT, (unsigned char*)buf, sizeof(buf) - 1); if (len <= 0) { log_error(LOG_LEVEL_ERROR, "read from client failed: %E"); @@ -1979,7 +1979,7 @@ static int send_http_request(struct client_state *csp) * Write the client's (modified) header to the server * (along with anything else that may be in the buffer) */ - write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr)); + write_failure = 0 != send_data(csp, SERVER, (const char*)hdr, strlen(hdr)); freez(hdr); if (write_failure) @@ -1988,7 +1988,7 @@ static int send_http_request(struct client_state *csp) csp->http->hostport); } else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0) - && (flush_iob(csp->server_connection.sfd, csp->client_iob, 0) < 0)) + && (flush_socket(csp, SERVER, csp->client_iob, 0) < 0)) { write_failure = 1; log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E", @@ -3070,6 +3070,10 @@ static void handle_established_connection(struct client_state *csp) * request including header, parse it and set some * variables according to loaded data. * + * Request can be received over tcp or ssl connection. + * Source will depend on the variable + * csp->http->client_ssl. + * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * @@ -3094,7 +3098,7 @@ static int process_http_header(struct client_state *csp) { return 1; } - ///* decide how to route the HTTP request */ + /* decide how to route the HTTP request */ fwd = forward_url(csp, http); if (NULL == fwd) { @@ -3226,8 +3230,11 @@ static void chat(struct client_state *csp) http->client_ssl = 0; http->server_ssl = 0; } - freez(csp->headers->first->str); + + /* + * Creating first line of request, from connect creates connect, from get creates get. + */ build_request_line(csp, fwd, &csp->headers->first->str); /* diff --git a/parsers.c b/parsers.c index 699ae7c5..f56345fe 100644 --- a/parsers.c +++ b/parsers.c @@ -4429,8 +4429,6 @@ jb_err get_destination_from_headers(const struct list *headers, struct http_requ char *p; char *host; - assert(!http->ssl); - host = get_header_value(headers, "Host:"); if (NULL == host) -- 2.26.2 From d38d05e2d144caa752f1a908045bb5a642733059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:54:14 +0200 Subject: [PATCH 54/83] Edited functions for sending and checking available data over tcp or ssl. Edited function send_data_delayed - Changed parameter client_state* to const. Changed return value to 0 on success and nonzero on error in all cases. Edited function data_is_available_tcp_ssl - Changed parameter client_state* to const. Edited to check SSL buffer first and when there are no pending data, tcp socket is checked. Parameter client_state* of functions: client send_data, flush_data and send_data also change to const, including ssl functions for data sending and receiving. --- jbsockets.c | 29 ++++++++++++++++------------- jbsockets.h | 10 +++++----- ssl_libressl.c | 13 ++++++------- ssl_libressl.h | 10 +++++----- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/jbsockets.c b/jbsockets.c index a64a23d5..2011a91c 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1746,7 +1746,7 @@ void mark_socket_for_close_on_execute(jb_socket fd) * value on error. * *********************************************************************/ -extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int maxLen) { +extern int recv_data(const struct client_state *csp, int src, unsigned char *buf, int maxLen) { if (src == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS @@ -1799,13 +1799,13 @@ extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int * nonzero on error. * *********************************************************************/ -extern int send_data_delayed(struct client_state *csp, int dest, const char *buf, int len, int delay) { +extern int send_data_delayed(const struct client_state *csp, int dest, const char *buf, int len, int delay) { if (dest == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS if (csp->http->client_ssl == 1) { - return ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char*)buf, len, delay); + return 0 > ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char*)buf, len, delay); } else #endif @@ -1817,7 +1817,7 @@ extern int send_data_delayed(struct client_state *csp, int dest, const char *buf { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS if (csp->http->server_ssl == 1) { - return ssl_send_data_delayed(&(csp->ssl_server_attr), (const unsigned char*)buf, len, delay); + return 0 > ssl_send_data_delayed(&(csp->ssl_server_attr), (const unsigned char*)buf, len, delay); } else #endif @@ -1849,7 +1849,7 @@ extern int send_data_delayed(struct client_state *csp, int dest, const char *buf * nonzero on error. * *********************************************************************/ -extern int send_data(struct client_state *csp, int dest, const char *buf, int len) { +extern int send_data(const struct client_state *csp, int dest, const char *buf, int len) { return send_data_delayed(csp, dest, buf, len, 0); } @@ -1873,7 +1873,7 @@ extern int send_data(struct client_state *csp, int dest, const char *buf, int le * indicates nothing was sent). On error, -1 is returned. * *********************************************************************/ -extern int flush_socket(struct client_state *csp, int dest, struct iob *iob, unsigned int delay) { +extern int flush_socket(const struct client_state *csp, int dest, struct iob *iob, unsigned int delay) { if (dest == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS @@ -1923,32 +1923,35 @@ extern int flush_socket(struct client_state *csp, int dest, struct iob *iob, uns * 0 otherwise. * *********************************************************************/ -extern int data_is_available_tcp_ssl(struct client_state *csp, int src, int seconds_to_wait) { +extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, int seconds_to_wait) { + int ret = 0; if (src == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS if (csp->http->client_ssl == 1) { - return is_ssl_pending(&(csp->ssl_client_attr)); + ret = is_ssl_pending(&(csp->ssl_client_attr)); } - else + if (ret == 0) #endif { - return data_is_available(csp->cfd, seconds_to_wait); + ret = data_is_available(csp->cfd, seconds_to_wait); } + return ret; } else if (src == SERVER) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS if (csp->http->server_ssl == 1) { - return is_ssl_pending(&(csp->ssl_server_attr)); + ret = is_ssl_pending(&(csp->ssl_server_attr)); } - else + if (ret == 0) #endif { - return data_is_available(csp->server_connection.sfd, seconds_to_wait); + ret = data_is_available(csp->server_connection.sfd, seconds_to_wait); } + return ret; } return 0; } diff --git a/jbsockets.h b/jbsockets.h index c45d5d68..6fdbc429 100644 --- a/jbsockets.h +++ b/jbsockets.h @@ -66,11 +66,11 @@ extern int socket_is_still_alive(jb_socket sfd); extern void mark_socket_for_close_on_execute(jb_socket fd); #endif -extern int send_data_delayed(struct client_state *csp, int destination, const char *buf, int len, int delay); -extern int recv_data(struct client_state *csp, int source, unsigned char *buf, int maxLen); -extern int send_data(struct client_state *csp, int destination, const char *buf, int len); -extern int flush_socket(struct client_state *csp, int destination, struct iob *iob, unsigned int delay); -extern int data_is_available_tcp_ssl(struct client_state *csp, int source, int seconds_to_wait); +extern int send_data_delayed(const struct client_state *csp, int destination, const char *buf, int len, int delay); +extern int recv_data(const struct client_state *csp, int source, unsigned char *buf, int maxLen); +extern int send_data(const struct client_state *csp, int destination, const char *buf, int len); +extern int flush_socket(const struct client_state *csp, int destination, struct iob *iob, unsigned int delay); +extern int data_is_available_tcp_ssl(const struct client_state *csp, int source, int seconds_to_wait); /* * Solaris workaround diff --git a/ssl_libressl.c b/ssl_libressl.c index 8320533c..185ac2e8 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -530,7 +530,7 @@ extern int server_use_ssl(struct client_state *csp) * Returns : Length of sent data or negative value on error. * *********************************************************************/ -extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len) { +extern int ssl_send_data(const ssl_connection_attr *connection, const unsigned char * buf, int len) { int ret = 0; ret = BIO_write(connection->ssl_bio, buf, len); @@ -559,11 +559,10 @@ exit: * 3 : len = Length of data to be sent to the SSL context * 4 : delay = Delay in milliseconds. * - * Returns : 0 on success (entire buffer sent). - * nonzero on error. + * Returns : Length of sent data or negative value on error. * *********************************************************************/ -extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay) { +extern int ssl_send_data_delayed(const ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay) { size_t i = 0; if (delay == 0) @@ -614,7 +613,7 @@ extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned * value on error. * *********************************************************************/ -extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen) { +extern int ssl_recv_data(const ssl_connection_attr *connection, unsigned char * buf, int maxLen) { int ret = 0; ret = BIO_read(connection->ssl_bio, buf, maxLen); @@ -644,7 +643,7 @@ exit: * >0 => Pending data length * *********************************************************************/ -extern size_t is_ssl_pending(ssl_connection_attr *connection) { +extern size_t is_ssl_pending(const ssl_connection_attr *connection) { return BIO_pending(connection->ssl_bio); } @@ -723,7 +722,7 @@ extern int tunnel_established_successfully(const char * server_response, unsigne * indicates nothing was sent). On error, -1 is returned. * *********************************************************************/ -extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob) { +extern long ssl_flush_socket(const ssl_connection_attr *connection, struct iob *iob) { /* Computing length of buffer part to send*/ long len = iob->eod - iob->cur; diff --git a/ssl_libressl.h b/ssl_libressl.h index a8660a1d..ada709a1 100644 --- a/ssl_libressl.h +++ b/ssl_libressl.h @@ -37,14 +37,14 @@ /* Boolean functions to get informations about SSL/TLS connections */ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); -extern size_t is_ssl_pending(ssl_connection_attr *connection); +extern size_t is_ssl_pending(const ssl_connection_attr *connection); extern int tunnel_established_successfully(const char * response, unsigned int response_len); /* Functions for sending and receiving data over SSL/TLS connections */ -extern int ssl_send_data(ssl_connection_attr *connection, const unsigned char * buf, int len); -extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay); -extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, int maxLen); -extern long ssl_flush_socket(ssl_connection_attr *connection, struct iob *iob); +extern int ssl_send_data(const ssl_connection_attr *connection, const unsigned char * buf, int len); +extern int ssl_send_data_delayed(const ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay); +extern int ssl_recv_data(const ssl_connection_attr *connection, unsigned char * buf, int maxLen); +extern long ssl_flush_socket(const ssl_connection_attr *connection, struct iob *iob); extern void ssl_send_certificate_error(struct client_state *csp); /* Functions for opening and closing SSL/TLS connections */ -- 2.26.2 From 829ce9f9d717a8c756f920395eaefd9e1e1331ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:55:12 +0200 Subject: [PATCH 55/83] Added receiving and processing of client request over ssl and then sending it to server over ssl. Also changed sending of error messages over ssl when it's used in functions: client_has_unsupported_expectations, send_crunch_response and parse_client_request. Renamed funciton process_http_header to process_client_request. --- jcc.c | 65 +++++++++++++++++++++++++++++++++++++++++------------- urlmatch.c | 22 +++++++++++++----- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/jcc.c b/jcc.c index b914d4b9..14d48a0f 100644 --- a/jcc.c +++ b/jcc.c @@ -522,7 +522,7 @@ static int client_has_unsupported_expectations(const struct client_state *csp) csp->ip_addr_str); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 417 0", csp->ip_addr_str, csp->http->cmd); - write_socket_delayed(csp->cfd, + send_data_delayed(csp, CLIENT, UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE, strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE), get_write_delay(csp)); @@ -850,8 +850,8 @@ static void send_crunch_response(const struct client_state *csp, struct http_res csp->ip_addr_str, http->ocmd, status_code, rsp->content_length); /* Write the answer to the client */ - if (write_socket_delayed(csp->cfd, rsp->head, rsp->head_length, get_write_delay(csp)) - || write_socket_delayed(csp->cfd, rsp->body, rsp->content_length, get_write_delay(csp))) + if (send_data_delayed(csp, CLIENT, rsp->head, rsp->head_length, get_write_delay(csp)) + || send_data_delayed(csp, CLIENT, rsp->body, rsp->content_length, get_write_delay(csp))) { /* There is nothing we can do about it. */ log_error(LOG_LEVEL_CONNECT, @@ -1914,7 +1914,7 @@ static jb_err parse_client_request(struct client_state *csp) csp->ip_addr_str); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, csp->http->cmd); - write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER), get_write_delay(csp)); + send_data_delayed(csp, CLIENT, CHEADER, strlen(CHEADER), get_write_delay(csp)); return JB_ERR_PARSE; } csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; @@ -1927,7 +1927,7 @@ static jb_err parse_client_request(struct client_state *csp) /* * A header filter broke the request line - bail out. */ - write_socket_delayed(csp->cfd, MESSED_UP_REQUEST_RESPONSE, + send_data_delayed(csp, CLIENT, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE), get_write_delay(csp)); /* XXX: Use correct size */ log_error(LOG_LEVEL_CLF, @@ -3064,7 +3064,7 @@ static void handle_established_connection(struct client_state *csp) /********************************************************************* * - * Function : process_http_header + * Function : process_client_request * * Description : This function can be called to receive client's * request including header, parse it and set some @@ -3080,33 +3080,34 @@ static void handle_established_connection(struct client_state *csp) * Returns : 0 on success, 1 on fail * *********************************************************************/ -static int process_http_header(struct client_state *csp) { - const struct forward_spec *fwd; +static int process_client_request(struct client_state *csp) { struct http_request *http; http = csp->http; - http->client_ssl = 0; - http->server_ssl = 0; + csp->requests_received_total = 0; if (receive_client_request(csp) != JB_ERR_OK) { + log_error(LOG_LEVEL_ERROR, "Receiving client request failed"); return 1; } if (parse_client_request(csp) != JB_ERR_OK) { + log_error(LOG_LEVEL_ERROR, "Parsing client request failed"); return 1; } - /* decide how to route the HTTP request */ - fwd = forward_url(csp, http); - if (NULL == fwd) + /* + * Decide how to route the HTTP request + */ + csp->use_fwd = forward_url(csp, http); + if (csp->use_fwd == NULL) { log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!"); /* Never get here - LOG_LEVEL_FATAL causes program exit */ return 1; } - csp->use_fwd = fwd; /* * Setting flags to use old solution with SSL tunel and to disable @@ -3168,9 +3169,11 @@ static void chat(struct client_state *csp) int ret = 0; http = csp->http; + http->client_ssl = 0; + http->server_ssl = 0; csp->dont_verify_certificate = 0; - ret = process_http_header(csp); + ret = process_client_request(csp); if (ret != 0) { return; } @@ -3585,6 +3588,38 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); + /* + * We have created SSL connection with client and server, so now we can receive + * client request header over ssl, filter it and send it to the server. + */ + if (csp->http->ssl && !csp->use_ssl_tunnel) + { + if (process_client_request(csp)) + { + close_client_and_server_ssl_connections(csp); + return; + } + + /* + * Creating first line of request, from connect creates connect, from get creates get. + */ + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); + + log_applied_actions(csp->action); + + if (send_http_request(csp)) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + close_client_and_server_ssl_connections(csp); + return; + } + } + /* XXX: should the time start earlier for optimistically sent data? */ csp->server_connection.request_sent = time(NULL); diff --git a/urlmatch.c b/urlmatch.c index dcef8787..0a6b7478 100644 --- a/urlmatch.c +++ b/urlmatch.c @@ -275,8 +275,13 @@ jb_err parse_http_url(const char *url, struct http_request *http, int require_pr * Short request line without protocol and host. * Most likely because the client's request * was intercepted and redirected into Privoxy. + * + * When we are receiving http request over ssl, there is + * no host, but we should have it from CONNECT request. */ - http->host = NULL; + if (http->client_ssl == 0) { + http->host = NULL; + } host_available = 0; } else if (require_protocol) @@ -296,7 +301,7 @@ jb_err parse_http_url(const char *url, struct http_request *http, int require_pr * https URL in and it's parsed by the function. (When the * URL is actually retrieved, SSL hides the path part). */ - http->path = strdup_or_die(http->ssl ? "/" : url_path); + http->path = strdup_or_die(url_path); *url_path = '\0'; http->hostport = strdup_or_die(url_noproto); } @@ -540,8 +545,13 @@ jb_err parse_http_request(const char *req, struct http_request *http) int n; jb_err err; - memset(http, '\0', sizeof(*http)); - + /* + * We are not reading client's request over ssl, so we didn't + * receive any information before over tcp and we can clean struct. + */ + if (http->client_ssl == 0) { + memset(http, '\0', sizeof(*http)); + } buf = strdup_or_die(req); n = ssplit(buf, " \r\n", v, SZ(v)); @@ -573,7 +583,9 @@ jb_err parse_http_request(const char *req, struct http_request *http) return JB_ERR_PARSE; } - http->ssl = !strcmpic(v[0], "CONNECT"); + if (http->ssl != 1) { + http->ssl = !strcmpic(v[0], "CONNECT"); + } err = parse_http_url(v[1], http, !http->ssl); if (err) -- 2.26.2 From 0dcf1b9b710393b2e738d9a5139bff35c83fb66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:56:30 +0200 Subject: [PATCH 56/83] Connection creating with requested server was excluded from chat() function. --- jcc.c | 506 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 272 insertions(+), 234 deletions(-) diff --git a/jcc.c b/jcc.c index 14d48a0f..ab2007c9 100644 --- a/jcc.c +++ b/jcc.c @@ -173,6 +173,11 @@ static void bind_ports_helper(struct configuration_spec *config, jb_socket socke static void close_ports_helper(jb_socket sockets[]); static void listen_loop(void); static void serve(struct client_state *csp); +void save_connection_destination(jb_socket sfd, + const struct http_request *http, + const struct forward_spec *fwd, + struct reusable_connection *server_connection); +static void mark_server_socket_tainted(struct client_state *csp); #ifdef __BEOS__ static int32 server_thread(void *data); @@ -706,6 +711,267 @@ static jb_err get_server_headers(struct client_state *csp) } + /********************************************************************** + * + * Function : create_server_connection + * + * Description : Creates connection with requested server, gateway, + * or the forwarder. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on success, other values if connection wasn't created + * successfully. + * + **********************************************************************/ +static int create_server_connection(struct client_state *csp) { + int ret = 0; + struct http_request *http; + const struct forward_spec *fwd; + struct http_response *rsp; + http = csp->http; + fwd = csp->use_fwd; + + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if ((csp->server_connection.sfd != JB_INVALID_SOCKET) + && socket_is_still_alive(csp->server_connection.sfd) + && connection_destination_matches(&csp->server_connection, http, fwd)) + { + log_error(LOG_LEVEL_CONNECT, + "Reusing server socket %d connected to %s. Total requests: %u.", + csp->server_connection.sfd, csp->server_connection.host, + csp->server_connection.requests_sent_total); + } + else + { + if (csp->server_connection.sfd != JB_INVALID_SOCKET) + { +#ifdef FEATURE_CONNECTION_SHARING + if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) + { + remember_connection(&csp->server_connection); + } + else +#endif /* def FEATURE_CONNECTION_SHARING */ + { + log_error(LOG_LEVEL_CONNECT, + "Closing server socket %d connected to %s. Total requests: %u.", + csp->server_connection.sfd, csp->server_connection.host, + csp->server_connection.requests_sent_total); + close_socket(csp->server_connection.sfd); + } + mark_connection_closed(&csp->server_connection); + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + + /* + * Connecting to destination server + */ + csp->server_connection.sfd = forwarded_connect(fwd, http, csp); + + if (csp->server_connection.sfd == JB_INVALID_SOCKET) + { + if (fwd->type != SOCKS_NONE) + { + /* Socks error. */ + rsp = error_response(csp, "forwarding-failed"); + } + else if (errno == EINVAL) + { + rsp = error_response(csp, "no-such-domain"); + } + else + { + rsp = error_response(csp, "connect-failed"); + } + + /* Write the answer to the client */ + if (rsp != NULL) + { + send_crunch_response(csp, rsp); + } + + /* + * Temporary workaround to prevent already-read client + * bodies from being parsed as new requests. For now we + * err on the safe side and throw all the following + * requests under the bus, even if no client body has been + * buffered. A compliant client will repeat the dropped + * requests on an untainted connection. + * + * The proper fix is to discard the no longer needed + * client body in the buffer (if there is one) and to + * continue parsing the bytes that follow. + */ + drain_and_close_socket(csp->cfd); + csp->cfd = JB_INVALID_SOCKET; + + return 1; + } + + /* + * Creating SSL/TLS connections with destinantion server or parent + * proxy. If forwarding is enabled, we must send client request to + * parent proxy and receive, parse and resend parent proxy answer. + */ + if (http->ssl && !csp->use_ssl_tunnel) + { + if (fwd->forward_host != NULL) + { + char server_response[BUFFER_SIZE]; + int ret = 0; + int len = 0; + char *hdr = list_to_text(csp->headers); + memset(server_response, 0, sizeof(server_response)); + + if (hdr == NULL) + { + log_error(LOG_LEVEL_FATAL, + "Out of memory parsing client header"); + } + list_remove_all(csp->headers); + + /* + * Sending client's CONNECT request to the parent proxy + */ + ret = write_socket(csp->server_connection.sfd, hdr, strlen(hdr)); + + freez(hdr); + + if (ret != 0) + { + log_error(LOG_LEVEL_CONNECT, + "Sending request headers to: %s failed", http->hostport); + mark_server_socket_tainted(csp); + return 1; + } + + /* Waitting for parent proxy server response */ + len = read_socket(csp->server_connection.sfd, server_response, + sizeof(server_response) - 1); + + if (len <= 0) + { + log_error(LOG_LEVEL_ERROR, "No response from parent proxy " + "server on socket %d.", csp->server_connection.sfd); + + rsp = error_response(csp, "no-server-data"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + mark_server_socket_tainted(csp); + return 1; + } + + /* + * Test if connection with destination server was established + * successfully by parent proxy. Then we can send response to + * the client and continue or stop. + */ + if (!tunnel_established_successfully(server_response, len)) + { + log_error(LOG_LEVEL_ERROR, "Forwarder hasn't established " + "connection with destination server."); + + write_socket(csp->cfd, server_response, len); + mark_server_socket_tainted(csp); + return 1; + } + + /* + * Parent proxy has established connection with destination server. + * Now we must create SSL/TLS connection with parent proxy. + */ + ret = create_server_ssl_connection(csp); + + /* + * If SLL/TLS connection wasn't created and invalid certificate + * wasn't detected, we can interrupt this fuction. Otherwise, we + * must inform client about invalid server certificate. + */ + + if (ret != 0 +#ifdef FEATURE_MBEDTLS + && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED + || csp->server_cert_verification_result == SSL_CERT_VALID) +#elif defined(FEATURE_LIBRESSL) + && (csp->server_cert_verification_result == X509_V_OK) +#endif + ) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + return 1; + } + + + /* + * SSL/TLS connection with parent proxy is established, we can + * inform client about success. + */ + ret = write_socket(csp->cfd, server_response, len); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Sending parent proxy response to client failed"); + mark_server_socket_tainted(csp); + return 1; + } + } + else + { + /* + * Parent proxy is not used, we can just create SSL/TLS connection + * with destination server + */ + ret = create_server_ssl_connection(csp); + + /* + * If SLL/TLS connection wasn't created and invalid certificate + * wasn't detected, we can interrupt this fuction. Otherwise, we + * must inform client about invalid server certificate. + */ + + if (ret != 0 +#ifdef FEATURE_MBEDTLS + && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED + || csp->server_cert_verification_result == SSL_CERT_VALID) +#elif defined(FEATURE_LIBRESSL) + && (csp->server_cert_verification_result == X509_V_OK) +#endif + ) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + return 1; + } + + + log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); + } + } + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + save_connection_destination(csp->server_connection.sfd, + http, fwd, &csp->server_connection); + csp->server_connection.keep_alive_timeout = + (unsigned)csp->config->keep_alive_timeout; + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + + return 0; +} + + /********************************************************************* * * Function : crunch_reason @@ -3264,242 +3530,14 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport); } - /* here we connect to the server, gateway, or the forwarder */ - -#ifdef FEATURE_CONNECTION_KEEP_ALIVE - if ((csp->server_connection.sfd != JB_INVALID_SOCKET) - && socket_is_still_alive(csp->server_connection.sfd) - && connection_destination_matches(&csp->server_connection, http, fwd)) - { - log_error(LOG_LEVEL_CONNECT, - "Reusing server socket %d connected to %s. Total requests: %u.", - csp->server_connection.sfd, csp->server_connection.host, - csp->server_connection.requests_sent_total); - } - else + /* + * Preparing connection with requested server. + */ + ret = create_server_connection(csp); + if (ret != 0) { - if (csp->server_connection.sfd != JB_INVALID_SOCKET) - { -#ifdef FEATURE_CONNECTION_SHARING - if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) - { - remember_connection(&csp->server_connection); - } - else -#endif /* def FEATURE_CONNECTION_SHARING */ - { - log_error(LOG_LEVEL_CONNECT, - "Closing server socket %d connected to %s. Total requests: %u.", - csp->server_connection.sfd, csp->server_connection.host, - csp->server_connection.requests_sent_total); - close_socket(csp->server_connection.sfd); - } - mark_connection_closed(&csp->server_connection); - } -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - - /* - * Connecting to destination server - */ - csp->server_connection.sfd = forwarded_connect(fwd, http, csp); - - if (csp->server_connection.sfd == JB_INVALID_SOCKET) - { - if (fwd->type != SOCKS_NONE) - { - /* Socks error. */ - rsp = error_response(csp, "forwarding-failed"); - } - else if (errno == EINVAL) - { - rsp = error_response(csp, "no-such-domain"); - } - else - { - rsp = error_response(csp, "connect-failed"); - } - - /* Write the answer to the client */ - if (rsp != NULL) - { - send_crunch_response(csp, rsp); - } - - /* - * Temporary workaround to prevent already-read client - * bodies from being parsed as new requests. For now we - * err on the safe side and throw all the following - * requests under the bus, even if no client body has been - * buffered. A compliant client will repeat the dropped - * requests on an untainted connection. - * - * The proper fix is to discard the no longer needed - * client body in the buffer (if there is one) and to - * continue parsing the bytes that follow. - */ - drain_and_close_socket(csp->cfd); - csp->cfd = JB_INVALID_SOCKET; - - return; - } - - /* - * Creating SSL/TLS connections with destinantion server or parent - * proxy. If forwarding is enabled, we must send client request to - * parent proxy and receive, parse and resend parent proxy answer. - */ - if (http->ssl && !csp->use_ssl_tunnel) - { - if (fwd->forward_host != NULL) - { - char server_response[BUFFER_SIZE]; - int ret = 0; - int len = 0; - char *hdr = list_to_text(csp->headers); - memset(server_response, 0, sizeof(server_response)); - - if (hdr == NULL) - { - log_error(LOG_LEVEL_FATAL, - "Out of memory parsing client header"); - } - list_remove_all(csp->headers); - - /* - * Sending client's CONNECT request to the parent proxy - */ - ret = write_socket(csp->server_connection.sfd, hdr, strlen(hdr)); - - freez(hdr); - - if (ret != 0) - { - log_error(LOG_LEVEL_CONNECT, - "Sending request headers to: %s failed", http->hostport); - mark_server_socket_tainted(csp); - return; - } - - /* Waitting for parent proxy server response */ - len = read_socket(csp->server_connection.sfd, server_response, - sizeof(server_response) - 1); - - if (len <= 0) - { - log_error(LOG_LEVEL_ERROR, "No response from parent proxy " - "server on socket %d.", csp->server_connection.sfd); - - rsp = error_response(csp, "no-server-data"); - if (rsp) - { - send_crunch_response(csp, rsp); - } - mark_server_socket_tainted(csp); - return; - } - - /* - * Test if connection with destination server was established - * successfully by parent proxy. Then we can send response to - * the client and continue or stop. - */ - if (!tunnel_established_successfully(server_response, len)) - { - log_error(LOG_LEVEL_ERROR, "Forwarder hasn't established " - "connection with destination server."); - - write_socket(csp->cfd, server_response, len); - mark_server_socket_tainted(csp); - return; - } - - /* - * Parent proxy has established connection with destination server. - * Now we must create SSL/TLS connection with parent proxy. - */ - ret = create_server_ssl_connection(csp); - - /* - * If SLL/TLS connection wasn't created and invalid certificate - * wasn't detected, we can interrupt this fuction. Otherwise, we - * must inform client about invalid server certificate. - */ - - if (ret != 0 -#ifdef FEATURE_MBEDTLS - && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED - || csp->server_cert_verification_result == SSL_CERT_VALID) -#elif defined(FEATURE_LIBRESSL) - && (csp->server_cert_verification_result == X509_V_OK) -#endif - ) - { - rsp = error_response(csp, "connect-failed"); - if (rsp) - { - send_crunch_response(csp, rsp); - } - return; - } - - - /* - * SSL/TLS connection with parent proxy is established, we can - * inform client about success. - */ - ret = write_socket(csp->cfd, server_response, len); - if (ret != 0) - { - log_error(LOG_LEVEL_ERROR, - "Sending parent proxy response to client failed"); - mark_server_socket_tainted(csp); - return; - } - } - else - { - /* - * Parent proxy is not used, we can just create SSL/TLS connection - * with destination server - */ - ret = create_server_ssl_connection(csp); - - /* - * If SLL/TLS connection wasn't created and invalid certificate - * wasn't detected, we can interrupt this fuction. Otherwise, we - * must inform client about invalid server certificate. - */ - - if (ret != 0 -#ifdef FEATURE_MBEDTLS - && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED - || csp->server_cert_verification_result == SSL_CERT_VALID) -#elif defined(FEATURE_LIBRESSL) - && (csp->server_cert_verification_result == X509_V_OK) -#endif - ) - { - rsp = error_response(csp, "connect-failed"); - if (rsp) - { - send_crunch_response(csp, rsp); - } - return; - } - - - log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); - } - } - -#ifdef FEATURE_CONNECTION_KEEP_ALIVE - save_connection_destination(csp->server_connection.sfd, - http, fwd, &csp->server_connection); - csp->server_connection.keep_alive_timeout = - (unsigned)csp->config->keep_alive_timeout; + return; } -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - csp->server_connection.requests_sent_total++; if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) -- 2.26.2 From c0656eb3a202e917e53d3efb10b541b3e86fd05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 21:57:41 +0200 Subject: [PATCH 57/83] Functions to send and receive data in jbsockets.c are now checking, whether ssl connection is already opened or not. Fixed bug - setting CSP_FLAG_CLIENT_HEADER_PARSING_DONE to 0, to allow to apply client_header_filters on client requests received over ssl. Sending and receiving data over tcp/ssl in functions client_protocol_is_unsupported and receive_chunked_client_request_body. --- jbsockets.c | 16 ++++++++-------- jcc.c | 10 ++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/jbsockets.c b/jbsockets.c index 2011a91c..b4bed371 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1750,7 +1750,7 @@ extern int recv_data(const struct client_state *csp, int src, unsigned char *buf if (src == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->client_ssl == 1) + if (csp->ssl_with_client_is_opened == 1) { return ssl_recv_data(&(csp->ssl_client_attr), buf, maxLen); } @@ -1763,7 +1763,7 @@ extern int recv_data(const struct client_state *csp, int src, unsigned char *buf else if (src == SERVER) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->server_ssl == 1) + if (csp->ssl_with_server_is_opened == 1) { return ssl_recv_data(&(csp->ssl_server_attr), buf, maxLen); } @@ -1803,7 +1803,7 @@ extern int send_data_delayed(const struct client_state *csp, int dest, const cha if (dest == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->client_ssl == 1) + if (csp->ssl_with_client_is_opened == 1) { return 0 > ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char*)buf, len, delay); } @@ -1816,7 +1816,7 @@ extern int send_data_delayed(const struct client_state *csp, int dest, const cha else if (dest == SERVER) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->server_ssl == 1) { + if (csp->ssl_with_server_is_opened == 1) { return 0 > ssl_send_data_delayed(&(csp->ssl_server_attr), (const unsigned char*)buf, len, delay); } else @@ -1877,7 +1877,7 @@ extern int flush_socket(const struct client_state *csp, int dest, struct iob *io if (dest == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->client_ssl == 1) + if (csp->ssl_with_client_is_opened == 1) { return ssl_flush_socket(&(csp->ssl_client_attr), iob); } @@ -1891,7 +1891,7 @@ extern int flush_socket(const struct client_state *csp, int dest, struct iob *io else if (dest == SERVER) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->server_ssl == 1) { + if (csp->ssl_with_server_is_opened == 1) { return ssl_flush_socket(&(csp->ssl_server_attr), iob); } else @@ -1928,7 +1928,7 @@ extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, in if (src == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->client_ssl == 1) + if (csp->ssl_with_client_is_opened == 1) { ret = is_ssl_pending(&(csp->ssl_client_attr)); } @@ -1942,7 +1942,7 @@ extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, in else if (src == SERVER) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS - if (csp->http->server_ssl == 1) + if (csp->ssl_with_server_is_opened == 1) { ret = is_ssl_pending(&(csp->ssl_server_attr)); } diff --git a/jcc.c b/jcc.c index ab2007c9..6dc6d10f 100644 --- a/jcc.c +++ b/jcc.c @@ -494,7 +494,7 @@ static int client_protocol_is_unsupported(const struct client_state *csp, char * log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req); freez(req); - write_socket_delayed(csp->cfd, response, strlen(response), + send_data_delayed(csp, CLIENT, response, strlen(response), get_write_delay(csp)); return TRUE; @@ -1766,7 +1766,7 @@ static jb_err receive_chunked_client_request_body(struct client_state *csp) "Timeout while waiting for the client body."); break; } - len = read_socket(csp->cfd, buf, sizeof(buf) - 1); + len = recv_data(csp, CLIENT, (unsigned char*)buf, sizeof(buf) - 1); if (len <= 0) { log_error(LOG_LEVEL_ERROR, "Read the client body failed: %E"); @@ -1779,7 +1779,7 @@ static jb_err receive_chunked_client_request_body(struct client_state *csp) } if (status != CHUNK_STATUS_BODY_COMPLETE) { - write_socket_delayed(csp->cfd, CLIENT_BODY_PARSE_ERROR_RESPONSE, + send_data_delayed(csp, CLIENT, CLIENT_BODY_PARSE_ERROR_RESPONSE, strlen(CLIENT_BODY_PARSE_ERROR_RESPONSE), get_write_delay(csp)); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Failed reading chunked client body\" 400 0", csp->ip_addr_str); @@ -2172,7 +2172,9 @@ static jb_err parse_client_request(struct client_state *csp) csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - + + /* Enabling CLIENT_HEADER_PARSING for header received over ssl */ + csp->flags &= ~CSP_FLAG_CLIENT_HEADER_PARSING_DONE; err = sed(csp, FILTER_CLIENT_HEADERS); if (JB_ERR_OK != err) { -- 2.26.2 From e2e8609916b320ca54434559a10f8652c0d79a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:02:29 +0200 Subject: [PATCH 58/83] Edited functions generating cgi messages to generate them with http or https prefix when ssl connection with client is opened. So these messages can be send over http or https connection. --- cgi.c | 176 +++++++++++++++++++++++++++++++--------------------- cgi.h | 4 +- cgiedit.c | 30 ++++++--- cgisimple.c | 90 ++++++++++++++++++--------- filters.c | 42 ++++++------- jcc.c | 8 +-- project.h | 1 + 7 files changed, 215 insertions(+), 136 deletions(-) diff --git a/cgi.c b/cgi.c index 22601760..75228285 100644 --- a/cgi.c +++ b/cgi.c @@ -68,6 +68,48 @@ /* jcc.h is for mutex semaphore globals only */ #include "jcc.h" + +/* Built-in parametrized error messages with http or https */ + +#define CGI_ERROR_NO_TEMPLATE(prefix) \ + "\n" \ + "\n" \ + " 500 Internal Privoxy Error\n" \ + " " \ + "\n" \ + "\n" \ + "

500 Internal Privoxy Error

\n" \ + "

Privoxy encountered an error while processing your request:

\n" \ + "

Could not load template file " + +#define CGI_ERROR_UNKNOWN(prefix) \ + "\n" \ + "\n" \ + " 500 Internal Privoxy Error\n" \ + " " \ + "\n" \ + "\n" \ + "

500 Internal Privoxy Error

\n" \ + "

Privoxy encountered an error while processing your request:

\n" \ + "

Unexpected internal error: " + +#define CGI_MEMORY_ERROR(prefix) \ + "\n" \ + "\n" \ + " 500 Internal Privoxy Error\n" \ + " " \ + "\n" \ + "\n" \ + "

500 Internal Privoxy Error

\n" \ + "

Privoxy ran out of memory while processing your request.

\n" \ + "

Please contact your proxy administrator, or try again later

\n" \ + "\n" \ + "\n" + +#define CGI_USER_MANUAL(prefix) \ + prefix "user-manual/" + + /* * List of CGI functions: name, handler, description * Note: Do NOT use single quotes in the description; @@ -286,7 +328,7 @@ const size_t image_blank_length = sizeof(image_blank_data) - 1; const size_t LOWER_LENGTH_LIMIT_FOR_COMPRESSION = 1024U; #endif -static struct http_response cgi_error_memory_response[1]; +static struct http_response cgi_error_memory_responses[2]; static struct http_response *dispatch_known_cgi(struct client_state * csp, const char * path); @@ -444,7 +486,8 @@ static int referrer_is_safe(const struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Denying access to %s. No referrer found.", csp->http->url); } - else if ((0 == strncmp(referrer, CGI_PREFIX, sizeof(CGI_PREFIX)-1) + else if ((0 == strncmp(referrer, csp->ssl_with_client_is_opened != 0 ? CGI_SSL_PREFIX : CGI_PREFIX, + sizeof(csp->ssl_with_client_is_opened != 0 ? CGI_SSL_PREFIX : CGI_PREFIX) - 1) || (0 == strncmp(referrer, alternative_prefix, strlen(alternative_prefix))))) { /* Trustworthy referrer */ @@ -508,7 +551,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, if (NULL == (path_copy = strdup(path))) { - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } query_args_start = path_copy; while (*query_args_start && *query_args_start != '?' && *query_args_start != '/') @@ -523,7 +566,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, if (JB_ERR_OK != err) { free(param_list); free(path_copy); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } else @@ -535,7 +578,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, if (NULL == (param_list = parse_cgi_parameters(query_args_start))) { free(path_copy); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } @@ -550,7 +593,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, { free(path_copy); free_map(param_list); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -611,7 +654,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, { /* Error in handler, probably out-of-memory */ free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } d++; @@ -881,13 +924,13 @@ struct http_response *error_response(struct client_state *csp, if (exports == NULL) { - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } if (NULL == (rsp = alloc_http_response())) { free_map(exports); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } #ifdef FEATURE_FORCE_LOAD @@ -905,7 +948,7 @@ struct http_response *error_response(struct client_state *csp, if (!err) err = map(exports, "host", 1, html_encode(csp->http->host), 0); if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0); if (!err) err = map(exports, "path", 1, html_encode_and_free_original(path), 0); - if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1); + if (!err) err = map(exports, "protocol", 1, csp->ssl_with_client_is_opened ? "https://" : "http://", 1); if (!err) { err = map(exports, "host-ip", 1, html_encode(csp->http->host_ip_addr_str), 0); @@ -921,7 +964,7 @@ struct http_response *error_response(struct client_state *csp, { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } if (!strcmp(templatename, "no-such-domain")) @@ -988,7 +1031,7 @@ struct http_response *error_response(struct client_state *csp, { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->status = strdup("503 Forwarding failure"); @@ -1014,14 +1057,14 @@ struct http_response *error_response(struct client_state *csp, { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } err = template_fill_for_cgi(csp, templatename, exports, rsp); if (err) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } return finish_http_response(csp, rsp); @@ -1078,7 +1121,8 @@ jb_err cgi_error_disabled(const struct client_state *csp, * Function : cgi_init_error_messages * * Description : Call at the start of the program to initialize - * the error message used by cgi_error_memory(). + * the error messages with http and https used by + * cgi_error_memory(). * * Parameters : N/A * @@ -1087,29 +1131,24 @@ jb_err cgi_error_disabled(const struct client_state *csp, *********************************************************************/ void cgi_init_error_messages(void) { - memset(cgi_error_memory_response, '\0', sizeof(*cgi_error_memory_response)); - cgi_error_memory_response->head = + memset(&(cgi_error_memory_responses[0]), '\0', sizeof(cgi_error_memory_responses[0])); + memset(&(cgi_error_memory_responses[1]), '\0', sizeof(cgi_error_memory_responses[1])); + cgi_error_memory_responses[0].head = cgi_error_memory_responses[1].head = "HTTP/1.0 500 Internal Privoxy Error\r\n" "Content-Type: text/html\r\n" "\r\n"; - cgi_error_memory_response->body = - "\n" - "\n" - " 500 Internal Privoxy Error\n" - " " - "\n" - "\n" - "

500 Internal Privoxy Error

\n" - "

Privoxy ran out of memory while processing your request.

\n" - "

Please contact your proxy administrator, or try again later

\n" - "\n" - "\n"; - - cgi_error_memory_response->head_length = - strlen(cgi_error_memory_response->head); - cgi_error_memory_response->content_length = - strlen(cgi_error_memory_response->body); - cgi_error_memory_response->crunch_reason = OUT_OF_MEMORY; + cgi_error_memory_responses[0].body = CGI_MEMORY_ERROR(CGI_PREFIX); + cgi_error_memory_responses[1].body = CGI_MEMORY_ERROR(CGI_SSL_PREFIX); + + + cgi_error_memory_responses[0].head_length = cgi_error_memory_responses[1].head_length = + strlen(cgi_error_memory_responses->head); + cgi_error_memory_responses[0].content_length = + strlen(cgi_error_memory_responses[0].body); + cgi_error_memory_responses[1].content_length = + strlen(cgi_error_memory_responses[1].body); + cgi_error_memory_responses[0].crunch_reason = + cgi_error_memory_responses[1].crunch_reason = OUT_OF_MEMORY; } @@ -1120,18 +1159,19 @@ void cgi_init_error_messages(void) * Description : Called if a CGI function runs out of memory. * Returns a statically-allocated error response. * - * Parameters : N/A + * Parameters : + * 1 : ssl = https links should be used * * Returns : http_response data structure for output. This is * statically allocated, for obvious reasons. * *********************************************************************/ -struct http_response *cgi_error_memory(void) +struct http_response *cgi_error_memory(const int ssl) { /* assert that it's been initialized. */ - assert(cgi_error_memory_response->head); + assert(cgi_error_memory_responses[ssl != 0].head); - return cgi_error_memory_response; + return &cgi_error_memory_responses[ssl != 0]; } @@ -1160,16 +1200,8 @@ jb_err cgi_error_no_template(const struct client_state *csp, { static const char status[] = "500 Internal Privoxy Error"; - static const char body_prefix[] = - "\n" - "\n" - " 500 Internal Privoxy Error\n" - " " - "\n" - "\n" - "

500 Internal Privoxy Error

\n" - "

Privoxy encountered an error while processing your request:

\n" - "

Could not load template file "; + static const char body_prefix[] = CGI_ERROR_NO_TEMPLATE(CGI_PREFIX); + static const char body_prefix_ssl[] = CGI_ERROR_NO_TEMPLATE(CGI_SSL_PREFIX); static const char body_suffix[] = " or one of its included components.

\n" "

Please contact your proxy administrator.

\n" @@ -1184,7 +1216,8 @@ jb_err cgi_error_no_template(const struct client_state *csp, ").

\n" "\n" "\n"; - const size_t body_size = strlen(body_prefix) + strlen(template_name) + strlen(body_suffix) + 1; + const size_t body_size = strlen(csp->ssl_with_client_is_opened != 0 ? body_prefix_ssl + : body_prefix) + strlen(template_name) + strlen(body_suffix) + 1; assert(csp); assert(rsp); @@ -1199,7 +1232,7 @@ jb_err cgi_error_no_template(const struct client_state *csp, rsp->is_static = 0; rsp->body = malloc_or_die(body_size); - strlcpy(rsp->body, body_prefix, body_size); + strlcpy(rsp->body, csp->ssl_with_client_is_opened != 0 ? body_prefix_ssl : body_prefix, body_size); strlcat(rsp->body, template_name, body_size); strlcat(rsp->body, body_suffix, body_size); @@ -1243,16 +1276,8 @@ jb_err cgi_error_unknown(const struct client_state *csp, { static const char status[] = "500 Internal Privoxy Error"; - static const char body_prefix[] = - "\n" - "\n" - " 500 Internal Privoxy Error\n" - " " - "\n" - "\n" - "

500 Internal Privoxy Error

\n" - "

Privoxy encountered an error while processing your request:

\n" - "

Unexpected internal error: "; + static const char body_prefix[] = CGI_ERROR_UNKNOWN(CGI_PREFIX); + static const char body_prefix_ssl[] = CGI_ERROR_UNKNOWN(CGI_SSL_PREFIX); static const char body_suffix[] = "

\n" "

Please " @@ -1261,7 +1286,8 @@ jb_err cgi_error_unknown(const struct client_state *csp, "\n" "\n"; /* Includes room for larger error numbers in the future. */ - const size_t body_size = sizeof(body_prefix) + sizeof(body_suffix) + 5; + const size_t body_size = csp->ssl_with_client_is_opened != 0 ? sizeof(body_prefix_ssl) : + sizeof(body_prefix) + sizeof(body_suffix) + 5; assert(csp); assert(rsp); @@ -1276,7 +1302,8 @@ jb_err cgi_error_unknown(const struct client_state *csp, rsp->body = malloc_or_die(body_size); - snprintf(rsp->body, body_size, "%s%d%s", body_prefix, error_to_report, body_suffix); + snprintf(rsp->body, body_size, "%s%d%s", csp->ssl_with_client_is_opened != 0 ? + body_prefix_ssl : body_prefix, error_to_report, body_suffix); rsp->status = strdup(status); if (rsp->status == NULL) @@ -1580,7 +1607,7 @@ struct http_response *finish_http_response(struct client_state *csp, struct http /* Special case - do NOT change this statically allocated response, * which is ready for output anyway. */ - if (rsp == cgi_error_memory_response) + if (rsp == &cgi_error_memory_responses[0] || rsp == &cgi_error_memory_responses[1]) { return rsp; } @@ -1748,7 +1775,7 @@ struct http_response *finish_http_response(struct client_state *csp, struct http if (err || (NULL == (rsp->head = list_to_text(rsp->headers)))) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->head_length = strlen(rsp->head); @@ -1791,9 +1818,10 @@ struct http_response *alloc_http_response(void) void free_http_response(struct http_response *rsp) { /* - * Must special case cgi_error_memory_response, which is never freed. + * Must special case cgi_error_memory_responses, which are never freed. */ - if (rsp && (rsp != cgi_error_memory_response)) + if (rsp && rsp != &cgi_error_memory_responses[0] + && rsp != &cgi_error_memory_responses[1]) { freez(rsp->status); freez(rsp->head); @@ -2179,8 +2207,10 @@ struct map *default_exports(const struct client_state *csp, const char *caller) if (!err) err = map(exports, "my-hostname", 1, html_encode(hostname ? hostname : "unknown"), 0); freez(hostname); if (!err) err = map(exports, "homepage", 1, html_encode(HOME_PAGE_URL), 0); - if (!err) err = map(exports, "default-cgi", 1, html_encode(CGI_PREFIX), 0); - if (!err) err = map(exports, "menu", 1, make_menu(caller, csp->config->feature_flags), 0); + if (!err) err = map(exports, "default-cgi", 1, html_encode(csp->ssl_with_client_is_opened != 0 ? + CGI_SSL_PREFIX : CGI_PREFIX), 0); + if (!err) err = map(exports, "menu", 1, make_menu(caller, csp->config->feature_flags, + csp->ssl_with_client_is_opened), 0); if (!err) err = map(exports, "code-status", 1, CODE_STATUS, 1); if (!strncmpic(csp->config->usermanual, "file://", 7) || !strncmpic(csp->config->usermanual, "http", 4)) @@ -2191,7 +2221,8 @@ struct map *default_exports(const struct client_state *csp, const char *caller) else { /* Manual is delivered by Privoxy. */ - if (!err) err = map(exports, "user-manual", 1, html_encode(CGI_PREFIX"user-manual/"), 0); + if (!err) err = map(exports, "user-manual", 1, + html_encode(CGI_USER_MANUAL(csp->ssl_with_client_is_opened != 0 ? CGI_SSL_PREFIX : CGI_PREFIX)), 0); } if (!err) err = map(exports, "actions-help-prefix", 1, ACTIONS_HELP_PREFIX ,1); #ifdef FEATURE_TOGGLE @@ -2371,12 +2402,13 @@ jb_err map_conditional(struct map *exports, const char *name, int choose_first) * 1 : self = name of CGI to leave out, can be NULL for * complete listing. * 2 : feature_flags = feature bitmap from csp->config + * 3 : ssl = menu should be created with https links * * * Returns : menu string, or NULL on out-of-memory error. * *********************************************************************/ -char *make_menu(const char *self, const unsigned feature_flags) +char *make_menu(const char *self, const unsigned feature_flags, int ssl) { const struct cgi_dispatcher *d; char *result = strdup(""); @@ -2409,7 +2441,7 @@ char *make_menu(const char *self, const unsigned feature_flags) * the "blocked" template's JavaScript. */ string_append(&result, "

  • http->ssl != 0 ? CGI_SSL_PREFIX: CGI_PREFIX)); } @@ -3193,7 +3207,7 @@ jb_err cgi_edit_actions_submit(struct client_state *csp, return err; } - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUIU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier, sectionid); edit_free_file(file); @@ -3314,7 +3328,7 @@ jb_err cgi_edit_actions_url(struct client_state *csp, return err; } - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUIU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier, section_start_line_number); edit_free_file(file); @@ -3437,7 +3451,7 @@ jb_err cgi_edit_actions_add_url(struct client_state *csp, return err; } - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUIU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier, sectionid); edit_free_file(file); @@ -3548,7 +3562,7 @@ jb_err cgi_edit_actions_remove_url(struct client_state *csp, return err; } - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u#l%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUUU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier, section_start_line_number); edit_free_file(file); @@ -3670,7 +3684,7 @@ jb_err cgi_edit_actions_section_remove(struct client_state *csp, return err; } - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier); edit_free_file(file); @@ -3833,7 +3847,7 @@ jb_err cgi_edit_actions_section_add(struct client_state *csp, return err; } - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier); edit_free_file(file); @@ -4022,7 +4036,7 @@ jb_err cgi_edit_actions_section_swap(struct client_state *csp, } } /* END if (section1 != section2) */ - snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u", + snprintf(target, sizeof(target), CGI_EDIT_AL_FOO_LUU(csp->http->ssl != 0 ? CGI_SSL_PREFIX : CGI_PREFIX), (long) time(NULL), file->identifier); edit_free_file(file); diff --git a/cgisimple.c b/cgisimple.c index 79b811f9..63cd4f95 100644 --- a/cgisimple.c +++ b/cgisimple.c @@ -63,6 +63,35 @@ #include "client-tags.h" #endif + +#define CGI_SHUTDOWN_REQUEST(prefix) \ + "\n" \ + "\n" \ + " Privoxy shutdown request received\n" \ + " \n" \ + " \n" \ + "\n" \ + "\n" \ + "

    Privoxy shutdown request received

    \n" \ + "

    Privoxy is going to shut down after the next request.

    \n" \ + "\n" \ + "\n" + +#define CGI_CLIENT_TAG_FORM(prefix) \ + "
    \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + "
    " + +#define CGI_CLIENT_TAGS(prefix) \ + prefix "client-tags" + +#define CGI_USER_MANUAL(prefix) \ + prefix "user-manual/" + + static jb_err show_defines(struct map *exports); static jb_err cgi_show_file(struct client_state *csp, struct http_response *rsp, @@ -172,18 +201,8 @@ jb_err cgi_die (struct client_state *csp, const struct map *parameters) { static const char status[] = "200 OK Privoxy shutdown request received"; - static const char body[] = - "\n" - "\n" - " Privoxy shutdown request received\n" - " \n" - " \n" - "\n" - "\n" - "

    Privoxy shutdown request received

    \n" - "

    Privoxy is going to shut down after the next request.

    \n" - "\n" - "\n"; + static const char body[] = CGI_SHUTDOWN_REQUEST(CGI_PREFIX) + static const char body_ssl[] = CGI_SHUTDOWN_REQUEST(CGI_SSL_PREFIX) assert(csp); assert(rsp); @@ -198,7 +217,7 @@ jb_err cgi_die (struct client_state *csp, rsp->head_length = 0; rsp->is_static = 0; - rsp->body = strdup_or_die(body); + rsp->body = strdup_or_die(csp->ssl_with_client_is_opened != 0 ? body_ssl : body); rsp->status = strdup_or_die(status); return JB_ERR_OK; @@ -286,12 +305,13 @@ jb_err cgi_show_request(struct client_state *csp, * 4 : toggle_state = Desired state after the button pressed 0 * 5 : expires = Whether or not the tag should be enabled. * Only checked if toggle_state is 1. + * 6 : ssl = form should be created with https links * * Returns : void * *********************************************************************/ static void cgi_create_client_tag_form(char *form, size_t size, - const char *tag, int toggle_state, int expires) + const char *tag, int toggle_state, int expires, int ssl) { char *button_name; @@ -305,13 +325,16 @@ static void cgi_create_client_tag_form(char *form, size_t size, button_name = "Disable"; } - snprintf(form, size, - "
    \n" - " \n" - " \n" - " \n" - " \n" - "
    ", tag, toggle_state, !expires, button_name); + if (ssl != 0) + { + snprintf(form, size, CGI_CLIENT_TAG_FORM(CGI_SSL_PREFIX), + tag, toggle_state, !expires, button_name); + } + else + { + snprintf(form, size, CGI_CLIENT_TAG_FORM(CGI_PREFIX), + tag, toggle_state, !expires, button_name); + } } /********************************************************************* @@ -375,11 +398,13 @@ jb_err cgi_show_client_tags(struct client_state *csp, if (!err) err = string_append(&client_tag_status, ""); if (!err) err = string_append(&client_tag_status, tag_state == 1 ? "Enabled" : "Disabled"); if (!err) err = string_append(&client_tag_status, ""); - cgi_create_client_tag_form(buf, sizeof(buf), this_tag->name, !tag_state, 1); + cgi_create_client_tag_form(buf, sizeof(buf), this_tag->name, !tag_state, 1, + csp->ssl_with_client_is_opened); if (!err) err = string_append(&client_tag_status, buf); if (tag_state == 0) { - cgi_create_client_tag_form(buf, sizeof(buf), this_tag->name, !tag_state, 0); + cgi_create_client_tag_form(buf, sizeof(buf), this_tag->name, !tag_state, 0, + csp->ssl_with_client_is_opened); if (!err) err = string_append(&client_tag_status, buf); } if (!err) err = string_append(&client_tag_status, ""); @@ -496,7 +521,8 @@ jb_err cgi_toggle_client_tag(struct client_state *csp, } rsp->status = strdup_or_die("302 Done dealing with toggle request"); if (enlist_unique_header(rsp->headers, - "Location", CGI_PREFIX "client-tags")) + "Location", CGI_CLIENT_TAGS(csp->ssl_with_client_is_opened != 0 ? + CGI_SSL_PREFIX : CGI_PREFIX))) { return JB_ERR_MEMORY; } @@ -533,6 +559,7 @@ jb_err cgi_send_banner(struct client_state *csp, const struct map *parameters) { char imagetype = lookup(parameters, "type")[0]; + int ssl = csp->ssl_with_client_is_opened; /* * If type is auto, then determine the right thing @@ -550,6 +577,8 @@ jb_err cgi_send_banner(struct client_state *csp, { static const char prefix1[] = CGI_PREFIX "send-banner?type="; static const char prefix2[] = "http://" CGI_SITE_1_HOST "/send-banner?type="; + static const char prefix1_ssl[] = CGI_SSL_PREFIX "send-banner?type="; + static const char prefix2_ssl[] = "https://" CGI_SITE_1_HOST "/send-banner?type="; const char *p = csp->action->string[ACTION_STRING_IMAGE_BLOCKER]; if (p == NULL) @@ -569,13 +598,15 @@ jb_err cgi_send_banner(struct client_state *csp, * If the action is to call this CGI, determine * the argument: */ - else if (0 == strncmpic(p, prefix1, sizeof(prefix1) - 1)) + else if (0 == strncmpic(p, ssl != 0 ? prefix1_ssl : prefix1, + sizeof(ssl != 0 ? prefix1_ssl : prefix1) - 1)) { - imagetype = p[sizeof(prefix1) - 1]; + imagetype = p[sizeof(ssl != 0 ? prefix1_ssl : prefix1) - 1]; } - else if (0 == strncmpic(p, prefix2, sizeof(prefix2) - 1)) + else if (0 == strncmpic(p, ssl != 0 ? prefix2_ssl : prefix2, + sizeof(ssl != 0 ? prefix2_ssl : prefix2) - 1)) { - imagetype = p[sizeof(prefix2) - 1]; + imagetype = p[sizeof(ssl != 0 ? prefix2_ssl : prefix2) - 1]; } /* @@ -982,7 +1013,8 @@ jb_err cgi_send_user_manual(struct client_state *csp, if (!parameters->first) { /* requested http://p.p/user-manual (without trailing slash) */ - return cgi_redirect(rsp, CGI_PREFIX "user-manual/"); + return cgi_redirect(rsp, CGI_USER_MANUAL(csp->ssl_with_client_is_opened != 0 ? + CGI_SSL_PREFIX : CGI_PREFIX)); } get_string_param(parameters, "file", &filename); diff --git a/filters.c b/filters.c index a0ddb939..9e09d337 100644 --- a/filters.c +++ b/filters.c @@ -554,7 +554,7 @@ struct http_response *block_url(struct client_state *csp) */ if (NULL == (rsp = alloc_http_response())) { - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -582,14 +582,14 @@ struct http_response *block_url(struct client_state *csp) if (rsp->body == NULL) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->content_length = image_pattern_length; if (enlist_unique_header(rsp->headers, "Content-Type", BUILTIN_IMAGE_MIMETYPE)) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } else if (0 == strcmpic(p, "blank")) @@ -599,14 +599,14 @@ struct http_response *block_url(struct client_state *csp) if (rsp->body == NULL) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->content_length = image_blank_length; if (enlist_unique_header(rsp->headers, "Content-Type", BUILTIN_IMAGE_MIMETYPE)) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } else @@ -616,7 +616,7 @@ struct http_response *block_url(struct client_state *csp) if (enlist_unique_header(rsp->headers, "Location", p)) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } @@ -655,7 +655,7 @@ struct http_response *block_url(struct client_state *csp) if (enlist_unique_header(rsp->headers, "Content-Type", new_content_type)) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } } @@ -674,7 +674,7 @@ struct http_response *block_url(struct client_state *csp) if (exports == NULL) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } #ifdef FEATURE_FORCE_LOAD @@ -715,14 +715,14 @@ struct http_response *block_url(struct client_state *csp) { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } err = template_fill_for_cgi(csp, "blocked", exports, rsp); if (err) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } } rsp->crunch_reason = BLOCKED; @@ -769,7 +769,7 @@ struct http_response *trust_url(struct client_state *csp) */ if (NULL == (rsp = alloc_http_response())) { - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->status = strdup_or_die("403 Request blocked by Privoxy"); @@ -777,7 +777,7 @@ struct http_response *trust_url(struct client_state *csp) if (exports == NULL) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -800,7 +800,7 @@ struct http_response *trust_url(struct client_state *csp) { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -818,7 +818,7 @@ struct http_response *trust_url(struct client_state *csp) { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -845,7 +845,7 @@ struct http_response *trust_url(struct client_state *csp) { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -873,7 +873,7 @@ struct http_response *trust_url(struct client_state *csp) { free_map(exports); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } /* @@ -883,7 +883,7 @@ struct http_response *trust_url(struct client_state *csp) if (err) { free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->crunch_reason = UNTRUSTED; @@ -1266,7 +1266,7 @@ struct http_response *redirect_url(struct client_state *csp) freez(new_url); if (encoded_url == NULL) { - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } new_url = encoded_url; assert(FALSE == url_requires_percent_encoding(new_url)); @@ -1286,7 +1286,7 @@ struct http_response *redirect_url(struct client_state *csp) if (NULL == (rsp = alloc_http_response())) { freez(new_url); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->status = strdup_or_die("302 Local Redirect from Privoxy"); @@ -1294,7 +1294,7 @@ struct http_response *redirect_url(struct client_state *csp) { freez(new_url); free_http_response(rsp); - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->crunch_reason = REDIRECTED; freez(new_url); @@ -2590,7 +2590,7 @@ struct http_response *direct_response(struct client_state *csp) /* Get mem for response or fail*/ if (NULL == (rsp = alloc_http_response())) { - return cgi_error_memory(); + return cgi_error_memory(csp->ssl_with_client_is_opened); } rsp->status = strdup_or_die("501 Not Implemented"); diff --git a/jcc.c b/jcc.c index 6dc6d10f..3cb4a0a2 100644 --- a/jcc.c +++ b/jcc.c @@ -1126,7 +1126,7 @@ static void send_crunch_response(const struct client_state *csp, struct http_res } /* Clean up and return */ - if (cgi_error_memory() != rsp) + if (cgi_error_memory(csp->ssl_with_client_is_opened) != rsp) { free_http_response(rsp); } @@ -2315,7 +2315,7 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "Out of memory. Failed to allocate the receive buffer."); - rsp = cgi_error_memory(); + rsp = cgi_error_memory(csp->ssl_with_client_is_opened); send_crunch_response(csp, rsp); return; } @@ -2921,7 +2921,7 @@ static void handle_established_connection(struct client_state *csp) * Send our static "Out-of-memory" page. */ log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush."); - rsp = cgi_error_memory(); + rsp = cgi_error_memory(csp->ssl_with_client_is_opened); send_crunch_response(csp, rsp); mark_server_socket_tainted(csp); close_client_and_server_ssl_connections(csp); @@ -3018,7 +3018,7 @@ static void handle_established_connection(struct client_state *csp) if (add_to_iob(csp->iob, csp->config->buffer_limit, csp->receive_buffer, len)) { log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers."); - rsp = cgi_error_memory(); + rsp = cgi_error_memory(csp->ssl_with_client_is_opened); send_crunch_response(csp, rsp); mark_server_socket_tainted(csp); close_client_and_server_ssl_connections(csp); diff --git a/project.h b/project.h index 5d8195ee..50e0960c 100644 --- a/project.h +++ b/project.h @@ -1624,6 +1624,7 @@ struct configuration_spec * INCLUDES the trailing slash. */ #define CGI_PREFIX "http://" CGI_SITE_2_HOST CGI_SITE_2_PATH "/" +#define CGI_SSL_PREFIX "https://" CGI_SITE_2_HOST CGI_SITE_2_PATH "/" #endif /* ndef PROJECT_H_INCLUDED */ -- 2.26.2 From 570b3a8abbda2dea45b5c2486ce30fd2a33d32f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:03:32 +0200 Subject: [PATCH 59/83] When CONNECT request to cgi url is received, connection with destination server is not created, but SSL connection with client is created. Then particular client request over SSL is received and cgi response to this request is created and sent to client. So this solves receiving of cgi requests over https and responses sending. --- jcc.c | 227 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 143 insertions(+), 84 deletions(-) diff --git a/jcc.c b/jcc.c index 3cb4a0a2..041d951e 100644 --- a/jcc.c +++ b/jcc.c @@ -956,7 +956,7 @@ static int create_server_connection(struct client_state *csp) { } - log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH SERVER CREATED SUCCESSFULLY"); + log_error(LOG_LEVEL_CONNECT, "SSL connection with server was created successfully"); } } @@ -1136,22 +1136,23 @@ static void send_crunch_response(const struct client_state *csp, struct http_res /********************************************************************* * - * Function : crunch_response_triggered + * Function : should_trigger_crunch_response * * Description : Checks if the request has to be crunched, - * and delivers the crunch response if necessary. + * and prepares the crunch response if necessary. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * 2 : crunchers = list of cruncher functions to run + * 3 : rsp = pointer where crunch response should be + * returned * - * Returns : TRUE if the request was answered with a crunch response - * FALSE otherwise. + * Returns : TRUE if the request should be answered with + * a crunch response, FALSE otherwise. * *********************************************************************/ -static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]) +static int should_trigger_crunch_response(struct client_state *csp, const struct cruncher crunchers[], int prepare_rsp, struct http_response **rsp) { - struct http_response *rsp = NULL; const struct cruncher *c; /* @@ -1160,10 +1161,11 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun * prevent unintentional blocks or redirects. */ if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING) - && (NULL != (rsp = dispatch_cgi(csp)))) + && NULL != (*rsp = dispatch_cgi(csp))) { - /* Deliver, log and free the interception response. */ - send_crunch_response(csp, rsp); + if (!prepare_rsp) { + free_http_response(*rsp); + } csp->flags |= CSP_FLAG_CRUNCHED; return TRUE; } @@ -1176,14 +1178,11 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun * applies to forced requests as well. */ if (((csp->flags & CSP_FLAG_TOGGLED_ON) && - !(csp->flags & CSP_FLAG_FORCED)) || - (c->flags & CF_IGNORE_FORCE)) + !(csp->flags & CSP_FLAG_FORCED)) || + (c->flags & CF_IGNORE_FORCE)) { - rsp = c->cruncher(csp); - if (NULL != rsp) + if (NULL != (*rsp = c->cruncher(csp))) { - /* Deliver, log and free the interception response. */ - send_crunch_response(csp, rsp); csp->flags |= CSP_FLAG_CRUNCHED; #ifdef FEATURE_STATISTICS if (c->flags & CF_COUNT_AS_REJECT) @@ -1192,6 +1191,9 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun } #endif /* def FEATURE_STATISTICS */ + if (!prepare_rsp) { + free_http_response(*rsp); + } return TRUE; } } @@ -1201,6 +1203,39 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun } +/********************************************************************* + * + * Function : crunch_response_triggered + * + * Description : Checks if the request has to be crunched, + * and delivers the crunch response if necessary. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : crunchers = list of cruncher functions to run + * + * Returns : TRUE if the request was answered with a crunch response + * FALSE otherwise. + * + *********************************************************************/ +static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]) +{ + struct http_response *rsp = NULL; + int should_be_triggered = FALSE; + + should_be_triggered = should_trigger_crunch_response(csp, crunchers, TRUE, &rsp); + + if (should_be_triggered == TRUE && rsp != NULL) + { + /* Deliver, log and free the interception response. */ + send_crunch_response(csp, rsp); + return TRUE; + } + + return FALSE; +} + + /********************************************************************* * * Function : build_request_line @@ -1561,6 +1596,7 @@ static void mark_server_socket_tainted(struct client_state *csp) csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; } + /********************************************************************* * * Function : get_request_line @@ -3434,6 +3470,8 @@ static void chat(struct client_state *csp) struct http_request *http; /* Skeleton for HTTP response, if we should intercept the request */ struct http_response *rsp; + struct http_response *crunch_rsp; + int should_send_crunch_rsp = FALSE; int ret = 0; http = csp->http; @@ -3511,8 +3549,10 @@ static void chat(struct client_state *csp) /* * We have a request. Check if one of the crunchers wants it. */ - if (crunch_response_triggered(csp, crunchers_all)) + should_send_crunch_rsp = should_trigger_crunch_response(csp, crunchers_all, !http->ssl, &crunch_rsp); + if (should_send_crunch_rsp && !http->ssl) { + send_crunch_response(csp, crunch_rsp); /* * Yes. The client got the crunch response and we're done here. */ @@ -3535,95 +3575,106 @@ static void chat(struct client_state *csp) /* * Preparing connection with requested server. */ - ret = create_server_connection(csp); - if (ret != 0) - { - return; - } - csp->server_connection.requests_sent_total++; - - if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) - { - /* Client headers have been sent optimistically */ - assert(csp->headers->last == NULL); - } - else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) - { - if (send_http_request(csp)) + if (!should_send_crunch_rsp) { + ret = create_server_connection(csp); + if (ret != 0) { - rsp = error_response(csp, "connect-failed"); - if (rsp) - { - send_crunch_response(csp, rsp); - } return; } + csp->server_connection.requests_sent_total++; } - else + + if (!should_send_crunch_rsp) { - /* - * Using old solution with SSL tunnel or new solution with SSL proxy - */ - list_remove_all(csp->headers); - if (csp->use_ssl_tunnel) + if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) { - /* - * We're running an SSL tunnel and we're not forwarding, - * so just ditch the client headers, send the "connect succeeded" - * message to the client, flush the rest, and get out of the way. - */ - if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + /* Client headers have been sent optimistically */ + assert(csp->headers->last == NULL); + } + else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) + { + if (send_http_request(csp)) { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } return; } } else { /* - * Creating an SSL proxy. If forwarding is disabled, we must send - * CSUCCEED mesage to client. Then SSL/TLS connection with client - * is created. + * Using old solution with SSL tunnel or new solution with SSL proxy */ - - if (fwd->forward_host == NULL) + list_remove_all(csp->headers); + if (csp->use_ssl_tunnel) { + /* + * We're running an SSL tunnel and we're not forwarding, + * so just ditch the client headers, send the "connect succeeded" + * message to the client, flush the rest, and get out of the way. + */ if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) { - log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); return; } } - - ret = create_client_ssl_connection(csp); - if (ret != 0) + else { - log_error(LOG_LEVEL_ERROR, - "Can't open secure connection with client"); - close_client_and_server_ssl_connections(csp); - return; - } + /* + * Creating an SSL proxy. If forwarding is disabled, we must send + * CSUCCEED mesage to client. Then SSL/TLS connection with client + * is created. + */ - /* - * If server certificate is invalid, we must inform client and then - * close connection with client. - */ + if (fwd->forward_host == NULL) + { + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); + return; + } + } + + ret = create_client_ssl_connection(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Can't open secure connection with client"); + close_client_and_server_ssl_connections(csp); + return; + } + + /* + * If server certificate is invalid, we must inform client and then + * close connection with client. + */ #ifdef FEATURE_MBEDTLS - if (csp->server_cert_verification_result != SSL_CERT_VALID) + if (csp->server_cert_verification_result != SSL_CERT_VALID) #elif defined(FEATURE_LIBRESSL) - if (csp->server_cert_verification_result != X509_V_OK) + if (csp->server_cert_verification_result != X509_V_OK) #endif #if defined(FEATURE_MBEDTLS) || defined(FEATURE_LIBRESSL) - { - ssl_send_certificate_error(csp); - close_client_and_server_ssl_connections(csp); - return; - } + { + ssl_send_certificate_error(csp); + close_client_and_server_ssl_connections(csp); + return; + } #endif - log_error(LOG_LEVEL_INFO, "SSL CONNECTION WITH CLIENT CREATED SUCCESSFULLY"); + log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); + } + clear_iob(csp->client_iob); } - clear_iob(csp->client_iob); + } + else + { + list_remove_all(csp->headers); + write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)); + ret = create_client_ssl_connection(csp); } log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); @@ -3632,7 +3683,7 @@ static void chat(struct client_state *csp) * We have created SSL connection with client and server, so now we can receive * client request header over ssl, filter it and send it to the server. */ - if (csp->http->ssl && !csp->use_ssl_tunnel) + if ((csp->http->ssl && !csp->use_ssl_tunnel) || should_send_crunch_rsp) { if (process_client_request(csp)) { @@ -3648,15 +3699,23 @@ static void chat(struct client_state *csp) log_applied_actions(csp->action); - if (send_http_request(csp)) + if (should_send_crunch_rsp) + { + crunch_response_triggered(csp, crunchers_all); + return; + } + else { - rsp = error_response(csp, "connect-failed"); - if (rsp) + if (send_http_request(csp)) { - send_crunch_response(csp, rsp); + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + close_client_and_server_ssl_connections(csp); + return; } - close_client_and_server_ssl_connections(csp); - return; } } -- 2.26.2 From 51946d40f052d7ff4d58142e8a7bee9b90b76050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:03:57 +0200 Subject: [PATCH 60/83] Added CONNECT into supported method. No error log will be loged. --- cgi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cgi.c b/cgi.c index 75228285..5dd5d2ba 100644 --- a/cgi.c +++ b/cgi.c @@ -399,7 +399,8 @@ struct http_response *dispatch_cgi(struct client_state *csp) } if (strcmpic(csp->http->gpc, "GET") - && strcmpic(csp->http->gpc, "HEAD")) + && strcmpic(csp->http->gpc, "HEAD") + && strcmpic(csp->http->gpc, "CONNECT")) { log_error(LOG_LEVEL_ERROR, "CGI request with unsupported method received: %s", csp->http->gpc); -- 2.26.2 From aba5d61f1bc1cd2854c78cf2ea3414415b59eeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:14:49 +0200 Subject: [PATCH 61/83] Edited functions to create and close ssl connections to set all flags and variables needed for keeping ssl session alive. Changed functions (server|client)_use_ssl() to check, whether ssl connection is really opened and ready to be used. Added new variables for ssl session reuse into http_request, client_state and reusable_connection structures. --- project.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ ssl_libressl.c | 41 +++++++++++++++++++++++++++++++--------- ssl_libressl.h | 3 +++ 3 files changed, 86 insertions(+), 9 deletions(-) diff --git a/project.h b/project.h index 50e0960c..40b62818 100644 --- a/project.h +++ b/project.h @@ -345,6 +345,7 @@ struct http_request int server_ssl; unsigned char hash_of_host_hex[(HASH_OF_HOST_BUF_SIZE * 2) + 1]; /**< chars for hash in hex string and one for '\0' */ unsigned char hash_of_host[HASH_OF_HOST_BUF_SIZE + 1]; /**< chars for bytes of hash and one for '\0' */ + int should_be_crunched; /* TRUE when crunch response should be send */ }; #ifdef FEATURE_MBEDTLS @@ -771,6 +772,7 @@ struct reusable_connection { jb_socket sfd; int in_use; + int ssl; /* connection use ssl */ time_t timestamp; /* XXX: rename? */ time_t request_sent; @@ -794,6 +796,14 @@ struct reusable_connection int gateway_port; char *forward_host; int forward_port; + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* Client connect request is kept here to be prepared in case + * when we use parent proxy server and we would have to + * restore ssl connection with server + */ + struct list connect_headers[1]; +#endif }; @@ -968,6 +978,44 @@ struct reusable_connection #define CSP_FLAG_FUZZED_INPUT 0x08000000U #endif +/* + * Flags for use in csp->flags + */ + +/** + * Flag for csp->ssl_flags: Set if ssl connection with server is + * being reused. + */ +#define CSP_SSL_FLAG_SERVER_CONNECTION_REUSED 0x01U + + +/** + * Flag for csp->ssl_flags: Set if ssl connection with client is + * being reused. + */ +#define CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED 0x02U + +/** + * Flag for csp->ssl_flags: Set if we can't close ssl connection + * because of future reusing. + */ +#define CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED 0x04U + + +/** + * Flag for csp->ssl_flags: Set if we should close ssl connection + * with server, because it can be tainted. + */ +#define CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED 0x08U + + +/** + * Flag for csp->ssl_flags: Set if we should close ssl connection + * with server and no reason is specified. + */ +#define CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION 0x10U + + /* * Flags for use in return codes of child processes */ @@ -1019,6 +1067,9 @@ struct client_state /** Multi-purpose flag container, see CSP_FLAG_* above */ unsigned int flags; + /** Multi-purpose flag container, see CSP_SSL_FLAG_* above */ + unsigned int ssl_flags; + /** Client PC's IP address, as reported by the accept() function. As a string. */ char *ip_addr_str; diff --git a/ssl_libressl.c b/ssl_libressl.c index 185ac2e8..7d8bcd79 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -192,6 +192,11 @@ extern int create_server_ssl_connection(struct client_state *csp) BIO_set_ssl(csp->ssl_server_attr.ssl_bio, csp->ssl_server_attr.ssl, BIO_CLOSE); csp->ssl_with_server_is_opened = 1; + csp->server_connection.ssl = 1; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags &= ~CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED; + csp->ssl_flags &= ~CSP_SSL_FLAG_SERVER_CONNECTION_REUSED; +#endif ret = 0; exit: if (ret == -1) { @@ -236,11 +241,17 @@ static void free_server_ssl_structures(struct client_state *csp) * Returns : N/A * **********************************************************************/ -static void close_server_ssl_connection(struct client_state *csp) +extern void close_server_ssl_connection(struct client_state *csp) { int ret = 0; - - if (csp->ssl_with_server_is_opened == 0) + + if (csp->ssl_with_server_is_opened == 0 +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + || (csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED + && !(csp->ssl_flags & CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED) + && !(csp->ssl_flags & CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION)) +#endif + ) { return; } @@ -252,6 +263,11 @@ static void close_server_ssl_connection(struct client_state *csp) free_server_ssl_structures(csp); csp->ssl_with_server_is_opened = 0; + csp->server_connection.ssl = 0; + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags &= ~CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION; +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ } @@ -289,11 +305,15 @@ static void free_client_ssl_structures(struct client_state *csp) * Returns : N/A * *********************************************************************/ -static void close_client_ssl_connection(struct client_state *csp) +extern void close_client_ssl_connection(struct client_state *csp) { int ret = 0; - - if (csp->ssl_with_client_is_opened == 0) + + if (csp->ssl_with_client_is_opened == 0 +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + || csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED +#endif + ) { return; } @@ -465,6 +485,9 @@ extern int create_client_ssl_connection(struct client_state *csp) { BIO_set_ssl(csp->ssl_client_attr.ssl_bio, csp->ssl_client_attr.ssl, BIO_CLOSE); csp->ssl_with_client_is_opened = 1; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags &= ~CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED; +#endif ret = 0; exit: if (ret != 0) { @@ -491,7 +514,7 @@ exit: *********************************************************************/ extern int client_use_ssl(struct client_state *csp) { - return csp->http->client_ssl; + return csp->ssl_with_client_is_opened; } @@ -511,7 +534,7 @@ extern int client_use_ssl(struct client_state *csp) *********************************************************************/ extern int server_use_ssl(struct client_state *csp) { - return csp->http->server_ssl; + return csp->ssl_with_server_is_opened; } @@ -633,7 +656,7 @@ exit: * * Function : is_ssl_pending * - * Description : Returns return the number of pending characters in + * Description : Returns the number of pending characters in * the BIO's read and write buffers. * * Parameters : diff --git a/ssl_libressl.h b/ssl_libressl.h index ada709a1..35601d2a 100644 --- a/ssl_libressl.h +++ b/ssl_libressl.h @@ -51,5 +51,8 @@ extern void ssl_send_certificate_error(struct client_state *csp); extern int create_client_ssl_connection(struct client_state *csp); extern int create_server_ssl_connection(struct client_state *csp); extern void close_client_and_server_ssl_connections(struct client_state *csp); +extern void close_server_ssl_connection(struct client_state *csp); +extern void close_client_ssl_connection(struct client_state *csp); + #endif /* ndef SSL_LIBRESSL_H_INCLUDED */ \ No newline at end of file -- 2.26.2 From bd7ee06f046580dcb087692c77a317ca99263e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:16:51 +0200 Subject: [PATCH 62/83] Added function connection_is_still_alive which checks also state of ssl connection when it's used. SSL variable in reusable_connection structure in gateway.c is set, cleaned and checked when reused_connection is stored, closed or compared. Cleaning ssl variable in urlmatch.c when client request starts with 'http://', because previous client request could be over ssl. --- gateway.c | 5 ++++- jbsockets.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ jbsockets.h | 1 + urlmatch.c | 4 +++- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/gateway.c b/gateway.c index c84e3b28..ccb12ede 100644 --- a/gateway.c +++ b/gateway.c @@ -222,6 +222,7 @@ void remember_connection(const struct reusable_connection *connection) reusable_connection[slot].host = strdup_or_die(connection->host); reusable_connection[slot].sfd = connection->sfd; reusable_connection[slot].port = connection->port; + reusable_connection[slot].ssl = connection->ssl; reusable_connection[slot].in_use = 0; reusable_connection[slot].timestamp = connection->timestamp; reusable_connection[slot].request_sent = connection->request_sent; @@ -289,6 +290,7 @@ void mark_connection_closed(struct reusable_connection *closed_connection) closed_connection->gateway_port = 0; freez(closed_connection->forward_host); closed_connection->forward_port = 0; + closed_connection->ssl = 0; } @@ -359,7 +361,8 @@ int connection_destination_matches(const struct reusable_connection *connection, if ((connection->forwarder_type != fwd->type) || (connection->gateway_port != fwd->gateway_port) || (connection->forward_port != fwd->forward_port) - || (connection->port != http->port)) + || (connection->port != http->port) + || (connection->ssl != http->ssl)) { return FALSE; } diff --git a/jbsockets.c b/jbsockets.c index b4bed371..5a25fab1 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1681,6 +1681,66 @@ int socket_is_still_alive(jb_socket sfd) } + +/********************************************************************* + * + * Function : connection_is_still_alive + * + * Description : Figures out whether or not a specified connection + * is still alive. Including test of ssl connection. + * (Whether "close notify" alert was received) + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : src = Value from communication_side enum + * + * Returns : TRUE for yes, otherwise FALSE. + * + *********************************************************************/ +extern int connection_is_still_alive(const struct client_state *csp, int src) +{ +#if defined(FEATURE_MBEDTLS) || defined(FEATURE_LIBRESSL) + int is_using_ssl = 0; + SSL *ssl; + char tmp[10]; + + if (src == CLIENT) + { + is_using_ssl = csp->ssl_with_client_is_opened; + ssl = csp->ssl_client_attr.ssl; + } + else if (src == SERVER) + { + is_using_ssl = csp->ssl_with_server_is_opened; + ssl = csp->ssl_server_attr.ssl; + } + + /* + * We have to call data_is_available_tcp_ssl and SSL_peek, because + * it loads SSL shutdown flag, which signals whether "close notify" + * alert was received or not. + */ + if (is_using_ssl && data_is_available_tcp_ssl(csp, src, 0)) { + SSL_peek(ssl, tmp, 1); + if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) + { + return FALSE; + } + } +#endif + if (src == CLIENT) + { + return socket_is_still_alive(csp->cfd); + } + else if (src == SERVER) + { + return socket_is_still_alive(csp->server_connection.sfd); + } + + return FALSE; +} + + #ifdef FEATURE_EXTERNAL_FILTERS /********************************************************************* * @@ -1925,6 +1985,7 @@ extern int flush_socket(const struct client_state *csp, int dest, struct iob *io *********************************************************************/ extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, int seconds_to_wait) { int ret = 0; + if (src == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS diff --git a/jbsockets.h b/jbsockets.h index 6fdbc429..63b50d7c 100644 --- a/jbsockets.h +++ b/jbsockets.h @@ -61,6 +61,7 @@ extern void get_host_information(jb_socket afd, char **ip_address, char **port, extern unsigned long resolve_hostname_to_ip(const char *host); extern int socket_is_still_alive(jb_socket sfd); +extern int connection_is_still_alive(const struct client_state *csp, int src); #ifdef FEATURE_EXTERNAL_FILTERS extern void mark_socket_for_close_on_execute(jb_socket fd); diff --git a/urlmatch.c b/urlmatch.c index 0a6b7478..65e411e6 100644 --- a/urlmatch.c +++ b/urlmatch.c @@ -260,6 +260,7 @@ jb_err parse_http_url(const char *url, struct http_request *http, int require_pr if (strncmpic(url_noproto, "http://", 7) == 0) { url_noproto += 7; + http->ssl = 0; } else if (strncmpic(url_noproto, "https://", 8) == 0) { @@ -279,7 +280,8 @@ jb_err parse_http_url(const char *url, struct http_request *http, int require_pr * When we are receiving http request over ssl, there is * no host, but we should have it from CONNECT request. */ - if (http->client_ssl == 0) { + if (http->client_ssl == 0) + { http->host = NULL; } host_available = 0; -- 2.26.2 From 6d227c3dcd14aa3443240c0f2fa9416cdc00eb9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:17:44 +0200 Subject: [PATCH 63/83] Changed client request processing, when request was received over reused ssl connection. When we have reused ssl connection, we already know destination and we receive only relative URI in request. We also have to set all flags when reusing ssl connection, change behaving for ssl tunnels and do other smaller changes. --- jcc.c | 57 ++++++++++++++++++++++++++++++++++++------------------- parsers.c | 27 +++++++++++++++++++++++--- parsers.h | 2 +- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/jcc.c b/jcc.c index 041d951e..b0ee529d 100644 --- a/jcc.c +++ b/jcc.c @@ -571,7 +571,12 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct { char *req; - if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS)) + if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS) +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* When ssl sesions are reused, we get only relative URI */ + && !(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED) +#endif + ) { log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid." " Privoxy isn't configured to accept intercepted requests.", @@ -586,7 +591,13 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct return JB_ERR_PARSE; } - else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http)) + else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http, +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + (csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED) != 0 +#else + FALSE +#endif + )) { #ifndef FEATURE_EXTENDED_HOST_PATTERNS /* Split the domain we just got for pattern matching */ @@ -1666,7 +1677,10 @@ static char *get_request_line(struct client_state *csp) } len = recv_data(csp, CLIENT, (unsigned char*)buf, sizeof(buf) - 1); - if (len <= 0) return NULL; + if (len <= 0) + { + return NULL; + } /* * If there is no memory left for buffering the @@ -2039,6 +2053,7 @@ static jb_err receive_client_request(struct client_state *csp) /* grab the rest of the client's headers */ init_list(headers); + for (;;) { p = get_header(csp->client_iob); @@ -2177,14 +2192,13 @@ static jb_err parse_client_request(struct client_state *csp) #ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) - && (!strcmpic(csp->http->ver, "HTTP/1.1")) - && (csp->http->ssl == 0)) + && (!strcmpic(csp->http->ver, "HTTP/1.1"))) { /* Assume persistence until further notice */ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; } - if (csp->http->ssl == 0) + if (!csp->use_ssl_tunnel) { /* * This whole block belongs to chat() but currently @@ -2205,6 +2219,10 @@ static jb_err parse_client_request(struct client_state *csp) } else { + /* + * It's ssl connection with tunnel, so we want to close connection + * when session ends. + */ csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ @@ -3376,7 +3394,7 @@ static void handle_established_connection(struct client_state *csp) * * Request can be received over tcp or ssl connection. * Source will depend on the variable - * csp->http->client_ssl. + * csp->ssl_with_client_is_opened. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) @@ -3396,6 +3414,15 @@ static int process_client_request(struct client_state *csp) { return 1; } + /* + * Setting flags to use old solution with SSL tunel and to disable + * certificates verification. + */ + if (http->ssl && csp->action->flags & ACTION_DISABLE_HTTPS_FILTER) + { + csp->use_ssl_tunnel = 1; + } + if (parse_client_request(csp) != JB_ERR_OK) { log_error(LOG_LEVEL_ERROR, "Parsing client request failed"); @@ -3413,24 +3440,16 @@ static int process_client_request(struct client_state *csp) { return 1; } - /* - * Setting flags to use old solution with SSL tunel and to disable - * certificates verification. - */ - if (http->ssl && csp->action->flags & ACTION_DISABLE_HTTPS_FILTER) - { - csp->use_ssl_tunnel = 1; - } - if (http->ssl && csp->action->flags & ACTION_IGNORE_CERTIFICATE_ERRORS) { csp->dont_verify_certificate = 1; } /* - * Presetting SSL client and server flags + * Presetting SSL client and server flags when ssl will be used. + * No matter who will create it. (client or proxy) */ - if (http->ssl && !csp->use_ssl_tunnel) + if (http->ssl) { http->client_ssl = 1; http->server_ssl = 1; @@ -3475,8 +3494,6 @@ static void chat(struct client_state *csp) int ret = 0; http = csp->http; - http->client_ssl = 0; - http->server_ssl = 0; csp->dont_verify_certificate = 0; ret = process_client_request(csp); diff --git a/parsers.c b/parsers.c index f56345fe..a9eb3b09 100644 --- a/parsers.c +++ b/parsers.c @@ -4408,7 +4408,8 @@ static jb_err parse_time_header(const char *header, time_t *result) * * Description : Parse the "Host:" header to get the request's destination. * Only needed if the client's request was forcefully - * redirected into Privoxy. + * redirected into Privoxy or when https request was received + * from reused client connection. * * Code mainly copied from client_host() which is currently * run too late for this purpose. @@ -4417,13 +4418,15 @@ static jb_err parse_time_header(const char *header, time_t *result) * 1 : headers = List of headers (one of them hopefully being * the "Host:" header) * 2 : http = storage for the result (host, port and hostport). + * 3 : reused_ssl_connection = TRUE when headers were received over + * reused ssl connection * * Returns : JB_ERR_MEMORY (or terminates) in case of memory problems, * JB_ERR_PARSE if the host header couldn't be found, * JB_ERR_OK otherwise. * *********************************************************************/ -jb_err get_destination_from_headers(const struct list *headers, struct http_request *http) +jb_err get_destination_from_headers(const struct list *headers, struct http_request *http, const int reused_ssl_connection) { char *q; char *p; @@ -4454,7 +4457,25 @@ jb_err get_destination_from_headers(const struct list *headers, struct http_requ } else { - http->port = 80; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (reused_ssl_connection) + { + http->port = 443; + } + else +#endif + { + http->port = 80; + } + } + + /* + * When connection is reused, we shouldn't send requests with + * absolute URIs, because destination is already known. + */ + if (reused_ssl_connection) + { + return JB_ERR_OK; } /* Rebuild request URL */ diff --git a/parsers.h b/parsers.h index d4cfc1c1..03243742 100644 --- a/parsers.h +++ b/parsers.h @@ -58,7 +58,7 @@ extern char *get_header_value(const struct list *header_list, const char *header extern jb_err sed(struct client_state *csp, int filter_server_headers); extern jb_err update_server_headers(struct client_state *csp); extern void get_http_time(int time_offset, char *buf, size_t buffer_size); -extern jb_err get_destination_from_headers(const struct list *headers, struct http_request *http); +extern jb_err get_destination_from_headers(const struct list *headers, struct http_request *http, const int reused_ssl_connection); extern unsigned long long get_expected_content_length(struct list *headers); extern jb_err client_transfer_encoding(struct client_state *csp, char **header); -- 2.26.2 From f8228957baa9942273b0ab449178411ba79a51c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:19:47 +0200 Subject: [PATCH 64/83] Changed creating of server connection. Added check, whether ssl connection is alive when it should be reused. Also changed behaving when parent proxy server is used and it's connection already timeouted. Then proxy tries to restore this connection. --- jcc.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/jcc.c b/jcc.c index b0ee529d..9a8fe2e8 100644 --- a/jcc.c +++ b/jcc.c @@ -747,7 +747,7 @@ static int create_server_connection(struct client_state *csp) { #ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->server_connection.sfd != JB_INVALID_SOCKET) - && socket_is_still_alive(csp->server_connection.sfd) + && connection_is_still_alive(csp, SERVER) && connection_destination_matches(&csp->server_connection, http, fwd)) { log_error(LOG_LEVEL_CONNECT, @@ -767,11 +767,18 @@ static int create_server_connection(struct client_state *csp) { else #endif /* def FEATURE_CONNECTION_SHARING */ { + /* + * Connection with server is not alive anymore. We can close it, + * and then we can open new one to the same destination. + */ log_error(LOG_LEVEL_CONNECT, - "Closing server socket %d connected to %s. Total requests: %u.", + "Closing server ssl connection and server socket %d " + "connected to %s. Total requests: %u.", csp->server_connection.sfd, csp->server_connection.host, csp->server_connection.requests_sent_total); - close_socket(csp->server_connection.sfd); + csp->ssl_flags |= CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION; + close_server_ssl_connection(csp); + drain_and_close_socket(csp->server_connection.sfd); } mark_connection_closed(&csp->server_connection); } @@ -834,7 +841,34 @@ static int create_server_connection(struct client_state *csp) { char server_response[BUFFER_SIZE]; int ret = 0; int len = 0; - char *hdr = list_to_text(csp->headers); + char *hdr = NULL; + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED) + { + /* + * Connection with parent proxy is going to be restored, + * so we have to send CONNECT request first. + */ + hdr = list_to_text(csp->server_connection.connect_headers); + log_error(LOG_LEVEL_CONNECT, "Going to restore ssl connection with parent proxy" + "- sending original CONNECT request."); + } + else + { +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + hdr = list_to_text(csp->headers); +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* + * Creating copy of CONNECT header for ssl connection restoring. + */ + if (csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED) + { + list_duplicate(csp->server_connection.connect_headers, csp->headers); + } + list_remove_all(csp->headers); + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ memset(server_response, 0, sizeof(server_response)); if (hdr == NULL) @@ -921,18 +955,27 @@ static int create_server_connection(struct client_state *csp) { return 1; } - +#ifdef FEATURE_CONNECTION_KEEP_ALIVE /* - * SSL/TLS connection with parent proxy is established, we can - * inform client about success. + * When ssl connection with client is reused, client has no + * idea about server connection restoring so we can't send + * information about it to him. */ - ret = write_socket(csp->cfd, server_response, len); - if (ret != 0) + if (!(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED)) +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ { - log_error(LOG_LEVEL_ERROR, - "Sending parent proxy response to client failed"); - mark_server_socket_tainted(csp); - return 1; + /* + * SSL/TLS connection with parent proxy is established, we can + * inform client about success. + */ + ret = write_socket(csp->cfd, server_response, len); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Sending parent proxy response to client failed"); + mark_server_socket_tainted(csp); + return 1; + } } } else @@ -966,7 +1009,6 @@ static int create_server_connection(struct client_state *csp) { return 1; } - log_error(LOG_LEVEL_CONNECT, "SSL connection with server was created successfully"); } } -- 2.26.2 From 15f6676481759acec65cf2913e99e41c4a8adedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:20:55 +0200 Subject: [PATCH 65/83] Setting flags for ssl sessions reusing at the begining of chat function. Crunch responses over reused ssl connection with client are send immediatelly. Added check if client ssl connection is already created, to avoid second connection openning. When connection is reused, we didn't received CONNECT request so received client requests are sent immediately to server and then is called function handle_established_connection. Fixed bug - removed list items freeing, which was redundant. --- jcc.c | 197 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 68 deletions(-) diff --git a/jcc.c b/jcc.c index 9a8fe2e8..b2c3b57b 100644 --- a/jcc.c +++ b/jcc.c @@ -876,7 +876,6 @@ static int create_server_connection(struct client_state *csp) { log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header"); } - list_remove_all(csp->headers); /* * Sending client's CONNECT request to the parent proxy @@ -3532,14 +3531,33 @@ static void chat(struct client_state *csp) /* Skeleton for HTTP response, if we should intercept the request */ struct http_response *rsp; struct http_response *crunch_rsp; - int should_send_crunch_rsp = FALSE; + int should_prepare_crunch_rsp = FALSE; int ret = 0; http = csp->http; csp->dont_verify_certificate = 0; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* + * Setting flags when we should reuse ssl connections and we have + * already created ssl connection which we are reusing. + */ + if (csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED) + { + if (csp->ssl_with_client_is_opened) + { + csp->ssl_flags |= CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED; + } + if (csp->ssl_with_server_is_opened) + { + csp->ssl_flags |= CSP_SSL_FLAG_SERVER_CONNECTION_REUSED; + } + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + ret = process_client_request(csp); - if (ret != 0) { + if (ret != 0) + { return; } fwd = csp->use_fwd; @@ -3608,8 +3626,13 @@ static void chat(struct client_state *csp) /* * We have a request. Check if one of the crunchers wants it. */ - should_send_crunch_rsp = should_trigger_crunch_response(csp, crunchers_all, !http->ssl, &crunch_rsp); - if (should_send_crunch_rsp && !http->ssl) +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + should_prepare_crunch_rsp = csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED || !http->ssl; +#else + should_prepare_crunch_rsp = !http->ssl; +#endif + http->should_be_crunched = should_trigger_crunch_response(csp, crunchers_all, should_prepare_crunch_rsp, &crunch_rsp); + if (http->should_be_crunched && should_prepare_crunch_rsp) { send_crunch_response(csp, crunch_rsp); /* @@ -3634,7 +3657,8 @@ static void chat(struct client_state *csp) /* * Preparing connection with requested server. */ - if (!should_send_crunch_rsp) { + if (!http->should_be_crunched) + { ret = create_server_connection(csp); if (ret != 0) { @@ -3643,100 +3667,137 @@ static void chat(struct client_state *csp) csp->server_connection.requests_sent_total++; } - if (!should_send_crunch_rsp) +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* + * When we are reusing connection with client, we don't want + * to creat new connection again. + */ + if (!(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED)) { - if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) - { - /* Client headers have been sent optimistically */ - assert(csp->headers->last == NULL); - } - else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + if (!http->should_be_crunched) { - if (send_http_request(csp)) + if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) { - rsp = error_response(csp, "connect-failed"); - if (rsp) - { - send_crunch_response(csp, rsp); - } - return; + /* Client headers have been sent optimistically */ + assert(csp->headers->last == NULL); } - } - else - { - /* - * Using old solution with SSL tunnel or new solution with SSL proxy - */ - list_remove_all(csp->headers); - if (csp->use_ssl_tunnel) + else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) { - /* - * We're running an SSL tunnel and we're not forwarding, - * so just ditch the client headers, send the "connect succeeded" - * message to the client, flush the rest, and get out of the way. - */ - if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + if (send_http_request(csp)) { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } return; } } else { /* - * Creating an SSL proxy. If forwarding is disabled, we must send - * CSUCCEED mesage to client. Then SSL/TLS connection with client - * is created. + * Using old solution with SSL tunnel or new solution with SSL proxy */ - - if (fwd->forward_host == NULL) + list_remove_all(csp->headers); + if (csp->use_ssl_tunnel) { + /* + * We're running an SSL tunnel and we're not forwarding, + * so just ditch the client headers, send the "connect succeeded" + * message to the client, flush the rest, and get out of the way. + */ if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) { - log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); return; } } - - ret = create_client_ssl_connection(csp); - if (ret != 0) + else { - log_error(LOG_LEVEL_ERROR, - "Can't open secure connection with client"); - close_client_and_server_ssl_connections(csp); - return; - } + /* + * Creating an SSL proxy. If forwarding is disabled, we must send + * CSUCCEED mesage to client. Then SSL/TLS connection with client + * is created. + */ - /* - * If server certificate is invalid, we must inform client and then - * close connection with client. - */ + if (fwd->forward_host == NULL) + { + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); + return; + } + } + + ret = create_client_ssl_connection(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Can't open secure connection with client"); +#ifndef FEATURE_CONNECTION_KEEP_ALIVE + close_client_and_server_ssl_connections(csp); +#endif + return; + } + + /* + * If server certificate is invalid, we must inform client and then + * close connection with client. + */ #ifdef FEATURE_MBEDTLS - if (csp->server_cert_verification_result != SSL_CERT_VALID) + if (csp->server_cert_verification_result != SSL_CERT_VALID) #elif defined(FEATURE_LIBRESSL) - if (csp->server_cert_verification_result != X509_V_OK) + if (csp->server_cert_verification_result != X509_V_OK) #endif #if defined(FEATURE_MBEDTLS) || defined(FEATURE_LIBRESSL) - { - ssl_send_certificate_error(csp); - close_client_and_server_ssl_connections(csp); - return; - } + { + ssl_send_certificate_error(csp); + close_client_and_server_ssl_connections(csp); + return; + } #endif - log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); + log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); + } + clear_iob(csp->client_iob); } - clear_iob(csp->client_iob); + log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); } + else + { + list_remove_all(csp->headers); + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); + return; + } + ret = create_client_ssl_connection(csp); + } +#ifdef FEATURE_CONNECTION_KEEP_ALIVE } - else + else { - list_remove_all(csp->headers); - write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)); - ret = create_client_ssl_connection(csp); + /* + * Sending client's request to server, when SSL connection is reused. + */ + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); + + if (send_http_request(csp)) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + mark_server_socket_tainted(csp); + close_client_and_server_ssl_connections(csp); + return; + } } - - log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ /* * We have created SSL connection with client and server, so now we can receive -- 2.26.2 From 338d38acf171b88c3954353cdddfb62fc9422d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:22:34 +0200 Subject: [PATCH 66/83] When ssl connection is reused, second request processing is turned off, because there isn't any second request part. When ssl connection is reused and tainted, ssl connections are closed properly. (function serve) Setting ssl_flags when server socket is marked as tainted and before serving new client request. --- jcc.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/jcc.c b/jcc.c index b2c3b57b..cfbd8ed5 100644 --- a/jcc.c +++ b/jcc.c @@ -1646,6 +1646,12 @@ static void mark_server_socket_tainted(struct client_state *csp) csp->server_connection.sfd); } csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (csp->http->server_ssl) + { + csp->ssl_flags |= CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED; + } +#endif } @@ -2586,7 +2592,7 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s", csp->config->socket_timeout, http->url); - if ((byte_count == 0) && (http->ssl == 0)) + if (byte_count == 0) { send_crunch_response(csp, error_response(csp, "connection-timeout")); } @@ -3801,10 +3807,21 @@ static void chat(struct client_state *csp) /* * We have created SSL connection with client and server, so now we can receive - * client request header over ssl, filter it and send it to the server. + * client request header over ssl, filter it and send it to the server. Requests + * from reused SSL connections were already received. */ - if ((csp->http->ssl && !csp->use_ssl_tunnel) || should_send_crunch_rsp) + if (((csp->http->ssl && !csp->use_ssl_tunnel) || http->should_be_crunched) +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + && !(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED) +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + ) { + /* + * Preparing flag for processing HTTPS request, so correct value + * will be given into function handle_established_connection. + */ + csp->flags &= ~CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; + if (process_client_request(csp)) { close_client_and_server_ssl_connections(csp); @@ -3819,7 +3836,7 @@ static void chat(struct client_state *csp) log_applied_actions(csp->action); - if (should_send_crunch_rsp) + if (http->should_be_crunched) { crunch_response_triggered(csp, crunchers_all); return; @@ -4041,7 +4058,8 @@ static void serve(struct client_state *csp) && (csp->cfd != JB_INVALID_SOCKET) && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE) && ((csp->flags & CSP_FLAG_SERVER_CONTENT_LENGTH_SET) - || (csp->flags & CSP_FLAG_CHUNKED)); + || (csp->flags & CSP_FLAG_CHUNKED)) + && !(csp->ssl_flags & CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED); if (!(csp->flags & CSP_FLAG_CRUNCHED) && (csp->server_connection.sfd != JB_INVALID_SOCKET)) @@ -4052,6 +4070,7 @@ static void serve(struct client_state *csp) } if (!(csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE) || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) + || (csp->ssl_flags & CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED) || !socket_is_still_alive(csp->server_connection.sfd) || !(latency < csp->server_connection.keep_alive_timeout)) { @@ -4069,6 +4088,10 @@ static void serve(struct client_state *csp) forget_connection(csp->server_connection.sfd); } #endif /* def FEATURE_CONNECTION_SHARING */ + + /* Setting flag to close ssl connections */ + csp->ssl_flags |= CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION; + close_server_ssl_connection(csp); close_socket(csp->server_connection.sfd); mark_connection_closed(&csp->server_connection); } @@ -4110,8 +4133,8 @@ static void serve(struct client_state *csp) } if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE) - && data_is_available(csp->cfd, (int)csp->config->keep_alive_timeout) - && socket_is_still_alive(csp->cfd)) + && data_is_available_tcp_ssl(csp, CLIENT, (int)csp->config->keep_alive_timeout) + && socket_is_still_alive(csp->cfd)) { log_error(LOG_LEVEL_CONNECT, "Client request %u arrived in time on socket %d.", @@ -4148,6 +4171,7 @@ static void serve(struct client_state *csp) privoxy_mutex_unlock(&connection_reuse_mutex); } #endif /* def FEATURE_CONNECTION_SHARING */ + csp->ssl_flags &= ~CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED; break; } } @@ -4170,6 +4194,11 @@ static void serve(struct client_state *csp) chat(csp); #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + /* + * Closing ssl and then tcp connections, if they were opened. + */ + csp->ssl_flags = 0; + close_client_and_server_ssl_connections(csp); if (csp->server_connection.sfd != JB_INVALID_SOCKET) { #ifdef FEATURE_CONNECTION_SHARING @@ -4199,7 +4228,6 @@ static void serve(struct client_state *csp) free_csp_resources(csp); csp->flags &= ~CSP_FLAG_ACTIVE; - } @@ -5241,6 +5269,15 @@ static void listen_loop(void) } #endif /* def FEATURE_ACL */ +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* Setting flag to keep ssl connections opened if possible */ + csp->ssl_flags = 0; + if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) + { + csp->ssl_flags = CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED; + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + if ((0 != config->max_client_connections) && (active_threads >= config->max_client_connections)) { -- 2.26.2 From da65566591bf4f5f7fbb43eb5ee022d3d297952a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:25:32 +0200 Subject: [PATCH 67/83] Removed ssl connection closing after mark_server_socket_tainted, because ssl connections are closed at the end of function serve() when tainted flags are set. Variable ssl_flags and defined flags for it was surrounded by ifdef FEATURE_CONNECTION_KEEP_ALIVE. --- jcc.c | 22 ++-------------------- project.h | 4 ++++ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/jcc.c b/jcc.c index cfbd8ed5..a62bd152 100644 --- a/jcc.c +++ b/jcc.c @@ -2704,7 +2704,6 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Send request over SSL/TLS to: %s failed", http->host); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -2775,7 +2774,6 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "The server still wants to talk, but the client hung up on us."); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; #endif /* def _WIN32 */ } @@ -2821,7 +2819,6 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. " "Unable to tell the client about the problem."); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } /* @@ -2950,7 +2947,6 @@ static void handle_established_connection(struct client_state *csp) freez(hdr); freez(p); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -2965,7 +2961,6 @@ static void handle_established_connection(struct client_state *csp) freez(hdr); freez(p); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -3025,7 +3020,6 @@ static void handle_established_connection(struct client_state *csp) rsp = cgi_error_memory(csp->ssl_with_client_is_opened); send_crunch_response(csp, rsp); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } hdrlen = strlen(hdr); @@ -3046,7 +3040,6 @@ static void handle_established_connection(struct client_state *csp) "Flush header and buffers to client failed"); freez(hdr); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -3090,7 +3083,6 @@ static void handle_established_connection(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Sending data to client failed"); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -3101,7 +3093,6 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "write to client failed: %E"); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -3122,7 +3113,6 @@ static void handle_established_connection(struct client_state *csp) rsp = cgi_error_memory(csp->ssl_with_client_is_opened); send_crunch_response(csp, rsp); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } @@ -3157,7 +3147,6 @@ static void handle_established_connection(struct client_state *csp) strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); } mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } else @@ -3203,7 +3192,6 @@ static void handle_established_connection(struct client_state *csp) } free_http_request(http); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } @@ -3243,7 +3231,6 @@ static void handle_established_connection(struct client_state *csp) free_http_request(http); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } @@ -3272,7 +3259,6 @@ static void handle_established_connection(struct client_state *csp) } free_http_request(http); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } hdr = list_to_text(csp->headers); @@ -3307,7 +3293,6 @@ static void handle_established_connection(struct client_state *csp) */ freez(hdr); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } /* Buffer and pcrs filter this if appropriate. */ @@ -3336,7 +3321,6 @@ static void handle_established_connection(struct client_state *csp) */ freez(hdr); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -3353,7 +3337,6 @@ static void handle_established_connection(struct client_state *csp) */ freez(hdr); mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -3391,14 +3374,12 @@ static void handle_established_connection(struct client_state *csp) strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); } mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } continue; } mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; /* huh? we should never get here */ } @@ -3799,7 +3780,6 @@ static void chat(struct client_state *csp) send_crunch_response(csp, rsp); } mark_server_socket_tainted(csp); - close_client_and_server_ssl_connections(csp); return; } } @@ -4197,7 +4177,9 @@ static void serve(struct client_state *csp) /* * Closing ssl and then tcp connections, if they were opened. */ +#ifdef FEATURE_CONNECTION_KEEP_ALIVE csp->ssl_flags = 0; +#endif close_client_and_server_ssl_connections(csp); if (csp->server_connection.sfd != JB_INVALID_SOCKET) { diff --git a/project.h b/project.h index 40b62818..ecdd75a0 100644 --- a/project.h +++ b/project.h @@ -978,6 +978,7 @@ struct reusable_connection #define CSP_FLAG_FUZZED_INPUT 0x08000000U #endif +#ifdef FEATURE_CONNECTION_KEEP_ALIVE /* * Flags for use in csp->flags */ @@ -1015,6 +1016,7 @@ struct reusable_connection */ #define CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION 0x10U +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ /* * Flags for use in return codes of child processes @@ -1067,8 +1069,10 @@ struct client_state /** Multi-purpose flag container, see CSP_FLAG_* above */ unsigned int flags; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE /** Multi-purpose flag container, see CSP_SSL_FLAG_* above */ unsigned int ssl_flags; +#endif /** Client PC's IP address, as reported by the accept() function. As a string. */ -- 2.26.2 From f72d7d5b70dbf2db490fa1c91df17ca5e2014e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:26:44 +0200 Subject: [PATCH 68/83] Replaced socket_is_still_alive for connection_is_still_alive when it's appropriate. So we are checking also whether ssl connection is still alive. --- jcc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/jcc.c b/jcc.c index a62bd152..23b66332 100644 --- a/jcc.c +++ b/jcc.c @@ -1705,7 +1705,7 @@ static char *get_request_line(struct client_state *csp) !data_is_available_tcp_ssl(csp, CLIENT, csp->config->socket_timeout) ) { - if (socket_is_still_alive(csp->cfd)) + if (connection_is_still_alive(csp, CLIENT)) { log_error(LOG_LEVEL_CONNECT, "No request line on socket %d received in time. Timeout: %d.", @@ -2765,7 +2765,7 @@ static void handle_established_connection(struct client_state *csp) * noticed pretty much right away anyway, so we can reduce the * overhead by skipping the check. */ - if (buffer_and_filter_content && !socket_is_still_alive(csp->cfd)) + if (buffer_and_filter_content && !connection_is_still_alive(csp, CLIENT)) { #ifdef _WIN32 log_error(LOG_LEVEL_CONNECT, @@ -4051,7 +4051,7 @@ static void serve(struct client_state *csp) if (!(csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE) || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) || (csp->ssl_flags & CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED) - || !socket_is_still_alive(csp->server_connection.sfd) + || !connection_is_still_alive(csp, SERVER) || !(latency < csp->server_connection.keep_alive_timeout)) { log_error(LOG_LEVEL_CONNECT, @@ -4060,7 +4060,7 @@ static void serve(struct client_state *csp) csp->server_connection.sfd, csp->server_connection.host, 0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE), 0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED), - socket_is_still_alive(csp->server_connection.sfd), + connection_is_still_alive(csp, SERVER), csp->server_connection.keep_alive_timeout); #ifdef FEATURE_CONNECTION_SHARING if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) @@ -4086,7 +4086,7 @@ static void serve(struct client_state *csp) if (continue_chatting) { if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0) - && socket_is_still_alive(csp->cfd)) + && connection_is_still_alive(csp, CLIENT)) { log_error(LOG_LEVEL_CONNECT, "Client request %d has been " "pipelined on socket %d and the socket is still alive.", @@ -4114,7 +4114,7 @@ static void serve(struct client_state *csp) if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE) && data_is_available_tcp_ssl(csp, CLIENT, (int)csp->config->keep_alive_timeout) - && socket_is_still_alive(csp->cfd)) + && connection_is_still_alive(csp, CLIENT)) { log_error(LOG_LEVEL_CONNECT, "Client request %u arrived in time on socket %d.", @@ -4126,7 +4126,7 @@ static void serve(struct client_state *csp) #ifdef FEATURE_CONNECTION_SHARING if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) && (csp->server_connection.sfd != JB_INVALID_SOCKET) - && (socket_is_still_alive(csp->server_connection.sfd))) + && (connection_is_still_alive(csp, SERVER))) { time_t time_open = time(NULL) - csp->server_connection.timestamp; @@ -4164,7 +4164,7 @@ static void serve(struct client_state *csp) csp->server_connection.sfd, csp->server_connection.host, 0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE), 0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED), - socket_is_still_alive(csp->server_connection.sfd), + connection_is_still_alive(csp, SERVER), csp->server_connection.keep_alive_timeout, config_file_change_detected); } -- 2.26.2 From 9826554914aaceb76a2966c133fa4c4e09615d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:28:37 +0200 Subject: [PATCH 69/83] Function connection_is_still_alive adapted to work with mbedtls. (To check close notification) Added macro FEATURE_SSL in configuration, which is set when any ssl library is set. Setting ssl_flags in mbedtls functions and other changes in mbedtls functions to enable ssl sessions reusing. --- acconfig.h | 3 +++ configure.in | 6 +++++ jbsockets.c | 50 ++++++++++++++++++++++++++++++++--------- jbsockets.h | 4 ++-- jcc.c | 13 ++++++----- ssl.c | 61 +++++++++++++++++++++++++++++++++----------------- ssl.h | 16 +++++++------ ssl_libressl.c | 12 +++++----- 8 files changed, 113 insertions(+), 52 deletions(-) diff --git a/acconfig.h b/acconfig.h index 5cdd1290..08eba4ae 100644 --- a/acconfig.h +++ b/acconfig.h @@ -134,6 +134,9 @@ /* Allow Privoxy to use mbedtls for SSL comunication and filtering. */ #undef FEATURE_MBEDTLS +/* Some SSL library is allowed to be used. */ +#undef FEATURE_SSL + /* * Allow filtering with scripts and programs. */ diff --git a/configure.in b/configure.in index da4a264e..2908a8ba 100644 --- a/configure.in +++ b/configure.in @@ -1096,22 +1096,28 @@ AC_ARG_ENABLE(mbedtls, [enablembedtls=$enableval], [enablembedtls=no]) +USAGE_SSL= if test $enablembedtls = yes; then echo Enabling mbedtls. AC_DEFINE(FEATURE_MBEDTLS) + AC_DEFINE(FEATURE_SSL) USAGE_MBEDTLS= USAGE_LIBRESSL=# else if test $disablelibressl = no; then echo Enabling libressl. AC_DEFINE(FEATURE_LIBRESSL) + AC_DEFINE(FEATURE_SSL) USAGE_MBEDTLS=# USAGE_LIBRESSL= + else + USAGE_SSL=# fi fi AC_SUBST(USAGE_MBEDTLS) AC_SUBST(USAGE_LIBRESSL) +AC_SUBST(USAGE_SSL) dnl ================================================================= dnl END of SSL libraries diff --git a/jbsockets.c b/jbsockets.c index 5a25fab1..9391cef6 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1697,37 +1697,65 @@ int socket_is_still_alive(jb_socket sfd) * Returns : TRUE for yes, otherwise FALSE. * *********************************************************************/ -extern int connection_is_still_alive(const struct client_state *csp, int src) +extern int connection_is_still_alive(struct client_state *csp, int src) { -#if defined(FEATURE_MBEDTLS) || defined(FEATURE_LIBRESSL) - int is_using_ssl = 0; +#ifdef FEATURE_SSL +#ifdef FEATURE_LIBRESSL SSL *ssl; - char tmp[10]; +#endif +#ifdef FEATURE_MBEDTLS + mbedtls_ssl_context *ssl; +#endif + int is_using_ssl = 0; + unsigned char tmp[10]; if (src == CLIENT) { is_using_ssl = csp->ssl_with_client_is_opened; +#ifdef FEATURE_LIBRESSL ssl = csp->ssl_client_attr.ssl; +#endif +#ifdef FEATURE_MBEDTLS + ssl = &csp->ssl_client_attr.ssl; +#endif } else if (src == SERVER) { is_using_ssl = csp->ssl_with_server_is_opened; +#ifdef FEATURE_LIBRESSL ssl = csp->ssl_server_attr.ssl; +#endif +#ifdef FEATURE_MBEDTLS + ssl = &csp->ssl_server_attr.ssl; +#endif } - /* - * We have to call data_is_available_tcp_ssl and SSL_peek, because - * it loads SSL shutdown flag, which signals whether "close notify" - * alert was received or not. - */ if (is_using_ssl && data_is_available_tcp_ssl(csp, src, 0)) { +#ifdef FEATURE_MBEDTLS + /* + * mbedtls_ssl_read reads available data and checks connection state. + * When connection was closed by peer, closure notifice is returned. + * Otherway, no chars are set to given buffer and stay pending. + */ + if (mbedtls_ssl_read(ssl, tmp, 0) == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + return FALSE; + } +#endif /* def FEATURE_MBEDTLS */ +#ifdef FEATURE_LIBRESSL + /* + * We have to call data_is_available_tcp_ssl and SSL_peek, because + * it loads SSL shutdown flag, which signals whether "close notify" + * alert was received or not. + */ SSL_peek(ssl, tmp, 1); if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) { return FALSE; } +#endif /* def FEATURE_LIBRESSL */ } -#endif +#endif /* def FEATURE_SSL */ + if (src == CLIENT) { return socket_is_still_alive(csp->cfd); @@ -1806,7 +1834,7 @@ void mark_socket_for_close_on_execute(jb_socket fd) * value on error. * *********************************************************************/ -extern int recv_data(const struct client_state *csp, int src, unsigned char *buf, int maxLen) { +extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int maxLen) { if (src == CLIENT) { #if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS diff --git a/jbsockets.h b/jbsockets.h index 63b50d7c..a2934ee2 100644 --- a/jbsockets.h +++ b/jbsockets.h @@ -61,14 +61,14 @@ extern void get_host_information(jb_socket afd, char **ip_address, char **port, extern unsigned long resolve_hostname_to_ip(const char *host); extern int socket_is_still_alive(jb_socket sfd); -extern int connection_is_still_alive(const struct client_state *csp, int src); +extern int connection_is_still_alive(struct client_state *csp, int src); #ifdef FEATURE_EXTERNAL_FILTERS extern void mark_socket_for_close_on_execute(jb_socket fd); #endif extern int send_data_delayed(const struct client_state *csp, int destination, const char *buf, int len, int delay); -extern int recv_data(const struct client_state *csp, int source, unsigned char *buf, int maxLen); +extern int recv_data(struct client_state *csp, int source, unsigned char *buf, int maxLen); extern int send_data(const struct client_state *csp, int destination, const char *buf, int len); extern int flush_socket(const struct client_state *csp, int destination, struct iob *iob, unsigned int delay); extern int data_is_available_tcp_ssl(const struct client_state *csp, int source, int seconds_to_wait); diff --git a/jcc.c b/jcc.c index 23b66332..17d253d7 100644 --- a/jcc.c +++ b/jcc.c @@ -941,7 +941,8 @@ static int create_server_connection(struct client_state *csp) { #ifdef FEATURE_MBEDTLS && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED || csp->server_cert_verification_result == SSL_CERT_VALID) -#elif defined(FEATURE_LIBRESSL) +#endif +#ifdef FEATURE_LIBRESSL && (csp->server_cert_verification_result == X509_V_OK) #endif ) @@ -995,7 +996,8 @@ static int create_server_connection(struct client_state *csp) { #ifdef FEATURE_MBEDTLS && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED || csp->server_cert_verification_result == SSL_CERT_VALID) -#elif defined(FEATURE_LIBRESSL) +#endif +#ifdef FEATURE_LIBRESSL && (csp->server_cert_verification_result == X509_V_OK) #endif ) @@ -3728,22 +3730,23 @@ static void chat(struct client_state *csp) return; } +#ifdef FEATURE_SSL /* * If server certificate is invalid, we must inform client and then * close connection with client. */ #ifdef FEATURE_MBEDTLS if (csp->server_cert_verification_result != SSL_CERT_VALID) -#elif defined(FEATURE_LIBRESSL) +#endif +#ifdef FEATURE_LIBRESSL if (csp->server_cert_verification_result != X509_V_OK) #endif -#if defined(FEATURE_MBEDTLS) || defined(FEATURE_LIBRESSL) { ssl_send_certificate_error(csp); close_client_and_server_ssl_connections(csp); return; } -#endif +#endif /* def FEATURE_SSL */ log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); } diff --git a/ssl.c b/ssl.c index bb9fcf1b..3f4b7580 100644 --- a/ssl.c +++ b/ssl.c @@ -88,19 +88,18 @@ static int seed_rng(struct client_state *csp); * * Function : client_use_ssl * - * Description : Tests if client in current client state structure should use - * SSL connection or standard connection. + * Description : Tests if ssl connection with client is opened. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * - * Returns : If client should use SSL/TLS connection, 1 is returned. + * Returns : If client uses SSL/TLS connection, 1 is returned. * Otherwise 0 is returned. * *********************************************************************/ extern int client_use_ssl(struct client_state *csp) { - return csp->http->client_ssl; + return csp->ssl_with_client_is_opened; } @@ -108,19 +107,18 @@ extern int client_use_ssl(struct client_state *csp) * * Function : server_use_ssl * - * Description : Tests if server in current client state structure should use - * SSL connection or standard connection. + * Description : Tests if ssl connection with server is opened. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * - * Returns : If server should use SSL/TLS connection, 1 is returned. - * Otherwise 0 is returned. + * Returns : If server uses SSL/TLS connection, 1 is returned. + * Otherwise 0 is returned * *********************************************************************/ extern int server_use_ssl(struct client_state *csp) { - return csp->http->server_ssl; + return csp->ssl_with_server_is_opened; } @@ -137,7 +135,7 @@ extern int server_use_ssl(struct client_state *csp) * >0 => Pending data length * *********************************************************************/ -extern size_t is_ssl_pending(ssl_connection_attr * connection) +extern size_t is_ssl_pending(const ssl_connection_attr * connection) { if (&(connection->ssl) == NULL) { @@ -163,7 +161,7 @@ extern size_t is_ssl_pending(ssl_connection_attr * connection) * Returns : Length of sent data or negative value on error. * *********************************************************************/ -extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * buf, int len) +extern int ssl_send_data(const ssl_connection_attr * connection, const unsigned char * buf, int len) { int ret = 0; char err_buf[ERROR_BUF_SIZE]; @@ -199,7 +197,7 @@ extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * /* * Sending one part of the buffer */ - while ((ret = mbedtls_ssl_write(&connection->ssl, + while ((ret = mbedtls_ssl_write((mbedtls_ssl_context*)&connection->ssl, (const unsigned char *)(buf + pos), send_len)) < 0) { @@ -237,7 +235,7 @@ extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * * nonzero on error. * *********************************************************************/ -extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay) { +extern int ssl_send_data_delayed(const ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay) { size_t i = 0; if (delay == 0) @@ -329,7 +327,7 @@ extern int ssl_recv_data(ssl_connection_attr *connection, unsigned char * buf, i * indicates nothing was sent). On error, -1 is returned. * *********************************************************************/ -extern long ssl_flush_socket(ssl_connection_attr * connection, struct iob *iob) +extern long ssl_flush_socket(const ssl_connection_attr * connection, struct iob *iob) { /* Computing length of buffer part to send*/ long len = iob->eod - iob->cur; @@ -585,7 +583,10 @@ extern int create_client_ssl_connection(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "Client successfully connected over SSL/TLS"); csp->ssl_with_client_is_opened = 1; - +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags &= ~CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED; +#endif + ret = 0; exit: /* * Freeing allocated paths to files @@ -621,11 +622,15 @@ exit: * Returns : N/A * *********************************************************************/ -static void close_client_ssl_connection(struct client_state *csp) +extern void close_client_ssl_connection(struct client_state *csp) { int ret = 0; - if (csp->ssl_with_client_is_opened == 0) + if (csp->ssl_with_client_is_opened == 0 +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + || csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED +#endif + ) { return; } @@ -852,8 +857,13 @@ extern int create_server_ssl_connection(struct client_state *csp) free_certificate_chain(csp); csp->ssl_with_server_is_opened = 1; + csp->server_connection.ssl = 1; csp->server_cert_verification_result = mbedtls_ssl_get_verify_result(&(csp->ssl_server_attr.ssl)); - +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags &= ~CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED; + csp->ssl_flags &= ~CSP_SSL_FLAG_SERVER_CONNECTION_REUSED; +#endif + ret = 0; exit: /* Freeing structures if connection wasn't created successfully */ if (ret < 0) @@ -878,11 +888,17 @@ exit: * Returns : N/A * **********************************************************************/ -static void close_server_ssl_connection(struct client_state *csp) +extern void close_server_ssl_connection(struct client_state *csp) { int ret = 0; - if (csp->ssl_with_server_is_opened == 0) + if (csp->ssl_with_server_is_opened == 0 +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + || (csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED + && !(csp->ssl_flags & CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED) + && !(csp->ssl_flags & CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION)) +#endif + ) { return; } @@ -896,6 +912,11 @@ static void close_server_ssl_connection(struct client_state *csp) free_server_ssl_structures(csp); csp->ssl_with_server_is_opened = 0; + csp->server_connection.ssl = 0; + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags &= ~CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION; +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ } diff --git a/ssl.h b/ssl.h index 1638fa54..d4170cc6 100644 --- a/ssl.h +++ b/ssl.h @@ -43,26 +43,28 @@ #define SSL_CERT_NOT_VERIFIED 0xFFFFFFFF /* Variables for one common RNG for all SSL use */ -static mbedtls_ctr_drbg_context ctr_drbg; -static mbedtls_entropy_context entropy; -static int rng_seeded; +mbedtls_ctr_drbg_context ctr_drbg; +mbedtls_entropy_context entropy; +int rng_seeded; /* Boolean functions to get informations about SSL/TLS connections */ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); -extern size_t is_ssl_pending(ssl_connection_attr *connection); +extern size_t is_ssl_pending(const ssl_connection_attr *connection); extern int tunnel_established_successfully(const char * response, unsigned int response_len); /* Functions for sending and receiving data over SSL/TLS connections */ -extern int ssl_send_data(ssl_connection_attr * connection, const unsigned char * buf, int len); -extern int ssl_send_data_delayed(ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay); +extern int ssl_send_data(const ssl_connection_attr * connection, const unsigned char * buf, int len); +extern int ssl_send_data_delayed(const ssl_connection_attr *connection, const unsigned char *buf, size_t len, unsigned int delay); extern int ssl_recv_data(ssl_connection_attr * connection, unsigned char * buf, int maxLen); -extern long ssl_flush_socket(ssl_connection_attr * connection, struct iob *iob); +extern long ssl_flush_socket(const ssl_connection_attr * connection, struct iob *iob); extern void ssl_send_certificate_error(struct client_state *csp); /* Functions for opening and closing SSL/TLS connections */ extern int create_client_ssl_connection(struct client_state *csp); extern int create_server_ssl_connection(struct client_state *csp); extern void close_client_and_server_ssl_connections(struct client_state *csp); +extern void close_server_ssl_connection(struct client_state *csp); +extern void close_client_ssl_connection(struct client_state *csp); #endif /* ndef SSL_H_INCLUDED */ diff --git a/ssl_libressl.c b/ssl_libressl.c index 7d8bcd79..fc3a5f34 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -502,13 +502,12 @@ exit: * * Function : client_use_ssl * - * Description : Tests if client in current client state structure should use - * SSL connection or standard connection. + * Description : Tests if ssl connection with client is opened. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * - * Returns : If client should use SSL/TLS connection, 1 is returned. + * Returns : If client uses SSL/TLS connection, 1 is returned. * Otherwise 0 is returned. * *********************************************************************/ @@ -522,14 +521,13 @@ extern int client_use_ssl(struct client_state *csp) * * Function : server_use_ssl * - * Description : Tests if server in current client state structure should use - * SSL connection or standard connection. + * Description : Tests if ssl connection with server is opened. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * - * Returns : If server should use SSL/TLS connection, 1 is returned. - * Otherwise 0 is returned. + * Returns : If server uses SSL/TLS connection, 1 is returned. + * Otherwise 0 is returned * *********************************************************************/ extern int server_use_ssl(struct client_state *csp) -- 2.26.2 From 841734db3720e8d7c2963a00598148f000861958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:33:15 +0200 Subject: [PATCH 70/83] Replaced if...else for sending and receiving data over tcp/ssl in handle_established_connection with functions, which decide according to given parameters. Removed redundant ssl connections closing. --- jcc.c | 284 ++++++++++++++-------------------------------------------- 1 file changed, 66 insertions(+), 218 deletions(-) diff --git a/jcc.c b/jcc.c index 17d253d7..01c77040 100644 --- a/jcc.c +++ b/jcc.c @@ -2404,7 +2404,6 @@ static void handle_established_connection(struct client_state *csp) int buffer_and_filter_content = 0; unsigned int write_delay; const struct forward_spec *fwd = csp->use_fwd; - int ret = 0; /* Skeleton for HTTP response, if we should intercept the request */ struct http_response *rsp; @@ -2683,67 +2682,37 @@ static void handle_established_connection(struct client_state *csp) /* * Reading data from standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) + len = recv_data(csp, CLIENT, (unsigned char*)csp->receive_buffer, max_bytes_to_read); + if (len <= 0) { - /* - * Receiving HTTP request from client over SSL/TLS and sending - * it to server over SSL/TLS. - */ - len = ssl_recv_data(&(csp->ssl_client_attr), - (unsigned char *) csp->receive_buffer, max_bytes_to_read); - - if (len <= 0) - { - mark_server_socket_tainted(csp); - break; - } - - ret = ssl_send_data(&(csp->ssl_server_attr), - (unsigned char *) csp->receive_buffer, len); - - if (ret < 0) - { - log_error(LOG_LEVEL_ERROR, - "Send request over SSL/TLS to: %s failed", http->host); - mark_server_socket_tainted(csp); - return; - } + mark_server_socket_tainted(csp); + break; /* "game over, man" */ } - else - { - len = read_socket(csp->cfd, csp->receive_buffer, max_bytes_to_read); - - if (len <= 0) - { - /* XXX: not sure if this is necessary. */ - mark_server_socket_tainted(csp); - break; /* "game over, man" */ - } #ifdef FEATURE_CONNECTION_KEEP_ALIVE - if (csp->expected_client_content_length != 0) + if (csp->expected_client_content_length != 0) + { + assert(len <= max_bytes_to_read); + csp->expected_client_content_length -= (unsigned)len; + log_error(LOG_LEVEL_CONNECT, + "Expected client content length set to %llu " + "after reading %d bytes.", + csp->expected_client_content_length, len); + if (csp->expected_client_content_length == 0) { - assert(len <= max_bytes_to_read); - csp->expected_client_content_length -= (unsigned)len; log_error(LOG_LEVEL_CONNECT, - "Expected client content length set to %llu " - "after reading %d bytes.", - csp->expected_client_content_length, len); - if (csp->expected_client_content_length == 0) - { - log_error(LOG_LEVEL_CONNECT, - "Done reading from the client."); - csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; - } + "Done reading from the client."); + log_error(LOG_LEVEL_ERROR, "CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ SET4"); + csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; } + } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ - if (write_socket(csp->server_connection.sfd, csp->receive_buffer, (size_t)len)) - { - log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host); - mark_server_socket_tainted(csp); - return; - } + if (send_data(csp, SERVER, csp->receive_buffer, (size_t)len)) + { + log_error(LOG_LEVEL_ERROR, "send data to: %s failed: %E", http->host); + mark_server_socket_tainted(csp); + return; } continue; } @@ -2784,19 +2753,10 @@ static void handle_established_connection(struct client_state *csp) /* * Reading data from standard or secured connection (HTTP/HTTPS) */ - if (server_use_ssl(csp)) - { - len = ssl_recv_data(&(csp->ssl_server_attr), - (unsigned char *)csp->receive_buffer, (int)csp->receive_buffer_size); - } - else - { - len = read_socket(csp->server_connection.sfd, csp->receive_buffer, (int)csp->receive_buffer_size); - } - + len = recv_data(csp, SERVER, (unsigned char *)csp->receive_buffer, (int)csp->receive_buffer_size); if (len < 0) { - log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host); + log_error(LOG_LEVEL_ERROR, "receive data from: %s failed: %E", http->host); if ((http->ssl && (fwd->forward_host == NULL)) && csp->use_ssl_tunnel) { @@ -2936,35 +2896,16 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) - { - if ((ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)hdr, strlen(hdr)) < 0) - || (ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)((p != NULL) ? p : csp->iob->cur), - (size_t)csp->content_length) < 0)) - { - log_error(LOG_LEVEL_ERROR, "write modified content to " - "client over SSL/TLS failed"); - freez(hdr); - freez(p); - mark_server_socket_tainted(csp); - return; - } - } - else + if (send_data_delayed(csp, CLIENT, hdr, strlen(hdr), write_delay) + || send_data_delayed(csp, CLIENT, + ((p != NULL) ? p : csp->iob->cur), + (size_t)csp->content_length, write_delay)) { - if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) - || write_socket_delayed(csp->cfd, - ((p != NULL) ? p : csp->iob->cur), - (size_t)csp->content_length, write_delay)) - { - log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); - freez(hdr); - freez(p); - mark_server_socket_tainted(csp); - return; - } + log_error(LOG_LEVEL_ERROR, "send modified content to client failed: %E"); + freez(hdr); + freez(p); + mark_server_socket_tainted(csp); + return; } freez(hdr); @@ -3029,35 +2970,16 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) - { - if ((ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)hdr, hdrlen) < 0) - || ((flushed = ssl_flush_socket(&(csp->ssl_client_attr), - csp->iob)) < 0) - || (ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)csp->receive_buffer, (size_t)len) < 0)) - { - log_error(LOG_LEVEL_CONNECT, - "Flush header and buffers to client failed"); - freez(hdr); - mark_server_socket_tainted(csp); - return; - } - } - else + if (send_data_delayed(csp, CLIENT, hdr, hdrlen, write_delay) + || ((flushed = flush_socket(csp, CLIENT, csp->iob, write_delay)) < 0) + || send_data_delayed(csp, CLIENT, csp->receive_buffer, + (size_t)len, write_delay)) { - if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay) - || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0) - || write_socket_delayed(csp->cfd, csp->receive_buffer, - (size_t)len, write_delay)) - { - log_error(LOG_LEVEL_CONNECT, - "Flush header and buffers to client failed: %E"); - freez(hdr); - mark_server_socket_tainted(csp); - return; - } + log_error(LOG_LEVEL_CONNECT, + "Flush header and buffers to client failed: %E"); + freez(hdr); + mark_server_socket_tainted(csp); + return; } /* @@ -3076,27 +2998,12 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) - { - ret = ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)csp->receive_buffer, len); - if (ret < 0) - { - log_error(LOG_LEVEL_ERROR, - "Sending data to client failed"); - mark_server_socket_tainted(csp); - return; - } - } - else + if (send_data_delayed(csp, CLIENT, csp->receive_buffer, + (size_t)len, write_delay)) { - if (write_socket_delayed(csp->cfd, csp->receive_buffer, - (size_t)len, write_delay)) - { - log_error(LOG_LEVEL_ERROR, "write to client failed: %E"); - mark_server_socket_tainted(csp); - return; - } + log_error(LOG_LEVEL_ERROR, "send data to client failed: %E"); + mark_server_socket_tainted(csp); + return; } } byte_count += (unsigned long long)len; @@ -3136,18 +3043,9 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) - { - ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE)); - } - else - { - write_socket_delayed(csp->cfd, - INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); - } + send_data_delayed(csp, CLIENT, + INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); mark_server_socket_tainted(csp); return; } @@ -3219,17 +3117,8 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if(client_use_ssl(csp)) - { - ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE)); - } - else - { - write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); - } + send_data_delayed(csp, CLIENT, INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); free_http_request(http); mark_server_socket_tainted(csp); @@ -3248,17 +3137,8 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) - { - ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE)); - } - else - { - write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); - } + send_data_delayed(csp, CLIENT, INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); free_http_request(http); mark_server_socket_tainted(csp); return; @@ -3308,39 +3188,18 @@ static void handle_established_connection(struct client_state *csp) * may be in the buffer) Use standard or secured * connection. */ - if (client_use_ssl(csp)) - { - if ((ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)hdr, strlen(hdr)) < 0) - || (len = ssl_flush_socket(&(csp->ssl_client_attr), - csp->iob) < 0)) - { - log_error(LOG_LEVEL_CONNECT, "Write header to client failed"); - - /* - * The write failed, so don't bother mentioning it - * to the client... it probably can't hear us anyway. - */ - freez(hdr); - mark_server_socket_tainted(csp); - return; - } - } - else + if (send_data_delayed(csp, CLIENT, hdr, strlen(hdr), write_delay) + || ((len = flush_socket(csp, CLIENT, csp->iob, write_delay)) < 0)) { - if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) - || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)) - { - log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); + log_error(LOG_LEVEL_CONNECT, "send header to client failed: %E"); - /* - * The write failed, so don't bother mentioning it - * to the client... it probably can't hear us anyway. - */ - freez(hdr); - mark_server_socket_tainted(csp); - return; - } + /* + * The write failed, so don't bother mentioning it + * to the client... it probably can't hear us anyway. + */ + freez(hdr); + mark_server_socket_tainted(csp); + return; } } @@ -3364,17 +3223,8 @@ static void handle_established_connection(struct client_state *csp) /* * Sending data with standard or secured connection (HTTP/HTTPS) */ - if (client_use_ssl(csp)) - { - ssl_send_data(&(csp->ssl_client_attr), - (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE)); - } - else - { - write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE, - strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); - } + send_data_delayed(csp, CLIENT, INVALID_SERVER_HEADERS_RESPONSE, + strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay); mark_server_socket_tainted(csp); return; } @@ -3385,8 +3235,6 @@ static void handle_established_connection(struct client_state *csp) return; /* huh? we should never get here */ } - close_client_and_server_ssl_connections(csp); - if (csp->content_length == 0) { /* -- 2.26.2 From df1172a452341924f2735864cecf09487b2ab8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:36:37 +0200 Subject: [PATCH 71/83] Added possibility to compile Privoxy without any ssl library. But without ssl library won't be any ssl feature available. --- cgi.c | 5 +- configure.in | 2 + jbsockets.c | 17 ++--- jcc.c | 178 ++++++++++++++++++++++++++++++++------------------- urlmatch.c | 12 +++- 5 files changed, 138 insertions(+), 76 deletions(-) diff --git a/cgi.c b/cgi.c index 5dd5d2ba..4271f01e 100644 --- a/cgi.c +++ b/cgi.c @@ -400,7 +400,10 @@ struct http_response *dispatch_cgi(struct client_state *csp) if (strcmpic(csp->http->gpc, "GET") && strcmpic(csp->http->gpc, "HEAD") - && strcmpic(csp->http->gpc, "CONNECT")) +#ifdef FEATURE_SSL + && strcmpic(csp->http->gpc, "CONNECT") +#endif /* def FEATURE_SSL */ + ) { log_error(LOG_LEVEL_ERROR, "CGI request with unsupported method received: %s", csp->http->gpc); diff --git a/configure.in b/configure.in index 2908a8ba..5cb94456 100644 --- a/configure.in +++ b/configure.in @@ -1112,6 +1112,8 @@ else USAGE_LIBRESSL= else USAGE_SSL=# + USAGE_MBEDTLS=# + USAGE_LIBRESSL=# fi fi diff --git a/jbsockets.c b/jbsockets.c index 9391cef6..3f37d9ab 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1837,7 +1837,7 @@ void mark_socket_for_close_on_execute(jb_socket fd) extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int maxLen) { if (src == CLIENT) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_client_is_opened == 1) { return ssl_recv_data(&(csp->ssl_client_attr), buf, maxLen); @@ -1850,7 +1850,7 @@ extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int } else if (src == SERVER) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_server_is_opened == 1) { return ssl_recv_data(&(csp->ssl_server_attr), buf, maxLen); @@ -1890,7 +1890,7 @@ extern int recv_data(struct client_state *csp, int src, unsigned char *buf, int extern int send_data_delayed(const struct client_state *csp, int dest, const char *buf, int len, int delay) { if (dest == CLIENT) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_client_is_opened == 1) { return 0 > ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char*)buf, len, delay); @@ -1903,8 +1903,9 @@ extern int send_data_delayed(const struct client_state *csp, int dest, const cha } else if (dest == SERVER) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_server_is_opened == 1) { + log_error(LOG_LEVEL_ERROR, "POSILANI DAT NA SERVER PRES SSL"); return 0 > ssl_send_data_delayed(&(csp->ssl_server_attr), (const unsigned char*)buf, len, delay); } else @@ -1964,7 +1965,7 @@ extern int send_data(const struct client_state *csp, int dest, const char *buf, extern int flush_socket(const struct client_state *csp, int dest, struct iob *iob, unsigned int delay) { if (dest == CLIENT) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_client_is_opened == 1) { return ssl_flush_socket(&(csp->ssl_client_attr), iob); @@ -1978,7 +1979,7 @@ extern int flush_socket(const struct client_state *csp, int dest, struct iob *io } else if (dest == SERVER) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_server_is_opened == 1) { return ssl_flush_socket(&(csp->ssl_server_attr), iob); } @@ -2016,7 +2017,7 @@ extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, in if (src == CLIENT) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_client_is_opened == 1) { ret = is_ssl_pending(&(csp->ssl_client_attr)); @@ -2030,7 +2031,7 @@ extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, in } else if (src == SERVER) { -#if defined FEATURE_LIBRESSL || defined FEATURE_MBEDTLS +#ifdef FEATURE_SSL if (csp->ssl_with_server_is_opened == 1) { ret = is_ssl_pending(&(csp->ssl_server_attr)); diff --git a/jcc.c b/jcc.c index 01c77040..ed166c6f 100644 --- a/jcc.c +++ b/jcc.c @@ -135,6 +135,11 @@ #include "ssl_libressl.h" #endif +#ifdef FEATURE_SSL +#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#define FEATURE_SSL_CONNECTION_KEEP_ALIVE +#endif +#endif int daemon_mode = 1; struct client_states clients[1]; @@ -572,7 +577,7 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct char *req; if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS) -#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE /* When ssl sesions are reused, we get only relative URI */ && !(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED) #endif @@ -592,11 +597,11 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct return JB_ERR_PARSE; } else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http, -#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE (csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED) != 0 #else FALSE -#endif +#endif /* def FEATURE_SSL_CONNECTION_KEEP_ALIVE */ )) { #ifndef FEATURE_EXTENDED_HOST_PATTERNS @@ -737,7 +742,6 @@ static jb_err get_server_headers(struct client_state *csp) * **********************************************************************/ static int create_server_connection(struct client_state *csp) { - int ret = 0; struct http_request *http; const struct forward_spec *fwd; struct http_response *rsp; @@ -776,8 +780,10 @@ static int create_server_connection(struct client_state *csp) { "connected to %s. Total requests: %u.", csp->server_connection.sfd, csp->server_connection.host, csp->server_connection.requests_sent_total); +#ifdef FEATURE_SSL csp->ssl_flags |= CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION; close_server_ssl_connection(csp); +#endif drain_and_close_socket(csp->server_connection.sfd); } mark_connection_closed(&csp->server_connection); @@ -829,6 +835,7 @@ static int create_server_connection(struct client_state *csp) { return 1; } +#ifdef FEATURE_SSL /* * Creating SSL/TLS connections with destinantion server or parent * proxy. If forwarding is enabled, we must send client request to @@ -836,10 +843,11 @@ static int create_server_connection(struct client_state *csp) { */ if (http->ssl && !csp->use_ssl_tunnel) { + int ret = 0; + if (fwd->forward_host != NULL) { char server_response[BUFFER_SIZE]; - int ret = 0; int len = 0; char *hdr = NULL; @@ -1013,6 +1021,7 @@ static int create_server_connection(struct client_state *csp) { log_error(LOG_LEVEL_CONNECT, "SSL connection with server was created successfully"); } } +#endif /* def FEATURE_SSL */ #ifdef FEATURE_CONNECTION_KEEP_ALIVE save_connection_destination(csp->server_connection.sfd, @@ -1648,7 +1657,7 @@ static void mark_server_socket_tainted(struct client_state *csp) csp->server_connection.sfd); } csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; -#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE if (csp->http->server_ssl) { csp->ssl_flags |= CSP_SSL_FLAG_SERVER_CONNECTION_TAINTED; @@ -2241,7 +2250,11 @@ static jb_err parse_client_request(struct client_state *csp) #ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) - && (!strcmpic(csp->http->ver, "HTTP/1.1"))) + && (!strcmpic(csp->http->ver, "HTTP/1.1")) +#ifndef FEATURE_SSL + && (csp->http->ssl == 0) +#endif /* def FEATURE_SSL */ + ) { /* Assume persistence until further notice */ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; @@ -2509,6 +2522,7 @@ static void handle_established_connection(struct client_state *csp) } #endif /* FEATURE_CONNECTION_KEEP_ALIVE */ +#ifdef FEATURE_SSL /* * Test if some data from client or destination server are pending * on SSL/TLS. We must work with them preferably. SSL/TLS data can @@ -2527,36 +2541,7 @@ static void handle_established_connection(struct client_state *csp) read_ssl_server = is_ssl_pending(&(csp->ssl_server_attr)); } - if (!read_ssl_server && !read_ssl_client) - { -#ifdef HAVE_POLL - poll_fds[0].fd = csp->cfd; -#ifdef FEATURE_CONNECTION_KEEP_ALIVE - if (!watch_client_socket) - { - /* - * Ignore incoming data, but still watch out - * for disconnects etc. These flags are always - * implied anyway but explicitly setting them - * doesn't hurt. - */ - poll_fds[0].events = POLLERR | POLLHUP; - } - else -#endif - { - poll_fds[0].events = POLLIN; - } - poll_fds[1].fd = csp->server_connection.sfd; - poll_fds[1].events = POLLIN; - n = poll(poll_fds, 2, csp->config->socket_timeout * 1000); -#else - timeout.tv_sec = csp->config->socket_timeout; - timeout.tv_usec = 0; - n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout); -#endif /* def HAVE_POLL */ - } - else + if (read_ssl_server || read_ssl_client) { #ifdef HAVE_POLL if (read_ssl_client) @@ -2588,12 +2573,46 @@ static void handle_established_connection(struct client_state *csp) } #endif /* def HAVE_POLL */ } + else +#endif /* def FEATURE_SSL*/ + { +#ifdef HAVE_POLL + poll_fds[0].fd = csp->cfd; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (!watch_client_socket) + { + /* + * Ignore incoming data, but still watch out + * for disconnects etc. These flags are always + * implied anyway but explicitly setting them + * doesn't hurt. + */ + poll_fds[0].events = POLLERR | POLLHUP; + } + else +#endif + { + poll_fds[0].events = POLLIN; + } + poll_fds[1].fd = csp->server_connection.sfd; + poll_fds[1].events = POLLIN; + n = poll(poll_fds, 2, csp->config->socket_timeout * 1000); +#else + timeout.tv_sec = csp->config->socket_timeout; + timeout.tv_usec = 0; + n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout); +#endif /* def HAVE_POLL */ + } if (n == 0) { log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s", csp->config->socket_timeout, http->url); - if (byte_count == 0) + if (byte_count == 0 +#ifndef FEATURE_SSL + && http->ssl == 0 +#endif + ) { send_crunch_response(csp, error_response(csp, "connection-timeout")); } @@ -2758,7 +2777,7 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "receive data from: %s failed: %E", http->host); - if ((http->ssl && (fwd->forward_host == NULL)) && csp->use_ssl_tunnel) + if (http->ssl && (fwd->forward_host == NULL) && csp->use_ssl_tunnel) { /* * Just hang up. We already confirmed the client's CONNECT @@ -3294,9 +3313,14 @@ static int process_client_request(struct client_state *csp) { /* * Setting flags to use old solution with SSL tunel and to disable - * certificates verification. + * certificates verification. We are also setting this flag, when + * no ssl library is used, because ssl tunneling will be used. */ - if (http->ssl && csp->action->flags & ACTION_DISABLE_HTTPS_FILTER) + if (http->ssl +#ifdef FEATURE_SSL + && csp->action->flags & ACTION_DISABLE_HTTPS_FILTER +#endif + ) { csp->use_ssl_tunnel = 1; } @@ -3366,7 +3390,9 @@ static void chat(struct client_state *csp) const struct forward_spec *fwd; struct http_request *http; /* Skeleton for HTTP response, if we should intercept the request */ +#ifdef FEATURE_SSL struct http_response *rsp; +#endif struct http_response *crunch_rsp; int should_prepare_crunch_rsp = FALSE; int ret = 0; @@ -3374,7 +3400,7 @@ static void chat(struct client_state *csp) http = csp->http; csp->dont_verify_certificate = 0; -#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE /* * Setting flags when we should reuse ssl connections and we have * already created ssl connection which we are reusing. @@ -3390,7 +3416,7 @@ static void chat(struct client_state *csp) csp->ssl_flags |= CSP_SSL_FLAG_SERVER_CONNECTION_REUSED; } } -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ +#endif /* def FEATURE_SSL_CONNECTION_KEEP_ALIVE */ ret = process_client_request(csp); if (ret != 0) @@ -3463,11 +3489,11 @@ static void chat(struct client_state *csp) /* * We have a request. Check if one of the crunchers wants it. */ -#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE should_prepare_crunch_rsp = csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED || !http->ssl; #else should_prepare_crunch_rsp = !http->ssl; -#endif +#endif /* def FEATURE_SSL_CONNECTION_KEEP_ALIVE */ http->should_be_crunched = should_trigger_crunch_response(csp, crunchers_all, should_prepare_crunch_rsp, &crunch_rsp); if (http->should_be_crunched && should_prepare_crunch_rsp) { @@ -3477,6 +3503,18 @@ static void chat(struct client_state *csp) */ return; } +#ifndef FEATURE_SSL + /* + * Request should be crunched over ssl, but we are not able to + * create ssl connection. + */ + else if (http->should_be_crunched && http->ssl) + { + send_data_delayed(csp, CLIENT, CHEADER, strlen(CHEADER), + get_write_delay(csp)); + return; + } +#endif /* ndef FEATURE_SSL */ log_applied_actions(csp->action); log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path); @@ -3504,14 +3542,14 @@ static void chat(struct client_state *csp) csp->server_connection.requests_sent_total++; } -#ifdef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE /* * When we are reusing connection with client, we don't want * to creat new connection again. */ if (!(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED)) { -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ +#endif /* def FEATURE_SSL_CONNECTION_KEEP_ALIVE */ if (!http->should_be_crunched) { if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) @@ -3533,23 +3571,12 @@ static void chat(struct client_state *csp) } else { + list_remove_all(csp->headers); +#ifdef FEATURE_SSL /* * Using old solution with SSL tunnel or new solution with SSL proxy */ - list_remove_all(csp->headers); - if (csp->use_ssl_tunnel) - { - /* - * We're running an SSL tunnel and we're not forwarding, - * so just ditch the client headers, send the "connect succeeded" - * message to the client, flush the rest, and get out of the way. - */ - if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) - { - return; - } - } - else + if (!csp->use_ssl_tunnel) { /* * Creating an SSL proxy. If forwarding is disabled, we must send @@ -3578,7 +3605,6 @@ static void chat(struct client_state *csp) return; } -#ifdef FEATURE_SSL /* * If server certificate is invalid, we must inform client and then * close connection with client. @@ -3594,14 +3620,28 @@ static void chat(struct client_state *csp) close_client_and_server_ssl_connections(csp); return; } -#endif /* def FEATURE_SSL */ log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); } + else +#endif /* def FEATURE_SSL */ + { + /* + * We're running an SSL tunnel and we're not forwarding, + * so just ditch the client headers, send the "connect succeeded" + * message to the client, flush the rest, and get out of the way. + */ + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + return; + } + } + clear_iob(csp->client_iob); } log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); } +#ifdef FEATURE_SSL else { list_remove_all(csp->headers); @@ -3686,6 +3726,7 @@ static void chat(struct client_state *csp) } } } +#endif /* def FEATURE_SSL */ /* XXX: should the time start earlier for optimistically sent data? */ csp->server_connection.request_sent = time(NULL); @@ -3920,9 +3961,11 @@ static void serve(struct client_state *csp) } #endif /* def FEATURE_CONNECTION_SHARING */ +#ifdef FEATURE_SSL /* Setting flag to close ssl connections */ csp->ssl_flags |= CSP_SSL_FLAG_CLOSE_SERVER_CONNECTION; close_server_ssl_connection(csp); +#endif /* def FEATURE_SSL */ close_socket(csp->server_connection.sfd); mark_connection_closed(&csp->server_connection); } @@ -4002,7 +4045,9 @@ static void serve(struct client_state *csp) privoxy_mutex_unlock(&connection_reuse_mutex); } #endif /* def FEATURE_CONNECTION_SHARING */ +#ifdef FEATURE_SSL csp->ssl_flags &= ~CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED; +#endif break; } } @@ -4025,6 +4070,7 @@ static void serve(struct client_state *csp) chat(csp); #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ +#ifdef FEATURE_SSL /* * Closing ssl and then tcp connections, if they were opened. */ @@ -4032,6 +4078,8 @@ static void serve(struct client_state *csp) csp->ssl_flags = 0; #endif close_client_and_server_ssl_connections(csp); +#endif /* def FEATURE_SSL */ + if (csp->server_connection.sfd != JB_INVALID_SOCKET) { #ifdef FEATURE_CONNECTION_SHARING @@ -5102,9 +5150,9 @@ static void listen_loop(void) } #endif /* def FEATURE_ACL */ -#ifdef FEATURE_CONNECTION_KEEP_ALIVE - /* Setting flag to keep ssl connections opened if possible */ csp->ssl_flags = 0; +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE + /* Setting flag to keep ssl connections opened if possible */ if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) { csp->ssl_flags = CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED; diff --git a/urlmatch.c b/urlmatch.c index 65e411e6..ec101ea7 100644 --- a/urlmatch.c +++ b/urlmatch.c @@ -280,7 +280,9 @@ jb_err parse_http_url(const char *url, struct http_request *http, int require_pr * When we are receiving http request over ssl, there is * no host, but we should have it from CONNECT request. */ +#ifdef FEATURE_SSL if (http->client_ssl == 0) +#endif { http->host = NULL; } @@ -547,11 +549,14 @@ jb_err parse_http_request(const char *req, struct http_request *http) int n; jb_err err; +#ifdef FEATURE_SSL /* * We are not reading client's request over ssl, so we didn't * receive any information before over tcp and we can clean struct. */ - if (http->client_ssl == 0) { + if (http->client_ssl == 0) +#endif /* def FEATURE_SSL */ + { memset(http, '\0', sizeof(*http)); } buf = strdup_or_die(req); @@ -585,7 +590,10 @@ jb_err parse_http_request(const char *req, struct http_request *http) return JB_ERR_PARSE; } - if (http->ssl != 1) { +#ifdef FEATURE_SSL + if (!http->ssl) +#endif + { http->ssl = !strcmpic(v[0], "CONNECT"); } -- 2.26.2 From b8ec3b69150b96975d5676f315ebcb542bd47c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:40:21 +0200 Subject: [PATCH 72/83] Part which is preparing connection with client (creating ssl connection, forwarding requests, sending succeed, ...) was excluded from function chat to separated function. --- jcc.c | 304 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 172 insertions(+), 132 deletions(-) diff --git a/jcc.c b/jcc.c index ed166c6f..15e5e375 100644 --- a/jcc.c +++ b/jcc.c @@ -162,6 +162,7 @@ static jb_err get_request_destination_elsewhere(struct client_state *csp, struct static jb_err get_server_headers(struct client_state *csp); static const char *crunch_reason(const struct http_response *rsp); static void send_crunch_response(const struct client_state *csp, struct http_response *rsp); +static int send_http_request(struct client_state *csp); static char *get_request_line(struct client_state *csp); static jb_err receive_client_request(struct client_state *csp); static jb_err parse_client_request(struct client_state *csp); @@ -1035,6 +1036,173 @@ static int create_server_connection(struct client_state *csp) { } +/********************************************************************** + * + * Function : prepare_client_connection + * + * Description : Takes existing tcp connection with client and prepares + * it for data transmission. So ssl connection can be + * created, "Connection established" message can be send + * and client request can be forwarded to server. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on success, other values when connection wasn't + * prepared well. + * + **********************************************************************/ +static int prepare_client_connection(struct client_state *csp) +{ + const struct forward_spec *fwd; + struct http_request *http; + /* Skeleton for HTTP response, if we should intercept the request */ + struct http_response *rsp; +#ifdef FEATURE_SSL + int ret = 0; +#endif + + http = csp->http; + fwd = csp->use_fwd; + +#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE + /* + * When we are reusing connection with client, we don't want + * to creat new connection again. + */ + if (!(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED)) + { +#endif /* def FEATURE_SSL_CONNECTION_KEEP_ALIVE */ + if (!http->should_be_crunched) + { + if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) + { + /* Client headers have been sent optimistically */ + assert(csp->headers->last == NULL); + } + else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) + { + if (send_http_request(csp)) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + return 1; + } + } + else + { + list_remove_all(csp->headers); +#ifdef FEATURE_SSL + /* + * Using old solution with SSL tunnel or new solution with SSL proxy + */ + if (!csp->use_ssl_tunnel) + { + /* + * Creating an SSL proxy. If forwarding is disabled, we must send + * CSUCCEED mesage to client. Then SSL/TLS connection with client + * is created. + */ + + if (fwd->forward_host == NULL) + { + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); + return 1; + } + } + + ret = create_client_ssl_connection(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Can't open secure connection with client"); +#ifndef FEATURE_CONNECTION_KEEP_ALIVE + close_client_and_server_ssl_connections(csp); +#endif + return 1; + } + + /* + * If server certificate is invalid, we must inform client and then + * close connection with client. + */ +#ifdef FEATURE_MBEDTLS + if (csp->server_cert_verification_result != SSL_CERT_VALID) +#endif +#ifdef FEATURE_LIBRESSL + if (csp->server_cert_verification_result != X509_V_OK) +#endif + { + ssl_send_certificate_error(csp); + close_client_and_server_ssl_connections(csp); + return 1; + } + + log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); + } + else +#endif /* def FEATURE_SSL */ + { + /* + * We're running an SSL tunnel and we're not forwarding, + * so just ditch the client headers, send the "connect succeeded" + * message to the client, flush the rest, and get out of the way. + */ + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + return 1; + } + } + + clear_iob(csp->client_iob); + } + log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); + } +#ifdef FEATURE_SSL + else + { + list_remove_all(csp->headers); + if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + close_client_and_server_ssl_connections(csp); + return 1; + } + ret = create_client_ssl_connection(csp); + } +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + } + else + { + /* + * Sending client's request to server, when SSL connection is reused. + */ + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); + + if (send_http_request(csp)) + { + rsp = error_response(csp, "connect-failed"); + if (rsp) + { + send_crunch_response(csp, rsp); + } + mark_server_socket_tainted(csp); + return 1; + } + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ +#endif /* def FEATURE_SSL */ + return 0; +} + + /********************************************************************* * * Function : crunch_reason @@ -3542,140 +3710,12 @@ static void chat(struct client_state *csp) csp->server_connection.requests_sent_total++; } -#ifdef FEATURE_SSL_CONNECTION_KEEP_ALIVE - /* - * When we are reusing connection with client, we don't want - * to creat new connection again. - */ - if (!(csp->ssl_flags & CSP_SSL_FLAG_CLIENT_CONNECTION_REUSED)) - { -#endif /* def FEATURE_SSL_CONNECTION_KEEP_ALIVE */ - if (!http->should_be_crunched) - { - if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) - { - /* Client headers have been sent optimistically */ - assert(csp->headers->last == NULL); - } - else if ((fwd->forward_host && csp->use_ssl_tunnel) || http->ssl == 0) - { - if (send_http_request(csp)) - { - rsp = error_response(csp, "connect-failed"); - if (rsp) - { - send_crunch_response(csp, rsp); - } - return; - } - } - else - { - list_remove_all(csp->headers); -#ifdef FEATURE_SSL - /* - * Using old solution with SSL tunnel or new solution with SSL proxy - */ - if (!csp->use_ssl_tunnel) - { - /* - * Creating an SSL proxy. If forwarding is disabled, we must send - * CSUCCEED mesage to client. Then SSL/TLS connection with client - * is created. - */ - - if (fwd->forward_host == NULL) - { - if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) - { - log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); - return; - } - } - - ret = create_client_ssl_connection(csp); - if (ret != 0) - { - log_error(LOG_LEVEL_ERROR, - "Can't open secure connection with client"); -#ifndef FEATURE_CONNECTION_KEEP_ALIVE - close_client_and_server_ssl_connections(csp); -#endif - return; - } - - /* - * If server certificate is invalid, we must inform client and then - * close connection with client. - */ -#ifdef FEATURE_MBEDTLS - if (csp->server_cert_verification_result != SSL_CERT_VALID) -#endif -#ifdef FEATURE_LIBRESSL - if (csp->server_cert_verification_result != X509_V_OK) -#endif - { - ssl_send_certificate_error(csp); - close_client_and_server_ssl_connections(csp); - return; - } - - log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); - } - else -#endif /* def FEATURE_SSL */ - { - /* - * We're running an SSL tunnel and we're not forwarding, - * so just ditch the client headers, send the "connect succeeded" - * message to the client, flush the rest, and get out of the way. - */ - if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) - { - return; - } - } - - clear_iob(csp->client_iob); - } - log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); - } -#ifdef FEATURE_SSL - else - { - list_remove_all(csp->headers); - if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) - { - log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); - return; - } - ret = create_client_ssl_connection(csp); - } -#ifdef FEATURE_CONNECTION_KEEP_ALIVE - } - else - { - /* - * Sending client's request to server, when SSL connection is reused. - */ - freez(csp->headers->first->str); - build_request_line(csp, fwd, &csp->headers->first->str); - - if (send_http_request(csp)) - { - rsp = error_response(csp, "connect-failed"); - if (rsp) - { - send_crunch_response(csp, rsp); - } - mark_server_socket_tainted(csp); - return; - } + ret = prepare_client_connection(csp); + if (ret != 0) { + return; } -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ +#ifdef FEATURE_SSL /* * We have created SSL connection with client and server, so now we can receive * client request header over ssl, filter it and send it to the server. Requests -- 2.26.2 From 725badc94ffad383e837f9bc835e8688c18a1cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:45:37 +0200 Subject: [PATCH 73/83] Added functions data_is_available_to_tcp_ssl_ssl_attr and connection_is_still_alive_ssl_attr. These functions will be able to work with given ssl_connection_attr, they don't need whole csp. These functions also replace parts of similar functions. --- jbsockets.c | 139 ++++++++++++++++++++++++++++++---------------------- jbsockets.h | 1 + 2 files changed, 81 insertions(+), 59 deletions(-) diff --git a/jbsockets.c b/jbsockets.c index 3f37d9ab..fa89ad15 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -127,6 +127,8 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct client_state *csp); #endif +static int data_is_available_tcp_ssl_ssl_attr(const ssl_connection_attr *connection, int is_using_ssl, int seconds_to_wait); + /********************************************************************* * * Function : set_no_delay_flag @@ -1470,6 +1472,8 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) set_no_delay_flag(afd); csp->cfd = afd; + csp->ssl_client_attr.socket_fd = csp->cfd; + #ifdef HAVE_RFC2553 csp->ip_addr_str = malloc_or_die(NI_MAXHOST); retval = getnameinfo((struct sockaddr *) &client, c_length, @@ -1699,45 +1703,60 @@ int socket_is_still_alive(jb_socket sfd) *********************************************************************/ extern int connection_is_still_alive(struct client_state *csp, int src) { -#ifdef FEATURE_SSL -#ifdef FEATURE_LIBRESSL - SSL *ssl; -#endif -#ifdef FEATURE_MBEDTLS - mbedtls_ssl_context *ssl; -#endif + ssl_connection_attr * ssl_connection_attr; int is_using_ssl = 0; - unsigned char tmp[10]; if (src == CLIENT) { is_using_ssl = csp->ssl_with_client_is_opened; -#ifdef FEATURE_LIBRESSL - ssl = csp->ssl_client_attr.ssl; -#endif -#ifdef FEATURE_MBEDTLS - ssl = &csp->ssl_client_attr.ssl; -#endif + ssl_connection_attr = &csp->ssl_client_attr; } else if (src == SERVER) { is_using_ssl = csp->ssl_with_server_is_opened; -#ifdef FEATURE_LIBRESSL - ssl = csp->ssl_server_attr.ssl; -#endif -#ifdef FEATURE_MBEDTLS - ssl = &csp->ssl_server_attr.ssl; -#endif + ssl_connection_attr = &csp->ssl_server_attr; } + else + { + return FALSE; + } + + return connection_is_still_alive_ssl_attr(ssl_connection_attr, is_using_ssl); +} + - if (is_using_ssl && data_is_available_tcp_ssl(csp, src, 0)) { +/********************************************************************* + * + * Function : connection_is_still_alive_ssl_attr + * + * Description : Figures out whether or not a given connection + * is still alive. (Whether "close notify" alert + * was received) Caller must give paremeter if + * connection uses ssl. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * 2 : is_using_ssl = TRUE when given connection uses ssl + * + * Returns : TRUE for yes, otherwise FALSE. + * + *********************************************************************/ +extern int connection_is_still_alive_ssl_attr(ssl_connection_attr *connection_attr, int is_using_ssl) +{ +#ifdef FEATURE_SSL + unsigned char tmp[10]; +#endif + + if (is_using_ssl && data_is_available_tcp_ssl_ssl_attr(connection_attr, 0, 0)) + { #ifdef FEATURE_MBEDTLS /* * mbedtls_ssl_read reads available data and checks connection state. * When connection was closed by peer, closure notifice is returned. * Otherway, no chars are set to given buffer and stay pending. */ - if (mbedtls_ssl_read(ssl, tmp, 0) == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + if (mbedtls_ssl_read(&connection_attr->ssl, tmp, 0) == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) + { return FALSE; } #endif /* def FEATURE_MBEDTLS */ @@ -1747,25 +1766,15 @@ extern int connection_is_still_alive(struct client_state *csp, int src) * it loads SSL shutdown flag, which signals whether "close notify" * alert was received or not. */ - SSL_peek(ssl, tmp, 1); - if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) + SSL_peek(connection_attr->ssl, tmp, 1); + if (SSL_get_shutdown(connection_attr->ssl) & SSL_RECEIVED_SHUTDOWN) { return FALSE; } #endif /* def FEATURE_LIBRESSL */ } -#endif /* def FEATURE_SSL */ - if (src == CLIENT) - { - return socket_is_still_alive(csp->cfd); - } - else if (src == SERVER) - { - return socket_is_still_alive(csp->server_connection.sfd); - } - - return FALSE; + return socket_is_still_alive(connection_attr->socket_fd); } @@ -2013,35 +2022,47 @@ extern int flush_socket(const struct client_state *csp, int dest, struct iob *io * *********************************************************************/ extern int data_is_available_tcp_ssl(const struct client_state *csp, int src, int seconds_to_wait) { - int ret = 0; - if (src == CLIENT) { -#ifdef FEATURE_SSL - if (csp->ssl_with_client_is_opened == 1) - { - ret = is_ssl_pending(&(csp->ssl_client_attr)); - } - if (ret == 0) -#endif - { - ret = data_is_available(csp->cfd, seconds_to_wait); - } - return ret; + return data_is_available_tcp_ssl_ssl_attr(&csp->ssl_client_attr, csp->ssl_with_client_is_opened, seconds_to_wait); } else if (src == SERVER) { -#ifdef FEATURE_SSL - if (csp->ssl_with_server_is_opened == 1) - { - ret = is_ssl_pending(&(csp->ssl_server_attr)); - } - if (ret == 0) -#endif - { - ret = data_is_available(csp->server_connection.sfd, seconds_to_wait); - } - return ret; + return data_is_available_tcp_ssl_ssl_attr(&csp->ssl_server_attr, csp->ssl_with_server_is_opened, seconds_to_wait); } return 0; } + + +/********************************************************************* + * + * Function : data_is_available_tcp_ssl_ssl_attr + * + * Description : Checks whether some data are available from given + * connection. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * 2 : is_using_ssl = TRUE when given connection uses ssl + * 3 : seconds_to_wait = number of seconds after which + * we give up. (only for tcp connection) + * + * Returns : TRUE for yes, otherwise FALSE. + * + *********************************************************************/ +static int data_is_available_tcp_ssl_ssl_attr(const ssl_connection_attr *connection_attr, int is_using_ssl, int seconds_to_wait) +{ + int ret = 0; + +#ifdef FEATURE_SSL + if (is_using_ssl == 1) + { + ret = is_ssl_pending(connection_attr); + } + if (ret == 0) +#endif + { + ret = data_is_available(connection_attr->socket_fd, seconds_to_wait); + } + return ret; +} \ No newline at end of file diff --git a/jbsockets.h b/jbsockets.h index a2934ee2..24b4f1fc 100644 --- a/jbsockets.h +++ b/jbsockets.h @@ -62,6 +62,7 @@ extern unsigned long resolve_hostname_to_ip(const char *host); extern int socket_is_still_alive(jb_socket sfd); extern int connection_is_still_alive(struct client_state *csp, int src); +extern int connection_is_still_alive_ssl_attr(ssl_connection_attr *connection, int is_using_ssl); #ifdef FEATURE_EXTERNAL_FILTERS extern void mark_socket_for_close_on_execute(jb_socket fd); -- 2.26.2 From 5a3ba3b3c09d9f831749825524c9302fc0cd06f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:47:10 +0200 Subject: [PATCH 74/83] Added functions free_ssl_structures and close_ssl_connection, which are able to work with given ssl_connection_attr. --- ssl_libressl.c | 78 ++++++++++++++++++++++++++++---------------------- ssl_libressl.h | 2 ++ 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/ssl_libressl.c b/ssl_libressl.c index fc3a5f34..bd6350c4 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -58,7 +58,6 @@ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); -static void free_server_ssl_structures(struct client_state *csp); extern int generate_key(RSA **key_rsa, struct client_state *csp); extern int generate_webpage_certificate(struct client_state * csp); static int file_exists(const char * path); @@ -200,31 +199,60 @@ extern int create_server_ssl_connection(struct client_state *csp) ret = 0; exit: if (ret == -1) { - free_server_ssl_structures(csp); + free_ssl_structures(&csp->ssl_server_attr); } return ret; } -/********************************************************************* +/********************************************************************** * - * Function : free_server_ssl_structures + * Function : free_ssl_structures * - * Description : Frees structures used for SSL communication with server + * Description : Frees given structures used for SSL communication. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) + * 1 : connection_attr = Attributes of ssl connection * * Returns : N/A * *********************************************************************/ -static void free_server_ssl_structures(struct client_state *csp) +extern void free_ssl_structures(ssl_connection_attr *connection_attr) { - SSL_free(csp->ssl_server_attr.ssl); - SSL_CTX_free(csp->ssl_server_attr.ctx); + SSL_free(connection_attr->ssl); + SSL_CTX_free(connection_attr->ctx); + connection_attr->socket_fd = JB_INVALID_SOCKET; +} + + +/********************************************************************** + * + * Function : close_ssl_connection + * + * Description : Closes SSL/TLS connection with given ssl attributes. + * This function doesn't check if attributes are not + * initialized. It must be done by caller. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * + * Returns : N/A + * + **********************************************************************/ +extern void close_ssl_connection(ssl_connection_attr *connection_attr) +{ + /* + * Notifying the peer that the connection is being closed. + */ + int ret = SSL_shutdown(connection_attr->ssl); + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, "SSL_shutdown of ssl connection failed"); + } - csp->ssl_server_attr.socket_fd = -1; + free_ssl_structures(connection_attr); + connection_attr->ssl = NULL; } @@ -261,7 +289,7 @@ extern void close_server_ssl_connection(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "SSL_shutdown with server failed"); } - free_server_ssl_structures(csp); + free_ssl_structures(&csp->ssl_server_attr); csp->ssl_with_server_is_opened = 0; csp->server_connection.ssl = 0; @@ -271,27 +299,6 @@ extern void close_server_ssl_connection(struct client_state *csp) } -/********************************************************************** - * - * Function : free_client_ssl_structures - * - * Description : Frees structures used for SSL communication with client - * - * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * - * Returns : N/A - * - *********************************************************************/ -static void free_client_ssl_structures(struct client_state *csp) -{ - SSL_free(csp->ssl_client_attr.ssl); - SSL_CTX_free(csp->ssl_client_attr.ctx); - - csp->ssl_client_attr.socket_fd = -1; -} - - /********************************************************************* * * Function : close_client_ssl_connection @@ -322,11 +329,12 @@ extern void close_client_ssl_connection(struct client_state *csp) * Notifying the peer that the connection is being closed. */ ret = SSL_shutdown(csp->ssl_client_attr.ssl); - if (ret < 0) { + if (ret < 0) + { log_error(LOG_LEVEL_ERROR, "SSL_shutdown with client failed"); } - free_client_ssl_structures(csp); + free_ssl_structures(&csp->ssl_client_attr); csp->ssl_with_client_is_opened = 0; } @@ -491,7 +499,7 @@ extern int create_client_ssl_connection(struct client_state *csp) { ret = 0; exit: if (ret != 0) { - free_client_ssl_structures(csp); + free_ssl_structures(&csp->ssl_client_attr); } return ret; diff --git a/ssl_libressl.h b/ssl_libressl.h index 35601d2a..66c3c615 100644 --- a/ssl_libressl.h +++ b/ssl_libressl.h @@ -53,6 +53,8 @@ extern int create_server_ssl_connection(struct client_state *csp); extern void close_client_and_server_ssl_connections(struct client_state *csp); extern void close_server_ssl_connection(struct client_state *csp); extern void close_client_ssl_connection(struct client_state *csp); +extern void free_ssl_structures(ssl_connection_attr *connection); +extern void close_ssl_connection(ssl_connection_attr *connection); #endif /* ndef SSL_LIBRESSL_H_INCLUDED */ \ No newline at end of file -- 2.26.2 From 889645c6cb975a155927726ba2d63adc2cf03ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:48:03 +0200 Subject: [PATCH 75/83] Edited function to remember shared connection. There was added storing of ssl connection attributes. Edited function forwarded_connect. It has two new output parameters. First to return ssl connection attributes when ssl connection was taken from shared connections. Second to determine, whether connection was found between shared connection or created. Other small changes to work properly with shared ssl connections. Added ssl connection attributes into reusable_connection struct to keep it when connection is shared. Added socket_fd into ssl_connection_attr struct. --- gateway.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++------- gateway.h | 6 +++-- project.h | 7 +++-- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/gateway.c b/gateway.c index ccb12ede..5c12044f 100644 --- a/gateway.c +++ b/gateway.c @@ -59,6 +59,14 @@ #include #endif /* def __OS2__ */ +#ifdef FEATURE_MBEDTLS +#include "ssl.h" +#endif + +#ifdef FEATURE_LIBRESSL +#include "ssl_libressl.h" +#endif + #include "project.h" #include "jcc.h" #include "errlog.h" @@ -176,10 +184,11 @@ extern void initialize_reusable_connections(void) * Parameters : * 1 : connection = The server connection to remember. * - * Returns : void + * Returns : TRUE when connection was remembered and FALSE when + * it wasn't possible to remember it. * *********************************************************************/ -void remember_connection(const struct reusable_connection *connection) +int remember_connection(struct reusable_connection *connection) { unsigned int slot = 0; int free_slot_found = FALSE; @@ -189,7 +198,7 @@ void remember_connection(const struct reusable_connection *connection) if (mark_connection_unused(connection)) { - return; + return TRUE; } privoxy_mutex_lock(&connection_reuse_mutex); @@ -214,8 +223,15 @@ void remember_connection(const struct reusable_connection *connection) "No free slots found to remember socket for %s:%d. Last slot %d.", connection->host, connection->port, slot); privoxy_mutex_unlock(&connection_reuse_mutex); + +#ifdef FEATURE_SSL + if (connection->ssl) + { + close_ssl_connection((ssl_connection_attr *)(&connection->ssl_server_attr)); + } +#endif /* def FEATURE_SSL */ close_socket(connection->sfd); - return; + return FALSE; } assert(NULL != connection->host); @@ -229,6 +245,9 @@ void remember_connection(const struct reusable_connection *connection) reusable_connection[slot].response_received = connection->response_received; reusable_connection[slot].keep_alive_timeout = connection->keep_alive_timeout; reusable_connection[slot].requests_sent_total = connection->requests_sent_total; +#ifdef FEATURE_SSL + reusable_connection[slot].ssl_server_attr = connection->ssl_server_attr; +#endif /* def FEATURE_SSL */ assert(reusable_connection[slot].gateway_host == NULL); assert(reusable_connection[slot].gateway_port == 0); @@ -258,6 +277,7 @@ void remember_connection(const struct reusable_connection *connection) reusable_connection[slot].forward_port = connection->forward_port; privoxy_mutex_unlock(&connection_reuse_mutex); + return TRUE; } #endif /* def FEATURE_CONNECTION_SHARING */ @@ -291,6 +311,10 @@ void mark_connection_closed(struct reusable_connection *closed_connection) freez(closed_connection->forward_host); closed_connection->forward_port = 0; closed_connection->ssl = 0; + +#ifdef FEATURE_SSL + closed_connection->ssl_server_attr.socket_fd = JB_INVALID_SOCKET; +#endif /* def FEATURE_SSL */ } @@ -367,7 +391,7 @@ int connection_destination_matches(const struct reusable_connection *connection, return FALSE; } - if (( (NULL != connection->gateway_host) + if (((NULL != connection->gateway_host) && (NULL != fwd->gateway_host) && strcmpic(connection->gateway_host, fwd->gateway_host)) && (connection->gateway_host != fwd->gateway_host)) @@ -378,7 +402,7 @@ int connection_destination_matches(const struct reusable_connection *connection, return FALSE; } - if (( (NULL != connection->forward_host) + if (((NULL != connection->forward_host) && (NULL != fwd->forward_host) && strcmpic(connection->forward_host, fwd->forward_host)) && (connection->forward_host != fwd->forward_host)) @@ -434,16 +458,32 @@ int close_unusable_connections(void) reusable_connection[slot].sfd, reusable_connection[slot].keep_alive_timeout, latency); +#ifdef FEATURE_SSL + if (reusable_connection[slot].ssl) + { + close_ssl_connection(&reusable_connection[slot].ssl_server_attr); + } +#endif /* def FEATURE_SSL */ close_socket(reusable_connection[slot].sfd); mark_connection_closed(&reusable_connection[slot]); } +#ifdef FEATURE_SSL + else if (!connection_is_still_alive_ssl_attr(&reusable_connection[slot].ssl_server_attr, reusable_connection[slot].ssl)) +#else else if (!socket_is_still_alive(reusable_connection[slot].sfd)) +#endif /* def FEATURE_SSL */ { log_error(LOG_LEVEL_CONNECT, "The connection to %s:%d in slot %d is no longer usable. " "Closing socket %d.", reusable_connection[slot].host, reusable_connection[slot].port, slot, reusable_connection[slot].sfd); +#ifdef FEATURE_SSL + if (reusable_connection[slot].ssl) + { + close_ssl_connection(&reusable_connection[slot].ssl_server_attr); + } +#endif /* def FEATURE_SSL */ close_socket(reusable_connection[slot].sfd); mark_connection_closed(&reusable_connection[slot]); } @@ -471,13 +511,16 @@ int close_unusable_connections(void) * Parameters : * 1 : http = The destination for the connection. * 2 : fwd = The forwarder settings. + * 3 : ssl_server_attr = Output parameter to return ssl + * connection attributes when there are any. * * Returns : JB_INVALID_SOCKET => No reusable connection found, * otherwise a usable socket. * *********************************************************************/ static jb_socket get_reusable_connection(const struct http_request *http, - const struct forward_spec *fwd) + const struct forward_spec *fwd, + ssl_connection_attr *ssl_server_attr) { jb_socket sfd = JB_INVALID_SOCKET; unsigned int slot = 0; @@ -495,6 +538,12 @@ static jb_socket get_reusable_connection(const struct http_request *http, { reusable_connection[slot].in_use = TRUE; sfd = reusable_connection[slot].sfd; +#ifdef FEATURE_SSL + if (reusable_connection[slot].ssl) + { + *ssl_server_attr = reusable_connection[slot].ssl_server_attr; + } +#endif /* def FEATURE_SSL */ log_error(LOG_LEVEL_CONNECT, "Found reusable socket %d for %s:%d in slot %d. Timestamp made %d " "seconds ago. Timeout: %d. Latency: %d. Requests served: %d", @@ -573,25 +622,34 @@ static int mark_connection_unused(const struct reusable_connection *connection) * 1 : fwd = the proxies to use when connecting. * 2 : http = the http request and apropos headers * 3 : csp = Current client state (buffers, headers, etc...) + * 4 : ssl_server_attr = Output parameter to return ssl connection + * attributes when appropriate reusable connection was found. + * 5 : connection_found = Output parameter to return TRUE when + * appropriate reusable connection was found and is returned, + * FALSE otherway. * * Returns : JB_INVALID_SOCKET => failure, else it is the socket file descriptor. * *********************************************************************/ -jb_socket forwarded_connect(const struct forward_spec * fwd, +extern jb_socket forwarded_connect(const struct forward_spec * fwd, struct http_request *http, - struct client_state *csp) + struct client_state *csp, + ssl_connection_attr *ssl_server_attr, + int *connection_found) { const char * dest_host; int dest_port; jb_socket sfd = JB_INVALID_SOCKET; + *connection_found = FALSE; #ifdef FEATURE_CONNECTION_SHARING if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)) { - sfd = get_reusable_connection(http, fwd); + sfd = get_reusable_connection(http, fwd, ssl_server_attr); if (JB_INVALID_SOCKET != sfd) { + *connection_found = TRUE; return sfd; } } diff --git a/gateway.h b/gateway.h index 544752cd..55cbb6b4 100644 --- a/gateway.h +++ b/gateway.h @@ -42,12 +42,14 @@ struct client_state; extern jb_socket forwarded_connect(const struct forward_spec * fwd, struct http_request *http, - struct client_state *csp); + struct client_state *csp, + ssl_connection_attr *ssl_server_attr, + int *connection_found); #ifdef FEATURE_CONNECTION_SHARING extern void initialize_reusable_connections(void); extern void forget_connection(jb_socket sfd); -extern void remember_connection(const struct reusable_connection *connection); +extern int remember_connection(struct reusable_connection *connection); extern int close_unusable_connections(void); #endif /* FEATURE_CONNECTION_SHARING */ diff --git a/project.h b/project.h index ecdd75a0..5c14c7eb 100644 --- a/project.h +++ b/project.h @@ -288,10 +288,12 @@ struct map * Srtuct of atributes necessary for SSL/TLS connection */ typedef struct { + int socket_fd; + #ifdef FEATURE_MBEDTLS mbedtls_ssl_context ssl; mbedtls_ssl_config conf; - mbedtls_net_context socket_fd; + mbedtls_net_context mbedtls_fd; mbedtls_x509_crt server_cert; mbedtls_x509_crt ca_cert; mbedtls_pk_context prim_key; @@ -302,7 +304,6 @@ typedef struct { #endif /* FEATURE_MBEDTLS */ #ifdef FEATURE_LIBRESSL - int socket_fd; SSL_CTX * ctx; SSL * ssl; BIO * bio, * ssl_bio; @@ -804,6 +805,8 @@ struct reusable_connection */ struct list connect_headers[1]; #endif + + ssl_connection_attr ssl_server_attr; }; -- 2.26.2 From fa9b2b98faca877378ddebe8fa7e3f19902352ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:48:42 +0200 Subject: [PATCH 76/83] Changed manipulation with shared connections, so shared ssl connections are closed properly. Also loaded ssl connection from shared ones doesn't create ssl session again. Added copying of ssl connection attributes in function save_connection_destination, so these attributes will be also saved. Removed redundant ssl connection closing. --- jcc.c | 61 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/jcc.c b/jcc.c index 15e5e375..d83899b7 100644 --- a/jcc.c +++ b/jcc.c @@ -182,6 +182,7 @@ static void serve(struct client_state *csp); void save_connection_destination(jb_socket sfd, const struct http_request *http, const struct forward_spec *fwd, + const ssl_connection_attr *ssl_server_attr, struct reusable_connection *server_connection); static void mark_server_socket_tainted(struct client_state *csp); @@ -748,6 +749,7 @@ static int create_server_connection(struct client_state *csp) { struct http_response *rsp; http = csp->http; fwd = csp->use_fwd; + int connection_found = FALSE; #ifdef FEATURE_CONNECTION_KEEP_ALIVE @@ -767,7 +769,10 @@ static int create_server_connection(struct client_state *csp) { #ifdef FEATURE_CONNECTION_SHARING if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) { - remember_connection(&csp->server_connection); + if (!remember_connection(&csp->server_connection)) + { + csp->ssl_with_server_is_opened = 0; + } } else #endif /* def FEATURE_CONNECTION_SHARING */ @@ -794,7 +799,8 @@ static int create_server_connection(struct client_state *csp) { /* * Connecting to destination server */ - csp->server_connection.sfd = forwarded_connect(fwd, http, csp); + csp->server_connection.sfd = forwarded_connect(fwd, http, csp, &(csp->ssl_server_attr), &connection_found); + csp->ssl_server_attr.socket_fd = csp->server_connection.sfd; if (csp->server_connection.sfd == JB_INVALID_SOCKET) { @@ -837,12 +843,24 @@ static int create_server_connection(struct client_state *csp) { } #ifdef FEATURE_SSL +#ifdef FEATURE_CONNECTION_SHARING + if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING && http->server_ssl && connection_found) + { + csp->ssl_flags |= CSP_SSL_FLAG_SERVER_CONNECTION_REUSED; + csp->ssl_with_server_is_opened = TRUE; + } + else + { + csp->ssl_with_server_is_opened = FALSE; + } +#endif /* def FEATURE_CONNECTION_SHARING */ + /* * Creating SSL/TLS connections with destinantion server or parent * proxy. If forwarding is enabled, we must send client request to * parent proxy and receive, parse and resend parent proxy answer. */ - if (http->ssl && !csp->use_ssl_tunnel) + if (http->ssl && !csp->use_ssl_tunnel && !csp->ssl_with_server_is_opened) { int ret = 0; @@ -1026,7 +1044,7 @@ static int create_server_connection(struct client_state *csp) { #ifdef FEATURE_CONNECTION_KEEP_ALIVE save_connection_destination(csp->server_connection.sfd, - http, fwd, &csp->server_connection); + http, fwd, &csp->ssl_server_attr, &csp->server_connection); csp->server_connection.keep_alive_timeout = (unsigned)csp->config->keep_alive_timeout; } @@ -1112,7 +1130,6 @@ static int prepare_client_connection(struct client_state *csp) if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) { log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); return 1; } } @@ -1122,9 +1139,6 @@ static int prepare_client_connection(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "Can't open secure connection with client"); -#ifndef FEATURE_CONNECTION_KEEP_ALIVE - close_client_and_server_ssl_connections(csp); -#endif return 1; } @@ -1140,7 +1154,6 @@ static int prepare_client_connection(struct client_state *csp) #endif { ssl_send_certificate_error(csp); - close_client_and_server_ssl_connections(csp); return 1; } @@ -1171,7 +1184,6 @@ static int prepare_client_connection(struct client_state *csp) if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED))) { log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - close_client_and_server_ssl_connections(csp); return 1; } ret = create_client_ssl_connection(csp); @@ -1655,6 +1667,7 @@ static void wait_for_alive_connections(void) void save_connection_destination(jb_socket sfd, const struct http_request *http, const struct forward_spec *fwd, + const ssl_connection_attr *ssl_server_attr, struct reusable_connection *server_connection) { assert(sfd != JB_INVALID_SOCKET); @@ -1663,6 +1676,8 @@ void save_connection_destination(jb_socket sfd, server_connection->sfd = sfd; server_connection->host = strdup_or_die(http->host); server_connection->port = http->port; + server_connection->ssl = http->server_ssl; + server_connection->ssl_server_attr = *ssl_server_attr; assert(NULL != fwd); assert(server_connection->gateway_host == NULL); @@ -3735,7 +3750,6 @@ static void chat(struct client_state *csp) if (process_client_request(csp)) { - close_client_and_server_ssl_connections(csp); return; } @@ -3808,6 +3822,7 @@ extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file) log_error(LOG_LEVEL_FATAL, "Failed to open %s: %E", fuzz_input_file); } + csp->ssl_server_attr.socket_fd = csp->server_connection.sfd; } csp->fwd = &fwd; csp->content_type |= CT_GIF; @@ -4069,10 +4084,19 @@ static void serve(struct client_state *csp) break; } - remember_connection(&csp->server_connection); + if (!remember_connection(&csp->server_connection)) + { + csp->ssl_with_server_is_opened = 0; + mark_connection_closed(&csp->server_connection); + } csp->server_connection.sfd = JB_INVALID_SOCKET; + +#ifdef FEATURE_SSL + close_client_ssl_connection(csp); +#endif drain_and_close_socket(csp->cfd); csp->cfd = JB_INVALID_SOCKET; + privoxy_mutex_lock(&connection_reuse_mutex); if (!monitor_thread_running) { @@ -4110,16 +4134,9 @@ static void serve(struct client_state *csp) chat(csp); #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ -#ifdef FEATURE_SSL /* * Closing ssl and then tcp connections, if they were opened. */ -#ifdef FEATURE_CONNECTION_KEEP_ALIVE - csp->ssl_flags = 0; -#endif - close_client_and_server_ssl_connections(csp); -#endif /* def FEATURE_SSL */ - if (csp->server_connection.sfd != JB_INVALID_SOCKET) { #ifdef FEATURE_CONNECTION_SHARING @@ -4128,6 +4145,12 @@ static void serve(struct client_state *csp) forget_connection(csp->server_connection.sfd); } #endif /* def FEATURE_CONNECTION_SHARING */ +#ifdef FEATURE_SSL +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + csp->ssl_flags = 0; +#endif + close_server_ssl_connection(csp); +#endif /* def FEATURE_SSL */ close_socket(csp->server_connection.sfd); } -- 2.26.2 From d00e5bc7697e8f95be51562146fe47b20b8c4bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:52:13 +0200 Subject: [PATCH 77/83] Added functions free_ssl_structures and close_ssl_connection into ssl.c, which are able to work with given ssl_connection_attr. So privoxy can use mbedtls with connection-sharing feature. Renamed socket_fd to mbedtls_fd to avoid name colision with variable for socket fd. Added client ssl connection closing. Added freeing of allocated memory and structures. Added missing semicolons in cgisimple.c in part of code to shut down Privoxy. --- cgisimple.c | 4 +- jcc.c | 1 + ssl.c | 159 +++++++++++++++++++++---------------------------- ssl.h | 1 + ssl_libressl.c | 26 ++++++-- ssl_libressl.h | 1 - 6 files changed, 93 insertions(+), 99 deletions(-) diff --git a/cgisimple.c b/cgisimple.c index 63cd4f95..16f551c1 100644 --- a/cgisimple.c +++ b/cgisimple.c @@ -201,8 +201,8 @@ jb_err cgi_die (struct client_state *csp, const struct map *parameters) { static const char status[] = "200 OK Privoxy shutdown request received"; - static const char body[] = CGI_SHUTDOWN_REQUEST(CGI_PREFIX) - static const char body_ssl[] = CGI_SHUTDOWN_REQUEST(CGI_SSL_PREFIX) + static const char body[] = CGI_SHUTDOWN_REQUEST(CGI_PREFIX); + static const char body_ssl[] = CGI_SHUTDOWN_REQUEST(CGI_SSL_PREFIX); assert(csp); assert(rsp); diff --git a/jcc.c b/jcc.c index d83899b7..14f1dc36 100644 --- a/jcc.c +++ b/jcc.c @@ -4160,6 +4160,7 @@ static void serve(struct client_state *csp) if (csp->cfd != JB_INVALID_SOCKET) { + close_client_ssl_connection(csp); log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. " "Keep-alive: %u. Socket alive: %u. Data available: %u. " "Configuration file change detected: %u. Requests received: %u.", diff --git a/ssl.c b/ssl.c index 3f4b7580..205014b7 100644 --- a/ssl.c +++ b/ssl.c @@ -79,9 +79,8 @@ static int ssl_verify_callback(void *data, mbedtls_x509_crt *crt, int depth, uin static void free_certificate_chain(struct client_state *csp); static unsigned int get_certificate_mutex_id(struct client_state *csp); static unsigned long get_certificate_serial(struct client_state *csp); -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 void free_ssl_structures(ssl_connection_attr *connection); /********************************************************************* @@ -400,7 +399,7 @@ extern int create_client_ssl_connection(struct client_state *csp) /* * Initializing mbedtls structures for SSL/TLS connection */ - mbedtls_net_init(&(csp->ssl_client_attr.socket_fd)); + mbedtls_net_init(&(csp->ssl_client_attr.mbedtls_fd)); mbedtls_ssl_init(&(csp->ssl_client_attr.ssl)); mbedtls_ssl_config_init(&(csp->ssl_client_attr.conf)); mbedtls_x509_crt_init(&(csp->ssl_client_attr.server_cert)); @@ -552,7 +551,7 @@ extern int create_client_ssl_connection(struct client_state *csp) } mbedtls_ssl_set_bio(&(csp->ssl_client_attr.ssl), - &(csp->ssl_client_attr.socket_fd), mbedtls_net_send, + &(csp->ssl_client_attr.mbedtls_fd), mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_session_reset(&(csp->ssl_client_attr.ssl)); @@ -561,7 +560,7 @@ extern int create_client_ssl_connection(struct client_state *csp) * can't be setted by mbedtls functions, because we already have created * TCP connection when starting this function. */ - csp->ssl_client_attr.socket_fd.fd = csp->cfd; + csp->ssl_client_attr.mbedtls_fd.fd = csp->cfd; /* * Handshake with client @@ -603,7 +602,7 @@ exit: /* Freeing structures if connection wasn't created successfully */ if (ret < 0) { - free_client_ssl_structures(csp); + free_ssl_structures(&csp->ssl_client_attr); } return ret; } @@ -624,8 +623,6 @@ exit: *********************************************************************/ extern void close_client_ssl_connection(struct client_state *csp) { - int ret = 0; - if (csp->ssl_with_client_is_opened == 0 #ifdef FEATURE_CONNECTION_KEEP_ALIVE || csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED @@ -635,51 +632,12 @@ extern void close_client_ssl_connection(struct client_state *csp) return; } - /* - * Notifying the peer that the connection is being closed. - */ - do { - ret = mbedtls_ssl_close_notify(&(csp->ssl_client_attr.ssl)); - } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + close_ssl_connection(&csp->ssl_client_attr); - free_client_ssl_structures(csp); csp->ssl_with_client_is_opened = 0; } -/********************************************************************** - * - * Function : free_client_ssl_structures - * - * Description : Frees structures used for SSL communication with client - * - * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * - * Returns : N/A - * - *********************************************************************/ -static void free_client_ssl_structures(struct client_state *csp) -{ - /* - * We can't use function mbedtls_net_free, because this function - * inter alia close TCP connection on setted fd. Instead of this - * function, we change fd to -1, which is the same what does - * rest of mbedtls_net_free function. - */ - csp->ssl_client_attr.socket_fd.fd = -1; - - /* Freeing mbedtls structures */ - mbedtls_x509_crt_free(&(csp->ssl_client_attr.server_cert)); - mbedtls_pk_free(&(csp->ssl_client_attr.prim_key)); - mbedtls_ssl_free(&(csp->ssl_client_attr.ssl)); - mbedtls_ssl_config_free(&(csp->ssl_client_attr.conf)); -#if defined(MBEDTLS_SSL_CACHE_C) - mbedtls_ssl_cache_free(&(csp->ssl_client_attr.cache)); -#endif -} - - /********************************************************************** * * Function : create_server_ssl_connection @@ -711,7 +669,7 @@ extern int create_server_ssl_connection(struct client_state *csp) /* * Initializing mbedtls structures for SSL/TLS connection */ - mbedtls_net_init(&(csp->ssl_server_attr.socket_fd)); + mbedtls_net_init(&(csp->ssl_server_attr.mbedtls_fd)); mbedtls_ssl_init(&(csp->ssl_server_attr.ssl)); mbedtls_ssl_config_init(&(csp->ssl_server_attr.conf)); mbedtls_x509_crt_init( &(csp->ssl_server_attr.ca_cert)); @@ -724,7 +682,7 @@ extern int create_server_ssl_connection(struct client_state *csp) * can't be setted by mbedtls functions, because we already have created * TCP connection when starting this function. */ - csp->ssl_server_attr.socket_fd.fd = csp->server_connection.sfd; + csp->ssl_server_attr.mbedtls_fd.fd = csp->server_connection.sfd; /* * Seed the RNG @@ -813,7 +771,7 @@ extern int create_server_ssl_connection(struct client_state *csp) } mbedtls_ssl_set_bio(&(csp->ssl_server_attr.ssl), - &(csp->ssl_server_attr.socket_fd), mbedtls_net_send, + &(csp->ssl_server_attr.mbedtls_fd), mbedtls_net_send, mbedtls_net_recv, NULL); /* @@ -868,13 +826,70 @@ exit: /* Freeing structures if connection wasn't created successfully */ if (ret < 0) { - free_server_ssl_structures(csp); + free_ssl_structures(&csp->ssl_server_attr); } return ret; } +/********************************************************************** + * + * Function : free_ssl_structures + * + * Description : Frees given structures used for SSL communication. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * + * Returns : N/A + * + *********************************************************************/ +static void free_ssl_structures(ssl_connection_attr *connection) +{ + /* + * We can't use function mbedtls_net_free, because this function + * inter alia close TCP connection on setted fd. Instead of this + * function, we change fd to -1, which is the same what does + * rest of mbedtls_net_free function. + */ + connection->mbedtls_fd.fd = JB_INVALID_SOCKET; + + mbedtls_x509_crt_free(&connection->ca_cert); + mbedtls_ssl_free(&connection->ssl); + mbedtls_ssl_config_free(&connection->conf); +} + + +/********************************************************************** + * + * Function : close_ssl_connection + * + * Description : Closes SSL/TLS connection with given ssl attributes. + * This function doesn't check if attributes are not + * initialized. It must be done by caller. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * + * Returns : N/A + * + **********************************************************************/ +extern void close_ssl_connection(ssl_connection_attr *connection) +{ + int ret = 0; + + /* + * Notifying the peer that the connection is being closed. + */ + do { + ret = mbedtls_ssl_close_notify(&connection->ssl); + } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + free_ssl_structures(connection); +} + + /********************************************************************** * * Function : close_server_ssl_connection @@ -890,8 +905,6 @@ exit: **********************************************************************/ extern void close_server_ssl_connection(struct client_state *csp) { - int ret = 0; - if (csp->ssl_with_server_is_opened == 0 #ifdef FEATURE_CONNECTION_KEEP_ALIVE || (csp->ssl_flags & CSP_SSL_FLAG_CONNECTIONS_TO_BE_REUSED @@ -903,14 +916,8 @@ extern void close_server_ssl_connection(struct client_state *csp) return; } - /* - * Notifying the peer that the connection is being closed. - */ - do { - ret = mbedtls_ssl_close_notify(&(csp->ssl_server_attr.ssl)); - } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + close_ssl_connection(&csp->ssl_server_attr); - free_server_ssl_structures(csp); csp->ssl_with_server_is_opened = 0; csp->server_connection.ssl = 0; @@ -921,34 +928,6 @@ extern void close_server_ssl_connection(struct client_state *csp) /********************************************************************* - * - * Function : free_server_ssl_structures - * - * Description : Frees structures used for SSL communication with server - * - * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * - * Returns : N/A - * - *********************************************************************/ -static void free_server_ssl_structures(struct client_state *csp) -{ - /* - * We can't use function mbedtls_net_free, because this function - * inter alia close TCP connection on setted fd. Instead of this - * function, we change fd to -1, which is the same what does - * rest of mbedtls_net_free function. - */ - csp->ssl_server_attr.socket_fd.fd = -1; - - mbedtls_x509_crt_free(&(csp->ssl_server_attr.ca_cert)); - mbedtls_ssl_free(&(csp->ssl_server_attr.ssl)); - mbedtls_ssl_config_free(&(csp->ssl_server_attr.conf)); -} - - -/* * Function : close_client_and_server_ssl_connections * * Description : Checks if client or server should use secured connection over @@ -959,7 +938,7 @@ static void free_server_ssl_structures(struct client_state *csp) * * Returns : N/A * - */ + *********************************************************************/ extern void close_client_and_server_ssl_connections(struct client_state *csp) { if (client_use_ssl(csp) == 1) diff --git a/ssl.h b/ssl.h index d4170cc6..d322f2b9 100644 --- a/ssl.h +++ b/ssl.h @@ -66,5 +66,6 @@ extern int create_server_ssl_connection(struct client_state *csp); extern void close_client_and_server_ssl_connections(struct client_state *csp); extern void close_server_ssl_connection(struct client_state *csp); extern void close_client_ssl_connection(struct client_state *csp); +extern void close_ssl_connection(ssl_connection_attr *connection); #endif /* ndef SSL_H_INCLUDED */ diff --git a/ssl_libressl.c b/ssl_libressl.c index bd6350c4..a1217bcd 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -67,6 +67,7 @@ static int host_to_hash(struct client_state *csp); static int ssl_cert_verify_callback(X509_STORE_CTX * ctx, void * arg); static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit, ASN1_VALUE *ext_struc); static char* generate_cert_info(X509* cert); +static void free_ssl_structures(ssl_connection_attr *connection_attr); /********************************************************************** @@ -188,7 +189,7 @@ extern int create_server_ssl_connection(struct client_state *csp) * Creating BIO to comunicate with server over ssl. */ csp->ssl_server_attr.ssl_bio = BIO_new(BIO_f_ssl()); - BIO_set_ssl(csp->ssl_server_attr.ssl_bio, csp->ssl_server_attr.ssl, BIO_CLOSE); + BIO_set_ssl(csp->ssl_server_attr.ssl_bio, csp->ssl_server_attr.ssl, BIO_NOCLOSE); csp->ssl_with_server_is_opened = 1; csp->server_connection.ssl = 1; @@ -218,7 +219,7 @@ exit: * Returns : N/A * *********************************************************************/ -extern void free_ssl_structures(ssl_connection_attr *connection_attr) +static void free_ssl_structures(ssl_connection_attr *connection_attr) { SSL_free(connection_attr->ssl); SSL_CTX_free(connection_attr->ctx); @@ -381,6 +382,8 @@ extern int create_client_ssl_connection(struct client_state *csp) { int ret = 0; csp->ssl_client_attr.socket_fd = csp->cfd; const SSL_METHOD * meth; + char *key_file = NULL; + char *cert_file = NULL; /* * Preparing hash of host for creating certificates @@ -396,9 +399,6 @@ extern int create_client_ssl_connection(struct client_state *csp) { /* * Preparing paths to certificates files and key file */ - char *key_file = NULL; - char *cert_file = NULL; - cert_file = make_certs_path(csp->config->certs_dir, (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE); if (cert_file == NULL) @@ -490,7 +490,7 @@ extern int create_client_ssl_connection(struct client_state *csp) { * Creating BIO to comunicate with client over ssl. */ csp->ssl_client_attr.ssl_bio = BIO_new(BIO_f_ssl()); - BIO_set_ssl(csp->ssl_client_attr.ssl_bio, csp->ssl_client_attr.ssl, BIO_CLOSE); + BIO_set_ssl(csp->ssl_client_attr.ssl_bio, csp->ssl_client_attr.ssl, BIO_NOCLOSE); csp->ssl_with_client_is_opened = 1; #ifdef FEATURE_CONNECTION_KEEP_ALIVE @@ -498,6 +498,20 @@ extern int create_client_ssl_connection(struct client_state *csp) { #endif ret = 0; exit: + /* + * Freeing allocated paths to files + */ + if (cert_file != NULL) + { + log_error(LOG_LEVEL_ERROR, "freeing cert file path 1"); + freez(cert_file); + } + if (key_file != NULL) + { + log_error(LOG_LEVEL_ERROR, "freeing cert file path 2"); + freez(key_file); + } + if (ret != 0) { free_ssl_structures(&csp->ssl_client_attr); } diff --git a/ssl_libressl.h b/ssl_libressl.h index 66c3c615..c9a7cd2e 100644 --- a/ssl_libressl.h +++ b/ssl_libressl.h @@ -53,7 +53,6 @@ extern int create_server_ssl_connection(struct client_state *csp); extern void close_client_and_server_ssl_connections(struct client_state *csp); extern void close_server_ssl_connection(struct client_state *csp); extern void close_client_ssl_connection(struct client_state *csp); -extern void free_ssl_structures(ssl_connection_attr *connection); extern void close_ssl_connection(ssl_connection_attr *connection); -- 2.26.2 From 6c3c3ae498b27839446d883ef7f09e523092b1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:55:15 +0200 Subject: [PATCH 78/83] Renamed ssl.h and ssl.c to ssl_mbedtls.h and ssl_mbedtls.c so it's easier to differ between used ssl libraries. --- GNUmakefile.in | 2 +- gateway.c | 2 +- jbsockets.c | 2 +- jcc.c | 2 +- ssl.c => ssl_mbedtls.c | 4 ++-- ssl.h => ssl_mbedtls.h | 10 +++++----- 6 files changed, 11 insertions(+), 11 deletions(-) rename ssl.c => ssl_mbedtls.c (99%) rename ssl.h => ssl_mbedtls.h (94%) diff --git a/GNUmakefile.in b/GNUmakefile.in index a2d88de4..b62f51a3 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -231,7 +231,7 @@ W32_HDRS = @WIN_ONLY@w32log.h w32taskbar.h win32.h w32res.h w32svrapi.h W32_LIB = @WIN_ONLY@-lwsock32 -lcomctl32 W32_INIS = @WIN_ONLY@config.txt trust.txt -SSL_MBEDTLS_SRC = @USAGE_MBEDTLS@ssl.c +SSL_MBEDTLS_SRC = @USAGE_MBEDTLS@ssl_mbedtls.c SSL_MBEDTLS_OBJS = @USAGE_MBEDTLS@$(SSL_MBEDTLS_SRC:.c=.o) SSL_MBEDTLS_HDRS = @USAGE_MBEDTLS@$(SSL_MBEDTLS_SRC:.c=.h) project.h SSL_MBEDTLS_LIB = @USAGE_MBEDTLS@mbedtls/library/libmbedx509.a mbedtls/library/libmbedtls.a mbedtls/library/libmbedcrypto.a diff --git a/gateway.c b/gateway.c index 5c12044f..a8a3896b 100644 --- a/gateway.c +++ b/gateway.c @@ -60,7 +60,7 @@ #endif /* def __OS2__ */ #ifdef FEATURE_MBEDTLS -#include "ssl.h" +#include "ssl_mbedtls.h" #endif #ifdef FEATURE_LIBRESSL diff --git a/jbsockets.c b/jbsockets.c index fa89ad15..49b115a6 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -95,7 +95,7 @@ #include "ssl_libressl.h" #endif #ifdef FEATURE_MBEDTLS -#include "ssl.h" +#include "ssl_mbedtls.h" #endif #include "project.h" diff --git a/jcc.c b/jcc.c index 14f1dc36..c91bba13 100644 --- a/jcc.c +++ b/jcc.c @@ -128,7 +128,7 @@ #endif #ifdef FEATURE_MBEDTLS -#include "ssl.h" +#include "ssl_mbedtls.h" #endif #ifdef FEATURE_LIBRESSL diff --git a/ssl.c b/ssl_mbedtls.c similarity index 99% rename from ssl.c rename to ssl_mbedtls.c index 205014b7..1da82bb3 100644 --- a/ssl.c +++ b/ssl_mbedtls.c @@ -1,6 +1,6 @@ /********************************************************************* * - * File : $Source: /cvsroot/ijbswa/current/ssl.c,v $ + * File : $Source: /cvsroot/ijbswa/current/ssl_mbedtls.c,v $ * * Purpose : File with SSL/TLS extension. Contains methods for * creating, using and closing SSL/TLS connections. @@ -39,7 +39,7 @@ #include "miscutil.h" #include "errlog.h" #include "jcc.h" -#include "ssl.h" +#include "ssl_mbedtls.h" /* Macros for searching begin and end of certificates diff --git a/ssl.h b/ssl_mbedtls.h similarity index 94% rename from ssl.h rename to ssl_mbedtls.h index d322f2b9..4c6ac459 100644 --- a/ssl.h +++ b/ssl_mbedtls.h @@ -1,9 +1,9 @@ -#ifndef SSL_H_INCLUDED -#define SSL_H_INCLUDED -#define SSL_H_VERSION +#ifndef SSL_MBEDTLS_H_INCLUDED +#define SSL_MBEDTLS_H_INCLUDED +#define SSL_MBEDTLS_H_VERSION /********************************************************************* * -* File : $Source: /cvsroot/ijbswa/current/ssl.h,v $ +* File : $Source: /cvsroot/ijbswa/current/ssl_mbedtls.h,v $ * * Purpose : File with SSL/TLS extension. Contains methods for * creating, using and closing SSL/TLS connections. @@ -68,4 +68,4 @@ extern void close_server_ssl_connection(struct client_state *csp); extern void close_client_ssl_connection(struct client_state *csp); extern void close_ssl_connection(ssl_connection_attr *connection); -#endif /* ndef SSL_H_INCLUDED */ +#endif /* ndef SSL_MBEDTLS_H_INCLUDED */ -- 2.26.2 From b0b074fc3aecc89efd15afb442ce8b667e1c843d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 22:58:18 +0200 Subject: [PATCH 79/83] Fixes to remove errors during WIN32 compilation using MingW. Last change necessary to compile Privoxy for Window using MingW is to add '-lws2_32' at the end of SSL_LIBRE_LIB and SSL_MBEDTLS_LIB in GNUmakefile, but it can't be done generaly, because it would cause an error during compilation for linux. --- GNUmakefile.in | 2 +- jcc.c | 3 ++- miscutil.c | 2 ++ project.h | 39 +++++++++++++++++++++------------------ 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/GNUmakefile.in b/GNUmakefile.in index b62f51a3..141061cf 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -770,7 +770,7 @@ w32taskbar.@OBJEXT@: w32taskbar.c config.h w32log.h w32taskbar.h win32.@OBJEXT@: win32.c config.h jcc.h loadcfg.h pcre/pcre.h pcre/pcreposix.h pcrs.h project.h w32log.h win32.h w32svrapi.h w32.res: w32.rc w32res.h icons/radar-01.ico icons/radar-02.ico icons/radar-03.ico icons/radar-04.ico icons/radar-05.ico icons/radar-06.ico icons/radar-07.ico icons/radar-08.ico icons/idle.ico icons/privoxy.ico config.h - windres -F pe-i386 -D__MINGW32__=0.2 -O coff -i $< -o $@ + i686-w64-mingw32-windres -F pe-i386 -D__MINGW32__=0.2 -O coff -i $< -o $@ $(PROGRAM): $(OBJS) $(W32_FILES) $(LD) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS) diff --git a/jcc.c b/jcc.c index c91bba13..bb433be7 100644 --- a/jcc.c +++ b/jcc.c @@ -2904,7 +2904,6 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_CONNECT, "Done reading from the client."); - log_error(LOG_LEVEL_ERROR, "CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ SET4"); csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; } } @@ -4160,7 +4159,9 @@ static void serve(struct client_state *csp) if (csp->cfd != JB_INVALID_SOCKET) { +#ifdef FEATURE_SSL close_client_ssl_connection(csp); +#endif log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. " "Keep-alive: %u. Socket alive: %u. Data available: %u. " "Configuration file change detected: %u. Requests received: %u.", diff --git a/miscutil.c b/miscutil.c index cd908ebe..8b0d5327 100644 --- a/miscutil.c +++ b/miscutil.c @@ -854,6 +854,7 @@ int privoxy_millisleep(unsigned milliseconds) } +#if !defined(_WIN32) || !defined(FEATURE_LIBRESSL) #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) /********************************************************************* * @@ -924,6 +925,7 @@ time_t timegm(struct tm *tm) return answer; } #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */ +#endif /* !defined(_WIN32) || !defined(FEATURE_LIBRESSL) */ #ifndef HAVE_SNPRINTF diff --git a/project.h b/project.h index 5c14c7eb..abe8ca58 100644 --- a/project.h +++ b/project.h @@ -45,22 +45,6 @@ #include "config.h" -#ifdef FEATURE_MBEDTLS -/* Mbedtls incldues */ -#include "mbedtls/net_sockets.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" - -#if defined(MBEDTLS_SSL_CACHE_C) -#include "mbedtls/ssl_cache.h" -#endif -#endif /* FEATURE_MBEDTLS */ - -#ifdef FEATURE_LIBRESSL -#include "openssl/ssl.h" -#endif /* FEATURE_LIBRESSL */ - - /* * Macros for SSL structures */ @@ -89,7 +73,7 @@ */ #ifdef STATIC_PCRE -# include "pcre.h" +# include "pcre/pcre.h" #else # ifdef PCRE_H_IN_SUBDIR # include @@ -105,7 +89,7 @@ #endif #ifdef STATIC_PCRE -# include "pcreposix.h" +# include "pcre/pcreposix.h" #else # ifdef PCRE_H_IN_SUBDIR # include @@ -126,6 +110,25 @@ #endif +#ifdef FEATURE_MBEDTLS +/* Mbedtls incldues */ +# include "mbedtls/net_sockets.h" +# include "mbedtls/entropy.h" +# include "mbedtls/ctr_drbg.h" + +# if defined(MBEDTLS_SSL_CACHE_C) +# include "mbedtls/ssl_cache.h" +# endif +#endif /* FEATURE_MBEDTLS */ + +#ifdef FEATURE_LIBRESSL +# ifdef _WIN32 +# undef X509_NAME +# endif +# include "openssl/ssl.h" +#endif /* FEATURE_LIBRESSL */ + + #ifdef _WIN32 typedef SOCKET jb_socket; -- 2.26.2 From bbe0604930ffd407e7ef02d2f2011468488fc88e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 23:00:06 +0200 Subject: [PATCH 80/83] Added new action to configure ciphersuites using Libressl. --- actionlist.h | 1 + project.h | 6 +++++- ssl_libressl.c | 13 +++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/actionlist.h b/actionlist.h index 84fd21b6..315f0f88 100644 --- a/actionlist.h +++ b/actionlist.h @@ -123,6 +123,7 @@ DEFINE_CGI_PARAM_NO_RADIO("redirect", ACTION_REDIRECT, DEFINE_ACTION_MULTI ("server-header-filter", ACTION_MULTI_SERVER_HEADER_FILTER) DEFINE_ACTION_MULTI ("server-header-tagger", ACTION_MULTI_SERVER_HEADER_TAGGER) DEFINE_ACTION_BOOL ("session-cookies-only", ACTION_SESSION_COOKIES_ONLY) +DEFINE_ACTION_STRING ("set-cipher-list", ACTION_SET_CIPHER_LIST, ACTION_STRING_CIPHER_LIST) DEFINE_ACTION_STRING ("set-image-blocker", ACTION_IMAGE_BLOCKER, ACTION_STRING_IMAGE_BLOCKER) DEFINE_CGI_PARAM_RADIO ("set-image-blocker", ACTION_IMAGE_BLOCKER, ACTION_STRING_IMAGE_BLOCKER, "pattern", 1) DEFINE_CGI_PARAM_RADIO ("set-image-blocker", ACTION_IMAGE_BLOCKER, ACTION_STRING_IMAGE_BLOCKER, "blank", 0) diff --git a/project.h b/project.h index abe8ca58..f81f9fb2 100644 --- a/project.h +++ b/project.h @@ -610,6 +610,8 @@ struct iob #define ACTION_DISABLE_HTTPS_FILTER 0x20000000UL /** Action bitmap: Turn certificates verification off */ #define ACTION_IGNORE_CERTIFICATE_ERRORS 0x40000000UL +/** Action bitmap: Sets specific cipher list */ +#define ACTION_SET_CIPHER_LIST 0x80000000UL /** Action string index: How to deanimate GIFs */ @@ -652,8 +654,10 @@ struct iob #define ACTION_STRING_LIMIT_COOKIE_LIFETIME 18 /** Action string index: how many milliseconds writes should be delayed. */ #define ACTION_STRING_DELAY_RESPONSE 19 +/** Action string index: Cipher list. */ +#define ACTION_STRING_CIPHER_LIST 20 /** Number of string actions. */ -#define ACTION_STRING_COUNT 20 +#define ACTION_STRING_COUNT 21 /* To make the ugly hack in sed easier to understand */ diff --git a/ssl_libressl.c b/ssl_libressl.c index a1217bcd..3518e3a5 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -137,6 +137,19 @@ extern int create_server_ssl_connection(struct client_state *csp) } csp->ssl_server_attr.ssl = SSL_new(csp->ssl_server_attr.ctx); + + /* Setting ciphersuites */ + if (csp->action->flags & ACTION_SET_CIPHER_LIST) + { + log_error(LOG_LEVEL_CONNECT, "Setting cipher list 1 \"%s\" for %s", csp->action->string[ACTION_STRING_CIPHER_LIST], csp->http->host); + ret = SSL_set_cipher_list(csp->ssl_server_attr.ssl, csp->action->string[ACTION_STRING_CIPHER_LIST]); + if (ret != 1) + { + log_error(LOG_LEVEL_ERROR, "Given cipher suite \"%s\" can't be set", csp->action->string[ACTION_STRING_CIPHER_LIST]); + ret = -1; + goto exit; + } + } /* * Setting hostname for handshake and server certificate verification -- 2.26.2 From ecff5560fd80854e8608c1feea65aed55a0cc7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 23:00:36 +0200 Subject: [PATCH 81/83] Added ciphersuites configuration using Mbed TLS. --- project.h | 1 + ssl_mbedtls.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/project.h b/project.h index f81f9fb2..296e9816 100644 --- a/project.h +++ b/project.h @@ -296,6 +296,7 @@ typedef struct { #ifdef FEATURE_MBEDTLS mbedtls_ssl_context ssl; mbedtls_ssl_config conf; + int* ciphersuites_list; mbedtls_net_context mbedtls_fd; mbedtls_x509_crt server_cert; mbedtls_x509_crt ca_cert; diff --git a/ssl_mbedtls.c b/ssl_mbedtls.c index 1da82bb3..7e629c3c 100644 --- a/ssl_mbedtls.c +++ b/ssl_mbedtls.c @@ -81,6 +81,7 @@ static unsigned int get_certificate_mutex_id(struct client_state *csp); static unsigned long get_certificate_serial(struct client_state *csp); static int seed_rng(struct client_state *csp); static void free_ssl_structures(ssl_connection_attr *connection); +static int* get_ciphersuites_from_string(const char* ciphersuites_string); /********************************************************************* @@ -746,6 +747,21 @@ extern int create_server_ssl_connection(struct client_state *csp) mbedtls_ssl_conf_dbg(&(csp->ssl_server_attr.conf), ssl_debug_callback, stdout); + /* Setting ciphersuites */ + if (csp->action->flags & ACTION_SET_CIPHER_LIST) { + csp->ssl_server_attr.ciphersuites_list = + get_ciphersuites_from_string(csp->action->string[ACTION_STRING_CIPHER_LIST]); + if (csp->ssl_server_attr.ciphersuites_list == NULL) + { + log_error(LOG_LEVEL_ERROR, "Given cipher suite \"%s\" can't be set", + csp->action->string[ACTION_STRING_CIPHER_LIST]); + ret = -1; + goto exit; + } + mbedtls_ssl_conf_ciphersuites(&(csp->ssl_server_attr.conf), + csp->ssl_server_attr.ciphersuites_list); + } + ret = mbedtls_ssl_setup(&(csp->ssl_server_attr.ssl), &(csp->ssl_server_attr.conf)); if ( ret != 0) @@ -857,6 +873,7 @@ static void free_ssl_structures(ssl_connection_attr *connection) mbedtls_x509_crt_free(&connection->ca_cert); mbedtls_ssl_free(&connection->ssl); + freez(connection->ciphersuites_list); mbedtls_ssl_config_free(&connection->conf); } @@ -952,6 +969,79 @@ extern void close_client_and_server_ssl_connections(struct client_state *csp) } +/********************************************************************* + * Function : get_ciphersuites_from_string + * + * Description : Converts string of ciphersuites marco's names to + * array of ciphersuite's ids. + * + * Parameters : + * 1 : ciphersuites_string = String containing allowed + * ciphersuites. + * + * Returns : Array of ciphersuite's ids + * + *********************************************************************/ +static int* get_ciphersuites_from_string(const char* parameter_string) { + size_t count = 2; + char* ciphersuites_index, *item_end, *ciphersuites_string; + int index = 0; + int *ciphersuite_ids; + const char separator = ':'; + int parameter_len = strlen(parameter_string); + + ciphersuites_string = calloc(parameter_len + 1, sizeof(char)); + if (ciphersuites_string == NULL) + { + log_error(LOG_LEVEL_ERROR, "get_ciphersuites_from_string failed: calloc fail"); + return NULL; + } + strncpy(ciphersuites_string, parameter_string, parameter_len); + ciphersuites_index = ciphersuites_string; + + while (*ciphersuites_index) + { + if (*ciphersuites_index++ == separator) + { + ++count; + } + } + + ciphersuite_ids = (int *)calloc(count, sizeof(int)); + if (ciphersuite_ids == NULL) + { + log_error(LOG_LEVEL_ERROR, "get_ciphersuites_from_string failed: calloc fail"); + freez(ciphersuites_string); + return NULL; + } + + ciphersuites_index = ciphersuites_string; + do { + item_end = strchr(ciphersuites_index, separator); + if (item_end != NULL) + { + *item_end = '\0'; + } + + int val = mbedtls_ssl_get_ciphersuite_id(ciphersuites_index); + ciphersuite_ids[index] = val; + 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; +} + + /********************************************************************* * * Function : tunnel_established_successfully -- 2.26.2 From 5a3fe2c29f24d68a0adfef20e05ce1ebbc662ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 23:02:47 +0200 Subject: [PATCH 82/83] All functinos from ssl libraries were separated into ssl_libressl.c and ssl_mbedtls.c files. --- jbsockets.c | 27 ++----------------------- jcc.c | 34 +++++++------------------------ ssl_libressl.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ ssl_libressl.h | 2 ++ ssl_mbedtls.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ ssl_mbedtls.h | 2 ++ 6 files changed, 121 insertions(+), 52 deletions(-) diff --git a/jbsockets.c b/jbsockets.c index 49b115a6..778ca8e3 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1744,36 +1744,13 @@ extern int connection_is_still_alive(struct client_state *csp, int src) extern int connection_is_still_alive_ssl_attr(ssl_connection_attr *connection_attr, int is_using_ssl) { #ifdef FEATURE_SSL - unsigned char tmp[10]; -#endif - if (is_using_ssl && data_is_available_tcp_ssl_ssl_attr(connection_attr, 0, 0)) { -#ifdef FEATURE_MBEDTLS - /* - * mbedtls_ssl_read reads available data and checks connection state. - * When connection was closed by peer, closure notifice is returned. - * Otherway, no chars are set to given buffer and stay pending. - */ - if (mbedtls_ssl_read(&connection_attr->ssl, tmp, 0) == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) - { + if (was_connection_closed_by_peer(connection_attr)) { return FALSE; } -#endif /* def FEATURE_MBEDTLS */ -#ifdef FEATURE_LIBRESSL - /* - * We have to call data_is_available_tcp_ssl and SSL_peek, because - * it loads SSL shutdown flag, which signals whether "close notify" - * alert was received or not. - */ - SSL_peek(connection_attr->ssl, tmp, 1); - if (SSL_get_shutdown(connection_attr->ssl) & SSL_RECEIVED_SHUTDOWN) - { - return FALSE; - } -#endif /* def FEATURE_LIBRESSL */ } - +#endif /* def FEATURE_SSL */ return socket_is_still_alive(connection_attr->socket_fd); } diff --git a/jcc.c b/jcc.c index bb433be7..ad2b2c97 100644 --- a/jcc.c +++ b/jcc.c @@ -965,14 +965,7 @@ static int create_server_connection(struct client_state *csp) { */ if (ret != 0 -#ifdef FEATURE_MBEDTLS - && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED - || csp->server_cert_verification_result == SSL_CERT_VALID) -#endif -#ifdef FEATURE_LIBRESSL - && (csp->server_cert_verification_result == X509_V_OK) -#endif - ) + && (is_server_certificate_valid(csp->server_cert_verification_result))) { rsp = error_response(csp, "connect-failed"); if (rsp) @@ -1018,16 +1011,8 @@ static int create_server_connection(struct client_state *csp) { * wasn't detected, we can interrupt this fuction. Otherwise, we * must inform client about invalid server certificate. */ - if (ret != 0 -#ifdef FEATURE_MBEDTLS - && (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED - || csp->server_cert_verification_result == SSL_CERT_VALID) -#endif -#ifdef FEATURE_LIBRESSL - && (csp->server_cert_verification_result == X509_V_OK) -#endif - ) + && (is_server_certificate_valid(csp->server_cert_verification_result))) { rsp = error_response(csp, "connect-failed"); if (rsp) @@ -1146,16 +1131,11 @@ static int prepare_client_connection(struct client_state *csp) * If server certificate is invalid, we must inform client and then * close connection with client. */ -#ifdef FEATURE_MBEDTLS - if (csp->server_cert_verification_result != SSL_CERT_VALID) -#endif -#ifdef FEATURE_LIBRESSL - if (csp->server_cert_verification_result != X509_V_OK) -#endif - { - ssl_send_certificate_error(csp); - return 1; - } + if (!is_server_certificate_valid(csp->server_cert_verification_result)) + { + ssl_send_certificate_error(csp); + return 1; + } log_error(LOG_LEVEL_CONNECT, "SSL connection with client was created successfully"); } diff --git a/ssl_libressl.c b/ssl_libressl.c index 3518e3a5..53fed659 100644 --- a/ssl_libressl.c +++ b/ssl_libressl.c @@ -763,6 +763,60 @@ extern int tunnel_established_successfully(const char * server_response, unsigne } +/********************************************************************* + * + * Function : was_connection_closed_by_peer + * + * Description : Check whether peer has sent "close notify" message + * to the proxy server. It would mean that peer has + * closed TLS connection with proxy server. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * + * Returns : 1 => Peer has closed the connection + * 0 => Peer hasn't closed the connection + * + *********************************************************************/ +extern int was_connection_closed_by_peer(ssl_connection_attr *connection_attr) { + unsigned char tmp[10]; + + /* + * We have to call data_is_available_tcp_ssl and SSL_peek, because + * it loads SSL shutdown flag, which signals whether "close notify" + * alert was received or not. + */ + SSL_peek(connection_attr->ssl, tmp, 1); + if (SSL_get_shutdown(connection_attr->ssl) & SSL_RECEIVED_SHUTDOWN) + { + return TRUE; + } + + return FALSE; +} + + +/********************************************************************* + * + * Function : is_server_certificate_valid + * + * Description : Check whether server's certificate is valid or not. + * Result is determined from given parameter, which is + * result of certificate verification. + * + * Parameters : + * 1 : server_cert_verification_result = Certificate + verification result + * + * Returns : 1 => Certificate is valid + * 0 => Certificate is invalid + * + *********************************************************************/ +extern int is_server_certificate_valid(uint32_t server_cert_verification_result) { + return server_cert_verification_result == X509_V_OK; +} + + /********************************************************************* * * Function : ssl_flush_socket diff --git a/ssl_libressl.h b/ssl_libressl.h index c9a7cd2e..9fb0d058 100644 --- a/ssl_libressl.h +++ b/ssl_libressl.h @@ -39,6 +39,8 @@ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); extern size_t is_ssl_pending(const ssl_connection_attr *connection); extern int tunnel_established_successfully(const char * response, unsigned int response_len); +extern int was_connection_closed_by_peer(ssl_connection_attr *connection_attr); +extern int is_server_certificate_valid(uint32_t server_cert_verification_result); /* Functions for sending and receiving data over SSL/TLS connections */ extern int ssl_send_data(const ssl_connection_attr *connection, const unsigned char * buf, int len); diff --git a/ssl_mbedtls.c b/ssl_mbedtls.c index 7e629c3c..5802c48b 100644 --- a/ssl_mbedtls.c +++ b/ssl_mbedtls.c @@ -1101,6 +1101,60 @@ extern int tunnel_established_successfully(const char * server_response, unsigne } +/********************************************************************* + * + * Function : was_connection_closed_by_peer + * + * Description : Check whether peer has sent "close notify" message + * to the proxy server. It would mean that peer has + * closed TLS connection with proxy server. + * + * Parameters : + * 1 : connection_attr = Attributes of ssl connection + * + * Returns : 1 => Peer has closed the connection + * 0 => Peer hasn't closed the connection + * + *********************************************************************/ +extern int was_connection_closed_by_peer(ssl_connection_attr *connection_attr) { + unsigned char tmp[10]; + + /* + * mbedtls_ssl_read reads available data and checks connection state. + * When connection was closed by peer, closure notifice is returned. + * Otherway, no chars are set to given buffer and stay pending. + */ + if (mbedtls_ssl_read(&connection_attr->ssl, tmp, 0) == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) + { + return TRUE; + } + + return FALSE; +} + + +/********************************************************************* + * + * Function : is_server_certificate_valid + * + * Description : Check whether server's certificate is valid or not. + * Result is determined from given parameter, which is + * result of certificate verification. + * + * Parameters : + * 1 : server_cert_verification_result = Certificate + verification result + * + * Returns : 1 => Certificate is valid + * 0 => Certificate is invalid + * + *********************************************************************/ +extern int is_server_certificate_valid(uint32_t server_cert_verification_result) { + return server_cert_verification_result == SSL_CERT_NOT_VERIFIED + || server_cert_verification_result == SSL_CERT_VALID; +} + + /*======================Certificates======================*/ /********************************************************************* diff --git a/ssl_mbedtls.h b/ssl_mbedtls.h index 4c6ac459..862024e7 100644 --- a/ssl_mbedtls.h +++ b/ssl_mbedtls.h @@ -52,6 +52,8 @@ extern int client_use_ssl(struct client_state *csp); extern int server_use_ssl(struct client_state *csp); extern size_t is_ssl_pending(const ssl_connection_attr *connection); extern int tunnel_established_successfully(const char * response, unsigned int response_len); +extern int was_connection_closed_by_peer(ssl_connection_attr *connection_attr); +extern int is_server_certificate_valid(uint32_t server_cert_verification_result); /* Functions for sending and receiving data over SSL/TLS connections */ extern int ssl_send_data(const ssl_connection_attr * connection, const unsigned char * buf, int len); -- 2.26.2 From b6fc6c5810dd0b1a65d878f494749061d4ddb045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20=C5=A0vec?= Date: Sun, 17 May 2020 23:04:18 +0200 Subject: [PATCH 83/83] Added documentation into INSTALL files and configure.in file. --- INSTALL | 21 +++++++++++ INSTALL.W32 | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 9 +++-- 3 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 INSTALL.W32 diff --git a/INSTALL b/INSTALL index 4acc4cf9..4d547df1 100644 --- a/INSTALL +++ b/INSTALL @@ -95,6 +95,27 @@ configurations, configure like this: Note that all of these options can also be disabled through the configuration file. +To build an executable with SSL features, which allows to filter HTTPS +communication, some SSL library has to be used. Defaultly LibreSSL is enabled. +To disable LibreSSL library, you can use: + +./configure --disable-libressl + +so no SSL feature will be supported. When LibreSSL is enabled, compiled +LibreSSL library is expected in directory "libressl" in source directory. + +To use MbedTLS library for SSL features, use: + +./configure --enable-mbedtls + +It will cause, that MbedTLS library will be used instead of LibreSSL. When +MbedTLS library is used, then it's expected compiled in directory "mbedtls" +in source directory. + +When some SSL library is used, required SSL attributes has to be configured +correctly in "config" file and relevant certificates, keys and directories have +to be prepared in specified paths. + WARNING: If installing as root, the install will fail unless a non-root user or group is specified, or a privoxy user and group already exist on the system. If a non-root user is specified, and no group, then the installation will try to diff --git a/INSTALL.W32 b/INSTALL.W32 new file mode 100644 index 00000000..fe2bd448 --- /dev/null +++ b/INSTALL.W32 @@ -0,0 +1,101 @@ +/********************************************************************* + * + * File : $Source: /cvsroot/ijbswa/current/doc/source/install.sgml,v $ + * + * Purpose : INSTALL file to help with building Privoxy for WIN32 + * from source using wine. + * + * Copyright : Written by and Copyright (C) 2001-2009 the + * Privoxy team. https://www.privoxy.org/ + * + * Based on the Internet Junkbuster originally written + * by and Copyright (C) 1997 Anonymous Coders and + * Junkbusters Corporation. http://www.junkbusters.com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * The GNU General Public License should be included with + * this file. If not, you can view it at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA + * + *********************************************************************/ + +------------------------------------------------------------------------------- + +To build Privoxy from source, autoconf, GNU make (gmake), and, of course, a C +compiler like gcc are required. + +When building from a source tarball, first unpack the source: + + tar xzvf privoxy-3.0.28-stable-src.tar.gz + cd privoxy-3.0.28-stable + +Then cryptographic library has to be prepared. Latest version of +recomended LibreSSL library can be downloaded here: + https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/ + +To prepare it for Privoxy build, move downloaded tar.gz file into +Privoxy directory and use: + + tar -xzvf ./libressl-x.x.x.tar.gz #x.x.x have to be replaced by downloaded version number + mv libressl-x.x.x libressl #x.x.x have to be replaced by downloaded version number + cd libressl + + CC=i686-w64-mingw32-gcc CPPFLAGS=-D__MINGW_USE_VC2005_COMPAT ./configure --host=i686-w64-mingw32 + make + +Then, to build from either unpacked tarball or CVS source: + + autoheader + autoconf + ./configure --host=i686-w64-mingw32 --enable-mingw32 --disable-pthread # (--help to see options) + # Edit GNUmakefile and rewrite "windres" to "i686-w64-mingw32-windres" + make # (the make from GNU, sometimes called gmake) + +To build an executable with security enhanced features so that users cannot +easily bypass the proxy (e.g. "Go There Anyway"), or alter their own +configurations, add following options to configure script: + + --disable-toggle --disable-editor --disable-force + +Note that all of these options can also be disabled through the configuration +file. + +To build an executable with SSL features, which allows to filter HTTPS +communication, some SSL library has to be used. Defaultly LibreSSL is enabled. +To disable LibreSSL library, you can use: + +./configure --disable-libressl + +so no SSL feature will be supported. When LibreSSL is enabled, compiled +LibreSSL library is expected in directory "libressl" in source directory. + +To use MbedTLS library for SSL features, use: + +./configure --enable-mbedtls + +It will cause, that MbedTLS library will be used instead of LibreSSL. When +MbedTLS library is used, then it's expected compiled in directory "mbedtls" +in source directory. + +When some SSL library is used, required SSL attributes has to be configured +correctly in "config" file and relevant certificates, keys and directories have +to be prepared in specified paths. + +Command make will create file privoxy.exe which can by run using wine or +OS Windows. + +Alternativly Cygwin can be used to build Privoxy for Windows OS. \ No newline at end of file diff --git a/configure.in b/configure.in index 5cb94456..587981ba 100644 --- a/configure.in +++ b/configure.in @@ -1025,7 +1025,7 @@ AC_SUBST(FEATURE_CLIENT_TAGS_ONLY) FUZZ_ONLY="#" AC_ARG_ENABLE(fuzz, -[ --enable-fuzz Enable code that makes fuzzing more convenient], +[ --enable-fuzz Enable code that makes fuzzing more convenient], [if test $enableval = yes; then FUZZ_ONLY="" AC_DEFINE(FUZZ,1,[Define to make fuzzing more convenient.]) @@ -1087,12 +1087,15 @@ dnl SSL libraries dnl ================================================================= AC_ARG_ENABLE(libressl, -[ --disable-libressl Set Privoxy not to use libressl for SSL comunication and filtering. Libressl is defaultly enabled.], +[ --disable-libressl Set Privoxy not to use LibreSSL for SSL communication. When no SSL library is enabled, + Privoxy will use SSL tunnel for SSL connections and encrypted data will not be filtered. + LibreSSL is defaultly enabled.], [disablelibressl=yes], [disablelibressl=no]) AC_ARG_ENABLE(mbedtls, -[ --enable-mbedtls Allow Privoxy to use mbedtls for SSL comunication and filtering.], +[ --enable-mbedtls Set Privoxy to use MbedTLS for SSL comunication. When this option is enabled, LibreSSL + is automatically disabled.], [enablembedtls=$enableval], [enablembedtls=no]) -- 2.26.2