Go to the documentation of this file.
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)
655 ssl_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) {
void fatal(const char *message)
#define SSL_FLAG_DONT_VERIFY_DOMAIN
bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, Security::ParsedPortFlags)
initialize a TLS client context with OpenSSL specific settings
void updateContextOptions(Security::ContextPointer &)
Setup the library specific 'options=' parameters for the given context.
#define Here()
source code location of the caller
#define SSL_FLAG_NO_DEFAULT_CA
virtual Security::ContextPointer createBlankContext() const
generate an unset security context object
std::shared_ptr< SSL_CTX > ContextPointer
Security::ContextPointer createClientContext(bool setOptions)
generate a security client-context from these configured options
bool atEnd() const
whether the end of the buffer has been reached
#define SSL_FLAG_DELAYED_AUTH
static const char * loadSystemTrustedCa(Security::ContextPointer &ctx)
static const CharacterSet ALPHA
void updateTlsVersionLimits()
sync the context options with tls-min-version=N configuration
Security::ParsedOptions value
SBuf & chop(size_type pos, size_type n=npos)
#define SQUIDSBUFPRINT(s)
void parseOptions()
parse and verify the [tls-]options= string in sslOptions
#define DBG_PARSE_NOTE(x)
TLS squid.conf settings for a remote server peer.
SBuf privateKeyFile
path of file containing private key in PEM format
#define SSL_FLAG_NO_SESSION_REUSE
int xatoi(const char *token)
void updateContextCrl(Security::ContextPointer &)
setup the CRL details for the given context
void fatalf(const char *fmt,...)
virtual void dumpCfg(std::ostream &, const char *pfx) const
output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
static const CharacterSet DIGIT
static struct ssl_option ssl_options[]
#define SSL_FLAG_DONT_VERIFY_PEER
SBuf & append(const SBuf &S)
static char * NextToken()
#define SSL_FLAG_VERIFY_CRL_ALL
void updateContextNpn(Security::ContextPointer &)
setup the NPN extension details for the given context
std::shared_ptr< SSL > SessionPointer
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
bool int64(int64_t &result, int base=0, bool allowSign=true, SBuf::size_type limit=SBuf::npos)
void updateContextCa(Security::ContextPointer &)
setup the CA details for the given context
TLS certificate and private key details from squid.conf.
an std::runtime_error with thrower location info
#define SSL_FLAG_CONDITIONAL_AUTH
void updateSessionOptions(Security::SessionPointer &)
setup any library-specific options that can be set for the given session
set of options we can parse and what they map to
#define SSL_FLAG_VERIFY_CRL
void updateContextTrust(Security::ContextPointer &)
decide which CAs to trust
optimized set of C chars, with quick membership test and merge support
SBuf certFile
path of file containing PEM format X.509 certificate
PeerOptions & ProxyOutgoingConfig()
configuration options for DIRECT server access
const char * ErrorString(const LibErrorCode code)
converts numeric LibErrorCode into a human-friendlier string
#define debugs(SECTION, LEVEL, CONTENT)
ParsedPortFlags parseFlags()
#define TLS_client_method
void parse_securePeerOptions(Security::PeerOptions *opt)
unsigned long LibErrorCode
TLS library-reported non-validation error.
virtual void parse(const char *)
parse a TLS squid.conf option