[squid-dev] [PATCH] crypto-ng: CA support for GnuTLS

Amos Jeffries squid3 at treenet.co.nz
Sat Oct 3 08:44:07 UTC 2015


Shuffle the cafile= context logics to libsecurity class PeerOptions.

* Rename the parameter tls-cafile= and allow multiple cafile= entries to
be used in squid.conf.

* Document the capath= option as only supported by OpenSSL and LibreSSL.

* Add GnuTLS support for CA loading.
 Although at this point GnuTLS contexts are not yet created.

Amos

-------------- next part --------------
=== modified file 'doc/release-notes/release-4.sgml'
--- doc/release-notes/release-4.sgml	2015-08-26 13:53:33 +0000
+++ doc/release-notes/release-4.sgml	2015-10-03 05:29:50 +0000
@@ -157,70 +157,73 @@
 	<tag>url_rewrite_timeout</tag>
 	<p>Squid times active requests to redirector. This option sets
 	   the timeout value and the Squid reaction to a timed out
 	   request.
 
 </descrip>
 
 <sect1>Changes to existing tags<label id="modifiedtags">
 <p>
 <descrip>
 	<tag>auth_param</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number
 	   of queued requests.
 
 	<tag>cache_peer</tag>
 	<p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
 	<p>All <em>ssloptions=</em> values for SSLv2 configuration or disabling
 	   have been removed.
 	<p>Removed <em>sslversion=</em> option. Use <em>tls-options=</em> instead.
 	<p>Manual squid.conf update may be required on upgrade.
+	<p>Replaced <em>sslcafile=</em> with <em>tls-cafile=</em> which takes multiple entries.
 
 	<tag>external_acl_type</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number
 	   of queued requests.
 
 	<tag>http_port</tag>
 	<p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
 	<p>All <em>option=</em> values for SSLv2 configuration or disabling
 	   have been removed.
 	<p>Removed <em>version=</em> option. Use <em>tls-options=</em> instead.
 	<p>New <em>options=SINGLE_ECDH_USE</em> parameter to enable ephemeral
 	   ECDH key exchange.
 	<p>Deprecated <em>dhparams=</em> option. Use <em>tls-dh=</em> instead.
 	   The new option allows to optionally specify an elliptic curve for
 	   ephemeral ECDH by adding <em>curve-name:</em> in front of the
 	   parameter file name.
 	<p>Manual squid.conf update may be required on upgrade.
+	<p>Replaced <em>cafile=</em> with <em>tls-cafile=</em> which takes multiple entries.
 
 	<tag>https_port</tag>
 	<p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
 	<p>All <em>options=</em> values for SSLv2
 	   configuration or disabling have been removed.
 	<p>Removed <em>version=</em> option. Use <em>tls-options=</em> instead.
 	<p>New <em>options=SINGLE_ECDH_USE</em> parameter to enable ephemeral
 	   ECDH key exchange.
 	<p>Deprecated <em>dhparams=</em> option. Use <em>tls-dh=</em> instead.
 	   The new option allows to optionally specify an elliptic curve for
 	   ephemeral ECDH by adding <em>curve-name:</em> in front of the
 	   parameter file name.
 	<p>Manual squid.conf update may be required on upgrade.
+	<p>Replaced <em>cafile=</em> with <em>tls-cafile=</em> which takes multiple entries.
 
 	<tag>icap_service</tag>
 	<p>New scheme <em>icaps://</em> to enable TLS/SSL connections to Secure ICAP
 	   servers on port 11344.
 	<p>New <em>tls-cert=</em> option to set TLS client certificate to use.
 	<p>New <em>tls-key=</em> option to set TLS private key matching the client
 	   certificate used.
 	<p>New <em>tls-min-version=1.N</em> option to set minimum TLS version allowed
 	   on server connections.
 	<p>New <em>tls-options=</em> option to set OpenSSL library parameters.
 	<p>New <em>tls-flags=</em> option to set flags modifying Squid TLS operations.
 	<p>New <em>tls-cipher=</em> option to set a list of ciphers permitted.
 	<p>New <em>tls-cafile=</em> option to set a file with additional CA
 	   certificate(s) to verify the server certificate.
 	<p>New <em>tls-crlfile=</em> option to set a file with a CRL to verify the
 	   server certificate.
 	<p>New <em>tls-domain=</em> option to verify the server certificate domain.
 
 	<tag>refresh_pattern</tag>
 	<p>Removed <em>ignore-auth</em>. Its commonly desired behaviour is
@@ -239,40 +242,41 @@
 	<tag>url_rewrite_children</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number
 	   of queued requests.
 
 </descrip>
 
 <sect1>Removed tags<label id="removedtags">
 <p>
 <descrip>
 	<tag>cache_peer_domain</tag>
 	<p>Superceded by <em>cache_peer_access</em>. Use dstdomain ACL
 	   in the access control list to restrict domains requested.
 
 	<tag>refresh_pattern</tag>
 	<p>Option <em>ignore-auth</em> removed. Its original intent was
 	   to improve caching. HTTP/1.1 permits caching of authenticated
 	   messages under conditions which Squid does check for and obey.
 
 	<tag>sslproxy_cafile</tag>
 	<p>Replaced by <em>tls_outgoing_options cafile=</em>.
