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.
9 /* DEBUG: section 83 SSL accelerator support */
13 /* MS Visual Studio Projects are monolithic, so we need the following
14 * #if to exclude the SSL code from compile process when not needed.
18 #include "acl/FilledChecklist.h"
19 #include "anyp/PortCfg.h"
25 #include "ipc/MemMap.h"
26 #include "security/CertError.h"
27 #include "security/ErrorDetail.h"
28 #include "security/Session.h"
29 #include "SquidConfig.h"
30 #include "SquidTime.h"
32 #include "ssl/Config.h"
33 #include "ssl/ErrorDetail.h"
34 #include "ssl/gadgets.h"
35 #include "ssl/support.h"
39 // TODO: Move ssl_ex_index_* global variables from global.cc here.
40 int ssl_ex_index_ssl_untrusted_chain
= -1;
42 static Ssl::CertsIndexedList SquidUntrustedCerts
;
44 const EVP_MD
*Ssl::DefaultSignHash
= NULL
;
46 std::vector
<const char *> Ssl::BumpModeStr
= {
59 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
60 \ingroup ServerProtocolSSLAPI
64 Ssl::AskPasswordCb(char *buf
, int size
, int rwflag
, void *userdata
)
70 snprintf(cmdline
, sizeof(cmdline
), "\"%s\" \"%s\"", ::Config
.Program
.ssl_password
, (const char *)userdata
);
71 in
= popen(cmdline
, "r");
73 if (fgets(buf
, size
, in
))
77 while (len
> 0 && (buf
[len
- 1] == '\n' || buf
[len
- 1] == '\r'))
87 /// \ingroup ServerProtocolSSLInternal
89 ssl_ask_password(SSL_CTX
* context
, const char * prompt
)
91 if (Config
.Program
.ssl_password
) {
92 SSL_CTX_set_default_passwd_cb(context
, Ssl::AskPasswordCb
);
93 SSL_CTX_set_default_passwd_cb_userdata(context
, (void *)prompt
);
97 #if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
99 ssl_temp_rsa_cb(SSL
* ssl
, int anInt
, int keylen
)
101 static RSA
*rsa_512
= nullptr;
102 static RSA
*rsa_1024
= nullptr;
103 static BIGNUM
*e
= nullptr;
109 if (!e
|| !BN_set_word(e
, RSA_F4
)) {
110 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Failed to set exponent for key " << keylen
);
123 if (rsa_512
&& RSA_generate_key_ex(rsa_512
, 512, e
, nullptr)) {
137 rsa_1024
= RSA_new();
138 if (rsa_1024
&& RSA_generate_key_ex(rsa_1024
, 1024, e
, nullptr)) {
150 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Unexpected key length " << keylen
);
155 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Failed to generate key " << keylen
);
160 if (Debug::Enabled(83, 5))
161 PEM_write_RSAPrivateKey(debug_log
, rsa
, NULL
, NULL
, 0, NULL
, NULL
);
163 debugs(83, DBG_IMPORTANT
, "Generated ephemeral RSA key of length " << keylen
);
171 Ssl::MaybeSetupRsaCallback(Security::ContextPointer
&ctx
)
173 #if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
174 debugs(83, 9, "Setting RSA key generation callback.");
175 SSL_CTX_set_tmp_rsa_callback(ctx
.get(), ssl_temp_rsa_cb
);
179 int Ssl::asn1timeToString(ASN1_TIME
*tm
, char *buf
, int len
)
183 bio
= BIO_new(BIO_s_mem());
185 if (ASN1_TIME_print(bio
, tm
))
186 write
= BIO_read(bio
, buf
, len
-1);
193 int Ssl::matchX509CommonNames(X509
*peer_cert
, void *check_data
, int (*check_func
)(void *check_data
, ASN1_STRING
*cn_data
))
197 X509_NAME
*name
= X509_get_subject_name(peer_cert
);
199 for (int i
= X509_NAME_get_index_by_NID(name
, NID_commonName
, -1); i
>= 0; i
= X509_NAME_get_index_by_NID(name
, NID_commonName
, i
)) {
201 ASN1_STRING
*cn_data
= X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name
, i
));
203 if ( (*check_func
)(check_data
, cn_data
) == 0)
207 STACK_OF(GENERAL_NAME
) * altnames
;
208 altnames
= (STACK_OF(GENERAL_NAME
)*)X509_get_ext_d2i(peer_cert
, NID_subject_alt_name
, NULL
, NULL
);
211 int numalts
= sk_GENERAL_NAME_num(altnames
);
212 for (int i
= 0; i
< numalts
; ++i
) {
213 const GENERAL_NAME
*check
= sk_GENERAL_NAME_value(altnames
, i
);
214 if (check
->type
!= GEN_DNS
) {
217 ASN1_STRING
*cn_data
= check
->d
.dNSName
;
219 if ( (*check_func
)(check_data
, cn_data
) == 0) {
220 sk_GENERAL_NAME_pop_free(altnames
, GENERAL_NAME_free
);
224 sk_GENERAL_NAME_pop_free(altnames
, GENERAL_NAME_free
);
229 static int check_domain( void *check_data
, ASN1_STRING
*cn_data
)
232 const char *server
= (const char *)check_data
;
234 if (cn_data
->length
== 0)
235 return 1; // zero length cn, ignore
237 if (cn_data
->length
> (int)sizeof(cn
) - 1)
238 return 1; //if does not fit our buffer just ignore
240 char *s
= reinterpret_cast<char*>(cn_data
->data
);
242 for (int i
= 0; i
< cn_data
->length
; ++i
, ++d
, ++s
) {
244 return 1; // always a domain mismatch. contains 0x00
247 cn
[cn_data
->length
] = '\0';
248 debugs(83, 4, "Verifying server domain " << server
<< " to certificate name/subjectAltName " << cn
);
249 return matchDomainName(server
, (cn
[0] == '*' ? cn
+ 1 : cn
), mdnRejectSubsubDomains
);
252 bool Ssl::checkX509ServerValidity(X509
*cert
, const char *server
)
254 return matchX509CommonNames(cert
, (void *)server
, check_domain
);
257 /// \ingroup ServerProtocolSSLInternal
259 ssl_verify_cb(int ok
, X509_STORE_CTX
* ctx
)
261 // preserve original ctx->error before SSL_ calls can overwrite it
262 Security::ErrorCode error_no
= ok
? SSL_ERROR_NONE
: X509_STORE_CTX_get_error(ctx
);
264 char buffer
[256] = "";
265 SSL
*ssl
= (SSL
*)X509_STORE_CTX_get_ex_data(ctx
, SSL_get_ex_data_X509_STORE_CTX_idx());
266 SSL_CTX
*sslctx
= SSL_get_SSL_CTX(ssl
);
267 SBuf
*server
= (SBuf
*)SSL_get_ex_data(ssl
, ssl_ex_index_server
);
268 void *dont_verify_domain
= SSL_CTX_get_ex_data(sslctx
, ssl_ctx_ex_index_dont_verify_domain
);
269 ACLChecklist
*check
= (ACLChecklist
*)SSL_get_ex_data(ssl
, ssl_ex_index_cert_error_check
);
270 X509
*peeked_cert
= (X509
*)SSL_get_ex_data(ssl
, ssl_ex_index_ssl_peeked_cert
);
271 Security::CertPointer peer_cert
;
272 peer_cert
.resetAndLock(X509_STORE_CTX_get0_cert(ctx
));
274 X509_NAME_oneline(X509_get_subject_name(peer_cert
.get()), buffer
, sizeof(buffer
));
276 // detect infinite loops
277 uint32_t *validationCounter
= static_cast<uint32_t *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_validation_counter
));
278 if (!validationCounter
) {
279 validationCounter
= new uint32_t(1);
280 SSL_set_ex_data(ssl
, ssl_ex_index_ssl_validation_counter
, validationCounter
);
282 // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
283 (*validationCounter
)++;
286 if ((*validationCounter
) >= SQUID_CERT_VALIDATION_ITERATION_MAX
) {
287 ok
= 0; // or the validation loop will never stop
288 error_no
= SQUID_X509_V_ERR_INFINITE_VALIDATION
;
289 debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
290 *validationCounter
<< " iterations while checking " << buffer
);
294 debugs(83, 5, "SSL Certificate signature OK: " << buffer
);
296 // Check for domain mismatch only if the current certificate is the peer certificate.
297 if (!dont_verify_domain
&& server
&& peer_cert
.get() == X509_STORE_CTX_get_current_cert(ctx
)) {
298 if (!Ssl::checkX509ServerValidity(peer_cert
.get(), server
->c_str())) {
299 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer
<< " does not match domainname " << server
);
301 error_no
= SQUID_X509_V_ERR_DOMAIN_MISMATCH
;
306 if (ok
&& peeked_cert
) {
307 // Check whether the already peeked certificate matches the new one.
308 if (X509_cmp(peer_cert
.get(), peeked_cert
) != 0) {
309 debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer
<< " does not match peeked certificate");
311 error_no
= SQUID_X509_V_ERR_CERT_CHANGE
;
316 Security::CertPointer broken_cert
;
317 broken_cert
.resetAndLock(X509_STORE_CTX_get_current_cert(ctx
));
319 broken_cert
= peer_cert
;
321 Security::CertErrors
*errs
= static_cast<Security::CertErrors
*>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_errors
));
322 const int depth
= X509_STORE_CTX_get_error_depth(ctx
);
324 errs
= new Security::CertErrors(Security::CertError(error_no
, broken_cert
, depth
));
325 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_errors
, (void *)errs
)) {
326 debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer
);
330 } else // remember another error number
331 errs
->push_back_unique(Security::CertError(error_no
, broken_cert
, depth
));
333 if (const char *err_descr
= Ssl::GetErrorDescr(error_no
))
334 debugs(83, 5, err_descr
<< ": " << buffer
);
336 debugs(83, DBG_IMPORTANT
, "SSL unknown certificate error " << error_no
<< " in " << buffer
);
338 // Check if the certificate error can be bypassed.
339 // Infinity validation loop errors can not bypassed.
340 if (error_no
!= SQUID_X509_V_ERR_INFINITE_VALIDATION
) {
342 ACLFilledChecklist
*filledCheck
= Filled(check
);
343 assert(!filledCheck
->sslErrors
);
344 filledCheck
->sslErrors
= new Security::CertErrors(Security::CertError(error_no
, broken_cert
));
345 filledCheck
->serverCert
= peer_cert
;
346 if (check
->fastCheck().allowed()) {
347 debugs(83, 3, "bypassing SSL error " << error_no
<< " in " << buffer
);
350 debugs(83, 5, "confirming SSL error " << error_no
);
352 delete filledCheck
->sslErrors
;
353 filledCheck
->sslErrors
= NULL
;
354 filledCheck
->serverCert
.reset();
356 // If the certificate validator is used then we need to allow all errors and
357 // pass them to certificate validator for more processing
358 else if (Ssl::TheConfig
.ssl_crt_validator
) {
364 if (Ssl::TheConfig
.ssl_crt_validator
) {
365 // Check if we have stored certificates chain. Store if not.
366 if (!SSL_get_ex_data(ssl
, ssl_ex_index_ssl_cert_chain
)) {
367 STACK_OF(X509
) *certStack
= X509_STORE_CTX_get1_chain(ctx
);
368 if (certStack
&& !SSL_set_ex_data(ssl
, ssl_ex_index_ssl_cert_chain
, certStack
))
369 sk_X509_pop_free(certStack
, X509_free
);
373 if (!ok
&& !SSL_get_ex_data(ssl
, ssl_ex_index_ssl_error_detail
) ) {
375 // Find the broken certificate. It may be intermediate.
376 Security::CertPointer
broken_cert(peer_cert
); // reasonable default if search fails
377 // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
378 if (error_no
!= SQUID_X509_V_ERR_DOMAIN_MISMATCH
) {
379 if (auto *last_used_cert
= X509_STORE_CTX_get_current_cert(ctx
))
380 broken_cert
.resetAndLock(last_used_cert
);
383 std::unique_ptr
<Security::ErrorDetail::Pointer
> edp(new Security::ErrorDetail::Pointer(
384 new Security::ErrorDetail(error_no
, peer_cert
, broken_cert
)));
385 if (SSL_set_ex_data(ssl
, ssl_ex_index_ssl_error_detail
, edp
.get()))
388 debugs(83, 2, "failed to store a " << buffer
<< " error detail: " << *edp
);
395 Ssl::ConfigurePeerVerification(Security::ContextPointer
&ctx
, const Security::ParsedPortFlags flags
)
399 // assume each flag is exclusive; flags creator must check this assumption
400 if (flags
& SSL_FLAG_DONT_VERIFY_PEER
) {
401 debugs(83, DBG_IMPORTANT
, "SECURITY WARNING: Peer certificates are not verified for validity!");
402 debugs(83, DBG_IMPORTANT
, "UPGRADE NOTICE: The DONT_VERIFY_PEER flag is deprecated. Remove the clientca= option to disable client certificates.");
403 mode
= SSL_VERIFY_NONE
;
405 else if (flags
& SSL_FLAG_DELAYED_AUTH
) {
406 debugs(83, DBG_PARSE_NOTE(3), "not requesting client certificates until ACL processing requires one");
407 mode
= SSL_VERIFY_NONE
;
409 else if (flags
& SSL_FLAG_CONDITIONAL_AUTH
) {
410 debugs(83, DBG_PARSE_NOTE(3), "will request the client certificate but ignore its absense");
411 mode
= SSL_VERIFY_PEER
;
414 debugs(83, DBG_PARSE_NOTE(3), "Requiring client certificates.");
415 mode
= SSL_VERIFY_PEER
|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
;
418 SSL_CTX_set_verify(ctx
.get(), mode
, (mode
!= SSL_VERIFY_NONE
) ? ssl_verify_cb
: nullptr);
422 Ssl::DisablePeerVerification(Security::ContextPointer
&ctx
)
424 debugs(83, DBG_PARSE_NOTE(3), "Not requiring any client certificates");
425 SSL_CTX_set_verify(ctx
.get(),SSL_VERIFY_NONE
,nullptr);
428 // "dup" function for SSL_get_ex_new_index("cert_err_check")
429 #if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
431 ssl_dupAclChecklist(CRYPTO_EX_DATA
*, const CRYPTO_EX_DATA
*, void *,
435 ssl_dupAclChecklist(CRYPTO_EX_DATA
*, CRYPTO_EX_DATA
*, void *,
439 // We do not support duplication of ACLCheckLists.
440 // If duplication is needed, we can count copies with cbdata.
445 // "free" function for SSL_get_ex_new_index("cert_err_check")
447 ssl_freeAclChecklist(void *, void *ptr
, CRYPTO_EX_DATA
*,
450 delete static_cast<ACLChecklist
*>(ptr
); // may be NULL
453 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
455 ssl_free_ErrorDetail(void *, void *ptr
, CRYPTO_EX_DATA
*,
458 const auto errDetail
= static_cast<Security::ErrorDetail::Pointer
*>(ptr
);
463 ssl_free_SslErrors(void *, void *ptr
, CRYPTO_EX_DATA
*,
466 Security::CertErrors
*errs
= static_cast <Security::CertErrors
*>(ptr
);
470 // "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
472 ssl_free_int(void *, void *ptr
, CRYPTO_EX_DATA
*,
475 uint32_t *counter
= static_cast <uint32_t *>(ptr
);
479 /// \ingroup ServerProtocolSSLInternal
480 /// Callback handler function to release STACK_OF(X509) "ex" data stored
481 /// in an SSL object.
483 ssl_free_CertChain(void *, void *ptr
, CRYPTO_EX_DATA
*,
486 STACK_OF(X509
) *certsChain
= static_cast <STACK_OF(X509
) *>(ptr
);
487 sk_X509_pop_free(certsChain
,X509_free
);
490 // "free" function for X509 certificates
492 ssl_free_X509(void *, void *ptr
, CRYPTO_EX_DATA
*,
495 X509
*cert
= static_cast <X509
*>(ptr
);
499 // "free" function for SBuf
501 ssl_free_SBuf(void *, void *ptr
, CRYPTO_EX_DATA
*,
504 SBuf
*buf
= static_cast <SBuf
*>(ptr
);
509 Ssl::Initialize(void)
511 static bool initialized
= false;
516 SQUID_OPENSSL_init_ssl();
518 #if !defined(OPENSSL_NO_ENGINE)
519 if (::Config
.SSL
.ssl_engine
) {
520 ENGINE_load_builtin_engines();
522 if (!(e
= ENGINE_by_id(::Config
.SSL
.ssl_engine
)))
523 fatalf("Unable to find SSL engine '%s'\n", ::Config
.SSL
.ssl_engine
);
525 if (!ENGINE_set_default(e
, ENGINE_METHOD_ALL
)) {
526 const auto ssl_error
= ERR_get_error();
527 fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error
));
531 if (::Config
.SSL
.ssl_engine
)
532 fatalf("Your OpenSSL has no SSL engine support\n");
535 const char *defName
= ::Config
.SSL
.certSignHash
? ::Config
.SSL
.certSignHash
: SQUID_SSL_SIGN_HASH_IF_NONE
;
536 Ssl::DefaultSignHash
= EVP_get_digestbyname(defName
);
537 if (!Ssl::DefaultSignHash
)
538 fatalf("Sign hash '%s' is not supported\n", defName
);
540 ssl_ex_index_server
= SSL_get_ex_new_index(0, (void *) "server", NULL
, NULL
, ssl_free_SBuf
);
541 ssl_ctx_ex_index_dont_verify_domain
= SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL
, NULL
, NULL
);
542 ssl_ex_index_cert_error_check
= SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL
, &ssl_dupAclChecklist
, &ssl_freeAclChecklist
);
543 ssl_ex_index_ssl_error_detail
= SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL
, NULL
, &ssl_free_ErrorDetail
);
544 ssl_ex_index_ssl_peeked_cert
= SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL
, NULL
, &ssl_free_X509
);
545 ssl_ex_index_ssl_errors
= SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL
, NULL
, &ssl_free_SslErrors
);
546 ssl_ex_index_ssl_cert_chain
= SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL
, NULL
, &ssl_free_CertChain
);
547 ssl_ex_index_ssl_validation_counter
= SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL
, NULL
, &ssl_free_int
);
548 ssl_ex_index_ssl_untrusted_chain
= SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL
, NULL
, &ssl_free_CertChain
);
552 Ssl::InitServerContext(Security::ContextPointer
&ctx
, AnyP::PortCfg
&port
)
561 Ssl::InitClientContext(Security::ContextPointer
&ctx
, Security::PeerOptions
&peer
, Security::ParsedPortFlags fl
)
566 if (!peer
.sslCipher
.isEmpty()) {
567 debugs(83, 5, "Using chiper suite " << peer
.sslCipher
<< ".");
569 const char *cipher
= peer
.sslCipher
.c_str();
570 if (!SSL_CTX_set_cipher_list(ctx
.get(), cipher
)) {
571 const auto ssl_error
= ERR_get_error();
572 fatalf("Failed to set SSL cipher suite '%s': %s\n",
573 cipher
, Security::ErrorString(ssl_error
));
577 if (!peer
.certs
.empty()) {
578 // TODO: support loading multiple cert/key pairs
579 auto &keys
= peer
.certs
.front();
580 if (!keys
.certFile
.isEmpty()) {
581 debugs(83, DBG_IMPORTANT
, "Using certificate in " << keys
.certFile
);
583 const char *certfile
= keys
.certFile
.c_str();
584 if (!SSL_CTX_use_certificate_chain_file(ctx
.get(), certfile
)) {
585 const auto ssl_error
= ERR_get_error();
586 fatalf("Failed to acquire SSL certificate '%s': %s\n",
587 certfile
, Security::ErrorString(ssl_error
));
590 debugs(83, DBG_IMPORTANT
, "Using private key in " << keys
.privateKeyFile
);
591 const char *keyfile
= keys
.privateKeyFile
.c_str();
592 ssl_ask_password(ctx
.get(), keyfile
);
594 if (!SSL_CTX_use_PrivateKey_file(ctx
.get(), keyfile
, SSL_FILETYPE_PEM
)) {
595 const auto ssl_error
= ERR_get_error();
596 fatalf("Failed to acquire SSL private key '%s': %s\n",
597 keyfile
, Security::ErrorString(ssl_error
));
600 debugs(83, 5, "Comparing private and public SSL keys.");
602 if (!SSL_CTX_check_private_key(ctx
.get())) {
603 const auto ssl_error
= ERR_get_error();
604 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
605 certfile
, keyfile
, Security::ErrorString(ssl_error
));
610 MaybeSetupRsaCallback(ctx
);
612 Ssl::ConfigurePeerVerification(ctx
, fl
);
617 /// \ingroup ServerProtocolSSLInternal
619 ssl_get_attribute(X509_NAME
* name
, const char *attribute_name
)
621 static char buffer
[1024];
624 if (strcmp(attribute_name
, "DN") == 0) {
625 X509_NAME_oneline(name
, buffer
, sizeof(buffer
));
627 int nid
= OBJ_txt2nid(const_cast<char *>(attribute_name
));
629 debugs(83, DBG_IMPORTANT
, "WARNING: Unknown SSL attribute name '" << attribute_name
<< "'");
632 X509_NAME_get_text_by_NID(name
, nid
, buffer
, sizeof(buffer
));
635 return *buffer
? buffer
: nullptr;
638 /// \ingroup ServerProtocolSSLInternal
640 Ssl::GetX509UserAttribute(X509
* cert
, const char *attribute_name
)
648 name
= X509_get_subject_name(cert
);
650 ret
= ssl_get_attribute(name
, attribute_name
);
656 Ssl::GetX509Fingerprint(X509
* cert
, const char *)
658 static char buf
[1024];
663 unsigned char md
[EVP_MAX_MD_SIZE
];
664 if (!X509_digest(cert
, EVP_sha1(), md
, &n
))
667 assert(3 * n
+ 1 < sizeof(buf
));
670 for (unsigned int i
=0; i
< n
; ++i
, s
+= 3) {
671 const char term
= (i
+ 1 < n
) ? ':' : '\0';
672 snprintf(s
, 4, "%02X%c", md
[i
], term
);
679 Ssl::GetX509PEM(X509
* cert
)
683 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
684 PEM_write_bio_X509(bio
.get(), cert
);
687 const auto len
= BIO_get_mem_data(bio
.get(), &ptr
);
688 return SBuf(ptr
, len
);
691 /// \ingroup ServerProtocolSSLInternal
693 Ssl::GetX509CAAttribute(X509
* cert
, const char *attribute_name
)
702 name
= X509_get_issuer_name(cert
);
704 ret
= ssl_get_attribute(name
, attribute_name
);
709 const char *sslGetUserAttribute(SSL
*ssl
, const char *attribute_name
)
714 X509
*cert
= SSL_get_peer_certificate(ssl
);
716 const char *attr
= Ssl::GetX509UserAttribute(cert
, attribute_name
);
722 const char *sslGetCAAttribute(SSL
*ssl
, const char *attribute_name
)
727 X509
*cert
= SSL_get_peer_certificate(ssl
);
729 const char *attr
= Ssl::GetX509CAAttribute(cert
, attribute_name
);
736 sslGetUserEmail(SSL
* ssl
)
738 return sslGetUserAttribute(ssl
, "emailAddress");
742 sslGetUserCertificatePEM(SSL
*ssl
)
746 if (const auto cert
= SSL_get_peer_certificate(ssl
))
747 return Ssl::GetX509PEM(cert
);
753 sslGetUserCertificateChainPEM(SSL
*ssl
)
757 auto chain
= SSL_get_peer_cert_chain(ssl
);
760 return sslGetUserCertificatePEM(ssl
);
762 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
764 for (int i
= 0; i
< sk_X509_num(chain
); ++i
) {
765 X509
*cert
= sk_X509_value(chain
, i
);
766 PEM_write_bio_X509(bio
.get(), cert
);
770 const auto len
= BIO_get_mem_data(bio
.get(), &ptr
);
771 return SBuf(ptr
, len
);
774 /// Create SSL context and apply ssl certificate and private key to it.
775 Security::ContextPointer
776 Ssl::createSSLContext(Security::CertPointer
& x509
, Security::PrivateKeyPointer
& pkey
, Security::ServerOptions
&options
)
778 Security::ContextPointer
ctx(options
.createBlankContext());
780 if (!SSL_CTX_use_certificate(ctx
.get(), x509
.get()))
781 return Security::ContextPointer();
783 if (!SSL_CTX_use_PrivateKey(ctx
.get(), pkey
.get()))
784 return Security::ContextPointer();
786 if (!options
.updateContextConfig(ctx
))
787 return Security::ContextPointer();
792 Security::ContextPointer
793 Ssl::GenerateSslContextUsingPkeyAndCertFromMemory(const char * data
, Security::ServerOptions
&options
, bool trusted
)
795 Security::CertPointer cert
;
796 Security::PrivateKeyPointer pkey
;
797 if (!readCertAndPrivateKeyFromMemory(cert
, pkey
, data
) || !cert
|| !pkey
)
798 return Security::ContextPointer();
800 Security::ContextPointer
ctx(createSSLContext(cert
, pkey
, options
));
802 Ssl::chainCertificatesToSSLContext(ctx
, options
);
806 Security::ContextPointer
807 Ssl::GenerateSslContext(CertificateProperties
const &properties
, Security::ServerOptions
&options
, bool trusted
)
809 Security::CertPointer cert
;
810 Security::PrivateKeyPointer pkey
;
811 if (!generateSslCertificate(cert
, pkey
, properties
) || !cert
|| !pkey
)
812 return Security::ContextPointer();
814 Security::ContextPointer
ctx(createSSLContext(cert
, pkey
, options
));
816 Ssl::chainCertificatesToSSLContext(ctx
, options
);
821 Ssl::chainCertificatesToSSLContext(Security::ContextPointer
&ctx
, Security::ServerOptions
&options
)
824 // Add signing certificate to the certificates chain
825 X509
*signingCert
= options
.signingCa
.cert
.get();
826 if (SSL_CTX_add_extra_chain_cert(ctx
.get(), signingCert
)) {
827 // increase the certificate lock
828 X509_up_ref(signingCert
);
830 const auto ssl_error
= ERR_get_error();
831 debugs(33, DBG_IMPORTANT
, "WARNING: can not add signing certificate to SSL context chain: " << Security::ErrorString(ssl_error
));
834 for (auto cert
: options
.signingCa
.chain
) {
835 if (SSL_CTX_add_extra_chain_cert(ctx
.get(), cert
.get())) {
836 // increase the certificate lock
837 X509_up_ref(cert
.get());
839 const auto error
= ERR_get_error();
840 debugs(83, DBG_IMPORTANT
, "WARNING: can not add certificate to SSL dynamic context chain: " << Security::ErrorString(error
));
846 Ssl::configureUnconfiguredSslContext(Security::ContextPointer
&ctx
, Ssl::CertSignAlgorithm signAlgorithm
,AnyP::PortCfg
&port
)
848 if (ctx
&& signAlgorithm
== Ssl::algSignTrusted
)
849 Ssl::chainCertificatesToSSLContext(ctx
, port
.secure
);
853 Ssl::configureSSL(SSL
*ssl
, CertificateProperties
const &properties
, AnyP::PortCfg
&port
)
855 Security::CertPointer cert
;
856 Security::PrivateKeyPointer pkey
;
857 if (!generateSslCertificate(cert
, pkey
, properties
))
866 if (!SSL_use_certificate(ssl
, cert
.get()))
869 if (!SSL_use_PrivateKey(ssl
, pkey
.get()))
876 Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL
*ssl
, const char *data
, AnyP::PortCfg
&port
)
878 Security::CertPointer cert
;
879 Security::PrivateKeyPointer pkey
;
880 if (!readCertAndPrivateKeyFromMemory(cert
, pkey
, data
))
886 if (!SSL_use_certificate(ssl
, cert
.get()))
889 if (!SSL_use_PrivateKey(ssl
, pkey
.get()))
896 Ssl::verifySslCertificate(const Security::ContextPointer
&ctx
, CertificateProperties
const &properties
)
898 #if HAVE_SSL_CTX_GET0_CERTIFICATE
899 X509
* cert
= SSL_CTX_get0_certificate(ctx
.get());
900 #elif SQUID_USE_SSLGETCERTIFICATE_HACK
901 // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
902 // Try to retrieve certificate directly from Security::ContextPointer object
903 X509
***pCert
= (X509
***)ctx
->cert
;
904 X509
* cert
= pCert
&& *pCert
? **pCert
: NULL
;
905 #elif SQUID_SSLGETCERTIFICATE_BUGGY
909 // Temporary ssl for getting X509 certificate from SSL_CTX.
910 Security::SessionPointer
ssl(Security::NewSessionObject(ctx
));
911 X509
* cert
= SSL_get_certificate(ssl
.get());
915 const auto time_notBefore
= X509_getm_notBefore(cert
);
916 const auto time_notAfter
= X509_getm_notAfter(cert
);
917 return (X509_cmp_current_time(time_notBefore
) < 0 && X509_cmp_current_time(time_notAfter
) > 0);
921 Ssl::setClientSNI(SSL
*ssl
, const char *fqdn
)
923 const Ip::Address
test(fqdn
);
924 if (!test
.isAnyAddr())
925 return; // raw IP is inappropriate for SNI
927 //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
928 // if the TLS servername extension (SNI) is enabled in openssl library.
929 #if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
930 if (!SSL_set_tlsext_host_name(ssl
, fqdn
)) {
931 const auto ssl_error
= ERR_get_error();
932 debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
933 Security::ErrorString(ssl_error
) << "\n");
936 debugs(83, 7, "no support for TLS servername extension (SNI)");
941 hasAuthorityInfoAccessCaIssuers(X509
*cert
)
943 AUTHORITY_INFO_ACCESS
*info
;
946 info
= static_cast<AUTHORITY_INFO_ACCESS
*>(X509_get_ext_d2i(cert
, NID_info_access
, NULL
, NULL
));
950 static char uri
[MAX_URL
];
953 for (int i
= 0; i
< sk_ACCESS_DESCRIPTION_num(info
); i
++) {
954 ACCESS_DESCRIPTION
*ad
= sk_ACCESS_DESCRIPTION_value(info
, i
);
955 if (OBJ_obj2nid(ad
->method
) == NID_ad_ca_issuers
) {
956 if (ad
->location
->type
== GEN_URI
) {
958 reinterpret_cast<const char *>(
959 ASN1_STRING_get0_data(ad
->location
->d
.uniformResourceIdentifier
)
966 AUTHORITY_INFO_ACCESS_free(info
);
967 return uri
[0] != '\0' ? uri
: nullptr;
971 Ssl::loadCerts(const char *certsFile
, Ssl::CertsIndexedList
&list
)
973 BIO
*in
= BIO_new_file(certsFile
, "r");
975 debugs(83, DBG_IMPORTANT
, "Failed to open '" << certsFile
<< "' to load certificates");
980 while((aCert
= PEM_read_bio_X509(in
, NULL
, NULL
, NULL
))) {
981 static char buffer
[2048];
982 X509_NAME_oneline(X509_get_subject_name(aCert
), buffer
, sizeof(buffer
));
983 list
.insert(std::pair
<SBuf
, X509
*>(SBuf(buffer
), aCert
));
985 debugs(83, 4, "Loaded " << list
.size() << " certificates from file: '" << certsFile
<< "'");
990 /// quickly find the issuer certificate of a certificate cert in the
991 /// Ssl::CertsIndexedList list
993 findCertIssuerFast(Ssl::CertsIndexedList
&list
, X509
*cert
)
995 static char buffer
[2048];
997 if (X509_NAME
*issuerName
= X509_get_issuer_name(cert
))
998 X509_NAME_oneline(issuerName
, buffer
, sizeof(buffer
));
1002 const auto ret
= list
.equal_range(SBuf(buffer
));
1003 for (Ssl::CertsIndexedList::iterator it
= ret
.first
; it
!= ret
.second
; ++it
) {
1004 X509
*issuer
= it
->second
;
1005 if (X509_check_issued(issuer
, cert
) == X509_V_OK
) {
1012 /// slowly find the issuer certificate of a given cert using linear search
1014 findCertIssuer(Security::CertList
const &list
, X509
*cert
)
1016 for (Security::CertList::const_iterator it
= list
.begin(); it
!= list
.end(); ++it
) {
1017 if (X509_check_issued(it
->get(), cert
) == X509_V_OK
)
1023 /// \return true if the cert issuer exist in the certificates stored in connContext
1025 issuerExistInCaDb(X509
*cert
, const Security::ContextPointer
&connContext
)
1030 X509_STORE_CTX
*storeCtx
= X509_STORE_CTX_new();
1032 debugs(83, DBG_IMPORTANT
, "Failed to allocate STORE_CTX object");
1036 bool gotIssuer
= false;
1037 X509_STORE
*store
= SSL_CTX_get_cert_store(connContext
.get());
1038 if (X509_STORE_CTX_init(storeCtx
, store
, nullptr, nullptr)) {
1039 X509
*issuer
= nullptr;
1040 gotIssuer
= (X509_STORE_CTX_get1_issuer(&issuer
, storeCtx
, cert
) > 0);
1044 const auto ssl_error
= ERR_get_error();
1045 debugs(83, DBG_IMPORTANT
, "Failed to initialize STORE_CTX object: " << Security::ErrorString(ssl_error
));
1047 X509_STORE_CTX_free(storeCtx
);
1053 Ssl::uriOfIssuerIfMissing(X509
*cert
, Security::CertList
const &serverCertificates
, const Security::ContextPointer
&context
)
1055 if (!cert
|| !serverCertificates
.size())
1058 if (!findCertIssuer(serverCertificates
, cert
)) {
1059 //if issuer is missing
1060 if (const char *issuerUri
= hasAuthorityInfoAccessCaIssuers(cert
)) {
1061 // There is a URI where we can download a certificate.
1062 if (!findCertIssuerFast(SquidUntrustedCerts
, cert
) &&
1063 !issuerExistInCaDb(cert
, context
)) {
1064 // and issuer not found in local databases containing
1065 // untrusted certificates and trusted CA certificates
1074 Ssl::missingChainCertificatesUrls(std::queue
<SBuf
> &URIs
, Security::CertList
const &serverCertificates
, const Security::ContextPointer
&context
)
1076 if (!serverCertificates
.size())
1079 for (const auto &i
: serverCertificates
) {
1080 if (const char *issuerUri
= uriOfIssuerIfMissing(i
.get(), serverCertificates
, context
))
1081 URIs
.push(SBuf(issuerUri
));
1086 Ssl::SSL_add_untrusted_cert(SSL
*ssl
, X509
*cert
)
1088 STACK_OF(X509
) *untrustedStack
= static_cast <STACK_OF(X509
) *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_untrusted_chain
));
1089 if (!untrustedStack
) {
1090 untrustedStack
= sk_X509_new_null();
1091 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_untrusted_chain
, untrustedStack
)) {
1092 sk_X509_pop_free(untrustedStack
, X509_free
);
1093 throw TextException("Failed to attach untrusted certificates chain", Here());
1096 sk_X509_push(untrustedStack
, cert
);
1099 /// Search for the issuer certificate of cert in sk list.
1101 sk_x509_findIssuer(STACK_OF(X509
) *sk
, X509
*cert
)
1106 const int skItemsNum
= sk_X509_num(sk
);
1107 for (int i
= 0; i
< skItemsNum
; ++i
) {
1108 X509
*issuer
= sk_X509_value(sk
, i
);
1109 if (X509_check_issued(issuer
, cert
) == X509_V_OK
)
1115 /// add missing issuer certificates to untrustedCerts
1117 completeIssuers(X509_STORE_CTX
*ctx
, STACK_OF(X509
) *untrustedCerts
)
1119 debugs(83, 2, "completing " << sk_X509_num(untrustedCerts
) << " OpenSSL untrusted certs using " << SquidUntrustedCerts
.size() << " configured untrusted certificates");
1121 const X509_VERIFY_PARAM
*param
= X509_STORE_CTX_get0_param(ctx
);
1122 int depth
= X509_VERIFY_PARAM_get_depth(param
);
1123 X509
*current
= X509_STORE_CTX_get0_cert(ctx
);
1125 for (i
= 0; current
&& (i
< depth
); ++i
) {
1126 if (X509_check_issued(current
, current
) == X509_V_OK
) {
1127 // either ctx->cert is itself self-signed or untrustedCerts
1128 // already contain the self-signed current certificate
1132 // untrustedCerts is short, not worth indexing
1133 X509
*issuer
= sk_x509_findIssuer(untrustedCerts
, current
);
1135 if ((issuer
= findCertIssuerFast(SquidUntrustedCerts
, current
)))
1136 sk_X509_push(untrustedCerts
, issuer
);
1142 debugs(83, 2, "exceeded the maximum certificate chain length: " << depth
);
1145 /// OpenSSL certificate validation callback.
1147 untrustedToStoreCtx_cb(X509_STORE_CTX
*ctx
,void *data
)
1149 debugs(83, 4, "Try to use pre-downloaded intermediate certificates");
1151 SSL
*ssl
= static_cast<SSL
*>(X509_STORE_CTX_get_ex_data(ctx
, SSL_get_ex_data_X509_STORE_CTX_idx()));
1152 STACK_OF(X509
) *sslUntrustedStack
= static_cast <STACK_OF(X509
) *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_untrusted_chain
));
1154 // OpenSSL already maintains ctx->untrusted but we cannot modify
1155 // internal OpenSSL list directly. We have to give OpenSSL our own
1156 // list, but it must include certificates on the OpenSSL ctx->untrusted
1157 STACK_OF(X509
) *oldUntrusted
= X509_STORE_CTX_get0_untrusted(ctx
);
1158 STACK_OF(X509
) *sk
= sk_X509_dup(oldUntrusted
); // oldUntrusted is always not NULL
1160 for (int i
= 0; i
< sk_X509_num(sslUntrustedStack
); ++i
) {
1161 X509
*cert
= sk_X509_value(sslUntrustedStack
, i
);
1162 sk_X509_push(sk
, cert
);
1165 // If the local untrusted certificates internal database is used
1166 // run completeIssuers to add missing certificates if possible.
1167 if (SquidUntrustedCerts
.size() > 0)
1168 completeIssuers(ctx
, sk
);
1170 X509_STORE_CTX_set0_untrusted(ctx
, sk
); // No locking/unlocking, just sets ctx->untrusted
1171 int ret
= X509_verify_cert(ctx
);
1172 X509_STORE_CTX_set0_untrusted(ctx
, oldUntrusted
); // Set back the old untrusted list
1173 sk_X509_free(sk
); // Release sk list
1178 Ssl::useSquidUntrusted(SSL_CTX
*sslContext
)
1180 SSL_CTX_set_cert_verify_callback(sslContext
, untrustedToStoreCtx_cb
, NULL
);
1184 Ssl::loadSquidUntrusted(const char *path
)
1186 return Ssl::loadCerts(path
, SquidUntrustedCerts
);
1190 Ssl::unloadSquidUntrusted()
1192 if (SquidUntrustedCerts
.size()) {
1193 for (Ssl::CertsIndexedList::iterator it
= SquidUntrustedCerts
.begin(); it
!= SquidUntrustedCerts
.end(); ++it
) {
1194 X509_free(it
->second
);
1196 SquidUntrustedCerts
.clear();
1200 bool Ssl::generateUntrustedCert(Security::CertPointer
&untrustedCert
, Security::PrivateKeyPointer
&untrustedPkey
, Security::CertPointer
const &cert
, Security::PrivateKeyPointer
const & pkey
)
1202 // Generate the self-signed certificate, using a hard-coded subject prefix
1203 Ssl::CertificateProperties certProperties
;
1204 if (const char *cn
= CommonHostName(cert
.get())) {
1205 certProperties
.commonName
= "Not trusted by \"";
1206 certProperties
.commonName
+= cn
;
1207 certProperties
.commonName
+= "\"";
1208 } else if (const char *org
= getOrganization(cert
.get())) {
1209 certProperties
.commonName
= "Not trusted by \"";
1210 certProperties
.commonName
+= org
;
1211 certProperties
.commonName
+= "\"";
1213 certProperties
.commonName
= "Not trusted";
1214 certProperties
.setCommonName
= true;
1215 // O, OU, and other CA subject fields will be mimicked
1216 // Expiration date and other common properties will be mimicked
1217 certProperties
.signAlgorithm
= Ssl::algSignSelf
;
1218 certProperties
.signWithPkey
.resetAndLock(pkey
.get());
1219 certProperties
.mimicCert
.resetAndLock(cert
.get());
1220 return Ssl::generateSslCertificate(untrustedCert
, untrustedPkey
, certProperties
);
1223 void Ssl::InRamCertificateDbKey(const Ssl::CertificateProperties
&certProperties
, SBuf
&key
)
1225 bool origSignatureAsKey
= false;
1226 if (certProperties
.mimicCert
) {
1227 if (auto *sig
= Ssl::X509_get_signature(certProperties
.mimicCert
)) {
1228 origSignatureAsKey
= true;
1229 key
.append((const char *)sig
->data
, sig
->length
);
1233 if (!origSignatureAsKey
|| certProperties
.setCommonName
) {
1234 // Use common name instead
1235 key
.append(certProperties
.commonName
.c_str());
1237 key
.append(certProperties
.setCommonName
? '1' : '0');
1238 key
.append(certProperties
.setValidAfter
? '1' : '0');
1239 key
.append(certProperties
.setValidBefore
? '1' : '0');
1240 key
.append(certProperties
.signAlgorithm
!= Ssl:: algSignEnd
? certSignAlgorithm(certProperties
.signAlgorithm
) : "-");
1241 key
.append(certProperties
.signHash
? EVP_MD_name(certProperties
.signHash
) : "-");
1243 if (certProperties
.mimicCert
) {
1244 Ssl::BIO_Pointer
bio(BIO_new_SBuf(&key
));
1245 ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509
), bio
.get(), (ASN1_VALUE
*)certProperties
.mimicCert
.get());
1250 bio_sbuf_create(BIO
* bio
)
1252 BIO_set_init(bio
, 0);
1253 BIO_set_data(bio
, NULL
);
1258 bio_sbuf_destroy(BIO
* bio
)
1266 bio_sbuf_write(BIO
* bio
, const char* data
, int len
)
1268 SBuf
*buf
= static_cast<SBuf
*>(BIO_get_data(bio
));
1269 // TODO: Convert exceptions into BIO errors
1270 buf
->append(data
, len
);
1275 bio_sbuf_puts(BIO
* bio
, const char* data
)
1277 // TODO: use bio_sbuf_write() instead
1278 SBuf
*buf
= static_cast<SBuf
*>(BIO_get_data(bio
));
1279 size_t oldLen
= buf
->length();
1281 return buf
->length() - oldLen
;
1285 bio_sbuf_ctrl(BIO
* bio
, int cmd
, long num
, void* ptr
) {
1286 SBuf
*buf
= static_cast<SBuf
*>(BIO_get_data(bio
));
1288 case BIO_CTRL_RESET
:
1289 // TODO: Convert exceptions into BIO errors
1292 case BIO_CTRL_FLUSH
:
1299 BIO
*Ssl::BIO_new_SBuf(SBuf
*buf
)
1301 #if HAVE_LIBCRYPTO_BIO_METH_NEW
1302 static BIO_METHOD
*BioSBufMethods
= nullptr;
1303 if (!BioSBufMethods
) {
1304 BioSBufMethods
= BIO_meth_new(BIO_TYPE_MEM
, "Squid-SBuf");
1305 BIO_meth_set_write(BioSBufMethods
, bio_sbuf_write
);
1306 BIO_meth_set_read(BioSBufMethods
, nullptr);
1307 BIO_meth_set_puts(BioSBufMethods
, bio_sbuf_puts
);
1308 BIO_meth_set_gets(BioSBufMethods
, nullptr);
1309 BIO_meth_set_ctrl(BioSBufMethods
, bio_sbuf_ctrl
);
1310 BIO_meth_set_create(BioSBufMethods
, bio_sbuf_create
);
1311 BIO_meth_set_destroy(BioSBufMethods
, bio_sbuf_destroy
);
1314 static BIO_METHOD
*BioSBufMethods
= new BIO_METHOD({
1327 BIO
*bio
= BIO_new(BioSBufMethods
);
1329 BIO_set_data(bio
, buf
);
1330 BIO_set_init(bio
, 1);
1334 #endif /* USE_OPENSSL */