42 encryptTransport =
true;
46 if (strncmp(token,
"disable", 7) == 0) {
51 if (strncmp(token,
"cert=", 5) == 0) {
54 certs.emplace_back(t);
55 }
else if (strncmp(token,
"key=", 4) == 0) {
56 if (certs.empty() || certs.back().certFile.isEmpty()) {
57 fatal(
"cert= option must be set before key= is used.");
62 }
else if (strncmp(token,
"version=", 8) == 0) {
63 debugs(0,
DBG_PARSE_NOTE(1),
"WARNING: UPGRADE: SSL version= is deprecated. Use options= and tls-min-version= to limit protocols instead.");
64 sslVersion =
xatoi(token + 8);
65 }
else if (strncmp(token,
"min-version=", 12) == 0) {
66 tlsMinVersion =
SBuf(token + 12);
68 }
else if (strncmp(token,
"options=", 8) == 0) {
69 sslOptions =
SBuf(token + 8);
71 }
else if (strncmp(token,
"cipher=", 7) == 0) {
72 sslCipher =
SBuf(token + 7);
73 }
else if (strncmp(token,
"cafile=", 7) == 0) {
74 caFiles.emplace_back(
SBuf(token + 7));
75 }
else if (strncmp(token,
"capath=", 7) == 0) {
76 caDir =
SBuf(token + 7);
80 }
else if (strncmp(token,
"crlfile=", 8) == 0) {
81 crlFile =
SBuf(token + 8);
83 }
else if (strncmp(token,
"flags=", 6) == 0) {
84 if (parsedFlags != 0) {
87 sslFlags =
SBuf(token + 6);
88 parsedFlags = parseFlags();
89 }
else if (strncmp(token,
"default-ca=off", 14) == 0 || strncmp(token,
"no-default-ca", 13) == 0) {
90 if (flags.tlsDefaultCa.configured() && flags.tlsDefaultCa)
91 fatalf(
"ERROR: previous default-ca settings conflict with %s", token);
92 flags.tlsDefaultCa.configure(
false);
93 }
else if (strncmp(token,
"default-ca=on", 13) == 0 || strncmp(token,
"default-ca", 10) == 0) {
94 if (flags.tlsDefaultCa.configured() && !flags.tlsDefaultCa)
95 fatalf(
"ERROR: previous default-ca settings conflict with %s", token);
96 flags.tlsDefaultCa.configure(
true);
97 }
else if (strncmp(token,
"domain=", 7) == 0) {
98 sslDomain =
SBuf(token + 7);
99 }
else if (strncmp(token,
"no-npn", 6) == 0) {
100 flags.tlsNpn =
false;
106 encryptTransport =
true;
112 if (!encryptTransport) {
113 os <<
' ' << pfx <<
"disable";
117 for (
auto &i : certs) {
118 if (!i.certFile.isEmpty())
119 os <<
' ' << pfx <<
"cert=" << i.certFile;
121 if (!i.privateKeyFile.isEmpty() && i.privateKeyFile != i.certFile)
122 os <<
' ' << pfx <<
"key=" << i.privateKeyFile;
125 if (!sslOptions.isEmpty())
126 os <<
' ' << pfx <<
"options=" << sslOptions;
128 if (!sslCipher.isEmpty())
129 os <<
' ' << pfx <<
"cipher=" << sslCipher;
131 for (
auto i : caFiles) {
132 os <<
' ' << pfx <<
"cafile=" << i;
135 if (!caDir.isEmpty())
136 os <<
' ' << pfx <<
"capath=" << caDir;
138 if (!crlFile.isEmpty())
139 os <<
' ' << pfx <<
"crlfile=" << crlFile;
141 if (!sslFlags.isEmpty())
142 os <<
' ' << pfx <<
"flags=" << sslFlags;
144 if (flags.tlsDefaultCa.configured()) {
147 if (flags.tlsDefaultCa)
148 os <<
' ' << pfx <<
"default-ca";
150 os <<
' ' << pfx <<
"default-ca=off";
154 os <<
' ' << pfx <<
"no-npn";
160 if (!tlsMinVersion.isEmpty()) {
163 tlsMinOptions.clear();
164 if (
tok.skip(
'1') &&
tok.skip(
'.') &&
tok.int64(v, 10,
false, 1) && v <= 3) {
172 add.
append(
":NO_TLSv1_1");
174 add.
append(
":NO_TLSv1_2");
177 add.
append(
":-VERS-TLS1.0");
179 add.
append(
":-VERS-TLS1.1");
181 add.
append(
":-VERS-TLS1.2");
184 if (!tlsMinOptions.isEmpty())
186 tlsMinOptions.
append(add);
196 if (sslVersion > 2) {
201 const char *add =
nullptr;
202 switch (sslVersion) {
205 add =
":NO_TLSv1:NO_TLSv1_1:NO_TLSv1_2:NO_TLSv1_3";
207 add =
":-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2:-VERS-TLS1.3";
212 add =
":NO_SSLv3:NO_TLSv1_1:NO_TLSv1_2:NO_TLSv1_3";
214 add =
":+VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2:-VERS-TLS1.3";
219 add =
":NO_SSLv3:NO_TLSv1:NO_TLSv1_2:NO_TLSv1_3";
221 add =
":-VERS-TLS1.0:+VERS-TLS1.1:-VERS-TLS1.2:-VERS-TLS1.3";
226 add =
":NO_SSLv3:NO_TLSv1:NO_TLSv1_1:NO_TLSv1_3";
228 add =
":-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.3";
235 if (sslOptions.isEmpty())
236 sslOptions.append(add+1, strlen(add+1));
238 sslOptions.append(add, strlen(add));
254 const auto x = ERR_get_error();
257 ctx = convertContextFromRawPtr(t);
261 gnutls_certificate_credentials_t t;
262 if (
const auto x = gnutls_certificate_allocate_credentials(&t)) {
265 ctx = convertContextFromRawPtr(t);
268 debugs(83, 1,
"WARNING: Failed to allocate TLS client context: No TLS library");
278 updateTlsVersionLimits();
283 updateContextOptions(t);
291 updateContextTrust(t);
305#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)
307 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
310#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)
312 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
315#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
317 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
320#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)
322 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
325#if defined(SSL_OP_TLS_D5_BUG)
327 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
330#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG)
332 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
335#if defined(SSL_OP_TLS_ROLLBACK_BUG)
337 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
340#if defined(SSL_OP_ALL)
345#if defined(SSL_OP_SINGLE_DH_USE)
347 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
350#if defined(SSL_OP_EPHEMERAL_RSA)
352 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
355#if defined(SSL_OP_PKCS1_CHECK_1)
357 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
360#if defined(SSL_OP_PKCS1_CHECK_2)
362 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
365#if defined(SSL_OP_NETSCAPE_CA_DN_BUG)
367 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
370#if defined(SSL_OP_NON_EXPORT_FIRST)
372 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
375#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
377 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
380#if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
382 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
385#if defined(SSL_OP_NO_SSLv3)
387 "NO_SSLv3", SSL_OP_NO_SSLv3
390#if defined(SSL_OP_NO_TLSv1)
392 "NO_TLSv1", SSL_OP_NO_TLSv1
397#if defined(SSL_OP_NO_TLSv1_1)
399 "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
404#if defined(SSL_OP_NO_TLSv1_2)
406 "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
411#if defined(SSL_OP_NO_TLSv1_3)
413 "NO_TLSv1_3", SSL_OP_NO_TLSv1_3
418#if defined(SSL_OP_NO_COMPRESSION)
420 "No_Compression", SSL_OP_NO_COMPRESSION
423#if defined(SSL_OP_NO_TICKET)
425 "NO_TICKET", SSL_OP_NO_TICKET
428#if defined(SSL_OP_SINGLE_ECDH_USE)
430 "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
459 str.
append(tlsMinOptions);
465 while (!
tok.atEnd()) {
467 MODE_ADD, MODE_REMOVE
470 if (
tok.skip(
'-') ||
tok.skip(
'!'))
484 if (
tok.prefix(option, optChars)) {
488 if (option.
cmp(opttmp->name) == 0) {
489 value = opttmp->value;
497 if (!found && tmp.
int64(hex, 16,
false) && tmp.
atEnd()) {
516 static const CharacterSet delims(
"TLS-option-delim",
":,");
517 if (!
tok.skipAll(delims) && !
tok.atEnd()) {
523#if defined(SSL_OP_NO_SSLv2)
526 op |= SSL_OP_NO_SSLv2;
532 parsedOptions.reset();
536 const char *err =
nullptr;
537 const char *priorities = str.
c_str();
538 gnutls_priority_t op;
539 const auto x = gnutls_priority_init(&op, priorities, &err);
540 if (x != GNUTLS_E_SUCCESS) {
544 debugs(83, 5,
"gnutls_priority_deinit p=" << (
void*)p);
545 gnutls_priority_deinit(p);
556 if (sslFlags.isEmpty())
569#if X509_V_FLAG_CRL_CHECK
577 static const CharacterSet delims(
"Flag-delimiter",
":,");
582 for (
size_t i = 0; flagTokens[i].mask; ++i) {
584 if (
tok.skip(flagTokens[i].label)) {
585 found = flagTokens[i].mask;
592 if (flags.tlsDefaultCa.configured() && flags.tlsDefaultCa)
593 fatal(
"ERROR: previous default-ca settings conflict with sslflags=NO_DEFAULT_CA");
594 debugs(83,
DBG_PARSE_NOTE(2),
"WARNING: flags=NO_DEFAULT_CA is deprecated. Use tls-default-ca=off instead.");
595 flags.tlsDefaultCa.configure(
false);
598 }
while (
tok.skipOne(delims));
600 const auto mutuallyExclusive =
604 typedef std::bitset<
sizeof(
decltype(fl))> ParsedPortFlagBits;
605 if (ParsedPortFlagBits(fl & mutuallyExclusive).count() > 1) {
607 throw TextException(
"CONDITIONAL_AUTH is not compatible with NO_DEFAULT_CA and DELAYED_AUTH flags",
Here());
609 " are deprecated and will become a fatal configuration error");
621 if (crlFile.isEmpty())
625 BIO *in = BIO_new_file(crlFile.c_str(),
"r");
627 debugs(83, 2,
"WARNING: Failed to open CRL file " << crlFile);
631 while (X509_CRL *crl = PEM_read_bio_X509_CRL(in,
nullptr,
nullptr,
nullptr)) {
643 SSL_CTX_set_options(ctx.get(), parsedOptions);
652#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
655ssl_next_proto_cb(SSL *,
unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void * )
657 static const unsigned char supported_protos[] = {8,
'h',
't',
't',
'p',
'/',
'1',
'.',
'1'};
658 (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos,
sizeof(supported_protos));
659 return SSL_TLSEXT_ERR_OK;
669#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
670 SSL_CTX_set_next_proto_select_cb(ctx.get(), &ssl_next_proto_cb,
nullptr);
681 debugs(83, 8,
"Setting default system Trusted CA. ctx=" << (
void*)ctx.get());
683 if (SSL_CTX_set_default_verify_paths(ctx.get()) == 0)
687 auto x = gnutls_certificate_set_x509_system_trust(ctx.get());
698 debugs(83, 8,
"Setting CA certificate locations.");
700 if (
const char *path = caDir.isEmpty() ?
nullptr : caDir.c_str()) {
701 if (!SSL_CTX_load_verify_locations(ctx.get(),
nullptr, path)) {
702 const auto x = ERR_get_error();
707 for (
auto i : caFiles) {
709 if (!SSL_CTX_load_verify_locations(ctx.get(), i.c_str(),
nullptr)) {
710 const auto x = ERR_get_error();
715 const auto x = gnutls_certificate_set_x509_trust_file(ctx.get(), i.c_str(), GNUTLS_X509_FMT_PEM);
723 if (!flags.tlsDefaultCa)
735 bool verifyCrl =
false;
736 X509_STORE *st = SSL_CTX_get_cert_store(ctx.get());
737 if (parsedCrl.size()) {
738 for (
auto &i : parsedCrl) {
739 if (!X509_STORE_add_crl(st, i.get()))
740 debugs(83, 2,
"WARNING: Failed to add CRL");
746#if X509_V_FLAG_CRL_CHECK
748 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
750 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK);
762#if defined(X509_V_FLAG_PARTIAL_CHAIN)
763 const auto st = SSL_CTX_get_cert_store(ctx.get());
765 if (X509_STORE_set_flags(st, X509_V_FLAG_PARTIAL_CHAIN) != 1) {
766 debugs(83,
DBG_IMPORTANT,
"ERROR: Failed to enable trust in intermediate CA certificates: " <<
783 debugs(83, 5,
"set OpenSSL options for session=" << s <<
", parsedOptions=" << parsedOptions);
785 SSL_set_options(s.get(), parsedOptions);
790 if (!parsedOptions) {
791 debugs(83, 5,
"set GnuTLS default priority/options for session=" << s);
792 x = gnutls_set_default_priority(s.get());
793 static const SBuf defaults(
"default");
796 debugs(83, 5,
"set GnuTLS session=" << s <<
", options='" << sslOptions <<
":" << tlsMinOptions <<
"'");
797 x = gnutls_priority_set(s.get(), parsedOptions.get());
801 if (x != GNUTLS_E_SUCCESS) {
#define Here()
source code location of the caller
int xatoi(const char *token)
void parse_securePeerOptions(Security::PeerOptions *opt)
static const char * loadSystemTrustedCa(Security::ContextPointer &ctx)
static struct ssl_option ssl_options[]
#define SQUIDSBUFPRINT(s)
optimized set of C chars, with quick membership test and merge support
static const CharacterSet DIGIT
static const CharacterSet ALPHA
static char * NextToken()
bool int64(int64_t &result, int base=0, bool allowSign=true, SBuf::size_type limit=SBuf::npos)
bool atEnd() const
whether the end of the buffer has been reached
SBuf & chop(size_type pos, size_type n=npos)
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
SBuf & append(const SBuf &S)
TLS certificate and private key details from squid.conf.
SBuf certFile
path of file containing PEM format X.509 certificate
SBuf privateKeyFile
path of file containing private key in PEM format
TLS squid.conf settings for a remote server peer.
void updateContextCrl(Security::ContextPointer &)
setup the CRL details for the given context
ParsedPortFlags parseFlags()
Security::ContextPointer createClientContext(bool setOptions)
generate a security client-context from these configured options
virtual void parse(const char *)
parse a TLS squid.conf option
void updateContextCa(Security::ContextPointer &)
setup the CA details for the given context
void updateContextOptions(Security::ContextPointer &)
Setup the library specific 'options=' parameters for the given context.
void updateTlsVersionLimits()
sync the context options with tls-min-version=N configuration
virtual void dumpCfg(std::ostream &, const char *pfx) const
output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
void updateContextTrust(Security::ContextPointer &)
decide which CAs to trust
void parseOptions()
parse and verify the [tls-]options= string in sslOptions
void updateContextNpn(Security::ContextPointer &)
setup the NPN extension details for the given context
virtual Security::ContextPointer createBlankContext() const
generate an unset security context object
void updateSessionOptions(Security::SessionPointer &)
setup any library-specific options that can be set for the given session
an std::runtime_error with thrower location info
#define DBG_PARSE_NOTE(x)
#define debugs(SECTION, LEVEL, CONTENT)
void fatal(const char *message)
void fatalf(const char *fmt,...)
std::shared_ptr< SSL_CTX > ContextPointer
std::shared_ptr< SSL > SessionPointer
unsigned long LibErrorCode
TLS library-reported non-validation error.
const char * ErrorString(const LibErrorCode code)
converts numeric LibErrorCode into a human-friendlier string
PeerOptions & ProxyOutgoingConfig()
configuration options for DIRECT server access
bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, Security::ParsedPortFlags)
initialize a TLS client context with OpenSSL specific settings
#define TLS_client_method
#define SSL_FLAG_CONDITIONAL_AUTH
#define SSL_FLAG_DONT_VERIFY_PEER
#define SSL_FLAG_NO_DEFAULT_CA
#define SSL_FLAG_VERIFY_CRL
#define SSL_FLAG_NO_SESSION_REUSE
#define SSL_FLAG_DONT_VERIFY_DOMAIN
#define SSL_FLAG_VERIFY_CRL_ALL
#define SSL_FLAG_DELAYED_AUTH
set of options we can parse and what they map to
Security::ParsedOptions value