+	   Which now takes multiple entries.
 
 	<tag>sslproxy_capath</tag>
 	<p>Replaced by <em>tls_outgoing_options capath=</em>.
 
 	<tag>sslproxy_cipher</tag>
 	<p>Replaced by <em>tls_outgoing_options cipher=</em>.
 
 	<tag>sslproxy_client_certificate</tag>
 	<p>Replaced by <em>tls_outgoing_options cert=</em>.
 
 	<tag>sslproxy_client_key</tag>
 	<p>Replaced by <em>tls_outgoing_options key=</em>.
 
 	<tag>sslproxy_flags</tag>
 	<p>Replaced by <em>tls_outgoing_options flags=</em>.
 
 	<tag>sslproxy_options</tag>
 	<p>Replaced by <em>tls_outgoing_options options=</em>.
 	<p>All values for SSLv2 configuration or disabling have been removed.
 	<p>Manual squid.conf update may be required on upgrade.

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2015-09-05 18:52:17 +0000
+++ src/cache_cf.cc	2015-09-30 13:01:19 +0000
@@ -3561,40 +3561,42 @@
                "in " << cfg_directive << ". Use 'ssl-bump' instead.");
         s->flags.tunnelSslBumping = true;
     } else if (strcmp(token, "ssl-bump") == 0) {
         s->flags.tunnelSslBumping = true;
     } else if (strncmp(token, "cert=", 5) == 0) {
         s->secure.parse(token);
     } else if (strncmp(token, "key=", 4) == 0) {
         s->secure.parse(token);
     } else if (strncmp(token, "version=", 8) == 0) {
         debugs(3, DBG_PARSE_NOTE(1), "UPGRADE WARNING: '" << token << "' is deprecated " <<
                "in " << cfg_directive << ". Use 'options=' instead.");
         s->secure.parse(token);
     } else if (strncmp(token, "options=", 8) == 0) {
         s->secure.parse(token);
     } else if (strncmp(token, "cipher=", 7) == 0) {
         s->secure.parse(token);
     } else if (strncmp(token, "clientca=", 9) == 0) {
         safe_free(s->clientca);
         s->clientca = xstrdup(token + 9);
     } else if (strncmp(token, "cafile=", 7) == 0) {
+        debugs(3, DBG_PARSE_NOTE(1), "UPGRADE WARNING: '" << token << "' is deprecated " <<
+               "in " << cfg_directive << ". Use 'tls-cafile=' instead.");
         s->secure.parse(token);
     } else if (strncmp(token, "capath=", 7) == 0) {
         s->secure.parse(token);
     } else if (strncmp(token, "crlfile=", 8) == 0) {
         s->secure.parse(token);
     } else if (strncmp(token, "dhparams=", 9) == 0) {
         debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: '" << token << "' is deprecated " <<
                "in " << cfg_directive << ". Use 'tls-dh=' instead.");
         safe_free(s->dhfile);
         s->dhfile = xstrdup(token + 9);
     } else if (strncmp(token, "tls-dh=", 7) == 0) {
         safe_free(s->tls_dh);
         s->tls_dh = xstrdup(token + 7);
     } else if (strncmp(token, "sslflags=", 9) == 0) {
         s->secure.parse(token+3);
     } else if (strncmp(token, "sslcontext=", 11) == 0) {
         safe_free(s->sslContextSessionId);
         s->sslContextSessionId = xstrdup(token + 11);
     } else if (strcmp(token, "generate-host-certificates") == 0) {
         s->generateHostCertificates = true;
@@ -3642,40 +3644,47 @@
         self_destruct();
         return;
     }
 
     char *token = ConfigParser::NextToken();
 
     if (!token) {
         self_destruct();
         return;
     }
 
     AnyP::PortCfgPointer s = new AnyP::PortCfg();
     s->transport = parsePortProtocol(protoName); // default; protocol=... overwrites
     parsePortSpecification(s, token);
 
     /* parse options ... */
     while ((token = ConfigParser::NextToken())) {
         parse_port_option(s, token);
     }
 
