2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 #include "base/Packable.h"
14 #include "parser/Tokenizer.h"
16 #include "security/PeerOptions.h"
19 #include "ssl/support.h"
24 Security::PeerOptions
Security::ProxyOutgoingConfig
;
26 Security::PeerOptions::PeerOptions()
28 // init options consistent with an empty sslOptions
33 Security::PeerOptions::parse(const char *token
)
36 // config says just "ssl" or "tls" (or "tls-")
37 encryptTransport
= true;
41 if (strncmp(token
, "disable", 7) == 0) {
46 if (strncmp(token
, "cert=", 5) == 0) {
48 t
.privateKeyFile
= t
.certFile
= SBuf(token
+ 5);
49 certs
.emplace_back(t
);
50 } else if (strncmp(token
, "key=", 4) == 0) {
51 if (certs
.empty() || certs
.back().certFile
.isEmpty()) {
52 fatal("cert= option must be set before key= is used.");
55 KeyData
&t
= certs
.back();
56 t
.privateKeyFile
= SBuf(token
+ 4);
57 } else if (strncmp(token
, "version=", 8) == 0) {
58 debugs(0, DBG_PARSE_NOTE(1), "UPGRADE WARNING: SSL version= is deprecated. Use options= and tls-min-version= to limit protocols instead.");
59 sslVersion
= xatoi(token
+ 8);
60 } else if (strncmp(token
, "min-version=", 12) == 0) {
61 tlsMinVersion
= SBuf(token
+ 12);
63 } else if (strncmp(token
, "options=", 8) == 0) {
64 sslOptions
= SBuf(token
+ 8);
66 } else if (strncmp(token
, "cipher=", 7) == 0) {
67 sslCipher
= SBuf(token
+ 7);
68 } else if (strncmp(token
, "cafile=", 7) == 0) {
69 caFiles
.emplace_back(SBuf(token
+ 7));
70 } else if (strncmp(token
, "capath=", 7) == 0) {
71 caDir
= SBuf(token
+ 7);
73 debugs(3, DBG_PARSE_NOTE(1), "WARNING: capath= option requires --with-openssl.");
75 } else if (strncmp(token
, "crlfile=", 8) == 0) {
76 crlFile
= SBuf(token
+ 8);
78 } else if (strncmp(token
, "flags=", 6) == 0) {
79 if (parsedFlags
!= 0) {
80 debugs(3, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags
<< " with " << SBuf(token
+ 6));
82 sslFlags
= SBuf(token
+ 6);
83 parsedFlags
= parseFlags();
84 } else if (strncmp(token
, "default-ca=off", 14) == 0 || strncmp(token
, "no-default-ca", 13) == 0) {
85 if (flags
.tlsDefaultCa
.configured() && flags
.tlsDefaultCa
)
86 fatalf("ERROR: previous default-ca settings conflict with %s", token
);
87 flags
.tlsDefaultCa
.configure(false);
88 } else if (strncmp(token
, "default-ca=on", 13) == 0 || strncmp(token
, "default-ca", 10) == 0) {
89 if (flags
.tlsDefaultCa
.configured() && !flags
.tlsDefaultCa
)
90 fatalf("ERROR: previous default-ca settings conflict with %s", token
);
91 flags
.tlsDefaultCa
.configure(true);
92 } else if (strncmp(token
, "domain=", 7) == 0) {
93 sslDomain
= SBuf(token
+ 7);
94 } else if (strncmp(token
, "no-npn", 6) == 0) {
97 debugs(3, DBG_CRITICAL
, "ERROR: Unknown TLS option '" << token
<< "'");
101 encryptTransport
= true;
105 Security::PeerOptions::dumpCfg(Packable
*p
, const char *pfx
) const
107 if (!encryptTransport
) {
108 p
->appendf(" %sdisable", pfx
);
109 return; // no other settings are relevant
112 for (auto &i
: certs
) {
113 if (!i
.certFile
.isEmpty())
114 p
->appendf(" %scert=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(i
.certFile
));
116 if (!i
.privateKeyFile
.isEmpty() && i
.privateKeyFile
!= i
.certFile
)
117 p
->appendf(" %skey=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(i
.privateKeyFile
));
120 if (!sslOptions
.isEmpty())
121 p
->appendf(" %soptions=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(sslOptions
));
123 if (!sslCipher
.isEmpty())
124 p
->appendf(" %scipher=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(sslCipher
));
126 for (auto i
: caFiles
) {
127 p
->appendf(" %scafile=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(i
));
130 if (!caDir
.isEmpty())
131 p
->appendf(" %scapath=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(caDir
));
133 if (!crlFile
.isEmpty())
134 p
->appendf(" %scrlfile=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(crlFile
));
136 if (!sslFlags
.isEmpty())
137 p
->appendf(" %sflags=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(sslFlags
));
139 if (flags
.tlsDefaultCa
.configured()) {
140 // default ON for peers / upstream servers
141 // default OFF for listening ports
142 if (flags
.tlsDefaultCa
)
143 p
->appendf(" %sdefault-ca", pfx
);
145 p
->appendf(" %sdefault-ca=off", pfx
);
149 p
->appendf(" %sno-npn", pfx
);
153 Security::PeerOptions::updateTlsVersionLimits()
155 if (!tlsMinVersion
.isEmpty()) {
156 ::Parser::Tokenizer
tok(tlsMinVersion
);
158 tlsMinOptions
.clear();
159 if (tok
.skip('1') && tok
.skip('.') && tok
.int64(v
, 10, false, 1) && v
<= 3) {
160 // only account for TLS here - SSL versions are handled by options= parameter
161 // avoid affecting options= parameter in cachemgr config report
165 add
.append(":NO_TLSv1");
167 add
.append(":NO_TLSv1_1");
169 add
.append(":NO_TLSv1_2");
172 add
.append(":-VERS-TLS1.0");
174 add
.append(":-VERS-TLS1.1");
176 add
.append(":-VERS-TLS1.2");
179 if (!tlsMinOptions
.isEmpty())
180 add
.chop(1); // remove the initial ':'
181 tlsMinOptions
.append(add
);
185 debugs(0, DBG_PARSE_NOTE(1), "WARNING: Unknown TLS minimum version: " << tlsMinVersion
);
191 if (sslVersion
> 2) {
192 // backward compatibility hack for sslversion= configuration
193 // only use if tls-min-version=N.N is not present
194 // values 0-2 for auto and SSLv2 are not supported any longer.
195 // Do it this way so we DO cause changes to options= in cachemgr config report
196 const char *add
= nullptr;
197 switch (sslVersion
) {
200 add
= ":NO_TLSv1:NO_TLSv1_1:NO_TLSv1_2:NO_TLSv1_3";
202 add
= ":-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2:-VERS-TLS1.3";
207 add
= ":NO_SSLv3:NO_TLSv1_1:NO_TLSv1_2:NO_TLSv1_3";
209 add
= ":+VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2:-VERS-TLS1.3";
214 add
= ":NO_SSLv3:NO_TLSv1:NO_TLSv1_2:NO_TLSv1_3";
216 add
= ":-VERS-TLS1.0:+VERS-TLS1.1:-VERS-TLS1.2:-VERS-TLS1.3";
221 add
= ":NO_SSLv3:NO_TLSv1:NO_TLSv1_1:NO_TLSv1_3";
223 add
= ":-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.3";
230 if (sslOptions
.isEmpty())
231 sslOptions
.append(add
+1, strlen(add
+1));
233 sslOptions
.append(add
, strlen(add
));
236 sslVersion
= 0; // prevent sslOptions being repeatedly appended
240 Security::ContextPointer
241 Security::PeerOptions::createBlankContext() const
243 Security::ContextPointer ctx
;
247 SSL_CTX
*t
= SSL_CTX_new(TLS_client_method());
249 const auto x
= ERR_get_error();
250 fatalf("Failed to allocate TLS client context: %s\n", Security::ErrorString(x
));
252 ctx
= convertContextFromRawPtr(t
);
255 // Initialize for X.509 certificate exchange
256 gnutls_certificate_credentials_t t
;
257 if (const auto x
= gnutls_certificate_allocate_credentials(&t
)) {
258 fatalf("Failed to allocate TLS client context: %s\n", Security::ErrorString(x
));
260 ctx
= convertContextFromRawPtr(t
);
263 debugs(83, 1, "WARNING: Failed to allocate TLS client context: No TLS library");
270 Security::ContextPointer
271 Security::PeerOptions::createClientContext(bool setOptions
)
273 updateTlsVersionLimits();
275 Security::ContextPointer
t(createBlankContext());
278 updateContextOptions(t
);
280 // XXX: temporary performance regression. c_str() data copies and prevents this being a const method
281 Ssl::InitClientContext(t
, *this, parsedFlags
);
286 updateContextTrust(t
);
293 /// set of options we can parse and what they map to
294 static struct ssl_option
{
300 #if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
302 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
305 #if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
307 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
310 #if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
312 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
315 #if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
317 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
320 #if SSL_OP_TLS_D5_BUG
322 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
325 #if SSL_OP_TLS_BLOCK_PADDING_BUG
327 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
330 #if SSL_OP_TLS_ROLLBACK_BUG
332 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
337 "ALL", (long)SSL_OP_ALL
340 #if SSL_OP_SINGLE_DH_USE
342 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
345 #if SSL_OP_EPHEMERAL_RSA
347 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
350 #if SSL_OP_PKCS1_CHECK_1
352 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
355 #if SSL_OP_PKCS1_CHECK_2
357 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
360 #if SSL_OP_NETSCAPE_CA_DN_BUG
362 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
365 #if SSL_OP_NON_EXPORT_FIRST
367 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
370 #if SSL_OP_CIPHER_SERVER_PREFERENCE
372 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
375 #if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
377 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
382 "NO_SSLv3", SSL_OP_NO_SSLv3
387 "NO_TLSv1", SSL_OP_NO_TLSv1
392 #if SSL_OP_NO_TLSv1_1
394 "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
399 #if SSL_OP_NO_TLSv1_2
401 "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
406 #if SSL_OP_NO_TLSv1_3
408 "NO_TLSv1_3", SSL_OP_NO_TLSv1_3
413 #if SSL_OP_NO_COMPRESSION
415 "No_Compression", SSL_OP_NO_COMPRESSION
420 "NO_TICKET", SSL_OP_NO_TICKET
423 #if SSL_OP_SINGLE_ECDH_USE
425 "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
435 #endif /* USE_OPENSSL */
438 * Pre-parse TLS options= parameter to be applied when the TLS objects created.
439 * Options must not used in the case of peek or stare bump mode.
442 Security::PeerOptions::parseOptions()
444 // do not allow repeated parsing when multiple contexts are created
445 // NP: we cannot use !parsedOptions because a nil value does have meaning there
450 // combination of settings we have to set via parsedOptions.
451 // options= with override by tls-min-version=
453 str
.append(sslOptions
);
454 str
.append(tlsMinOptions
);
457 ::Parser::Tokenizer
tok(str
);
460 while (!tok
.atEnd()) {
462 MODE_ADD
, MODE_REMOVE
465 if (tok
.skip('-') || tok
.skip('!'))
468 (void)tok
.skip('+'); // default action is add. ignore if missing operator
472 static const CharacterSet optChars
= CharacterSet("TLS-option", "_") + CharacterSet::ALPHA
+ CharacterSet::DIGIT
;
477 // Bug 4429: identify the full option name before determining text or numeric
478 if (tok
.prefix(option
, optChars
)) {
480 // find the named option in our supported set
481 for (struct ssl_option
*opttmp
= ssl_options
; opttmp
->name
; ++opttmp
) {
482 if (option
.cmp(opttmp
->name
) == 0) {
483 value
= opttmp
->value
;
488 // Special case.. hex specification
489 ::Parser::Tokenizer
tmp(option
);
490 if (!value
&& tmp
.int64(hex
, 16, false) && tmp
.atEnd()) {
505 debugs(83, DBG_PARSE_NOTE(1), "ERROR: Unknown TLS option " << option
);
508 static const CharacterSet
delims("TLS-option-delim",":,");
509 if (!tok
.skipAll(delims
) && !tok
.atEnd()) {
510 fatalf("Unknown TLS option '" SQUIDSBUFPH
"'", SQUIDSBUFPRINT(tok
.remaining()));
516 // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
517 op
= op
| SSL_OP_NO_SSLv2
;
523 parsedOptions
.reset();
527 const char *err
= nullptr;
528 const char *priorities
= str
.c_str();
529 gnutls_priority_t op
;
530 const auto x
= gnutls_priority_init(&op
, priorities
, &err
);
531 if (x
!= GNUTLS_E_SUCCESS
) {
532 fatalf("(%s) in TLS options '%s'", ErrorString(x
), err
);
534 parsedOptions
= Security::ParsedOptions(op
, [](gnutls_priority_t p
) {
535 debugs(83, 5, "gnutls_priority_deinit p=" << (void*)p
);
536 gnutls_priority_deinit(p
);
542 * Parses the TLS flags squid.conf parameter
544 Security::ParsedPortFlags
545 Security::PeerOptions::parseFlags()
547 if (sslFlags
.isEmpty())
552 ParsedPortFlags mask
;
554 { SBuf("NO_DEFAULT_CA"), SSL_FLAG_NO_DEFAULT_CA
},
555 { SBuf("DELAYED_AUTH"), SSL_FLAG_DELAYED_AUTH
},
556 { SBuf("DONT_VERIFY_PEER"), SSL_FLAG_DONT_VERIFY_PEER
},
557 { SBuf("CONDITIONAL_AUTH"), SSL_FLAG_CONDITIONAL_AUTH
},
558 { SBuf("DONT_VERIFY_DOMAIN"), SSL_FLAG_DONT_VERIFY_DOMAIN
},
559 { SBuf("NO_SESSION_REUSE"), SSL_FLAG_NO_SESSION_REUSE
},
560 #if X509_V_FLAG_CRL_CHECK
561 { SBuf("VERIFY_CRL"), SSL_FLAG_VERIFY_CRL
},
562 { SBuf("VERIFY_CRL_ALL"), SSL_FLAG_VERIFY_CRL_ALL
},
567 ::Parser::Tokenizer
tok(sslFlags
);
568 static const CharacterSet
delims("Flag-delimiter", ":,");
570 ParsedPortFlags fl
= 0;
572 ParsedPortFlags found
= 0;
573 for (size_t i
= 0; flagTokens
[i
].mask
; ++i
) {
574 // XXX: skips FOO in FOOBAR, missing merged flags and trailing typos
575 if (tok
.skip(flagTokens
[i
].label
)) {
576 found
= flagTokens
[i
].mask
;
581 fatalf("Unknown TLS flag '" SQUIDSBUFPH
"'", SQUIDSBUFPRINT(tok
.remaining()));
582 if (found
== SSL_FLAG_NO_DEFAULT_CA
) {
583 if (flags
.tlsDefaultCa
.configured() && flags
.tlsDefaultCa
)
584 fatal("ERROR: previous default-ca settings conflict with sslflags=NO_DEFAULT_CA");
585 debugs(83, DBG_PARSE_NOTE(2), "WARNING: flags=NO_DEFAULT_CA is deprecated. Use tls-default-ca=off instead.");
586 flags
.tlsDefaultCa
.configure(false);
589 } while (tok
.skipOne(delims
));
591 const auto mutuallyExclusive
=
592 SSL_FLAG_DONT_VERIFY_PEER
|
593 SSL_FLAG_DELAYED_AUTH
|
594 SSL_FLAG_CONDITIONAL_AUTH
;
595 typedef std::bitset
<sizeof(decltype(fl
))> ParsedPortFlagBits
;
596 if (ParsedPortFlagBits(fl
& mutuallyExclusive
).count() > 1) {
597 if (fl
& SSL_FLAG_CONDITIONAL_AUTH
)
598 throw TextException("CONDITIONAL_AUTH is not compatible with NO_DEFAULT_CA and DELAYED_AUTH flags", Here());
599 debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT
), "WARNING: Mixtures of incompatible TLS flags" <<
600 " are deprecated and will become a fatal configuration error");
606 /// Load a CRLs list stored in the file whose /path/name is in crlFile
607 /// replaces any CRL loaded previously
609 Security::PeerOptions::loadCrlFile()
612 if (crlFile
.isEmpty())
616 BIO
*in
= BIO_new_file(crlFile
.c_str(), "r");
618 debugs(83, 2, "WARNING: Failed to open CRL file " << crlFile
);
622 while (X509_CRL
*crl
= PEM_read_bio_X509_CRL(in
,NULL
,NULL
,NULL
)) {
623 parsedCrl
.emplace_back(Security::CrlPointer(crl
));
630 Security::PeerOptions::updateContextOptions(Security::ContextPointer
&ctx
)
634 SSL_CTX_set_options(ctx
.get(), parsedOptions
);
636 // NP: GnuTLS uses 'priorities' which are set only per-session instead.
640 #if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
641 // Dummy next_proto_neg callback
643 ssl_next_proto_cb(SSL
*s
, unsigned char **out
, unsigned char *outlen
, const unsigned char *in
, unsigned int inlen
, void *arg
)
645 static const unsigned char supported_protos
[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
646 (void)SSL_select_next_proto(out
, outlen
, in
, inlen
, supported_protos
, sizeof(supported_protos
));
647 return SSL_TLSEXT_ERR_OK
;
652 Security::PeerOptions::updateContextNpn(Security::ContextPointer
&ctx
)
657 #if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
658 SSL_CTX_set_next_proto_select_cb(ctx
.get(), &ssl_next_proto_cb
, nullptr);
661 // NOTE: GnuTLS does not support the obsolete NPN extension.
662 // it does support ALPN per-session, not per-context.
666 loadSystemTrustedCa(Security::ContextPointer
&ctx
)
668 debugs(83, 8, "Setting default system Trusted CA. ctx=" << (void*)ctx
.get());
670 if (SSL_CTX_set_default_verify_paths(ctx
.get()) == 0)
671 return Security::ErrorString(ERR_get_error());
674 auto x
= gnutls_certificate_set_x509_system_trust(ctx
.get());
676 return Security::ErrorString(x
);
683 Security::PeerOptions::updateContextCa(Security::ContextPointer
&ctx
)
685 debugs(83, 8, "Setting CA certificate locations.");
687 if (const char *path
= caDir
.isEmpty() ? nullptr : caDir
.c_str()) {
688 if (!SSL_CTX_load_verify_locations(ctx
.get(), nullptr, path
)) {
689 const auto x
= ERR_get_error();
690 debugs(83, DBG_IMPORTANT
, "WARNING: Ignoring error setting CA certificate location " << path
<< ": " << Security::ErrorString(x
));
694 for (auto i
: caFiles
) {
696 if (!SSL_CTX_load_verify_locations(ctx
.get(), i
.c_str(), nullptr)) {
697 const auto x
= ERR_get_error();
698 debugs(83, DBG_IMPORTANT
, "WARNING: Ignoring error setting CA certificate location " <<
699 i
<< ": " << Security::ErrorString(x
));
702 const auto x
= gnutls_certificate_set_x509_trust_file(ctx
.get(), i
.c_str(), GNUTLS_X509_FMT_PEM
);
704 debugs(83, DBG_IMPORTANT
, "WARNING: Ignoring error setting CA certificate location " <<
705 i
<< ": " << Security::ErrorString(x
));
710 if (!flags
.tlsDefaultCa
)
713 if (const char *err
= loadSystemTrustedCa(ctx
)) {
714 debugs(83, DBG_IMPORTANT
, "WARNING: Ignoring error setting default trusted CA : " << err
);
719 Security::PeerOptions::updateContextCrl(Security::ContextPointer
&ctx
)
722 bool verifyCrl
= false;
723 X509_STORE
*st
= SSL_CTX_get_cert_store(ctx
.get());
724 if (parsedCrl
.size()) {
725 for (auto &i
: parsedCrl
) {
726 if (!X509_STORE_add_crl(st
, i
.get()))
727 debugs(83, 2, "WARNING: Failed to add CRL");
733 #if X509_V_FLAG_CRL_CHECK
734 if ((parsedFlags
& SSL_FLAG_VERIFY_CRL_ALL
))
735 X509_STORE_set_flags(st
, X509_V_FLAG_CRL_CHECK
|X509_V_FLAG_CRL_CHECK_ALL
);
736 else if (verifyCrl
|| (parsedFlags
& SSL_FLAG_VERIFY_CRL
))
737 X509_STORE_set_flags(st
, X509_V_FLAG_CRL_CHECK
);
740 #endif /* USE_OPENSSL */
744 Security::PeerOptions::updateContextTrust(Security::ContextPointer
&ctx
)
747 #if defined(X509_V_FLAG_PARTIAL_CHAIN)
748 const auto st
= SSL_CTX_get_cert_store(ctx
.get());
750 if (X509_STORE_set_flags(st
, X509_V_FLAG_PARTIAL_CHAIN
) != 1) {
751 debugs(83, DBG_IMPORTANT
, "ERROR: Failed to enable trust in intermediate CA certificates: " <<
752 Security::ErrorString(ERR_get_error()));
756 // Modern GnuTLS versions trust intermediate CA certificates by default.
757 #endif /* TLS library */
761 Security::PeerOptions::updateSessionOptions(Security::SessionPointer
&s
)
765 debugs(83, 5, "set OpenSSL options for session=" << s
<< ", parsedOptions=" << parsedOptions
);
766 // XXX: Options already set before (via the context) are not cleared!
767 SSL_set_options(s
.get(), parsedOptions
);
772 if (!parsedOptions
) {
773 debugs(83, 5, "set GnuTLS default priority/options for session=" << s
);
774 x
= gnutls_set_default_priority(s
.get());
775 static const SBuf
defaults("default");
778 debugs(83, 5, "set GnuTLS session=" << s
<< ", options='" << sslOptions
<< ":" << tlsMinOptions
<< "'");
779 x
= gnutls_priority_set(s
.get(), parsedOptions
.get());
783 if (x
!= GNUTLS_E_SUCCESS
) {
784 debugs(83, DBG_IMPORTANT
, "ERROR: session=" << s
<< " Failed to set TLS options (" << errMsg
<< ":" << tlsMinVersion
<< "). error: " << Security::ErrorString(x
));
790 parse_securePeerOptions(Security::PeerOptions
*opt
)
792 while(const char *token
= ConfigParser::NextToken())