Go to the documentation of this file.
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)
650 ssl_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) {
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
PeerOptions ProxyOutgoingConfig
configuration options for DIRECT server access
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
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