+#if USE_OPENSSL
+    // if clientca has been defined but not cafile, then use it to verify
+    // but if cafile has been defined, only use that to verify
+    if (s->clientca && !s->secure.caFiles.size())
+        s->secure.caFiles.emplace_back(SBuf(s->clientca));
+#endif
+
     if (s->transport.protocol == AnyP::PROTO_HTTPS) {
         s->secure.encryptTransport = true;
 #if USE_OPENSSL
         /* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */
         const bool hijacked = s->flags.isIntercepted();
         if (s->flags.tunnelSslBumping && !hijacked) {
             debugs(3, DBG_CRITICAL, "FATAL: ssl-bump on https_port requires tproxy/intercept which is missing.");
             self_destruct();
         }
         if (hijacked && !s->flags.tunnelSslBumping) {
             debugs(3, DBG_CRITICAL, "FATAL: tproxy/intercept on https_port requires ssl-bump which is missing.");
             self_destruct();
         }
 #endif
         if (s->flags.proxySurrogate) {
             debugs(3,DBG_CRITICAL, "FATAL: https_port: require-proxy-header option is not supported on HTTPS ports.");
             self_destruct();
         }
     } else if (protoName.cmp("FTP") == 0) {
         /* ftp_port does not support ssl-bump */

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2015-08-30 01:07:47 +0000
+++ src/cf.data.pre	2015-09-30 13:39:34 +0000
@@ -1948,46 +1948,47 @@
 				      The adopted curve should be specified
 				      using the tls-dh option.
 
 			    NO_TICKET
 				      Disable use of RFC5077 session tickets.
 				      Some servers may have problems
 				      understanding the TLS extension due
 				      to ambiguous specification in RFC4507.
 
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
 				      strength to some attacks.
 
 			See the OpenSSL SSL_CTX_set_options documentation for a
 			more complete list.
 
 	   clientca=	File containing the list of CAs to use when
 			requesting a client certificate.
 
-	   cafile=	File containing additional CA certificates to
-			use when verifying client certificates. If unset
-			clientca will be used.
+	   tls-cafile=	PEM file containing CA certificates to use when verifying
+			client certificates. If not configured clientca will be
+			used. May be repeated to load multiple files.
 
 	   capath=	Directory containing additional CA certificates
 			and CRL lists to use when verifying client certificates.
+			Requires OpenSSL or LibreSSL.
 
 	   crlfile=	File of additional CRL lists to use when verifying
 			the client certificate, in addition to CRLs stored in
 			the capath. Implies VERIFY_CRL flag below.
 
 	   tls-dh=[curve:]file
 			File containing DH parameters for temporary/ephemeral DH key
 			exchanges, optionally prefixed by a curve for ephemeral ECDH
 			key exchanges.
 			See OpenSSL documentation for details on how to create the
 			DH parameter file. Supported curves for ECDH can be listed
 			using the "openssl ecparam -list_curves" command.
 			WARNING: EDH and EECDH ciphers will be silently disabled if
 				 this option is not set.
 
 	   sslflags=	Various flags modifying the use of SSL:
 			    DELAYED_AUTH
 				Don't request client certificates
 				immediately, but wait until acl processing
 				requires a certificate (not yet implemented).
@@ -2132,46 +2133,47 @@
 				      The adopted curve should be specified
 				      using the tls-dh option.
 
 			    SSL_OP_NO_TICKET
 				      Disable use of RFC5077 session tickets.
 				      Some servers may have problems
 				      understanding the TLS extension due
 				      to ambiguous specification in RFC4507.
 
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
 				      strength to some attacks.
 
 			See the OpenSSL SSL_CTX_set_options documentation for a
 			more complete list.
 
 	   clientca=	File containing the list of CAs to use when
 			requesting a client certificate.
 
-	   cafile=	File containing additional CA certificates to
-			use when verifying client certificates. If unset
-			clientca will be used.
+	   tls-cafile=	PEM file containing CA certificates to use when verifying
+			client certificates. If not configured clientca will be
+			used. May be repeated to load multiple files.
 
 	   capath=	Directory containing additional CA certificates
 			and CRL lists to use when verifying client certificates.
+			Requires OpenSSL or LibreSSL.
 
 	   crlfile=	File of additional CRL lists to use when verifying
 			the client certificate, in addition to CRLs stored in
 			the capath. Implies VERIFY_CRL flag below.
 
 	   tls-dh=[curve:]file
 			File containing DH parameters for temporary/ephemeral DH key
 			exchanges, optionally prefixed by a curve for ephemeral ECDH
 			key exchanges.
 
 	   sslflags=	Various flags modifying the use of SSL:
 			    DELAYED_AUTH
 				Don't request client certificates
 				immediately, but wait until acl processing
 				requires a certificate (not yet implemented).
 			    NO_DEFAULT_CA
 				Don't use the default CA lists built in
 				to OpenSSL.
 			    NO_SESSION_REUSE
 				Don't allow for session reuse. Each connection
@@ -2630,45 +2632,46 @@
 			    NO_TLSv1_2  Disallow the use of TLSv1.2
 
 			    SINGLE_DH_USE
 				      Always create a new key when using
 				      temporary/ephemeral DH key exchanges
 
 			    SSL_OP_NO_TICKET
 				      Disable use of RFC5077 session tickets.
 				      Some servers may have problems
 				      understanding the TLS extension due
 				      to ambiguous specification in RFC4507.
 
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
 				      strength to some attacks.
 
 			See the OpenSSL SSL_CTX_set_options documentation for a
 			more complete list.
 	
-	cafile=... 	A file containing additional CA certificates to use
-			when verifying the peer certificate.
-	
-	capath=...	A directory containing additional CA certificates to
+	cafile=		PEM file containing CA certificates to use when verifying
+			the peer certificate. May be repeated to load multiple files.
+
+	capath=		A directory containing additional CA certificates to
 			use when verifying the peer certificate.
+			Requires OpenSSL or LibreSSL.
 	
 	crlfile=... 	A certificate revocation list file to use when
 			verifying the peer certificate.
 	
 	flags=...	Specify various flags modifying the TLS implementation:
 	
 			DONT_VERIFY_PEER
 				Accept certificates even if they fail to
 				verify.
 			NO_DEFAULT_CA
 				Don't use the default CA list built in
 				to OpenSSL.
 			DONT_VERIFY_DOMAIN
 				Don't verify the peer certificate
 				matches the server name
 	
 	domain= 	The peer name as advertised in its certificate.
 			Used for verifying the correctness of the received peer
 			certificate. If not specified the peer hostname will be
 			used.
@@ -3367,45 +3370,46 @@
 			    NO_TLSv1_2  Disallow the use of TLSv1.2
 
 			    SINGLE_DH_USE
 				      Always create a new key when using
 				      temporary/ephemeral DH key exchanges
 
 			    SSL_OP_NO_TICKET
 				      Disable use of RFC5077 session tickets.
 				      Some servers may have problems
 				      understanding the TLS extension due
 				      to ambiguous specification in RFC4507.
 
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
 				      strength to some attacks.
 
 			See the OpenSSL SSL_CTX_set_options documentation for a
 			more complete list.
 	
-	sslcafile=... 	A file containing additional CA certificates to use
-			when verifying the peer certificate.
+	tls-cafile=	PEM file containing CA certificates to use when verifying
+			the peer certificate. May be repeated to load multiple files.
 	
 	sslcapath=...	A directory containing additional CA certificates to
 			use when verifying the peer certificate.
+			Requires OpenSSL or LibreSSL.
 	
 	sslcrlfile=... 	A certificate revocation list file to use when
 			verifying the peer certificate.
 	
 	sslflags=...	Specify various flags modifying the SSL implementation:
 	
 			DONT_VERIFY_PEER
 				Accept certificates even if they fail to
 				verify.
 
 			NO_DEFAULT_CA
 				Don't use the default CA list built in
 				to OpenSSL.
 
 			DONT_VERIFY_DOMAIN
 				Don't verify the peer certificate
 				matches the server name
 	
 	ssldomain= 	The peer name as advertised in it's certificate.
 			Used for verifying the correctness of the received peer
@@ -8524,48 +8528,50 @@
 
 			    NO_SSLv3    Disallow the use of SSLv3
 
 			    NO_TLSv1    Disallow the use of TLSv1.0
 			    NO_TLSv1_1  Disallow the use of TLSv1.1
 			    NO_TLSv1_2  Disallow the use of TLSv1.2
 
 			    SINGLE_DH_USE
 				      Always create a new key when using
 				      temporary/ephemeral DH key exchanges
 
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
 				      strength to some attacks.
 
 			See the OpenSSL SSL_CTX_set_options documentation for a
 			more complete list. Options relevant only to SSLv2 are
 			not supported.
 
-	tls-cafile=...	A PEM file containing additional CA certificates to use
-			when verifying the icap server certificate. Used
-			to specify intermediate CA certificate(s) if not sent
-			by the server. Or the full CA chain for the server
-			when using the NO_DEFAULT_CA flag.
+	tls-cafile=	PEM file containing CA certificates to use when verifying
+			the icap server certificate.
+			Use to specify intermediate CA certificate(s) if not sent
+			by the server. Or the full CA chain for the server when
+			using the NO_DEFAULT_CA flag.
+			May be repeated to load multiple files.
 
 	tls-capath=...	A directory containing additional CA certificates to
 			use when verifying the icap server certificate.
+			Requires OpenSSL or LibreSSL.
 
 	tls-crlfile=...	A certificate revocation list file to use when
 			verifying the icap server certificate.
 
 	tls-flags=...	Specify various flags modifying the Squid TLS implementation:
 
 			DONT_VERIFY_PEER
 				Accept certificates even if they fail to
 				verify.
 			NO_DEFAULT_CA
 				Don't use the default CA list built into
 				OpenSSL.
 			DONT_VERIFY_DOMAIN
 				Don't verify the icap server certificate
 				matches the server name
 
 	tls-domain=	The icap server name as advertised in it's certificate.
 			Used for verifying the correctness of the received icap
 			server certificate. If not specified the icap server
 			hostname extracted from ICAP URI will be used.

=== modified file 'src/security/Context.h'
--- src/security/Context.h	2015-03-21 11:58:32 +0000
+++ src/security/Context.h	2015-10-02 18:51:31 +0000
@@ -10,31 +10,31 @@
 #define SQUID_SRC_SECURITY_CONTEXT_H
 
 #if USE_OPENSSL
 #if HAVE_OPENSSL_SSL_H
 #include <openssl/ssl.h>
 #endif
 #endif
 
 #if USE_GNUTLS
 #if HAVE_GNUTLS_GNUTLS_H
 #include <gnutls/gnutls.h>
 #endif
 #endif
 
 namespace Security {
 
 #if USE_OPENSSL
 typedef SSL_CTX* ContextPointer;
 
 #elif USE_GNUTLS
-typedef gnutls_certificate_credentials_t* ContextPointer;
+typedef gnutls_certificate_credentials_t ContextPointer;
 
 #else
 // use void* so we can check against NULL
 typedef void* ContextPointer;
 #endif
 
 } // namespace Security
 
 #endif /* SQUID_SRC_SECURITY_CONTEXT_H */
 

=== modified file 'src/security/PeerOptions.cc'
--- src/security/PeerOptions.cc	2015-09-24 21:08:23 +0000
+++ src/security/PeerOptions.cc	2015-10-03 04:56:55 +0000
@@ -9,48 +9,48 @@
 #include "squid.h"
 #include "base/Packable.h"
 #include "Debug.h"
 #include "fatal.h"
 #include "globals.h"
 #include "parser/Tokenizer.h"
 #include "parser/Tokenizer.h"
 #include "Parsing.h"
 #include "security/PeerOptions.h"
 
 #if USE_OPENSSL
 #include "ssl/support.h"
 #endif
 
 Security::PeerOptions Security::ProxyOutgoingConfig;
 
 Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) :
     certFile(p.certFile),
     privateKeyFile(p.privateKeyFile),
     sslOptions(p.sslOptions),
