37 encryptTransport =
true;
41 if (strncmp(token,
"disable", 7) == 0) {
46 if (strncmp(token,
"cert=", 5) == 0) {
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.");
57 }
else if (strncmp(token,
"version=", 8) == 0) {
58 debugs(0,
DBG_PARSE_NOTE(1),
"WARNING: UPGRADE: 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);
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) {
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) {
101 encryptTransport =
true;
107 if (!encryptTransport) {
108 os <<
' ' << pfx <<
"disable";
112 for (
auto &i : certs) {
113 if (!i.certFile.isEmpty())
114 os <<
' ' << pfx <<
"cert=" << i.certFile;
116 if (!i.privateKeyFile.isEmpty() && i.privateKeyFile != i.certFile)
117 os <<
' ' << pfx <<
"key=" << i.privateKeyFile;
120 if (!sslOptions.isEmpty())
121 os <<
' ' << pfx <<
"options=" << sslOptions;
123 if (!sslCipher.isEmpty())
124 os <<
' ' << pfx <<
"cipher=" << sslCipher;
126 for (
auto i : caFiles) {
127 os <<
' ' << pfx <<
"cafile=" << i;
130 if (!caDir.isEmpty())
131 os <<
' ' << pfx <<
"capath=" << caDir;
133 if (!crlFile.isEmpty())
134 os <<
' ' << pfx <<
"crlfile=" << crlFile;
136 if (!sslFlags.isEmpty())
137 os <<
' ' << pfx <<
"flags=" << sslFlags;
139 if (flags.tlsDefaultCa.configured()) {
142 if (flags.tlsDefaultCa)
143 os <<
' ' << pfx <<
"default-ca";
145 os <<
' ' << pfx <<
"default-ca=off";
149 os <<
' ' << pfx <<
"no-npn";
155 if (!tlsMinVersion.isEmpty()) {
158 tlsMinOptions.clear();
159 if (
tok.skip(
'1') &&
tok.skip(
'.') &&
tok.int64(v, 10,
false, 1) && v <= 3) {
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())
181 tlsMinOptions.
append(add);
191 if (sslVersion > 2) {
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));
249 const auto x = ERR_get_error();
252 ctx = convertContextFromRawPtr(t);
256 gnutls_certificate_credentials_t t;
257 if (
const auto x = gnutls_certificate_allocate_credentials(&t)) {
260 ctx = convertContextFromRawPtr(t);
263 debugs(83, 1,
"WARNING: Failed to allocate TLS client context: No TLS library");
273 updateTlsVersionLimits();
278 updateContextOptions(t);
286 updateContextTrust(t);
300#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)
302 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
305#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)
307 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
310#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
312 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
315#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)
317 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
320#if defined(SSL_OP_TLS_D5_BUG)
322 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
325#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG)
327 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
330#if defined(SSL_OP_TLS_ROLLBACK_BUG)
332 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
335#if defined(SSL_OP_ALL)
340#if defined(SSL_OP_SINGLE_DH_USE)
342 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
345#if defined(SSL_OP_EPHEMERAL_RSA)
347 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
350#if defined(SSL_OP_PKCS1_CHECK_1)
352 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
355#if defined(SSL_OP_PKCS1_CHECK_2)
357 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
360#if defined(SSL_OP_NETSCAPE_CA_DN_BUG)
362 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
365#if defined(SSL_OP_NON_EXPORT_FIRST)
367 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
370#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
372 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
375#if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
377 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
380#if defined(SSL_OP_NO_SSLv3)
382 "NO_SSLv3", SSL_OP_NO_SSLv3
385#if defined(SSL_OP_NO_TLSv1)
387 "NO_TLSv1", SSL_OP_NO_TLSv1
392#if defined(SSL_OP_NO_TLSv1_1)
394 "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
399#if defined(SSL_OP_NO_TLSv1_2)
401 "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
406#if defined(SSL_OP_NO_TLSv1_3)
408 "NO_TLSv1_3", SSL_OP_NO_TLSv1_3
413#if defined(SSL_OP_NO_COMPRESSION)
415 "No_Compression", SSL_OP_NO_COMPRESSION
418#if defined(SSL_OP_NO_TICKET)
420 "NO_TICKET", SSL_OP_NO_TICKET
423#if defined(SSL_OP_SINGLE_ECDH_USE)
425 "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
454 str.
append(tlsMinOptions);
460 while (!
tok.atEnd()) {
462 MODE_ADD, MODE_REMOVE
465 if (
tok.skip(
'-') ||
tok.skip(
'!'))
479 if (
tok.prefix(option, optChars)) {
483 if (option.
cmp(opttmp->name) == 0) {
484 value = opttmp->value;
492 if (!found && tmp.
int64(hex, 16,
false) && tmp.
atEnd()) {
511 static const CharacterSet delims(
"TLS-option-delim",
":,");
512 if (!
tok.skipAll(delims) && !
tok.atEnd()) {
518#if defined(SSL_OP_NO_SSLv2)
521 op |= SSL_OP_NO_SSLv2;
527 parsedOptions.reset();
531 const char *err =
nullptr;
532 const char *priorities = str.
c_str();
533 gnutls_priority_t op;
534 const auto x = gnutls_priority_init(&op, priorities, &err);
535 if (x != GNUTLS_E_SUCCESS) {
539 debugs(83, 5,
"gnutls_priority_deinit p=" << (
void*)p);
540 gnutls_priority_deinit(p);
551 if (sslFlags.isEmpty())
564#if X509_V_FLAG_CRL_CHECK
572 static const CharacterSet delims(
"Flag-delimiter",
":,");
577 for (
size_t i = 0; flagTokens[i].mask; ++i) {
579 if (
tok.skip(flagTokens[i].label)) {
580 found = flagTokens[i].mask;
587 if (flags.tlsDefaultCa.configured() && flags.tlsDefaultCa)
588 fatal(
"ERROR: previous default-ca settings conflict with sslflags=NO_DEFAULT_CA");
589 debugs(83,
DBG_PARSE_NOTE(2),
"WARNING: flags=NO_DEFAULT_CA is deprecated. Use tls-default-ca=off instead.");
590 flags.tlsDefaultCa.configure(
false);
593 }
while (
tok.skipOne(delims));
595 const auto mutuallyExclusive =
599 typedef std::bitset<
sizeof(
decltype(fl))> ParsedPortFlagBits;
600 if (ParsedPortFlagBits(fl & mutuallyExclusive).count() > 1) {
602 throw TextException(
"CONDITIONAL_AUTH is not compatible with NO_DEFAULT_CA and DELAYED_AUTH flags",
Here());
604 " are deprecated and will become a fatal configuration error");
616 if (crlFile.isEmpty())
620 BIO *in = BIO_new_file(crlFile.c_str(),
"r");
622 debugs(83, 2,
"WARNING: Failed to open CRL file " << crlFile);
626 while (X509_CRL *crl = PEM_read_bio_X509_CRL(in,
nullptr,
nullptr,
nullptr)) {
638 SSL_CTX_set_options(ctx.get(), parsedOptions);
647#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
650ssl_next_proto_cb(SSL *,
unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void * )
652 static const unsigned char supported_protos[] = {8,
'h',
't',
't',
'p',
'/',
'1',
'.',
'1'};
653 (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos,
sizeof(supported_protos));
654 return SSL_TLSEXT_ERR_OK;
664#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
665 SSL_CTX_set_next_proto_select_cb(ctx.get(), &ssl_next_proto_cb,
nullptr);
676 debugs(83, 8,
"Setting default system Trusted CA. ctx=" << (
void*)ctx.get());
678 if (SSL_CTX_set_default_verify_paths(ctx.get()) == 0)
682 auto x = gnutls_certificate_set_x509_system_trust(ctx.get());
693 debugs(83, 8,
"Setting CA certificate locations.");
695 if (
const char *path = caDir.isEmpty() ?
nullptr : caDir.c_str()) {
696 if (!SSL_CTX_load_verify_locations(ctx.get(),
nullptr, path)) {
697 const auto x = ERR_get_error();
702 for (
auto i : caFiles) {
704 if (!SSL_CTX_load_verify_locations(ctx.get(), i.c_str(),
nullptr)) {
705 const auto x = ERR_get_error();
710 const auto x = gnutls_certificate_set_x509_trust_file(ctx.get(), i.c_str(), GNUTLS_X509_FMT_PEM);
718 if (!flags.tlsDefaultCa)
730 bool verifyCrl =
false;
731 X509_STORE *st = SSL_CTX_get_cert_store(ctx.get());
732 if (parsedCrl.size()) {
733 for (
auto &i : parsedCrl) {
734 if (!X509_STORE_add_crl(st, i.get()))
735 debugs(83, 2,
"WARNING: Failed to add CRL");
741#if X509_V_FLAG_CRL_CHECK
743 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
745 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK);
757#if defined(X509_V_FLAG_PARTIAL_CHAIN)
758 const auto st = SSL_CTX_get_cert_store(ctx.get());
760 if (X509_STORE_set_flags(st, X509_V_FLAG_PARTIAL_CHAIN) != 1) {
761 debugs(83,
DBG_IMPORTANT,
"ERROR: Failed to enable trust in intermediate CA certificates: " <<
778 debugs(83, 5,
"set OpenSSL options for session=" << s <<
", parsedOptions=" << parsedOptions);
780 SSL_set_options(s.get(), parsedOptions);
785 if (!parsedOptions) {
786 debugs(83, 5,
"set GnuTLS default priority/options for session=" << s);
787 x = gnutls_set_default_priority(s.get());
788 static const SBuf defaults(
"default");
791 debugs(83, 5,
"set GnuTLS session=" << s <<
", options='" << sslOptions <<
":" << tlsMinOptions <<
"'");
792 x = gnutls_priority_set(s.get(), parsedOptions.get());
796 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.
PeerOptions ProxyOutgoingConfig
configuration options for DIRECT server access
const char * ErrorString(const LibErrorCode code)
converts numeric LibErrorCode into a human-friendlier string
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