-    caFile(p.caFile),
     caDir(p.caDir),
     crlFile(p.crlFile),
     sslCipher(p.sslCipher),
     sslFlags(p.sslFlags),
     sslDomain(p.sslDomain),
     parsedOptions(p.parsedOptions),
     parsedFlags(p.parsedFlags),
+    caFiles(p.caFiles),
     parsedCrl(p.parsedCrl),
     sslVersion(p.sslVersion),
     encryptTransport(p.encryptTransport)
 {
 }
 
 void
 Security::PeerOptions::parse(const char *token)
 {
     if (!*token) {
         // config says just "ssl" or "tls" (or "tls-")
         encryptTransport = true;
         return;
     }
 
     if (strncmp(token, "disable", 7) == 0) {
         clear();
         return;
     }
 
@@ -58,84 +58,88 @@
         certFile = SBuf(token + 5);
         if (privateKeyFile.isEmpty())
             privateKeyFile = certFile;
     } else if (strncmp(token, "key=", 4) == 0) {
         privateKeyFile = SBuf(token + 4);
         if (certFile.isEmpty()) {
             debugs(3, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
             certFile = privateKeyFile;
         }
     } else if (strncmp(token, "version=", 8) == 0) {
         debugs(0, DBG_PARSE_NOTE(1), "UPGRADE WARNING: SSL version= is deprecated. Use options= to limit protocols instead.");
         sslVersion = xatoi(token + 8);
     } else if (strncmp(token, "min-version=", 12) == 0) {
         tlsMinVersion = SBuf(token + 12);
     } else if (strncmp(token, "options=", 8) == 0) {
         sslOptions = SBuf(token + 8);
         parsedOptions = parseOptions();
     } else if (strncmp(token, "cipher=", 7) == 0) {
         sslCipher = SBuf(token + 7);
     } else if (strncmp(token, "cafile=", 7) == 0) {
-        caFile = SBuf(token + 7);
+        caFiles.emplace_back(SBuf(token + 7));
     } else if (strncmp(token, "capath=", 7) == 0) {
         caDir = SBuf(token + 7);
+#if !USE_OPENSSL
+        debugs(3, DBG_PARSE_NOTE(1), "WARNING: capath= option requires --with-openssl.");
+#endif
     } else if (strncmp(token, "crlfile=", 8) == 0) {
         crlFile = SBuf(token + 8);
         loadCrlFile();
     } else if (strncmp(token, "flags=", 6) == 0) {
         if (parsedFlags != 0) {
             debugs(3, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
         }
         sslFlags = SBuf(token + 6);
         parsedFlags = parseFlags();
     } else if (strncmp(token, "domain=", 7) == 0) {
         sslDomain = SBuf(token + 7);
     } else {
         debugs(3, DBG_CRITICAL, "ERROR: Unknown TLS option '" << token << "'");
         return;
     }
 
     encryptTransport = true;
 }
 
 void
 Security::PeerOptions::dumpCfg(Packable *p, const char *pfx) const
 {
     if (!encryptTransport) {
         p->appendf(" %sdisable", pfx);
         return; // no other settings are relevant
     }
 
     if (!certFile.isEmpty())
         p->appendf(" %scert=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(certFile));
 
     if (!privateKeyFile.isEmpty() && privateKeyFile != certFile)
         p->appendf(" %skey=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(privateKeyFile));
 
     if (!sslOptions.isEmpty())
         p->appendf(" %soptions=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslOptions));
 
     if (!sslCipher.isEmpty())
         p->appendf(" %scipher=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslCipher));
 
-    if (!caFile.isEmpty())
-        p->appendf(" %scafile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caFile));
+    for (auto i : caFiles) {
+        p->appendf(" %scafile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(i));
+    }
 
     if (!caDir.isEmpty())
         p->appendf(" %scapath=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caDir));
 
     if (!crlFile.isEmpty())
         p->appendf(" %scrlfile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(crlFile));
 
     if (!sslFlags.isEmpty())
         p->appendf(" %sflags=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslFlags));
 }
 
 void
 Security::PeerOptions::updateTlsVersionLimits()
 {
     if (!tlsMinVersion.isEmpty()) {
         ::Parser::Tokenizer tok(tlsMinVersion);
         int64_t v = 0;
         if (tok.skip('1') && tok.skip('.') && tok.int64(v, 10, false, 1) && v <= 3) {
             // only account for TLS here - SSL versions are handled by options= parameter
             // avoid affecting options= parameter in cachemgr config report
@@ -174,51 +178,54 @@
             break;
         case 6:
             add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_1";
             break;
         default: // nothing
             break;
         }
         if (add) {
             if (!sslOptions.isEmpty())
                 sslOptions.append(",",1);
             sslOptions.append(add, strlen(add));
         }
         sslVersion = 0; // prevent sslOptions being repeatedly appended
     }
 }
 
 // XXX: make a GnuTLS variant
 Security::ContextPointer
 Security::PeerOptions::createClientContext(bool setOptions)
 {
-    Security::ContextPointer t = NULL;
+    Security::ContextPointer t = nullptr;
 
     updateTlsVersionLimits();
+
 #if USE_OPENSSL
     // XXX: temporary performance regression. c_str() data copies and prevents this being a const method
     t = sslCreateClientContext(certFile.c_str(), privateKeyFile.c_str(), sslCipher.c_str(),
-                               (setOptions ? parsedOptions : 0), parsedFlags,
-                               caFile.c_str(), caDir.c_str());
+                               (setOptions ? parsedOptions : 0), parsedFlags);
 #endif
 
-    updateContextCrl(t);
+    if (t) {
+        updateContextCa(t);
+        updateContextCrl(t);
+    }
 
     return t;
 }
 
 /// set of options we can parse and what they map to
 static struct ssl_option {
     const char *name;
     long value;
 
 } ssl_options[] = {
 
 #if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
     {
         "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
     },
 #endif
 #if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
     {
         "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
     },
@@ -459,40 +466,74 @@
 {
     parsedCrl.clear();
     if (crlFile.isEmpty())
         return;
 
 #if USE_OPENSSL
     BIO *in = BIO_new_file(crlFile.c_str(), "r");
     if (!in) {
         debugs(83, 2, "WARNING: Failed to open CRL file " << crlFile);
         return;
     }
 
     while (X509_CRL *crl = PEM_read_bio_X509_CRL(in,NULL,NULL,NULL)) {
         parsedCrl.emplace_back(Security::CrlPointer(crl));
     }
     BIO_free(in);
 #endif
 }
 
 void
+Security::PeerOptions::updateContextCa(Security::ContextPointer &ctx)
+{
+    debugs(83, 8, "Setting CA certificate locations.");
+
+    for (auto i : caFiles) {
+#if USE_OPENSSL
+        if (!SSL_CTX_load_verify_locations(ctx, i.c_str(), caDir.c_str())) {
+            const int ssl_error = ERR_get_error();
+            debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
+        }
+#elif USE_GNUTLS
+        if (gnutls_certificate_set_x509_trust_file(ctx, i.c_str(), GNUTLS_X509_FMT_PEM) < 0) {
+            debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate location: " << i);
+        }
+#endif
+    }
+
+    if ((parsedFlags & SSL_FLAG_NO_DEFAULT_CA))
+        return;
+
+#if USE_OPENSSL
+    if (!SSL_CTX_set_default_verify_paths(ctx)) {
+        const int ssl_error = ERR_get_error();
+        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA : "
+               << ERR_error_string(ssl_error, NULL));
+    }
+#elif USE_GNUTLS
+    if (gnutls_certificate_set_x509_system_trust(ctx) != GNUTLS_E_SUCCESS) {
+        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA.");
+    }
+#endif
+}
+
+void
 Security::PeerOptions::updateContextCrl(Security::ContextPointer &ctx)
 {
 #if USE_OPENSSL
     bool verifyCrl = false;
     X509_STORE *st = SSL_CTX_get_cert_store(ctx);
     if (parsedCrl.size()) {
         for (auto &i : parsedCrl) {
             if (!X509_STORE_add_crl(st, i.get()))
                 debugs(83, 2, "WARNING: Failed to add CRL");
             else
                 verifyCrl = true;
         }
     }
 
 #if X509_V_FLAG_CRL_CHECK
     if ((parsedFlags & SSL_FLAG_VERIFY_CRL_ALL))
         X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
     else if (verifyCrl || (parsedFlags & SSL_FLAG_VERIFY_CRL))
         X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK);
 #endif

=== modified file 'src/security/PeerOptions.h'
--- src/security/PeerOptions.h	2015-09-24 21:08:23 +0000
+++ src/security/PeerOptions.h	2015-09-30 13:53:12 +0000
@@ -20,68 +20,71 @@
 
 /// TLS squid.conf settings for a remote server peer
 class PeerOptions
 {
 public:
     PeerOptions() : parsedOptions(0), parsedFlags(0), sslVersion(0), encryptTransport(false) {}
     PeerOptions(const PeerOptions &);
 
     /// parse a TLS squid.conf option
     void parse(const char *);
 
     /// reset the configuration details to default
     void clear() {*this = PeerOptions();}
 
     /// generate a security client-context from these configured options
     Security::ContextPointer createClientContext(bool setOptions);
 
     /// sync the context options with tls-min-version=N configuration
     void updateTlsVersionLimits();
 
+    /// setup the CA details for the given context
+    void updateContextCa(Security::ContextPointer &);
+
     /// setup the CRL details for the given context
     void updateContextCrl(Security::ContextPointer &);
 
     /// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
     void dumpCfg(Packable *, const char *pfx) const;
 
 private:
     long parseOptions();
     long parseFlags();
     void loadCrlFile();
 
 public:
     SBuf certFile;       ///< path of file containing PEM format X509 certificate
     SBuf privateKeyFile; ///< path of file containing private key in PEM format
     SBuf sslOptions;     ///< library-specific options string
-    SBuf caFile;         ///< path of file containing trusted Certificate Authority
     SBuf caDir;          ///< path of directory containing a set of trusted Certificate Authorities
     SBuf crlFile;        ///< path of file containing Certificate Revoke List
 
     SBuf sslCipher;
     SBuf sslFlags;       ///< flags defining what TLS operations Squid performs
     SBuf sslDomain;
 
     SBuf tlsMinVersion;  ///< version label for minimum TLS version to permit
 
     long parsedOptions; ///< parsed value of sslOptions
     long parsedFlags;   ///< parsed value of sslFlags
 
+    std::list<SBuf> caFiles;  ///< paths of files containing trusted Certificate Authority
     Security::CertRevokeList parsedCrl; ///< CRL to use when verifying the remote end certificate
 
 private:
     int sslVersion;
 
 public:
     /// whether transport encryption (TLS/SSL) is to be used on connections to the peer
     bool encryptTransport;
 };
 
 /// configuration options for DIRECT server access
 extern PeerOptions ProxyOutgoingConfig;
 
 } // namespace Security
 
 // parse the tls_outgoing_options directive
 void parse_securePeerOptions(Security::PeerOptions *);
 #define free_securePeerOptions(x) Security::ProxyOutgoingConfig.clear()
 #define dump_securePeerOptions(e,n,x) do { (e)->appendf(n); (x).dumpCfg((e),""); (e)->append("\n",1); } while(false)
 

=== modified file 'src/ssl/support.cc'
--- src/ssl/support.cc	2015-09-24 21:08:23 +0000
+++ src/ssl/support.cc	2015-09-30 12:26:01 +0000
@@ -559,53 +559,41 @@
         if (!SSL_CTX_set_cipher_list(sslContext, port.secure.sslCipher.c_str())) {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << ERR_error_string(ssl_error, NULL));
             return false;
         }
     }
 
     debugs(83, 9, "Setting RSA key generation callback.");
     SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
 
     if (port.eecdhCurve) {
         debugs(83, 9, "Setting Ephemeral ECDH curve to " << port.eecdhCurve << ".");
 
         if (!configureSslEECDH(sslContext, port.eecdhCurve)) {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Unable to configure Ephemeral ECDH: " << ERR_error_string(ssl_error, NULL));
             return false;
         }
     }
 
-    debugs(83, 9, "Setting CA certificate locations.");
-
-    const char *cafile = port.secure.caFile.isEmpty() ? port.clientca : port.secure.caFile.c_str();
-    if ((cafile || !port.secure.caDir.isEmpty()) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.secure.caDir.c_str())) {
-        ssl_error = ERR_get_error();
-        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
-    }
-
-    if (!(port.secure.parsedFlags & SSL_FLAG_NO_DEFAULT_CA) &&
-            !SSL_CTX_set_default_verify_paths(sslContext)) {
-        ssl_error = ERR_get_error();
-        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
-    }
+    port.secure.updateContextCa(sslContext);
 
     if (port.clientCA.get()) {
         ERR_clear_error();
         if (STACK_OF(X509_NAME) *clientca = SSL_dup_CA_list(port.clientCA.get())) {
             SSL_CTX_set_client_CA_list(sslContext, clientca);
         } else {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Failed to dupe the client CA list: " << ERR_error_string(ssl_error, NULL));
             return false;
         }
 
         if (port.secure.parsedFlags & SSL_FLAG_DELAYED_AUTH) {
             debugs(83, 9, "Not requesting client certificates until acl processing requires one");
             SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
         } else {
             debugs(83, 9, "Requiring client certificates.");
             SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
         }
 
         port.secure.updateContextCrl(sslContext);
@@ -695,41 +683,41 @@
         debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
         SSL_CTX_free(sslContext);
         return NULL;
     }
 
     return sslContext;
 }
 
 #if defined(TLSEXT_TYPE_next_proto_neg)
 //Dummy next_proto_neg callback
 static int
 ssl_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
 {
     static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
     (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos, sizeof(supported_protos));
     return SSL_TLSEXT_ERR_OK;
 }
 #endif
 
 SSL_CTX *
-sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long fl, const char *CAfile, const char *CApath)
+sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long fl)
 {
     ssl_initialize();
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
     SSL_CTX *sslContext = SSL_CTX_new(TLS_client_method());
 #else
     SSL_CTX *sslContext = SSL_CTX_new(SSLv23_client_method());
 #endif
 
     if (sslContext == NULL) {
         const int ssl_error = ERR_get_error();
         fatalf("Failed to allocate SSL context: %s\n",
                ERR_error_string(ssl_error, NULL));
     }
 
     SSL_CTX_set_options(sslContext, options);
 
 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
     SSL_CTX_set_info_callback(sslContext, ssl_info_cb);
 #endif
@@ -765,53 +753,40 @@
         debugs(83, 5, "Comparing private and public SSL keys.");
 
         if (!SSL_CTX_check_private_key(sslContext)) {
             const int ssl_error = ERR_get_error();
             fatalf("SSL private key '%s' does not match public key '%s': %s\n",
                    certfile, keyfile, ERR_error_string(ssl_error, NULL));
         }
     }
 
     debugs(83, 9, "Setting RSA key generation callback.");
     SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
 
     if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
         debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!");
         SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
     } else {
         debugs(83, 9, "Setting certificate verification callback.");
         SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
     }
 
-    debugs(83, 9, "Setting CA certificate locations.");
-
-    if ((*CAfile || *CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) {
-        const int ssl_error = ERR_get_error();
-        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
-    }
-
-    if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
-            !SSL_CTX_set_default_verify_paths(sslContext)) {
-        const int ssl_error = ERR_get_error();
-        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
-    }
-
 #if defined(TLSEXT_TYPE_next_proto_neg)
     SSL_CTX_set_next_proto_select_cb(sslContext, &ssl_next_proto_cb, NULL);
 #endif
     return sslContext;
 }
 
 /// \ingroup ServerProtocolSSLInternal
 int
 ssl_read_method(int fd, char *buf, int len)
 {
     SSL *ssl = fd_table[fd].ssl;
     int i;
 
 #if DONT_DO_THIS
 
     if (!SSL_is_init_finished(ssl)) {
         errno = ENOTCONN;
         return -1;
     }
 

=== modified file 'src/ssl/support.h'
--- src/ssl/support.h	2015-09-24 21:08:23 +0000
+++ src/ssl/support.h	2015-09-30 12:20:20 +0000
@@ -73,41 +73,41 @@
 {
 public:
     ssl_error_t code; ///< certificate error code
     Security::CertPointer cert; ///< certificate with the above error code
     CertError(ssl_error_t anErr, X509 *aCert);
     CertError(CertError const &err);
     CertError & operator = (const CertError &old);
     bool operator == (const CertError &ce) const;
     bool operator != (const CertError &ce) const;
 };
 
 /// Holds a list of certificate SSL errors
 typedef CbDataList<Ssl::CertError> CertErrors;
 
 } //namespace Ssl
 
 /// \ingroup ServerProtocolSSLAPI
 SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port);
 
 /// \ingroup ServerProtocolSSLAPI
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags, const char *CAfile, const char *CApath);
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags);
 
 /// \ingroup ServerProtocolSSLAPI
 int ssl_read_method(int, char *, int);
 
 /// \ingroup ServerProtocolSSLAPI
 int ssl_write_method(int, const char *, int);
 
 /// \ingroup ServerProtocolSSLAPI
 void ssl_shutdown_method(SSL *ssl);
 
 /// \ingroup ServerProtocolSSLAPI
 const char *sslGetUserEmail(SSL *ssl);
 
 /// \ingroup ServerProtocolSSLAPI
 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name);
 
 /// \ingroup ServerProtocolSSLAPI
 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name);
 
 /// \ingroup ServerProtocolSSLAPI

=== modified file 'src/tests/stub_libsecurity.cc'
--- src/tests/stub_libsecurity.cc	2015-09-24 21:08:23 +0000
+++ src/tests/stub_libsecurity.cc	2015-09-30 12:21:00 +0000
@@ -4,26 +4,27 @@
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 #include "comm/Connection.h"
 
 #define STUB_API "security/libsecurity.la"
 #include "tests/STUB.h"
 
 #include "security/EncryptorAnswer.h"
 Security::EncryptorAnswer::~EncryptorAnswer() {}
 std::ostream &Security::operator <<(std::ostream &os, const Security::EncryptorAnswer &) STUB_RETVAL(os)
 
 #include "security/PeerOptions.h"
 Security::PeerOptions Security::ProxyOutgoingConfig;
 void Security::PeerOptions::parse(char const*) STUB
 Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL)
 void Security::PeerOptions::updateTlsVersionLimits() STUB
+void Security::PeerOptions::updateContextCa(Security::ContextPointer &) STUB
 void Security::PeerOptions::updateContextCrl(Security::ContextPointer &) STUB
 void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB
 long Security::PeerOptions::parseOptions() STUB_RETVAL(0)
 long Security::PeerOptions::parseFlags() STUB_RETVAL(0)
 void parse_securePeerOptions(Security::PeerOptions *) STUB
 

=== modified file 'src/tests/stub_libsslsquid.cc'
--- src/tests/stub_libsslsquid.cc	2015-09-24 21:08:23 +0000
+++ src/tests/stub_libsslsquid.cc	2015-09-30 12:20:45 +0000
@@ -40,41 +40,41 @@
 void Ssl::GlobalContextStorage::reconfigureStart() STUB
 //Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage;
 
 #include "ssl/ErrorDetail.h"
 Ssl::ssl_error_t parseErrorString(const char *name) STUB_RETVAL(0)
 //const char *Ssl::getErrorName(ssl_error_t value) STUB_RETVAL(NULL)
 Ssl::ErrorDetail::ErrorDetail(ssl_error_t err_no, X509 *, X509 *, const char *) STUB
 Ssl::ErrorDetail::ErrorDetail(ErrorDetail const &) STUB
 const String & Ssl::ErrorDetail::toString() const STUB_RETSTATREF(String)
 
 #include "ssl/support.h"
 namespace Ssl
 {
 //CertError::CertError(ssl_error_t anErr, X509 *aCert) STUB
 //CertError::CertError(CertError const &err) STUB
 CertError & CertError::operator = (const CertError &old) STUB_RETVAL(*this)
 bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false)
 bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false)
 } // namespace Ssl
 SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port) STUB_RETVAL(NULL)
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags, const char *CAfile, const char *CApath) STUB_RETVAL(NULL)
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags) STUB_RETVAL(NULL)
 int ssl_read_method(int, char *, int) STUB_RETVAL(0)
 int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
 void ssl_shutdown_method(SSL *ssl) STUB
 const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
 const char *sslGetUserCertificatePEM(SSL *ssl) STUB_RETVAL(NULL)
 const char *sslGetUserCertificateChainPEM(SSL *ssl) STUB_RETVAL(NULL)
 namespace Ssl
 {
 //GETX509ATTRIBUTE GetX509UserAttribute;
 //GETX509ATTRIBUTE GetX509CAAttribute;
 //GETX509ATTRIBUTE GetX509Fingerprint;
 const char *BumpModeStr[] = {""};
 DH *readDHParams(const char *dhfile) STUB_RETVAL(NULL)
 bool generateUntrustedCert(Security::CertPointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey) STUB_RETVAL(false)
 SSL_CTX * generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) STUB_RETVAL(NULL)
 bool verifySslCertificate(SSL_CTX * sslContext,  CertificateProperties const &properties) STUB_RETVAL(false)
 SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) STUB_RETVAL(NULL)
 void addChainToSslContext(SSL_CTX *sslContext, STACK_OF(X509) *certList) STUB



More information about the squid-dev mailing list