2 * Copyright (C) 1996-2016 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"
24 #include "ipc/MemMap.h"
25 #include "SquidConfig.h"
26 #include "SquidTime.h"
28 #include "ssl/Config.h"
29 #include "ssl/ErrorDetail.h"
30 #include "ssl/gadgets.h"
31 #include "ssl/support.h"
36 // TODO: Move ssl_ex_index_* global variables from global.cc here.
37 int ssl_ex_index_ssl_untrusted_chain
= -1;
39 Ipc::MemMap
*Ssl::SessionCache
= NULL
;
40 const char *Ssl::SessionCacheName
= "ssl_session_cache";
42 static Ssl::CertsIndexedList SquidUntrustedCerts
;
44 const EVP_MD
*Ssl::DefaultSignHash
= NULL
;
46 const char *Ssl::BumpModeStr
[] = {
60 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
61 \ingroup ServerProtocolSSLAPI
64 /// \ingroup ServerProtocolSSLInternal
66 ssl_ask_password_cb(char *buf
, int size
, int rwflag
, void *userdata
)
72 snprintf(cmdline
, sizeof(cmdline
), "\"%s\" \"%s\"", Config
.Program
.ssl_password
, (const char *)userdata
);
73 in
= popen(cmdline
, "r");
75 if (fgets(buf
, size
, in
))
79 while (len
> 0 && (buf
[len
- 1] == '\n' || buf
[len
- 1] == '\r'))
89 /// \ingroup ServerProtocolSSLInternal
91 ssl_ask_password(SSL_CTX
* context
, const char * prompt
)
93 if (Config
.Program
.ssl_password
) {
94 SSL_CTX_set_default_passwd_cb(context
, ssl_ask_password_cb
);
95 SSL_CTX_set_default_passwd_cb_userdata(context
, (void *)prompt
);
99 /// \ingroup ServerProtocolSSLInternal
101 ssl_temp_rsa_cb(SSL
* ssl
, int anInt
, int keylen
)
103 static RSA
*rsa_512
= NULL
;
104 static RSA
*rsa_1024
= NULL
;
113 rsa_512
= RSA_generate_key(512, RSA_F4
, NULL
, NULL
);
123 rsa_1024
= RSA_generate_key(1024, RSA_F4
, NULL
, NULL
);
131 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Unexpected key length " << keylen
);
136 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Failed to generate key " << keylen
);
141 if (Debug::Enabled(83, 5))
142 PEM_write_RSAPrivateKey(debug_log
, rsa
, NULL
, NULL
, 0, NULL
, NULL
);
144 debugs(83, DBG_IMPORTANT
, "Generated ephemeral RSA key of length " << keylen
);
150 int Ssl::asn1timeToString(ASN1_TIME
*tm
, char *buf
, int len
)
154 bio
= BIO_new(BIO_s_mem());
156 if (ASN1_TIME_print(bio
, tm
))
157 write
= BIO_read(bio
, buf
, len
-1);
164 int Ssl::matchX509CommonNames(X509
*peer_cert
, void *check_data
, int (*check_func
)(void *check_data
, ASN1_STRING
*cn_data
))
168 X509_NAME
*name
= X509_get_subject_name(peer_cert
);
170 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
)) {
172 ASN1_STRING
*cn_data
= X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name
, i
));
174 if ( (*check_func
)(check_data
, cn_data
) == 0)
178 STACK_OF(GENERAL_NAME
) * altnames
;
179 altnames
= (STACK_OF(GENERAL_NAME
)*)X509_get_ext_d2i(peer_cert
, NID_subject_alt_name
, NULL
, NULL
);
182 int numalts
= sk_GENERAL_NAME_num(altnames
);
183 for (int i
= 0; i
< numalts
; ++i
) {
184 const GENERAL_NAME
*check
= sk_GENERAL_NAME_value(altnames
, i
);
185 if (check
->type
!= GEN_DNS
) {
188 ASN1_STRING
*cn_data
= check
->d
.dNSName
;
190 if ( (*check_func
)(check_data
, cn_data
) == 0) {
191 sk_GENERAL_NAME_pop_free(altnames
, GENERAL_NAME_free
);
195 sk_GENERAL_NAME_pop_free(altnames
, GENERAL_NAME_free
);
200 static int check_domain( void *check_data
, ASN1_STRING
*cn_data
)
203 const char *server
= (const char *)check_data
;
205 if (cn_data
->length
== 0)
206 return 1; // zero length cn, ignore
208 if (cn_data
->length
> (int)sizeof(cn
) - 1)
209 return 1; //if does not fit our buffer just ignore
211 char *s
= reinterpret_cast<char*>(cn_data
->data
);
213 for (int i
= 0; i
< cn_data
->length
; ++i
, ++d
, ++s
) {
215 return 1; // always a domain mismatch. contains 0x00
218 cn
[cn_data
->length
] = '\0';
219 debugs(83, 4, "Verifying server domain " << server
<< " to certificate name/subjectAltName " << cn
);
220 return matchDomainName(server
, (cn
[0] == '*' ? cn
+ 1 : cn
), mdnRejectSubsubDomains
);
223 bool Ssl::checkX509ServerValidity(X509
*cert
, const char *server
)
225 return matchX509CommonNames(cert
, (void *)server
, check_domain
);
228 /// \ingroup ServerProtocolSSLInternal
230 ssl_verify_cb(int ok
, X509_STORE_CTX
* ctx
)
232 // preserve original ctx->error before SSL_ calls can overwrite it
233 Ssl::ssl_error_t error_no
= ok
? SSL_ERROR_NONE
: ctx
->error
;
235 char buffer
[256] = "";
236 SSL
*ssl
= (SSL
*)X509_STORE_CTX_get_ex_data(ctx
, SSL_get_ex_data_X509_STORE_CTX_idx());
237 Security::ContextPtr sslctx
= SSL_get_SSL_CTX(ssl
);
238 SBuf
*server
= (SBuf
*)SSL_get_ex_data(ssl
, ssl_ex_index_server
);
239 void *dont_verify_domain
= SSL_CTX_get_ex_data(sslctx
, ssl_ctx_ex_index_dont_verify_domain
);
240 ACLChecklist
*check
= (ACLChecklist
*)SSL_get_ex_data(ssl
, ssl_ex_index_cert_error_check
);
241 X509
*peeked_cert
= (X509
*)SSL_get_ex_data(ssl
, ssl_ex_index_ssl_peeked_cert
);
242 X509
*peer_cert
= ctx
->cert
;
244 X509_NAME_oneline(X509_get_subject_name(peer_cert
), buffer
,
247 // detect infinite loops
248 uint32_t *validationCounter
= static_cast<uint32_t *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_validation_counter
));
249 if (!validationCounter
) {
250 validationCounter
= new uint32_t(1);
251 SSL_set_ex_data(ssl
, ssl_ex_index_ssl_validation_counter
, validationCounter
);
253 // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
254 (*validationCounter
)++;
257 if ((*validationCounter
) >= SQUID_CERT_VALIDATION_ITERATION_MAX
) {
258 ok
= 0; // or the validation loop will never stop
259 error_no
= SQUID_X509_V_ERR_INFINITE_VALIDATION
;
260 debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
261 *validationCounter
<< " iterations while checking " << buffer
);
265 debugs(83, 5, "SSL Certificate signature OK: " << buffer
);
267 // Check for domain mismatch only if the current certificate is the peer certificate.
268 if (!dont_verify_domain
&& server
&& peer_cert
== X509_STORE_CTX_get_current_cert(ctx
)) {
269 if (!Ssl::checkX509ServerValidity(peer_cert
, server
->c_str())) {
270 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer
<< " does not match domainname " << server
);
272 error_no
= SQUID_X509_V_ERR_DOMAIN_MISMATCH
;
277 if (ok
&& peeked_cert
) {
278 // Check whether the already peeked certificate matches the new one.
279 if (X509_cmp(peer_cert
, peeked_cert
) != 0) {
280 debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer
<< " does not match peeked certificate");
282 error_no
= SQUID_X509_V_ERR_CERT_CHANGE
;
287 X509
*broken_cert
= X509_STORE_CTX_get_current_cert(ctx
);
289 broken_cert
= peer_cert
;
291 Ssl::CertErrors
*errs
= static_cast<Ssl::CertErrors
*>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_errors
));
293 const int depth
= X509_STORE_CTX_get_error_depth(ctx
);
294 errs
= new Ssl::CertErrors(Ssl::CertError(error_no
, broken_cert
, depth
));
295 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_errors
, (void *)errs
)) {
296 debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer
);
300 } else // remember another error number
301 errs
->push_back_unique(Ssl::CertError(error_no
, broken_cert
));
303 if (const char *err_descr
= Ssl::GetErrorDescr(error_no
))
304 debugs(83, 5, err_descr
<< ": " << buffer
);
306 debugs(83, DBG_IMPORTANT
, "SSL unknown certificate error " << error_no
<< " in " << buffer
);
308 // Check if the certificate error can be bypassed.
309 // Infinity validation loop errors can not bypassed.
310 if (error_no
!= SQUID_X509_V_ERR_INFINITE_VALIDATION
) {
312 ACLFilledChecklist
*filledCheck
= Filled(check
);
313 assert(!filledCheck
->sslErrors
);
314 filledCheck
->sslErrors
= new Ssl::CertErrors(Ssl::CertError(error_no
, broken_cert
));
315 filledCheck
->serverCert
.resetAndLock(peer_cert
);
316 if (check
->fastCheck() == ACCESS_ALLOWED
) {
317 debugs(83, 3, "bypassing SSL error " << error_no
<< " in " << buffer
);
320 debugs(83, 5, "confirming SSL error " << error_no
);
322 delete filledCheck
->sslErrors
;
323 filledCheck
->sslErrors
= NULL
;
324 filledCheck
->serverCert
.reset();
326 // If the certificate validator is used then we need to allow all errors and
327 // pass them to certficate validator for more processing
328 else if (Ssl::TheConfig
.ssl_crt_validator
) {
334 if (Ssl::TheConfig
.ssl_crt_validator
) {
335 // Check if we have stored certificates chain. Store if not.
336 if (!SSL_get_ex_data(ssl
, ssl_ex_index_ssl_cert_chain
)) {
337 STACK_OF(X509
) *certStack
= X509_STORE_CTX_get1_chain(ctx
);
338 if (certStack
&& !SSL_set_ex_data(ssl
, ssl_ex_index_ssl_cert_chain
, certStack
))
339 sk_X509_pop_free(certStack
, X509_free
);
343 if (!ok
&& !SSL_get_ex_data(ssl
, ssl_ex_index_ssl_error_detail
) ) {
345 // Find the broken certificate. It may be intermediate.
346 X509
*broken_cert
= peer_cert
; // reasonable default if search fails
347 // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
348 if (error_no
!= SQUID_X509_V_ERR_DOMAIN_MISMATCH
) {
349 if (X509
*last_used_cert
= X509_STORE_CTX_get_current_cert(ctx
))
350 broken_cert
= last_used_cert
;
353 Ssl::ErrorDetail
*errDetail
=
354 new Ssl::ErrorDetail(error_no
, peer_cert
, broken_cert
);
356 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_error_detail
, errDetail
)) {
357 debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer
);
365 // "dup" function for SSL_get_ex_new_index("cert_err_check")
367 ssl_dupAclChecklist(CRYPTO_EX_DATA
*, CRYPTO_EX_DATA
*, void *,
370 // We do not support duplication of ACLCheckLists.
371 // If duplication is needed, we can count copies with cbdata.
376 // "free" function for SSL_get_ex_new_index("cert_err_check")
378 ssl_freeAclChecklist(void *, void *ptr
, CRYPTO_EX_DATA
*,
381 delete static_cast<ACLChecklist
*>(ptr
); // may be NULL
384 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
386 ssl_free_ErrorDetail(void *, void *ptr
, CRYPTO_EX_DATA
*,
389 Ssl::ErrorDetail
*errDetail
= static_cast <Ssl::ErrorDetail
*>(ptr
);
394 ssl_free_SslErrors(void *, void *ptr
, CRYPTO_EX_DATA
*,
397 Ssl::CertErrors
*errs
= static_cast <Ssl::CertErrors
*>(ptr
);
401 // "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
403 ssl_free_int(void *, void *ptr
, CRYPTO_EX_DATA
*,
406 uint32_t *counter
= static_cast <uint32_t *>(ptr
);
410 /// \ingroup ServerProtocolSSLInternal
411 /// Callback handler function to release STACK_OF(X509) "ex" data stored
412 /// in an SSL object.
414 ssl_free_CertChain(void *, void *ptr
, CRYPTO_EX_DATA
*,
417 STACK_OF(X509
) *certsChain
= static_cast <STACK_OF(X509
) *>(ptr
);
418 sk_X509_pop_free(certsChain
,X509_free
);
421 // "free" function for X509 certificates
423 ssl_free_X509(void *, void *ptr
, CRYPTO_EX_DATA
*,
426 X509
*cert
= static_cast <X509
*>(ptr
);
430 // "free" function for SBuf
432 ssl_free_SBuf(void *, void *ptr
, CRYPTO_EX_DATA
*,
435 SBuf
*buf
= static_cast <SBuf
*>(ptr
);
440 Ssl::Initialize(void)
442 static bool initialized
= false;
447 SSL_load_error_strings();
448 SSLeay_add_ssl_algorithms();
450 #if HAVE_OPENSSL_ENGINE_H
451 if (::Config
.SSL
.ssl_engine
) {
453 if (!(e
= ENGINE_by_id(::Config
.SSL
.ssl_engine
)))
454 fatalf("Unable to find SSL engine '%s'\n", ::Config
.SSL
.ssl_engine
);
456 if (!ENGINE_set_default(e
, ENGINE_METHOD_ALL
)) {
457 const int ssl_error
= ERR_get_error();
458 fatalf("Failed to initialise SSL engine: %s\n", ERR_error_string(ssl_error
, NULL
));
462 if (::Config
.SSL
.ssl_engine
)
463 fatalf("Your OpenSSL has no SSL engine support\n");
466 const char *defName
= ::Config
.SSL
.certSignHash
? ::Config
.SSL
.certSignHash
: SQUID_SSL_SIGN_HASH_IF_NONE
;
467 Ssl::DefaultSignHash
= EVP_get_digestbyname(defName
);
468 if (!Ssl::DefaultSignHash
)
469 fatalf("Sign hash '%s' is not supported\n", defName
);
471 ssl_ex_index_server
= SSL_get_ex_new_index(0, (void *) "server", NULL
, NULL
, ssl_free_SBuf
);
472 ssl_ctx_ex_index_dont_verify_domain
= SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL
, NULL
, NULL
);
473 ssl_ex_index_cert_error_check
= SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL
, &ssl_dupAclChecklist
, &ssl_freeAclChecklist
);
474 ssl_ex_index_ssl_error_detail
= SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL
, NULL
, &ssl_free_ErrorDetail
);
475 ssl_ex_index_ssl_peeked_cert
= SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL
, NULL
, &ssl_free_X509
);
476 ssl_ex_index_ssl_errors
= SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL
, NULL
, &ssl_free_SslErrors
);
477 ssl_ex_index_ssl_cert_chain
= SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL
, NULL
, &ssl_free_CertChain
);
478 ssl_ex_index_ssl_validation_counter
= SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL
, NULL
, &ssl_free_int
);
479 ssl_ex_index_ssl_untrusted_chain
= SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL
, NULL
, &ssl_free_CertChain
);
482 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
484 ssl_info_cb(const SSL
*ssl
, int where
, int ret
)
487 if ((where
& SSL_CB_HANDSHAKE_DONE
) != 0) {
488 // disable renegotiation (CVE-2009-3555)
489 ssl
->s3
->flags
|= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
;
495 configureSslContext(Security::ContextPtr sslContext
, AnyP::PortCfg
&port
)
498 SSL_CTX_set_options(sslContext
, port
.secure
.parsedOptions
);
500 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
501 SSL_CTX_set_info_callback(sslContext
, ssl_info_cb
);
504 if (port
.sslContextSessionId
)
505 SSL_CTX_set_session_id_context(sslContext
, (const unsigned char *)port
.sslContextSessionId
, strlen(port
.sslContextSessionId
));
507 if (port
.secure
.parsedFlags
& SSL_FLAG_NO_SESSION_REUSE
) {
508 SSL_CTX_set_session_cache_mode(sslContext
, SSL_SESS_CACHE_OFF
);
511 if (Config
.SSL
.unclean_shutdown
) {
512 debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
514 SSL_CTX_set_quiet_shutdown(sslContext
, 1);
517 if (!port
.secure
.sslCipher
.isEmpty()) {
518 debugs(83, 5, "Using chiper suite " << port
.secure
.sslCipher
<< ".");
520 if (!SSL_CTX_set_cipher_list(sslContext
, port
.secure
.sslCipher
.c_str())) {
521 ssl_error
= ERR_get_error();
522 debugs(83, DBG_CRITICAL
, "ERROR: Failed to set SSL cipher suite '" << port
.secure
.sslCipher
<< "': " << ERR_error_string(ssl_error
, NULL
));
527 debugs(83, 9, "Setting RSA key generation callback.");
528 SSL_CTX_set_tmp_rsa_callback(sslContext
, ssl_temp_rsa_cb
);
530 port
.secure
.updateContextEecdh(sslContext
);
531 port
.secure
.updateContextCa(sslContext
);
533 if (port
.clientCA
.get()) {
535 if (STACK_OF(X509_NAME
) *clientca
= SSL_dup_CA_list(port
.clientCA
.get())) {
536 SSL_CTX_set_client_CA_list(sslContext
, clientca
);
538 ssl_error
= ERR_get_error();
539 debugs(83, DBG_CRITICAL
, "ERROR: Failed to dupe the client CA list: " << ERR_error_string(ssl_error
, NULL
));
543 if (port
.secure
.parsedFlags
& SSL_FLAG_DELAYED_AUTH
) {
544 debugs(83, 9, "Not requesting client certificates until acl processing requires one");
545 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, NULL
);
547 debugs(83, 9, "Requiring client certificates.");
548 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, ssl_verify_cb
);
551 port
.secure
.updateContextCrl(sslContext
);
554 debugs(83, 9, "Not requiring any client certificates");
555 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, NULL
);
558 if (port
.secure
.parsedFlags
& SSL_FLAG_DONT_VERIFY_DOMAIN
)
559 SSL_CTX_set_ex_data(sslContext
, ssl_ctx_ex_index_dont_verify_domain
, (void *) -1);
561 Ssl::SetSessionCallbacks(sslContext
);
567 Ssl::InitServerContext(const Security::ContextPointer
&ctx
, AnyP::PortCfg
&port
)
572 if (!SSL_CTX_use_certificate(ctx
.get(), port
.signingCert
.get())) {
573 const int ssl_error
= ERR_get_error();
574 const auto &keys
= port
.secure
.certs
.front();
575 debugs(83, DBG_CRITICAL
, "ERROR: Failed to acquire TLS certificate '" << keys
.certFile
<< "': " << ERR_error_string(ssl_error
, NULL
));
579 if (!SSL_CTX_use_PrivateKey(ctx
.get(), port
.signPkey
.get())) {
580 const int ssl_error
= ERR_get_error();
581 const auto &keys
= port
.secure
.certs
.front();
582 debugs(83, DBG_CRITICAL
, "ERROR: Failed to acquire TLS private key '" << keys
.privateKeyFile
<< "': " << ERR_error_string(ssl_error
, NULL
));
586 Ssl::addChainToSslContext(ctx
.get(), port
.certsToChain
.get());
589 debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
591 if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
592 ssl_error = ERR_get_error();
593 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
597 debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
598 ssl_ask_password(ctx.get(), keyfile);
600 if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
601 ssl_error = ERR_get_error();
602 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
606 debugs(83, 5, "Comparing private and public SSL keys.");
608 if (!SSL_CTX_check_private_key(ctx.get())) {
609 ssl_error = ERR_get_error();
610 debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
611 keyfile << "': " << ERR_error_string(ssl_error, NULL));
616 if (!configureSslContext(ctx
.get(), port
)) {
617 debugs(83, DBG_CRITICAL
, "ERROR: Configuring static SSL context");
625 Ssl::InitClientContext(Security::ContextPtr
&sslContext
, Security::PeerOptions
&peer
, long options
, long fl
)
630 SSL_CTX_set_options(sslContext
, options
);
632 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
633 SSL_CTX_set_info_callback(sslContext
, ssl_info_cb
);
636 if (!peer
.sslCipher
.isEmpty()) {
637 debugs(83, 5, "Using chiper suite " << peer
.sslCipher
<< ".");
639 const char *cipher
= peer
.sslCipher
.c_str();
640 if (!SSL_CTX_set_cipher_list(sslContext
, cipher
)) {
641 const int ssl_error
= ERR_get_error();
642 fatalf("Failed to set SSL cipher suite '%s': %s\n",
643 cipher
, ERR_error_string(ssl_error
, NULL
));
647 if (!peer
.certs
.empty()) {
648 // TODO: support loading multiple cert/key pairs
649 auto &keys
= peer
.certs
.front();
650 if (!keys
.certFile
.isEmpty()) {
651 debugs(83, DBG_IMPORTANT
, "Using certificate in " << keys
.certFile
);
653 const char *certfile
= keys
.certFile
.c_str();
654 if (!SSL_CTX_use_certificate_chain_file(sslContext
, certfile
)) {
655 const int ssl_error
= ERR_get_error();
656 fatalf("Failed to acquire SSL certificate '%s': %s\n",
657 certfile
, ERR_error_string(ssl_error
, NULL
));
660 debugs(83, DBG_IMPORTANT
, "Using private key in " << keys
.privateKeyFile
);
661 const char *keyfile
= keys
.privateKeyFile
.c_str();
662 ssl_ask_password(sslContext
, keyfile
);
664 if (!SSL_CTX_use_PrivateKey_file(sslContext
, keyfile
, SSL_FILETYPE_PEM
)) {
665 const int ssl_error
= ERR_get_error();
666 fatalf("Failed to acquire SSL private key '%s': %s\n",
667 keyfile
, ERR_error_string(ssl_error
, NULL
));
670 debugs(83, 5, "Comparing private and public SSL keys.");
672 if (!SSL_CTX_check_private_key(sslContext
)) {
673 const int ssl_error
= ERR_get_error();
674 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
675 certfile
, keyfile
, ERR_error_string(ssl_error
, NULL
));
680 debugs(83, 9, "Setting RSA key generation callback.");
681 SSL_CTX_set_tmp_rsa_callback(sslContext
, ssl_temp_rsa_cb
);
683 if (fl
& SSL_FLAG_DONT_VERIFY_PEER
) {
684 debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!");
685 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, NULL
);
687 debugs(83, 9, "Setting certificate verification callback.");
688 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, ssl_verify_cb
);
694 /// \ingroup ServerProtocolSSLInternal
696 ssl_read_method(int fd
, char *buf
, int len
)
698 auto ssl
= fd_table
[fd
].ssl
.get();
702 if (!SSL_is_init_finished(ssl
)) {
709 int i
= SSL_read(ssl
, buf
, len
);
711 if (i
> 0 && SSL_pending(ssl
) > 0) {
712 debugs(83, 2, "SSL FD " << fd
<< " is pending");
713 fd_table
[fd
].flags
.read_pending
= true;
715 fd_table
[fd
].flags
.read_pending
= false;
720 /// \ingroup ServerProtocolSSLInternal
722 ssl_write_method(int fd
, const char *buf
, int len
)
724 auto ssl
= fd_table
[fd
].ssl
.get();
725 if (!SSL_is_init_finished(ssl
)) {
730 int i
= SSL_write(ssl
, buf
, len
);
735 ssl_shutdown_method(SSL
*ssl
)
740 /// \ingroup ServerProtocolSSLInternal
742 ssl_get_attribute(X509_NAME
* name
, const char *attribute_name
)
744 static char buffer
[1024];
747 if (strcmp(attribute_name
, "DN") == 0) {
748 X509_NAME_oneline(name
, buffer
, sizeof(buffer
));
750 int nid
= OBJ_txt2nid(const_cast<char *>(attribute_name
));
752 debugs(83, DBG_IMPORTANT
, "WARNING: Unknown SSL attribute name '" << attribute_name
<< "'");
755 X509_NAME_get_text_by_NID(name
, nid
, buffer
, sizeof(buffer
));
758 return *buffer
? buffer
: nullptr;
761 /// \ingroup ServerProtocolSSLInternal
763 Ssl::GetX509UserAttribute(X509
* cert
, const char *attribute_name
)
771 name
= X509_get_subject_name(cert
);
773 ret
= ssl_get_attribute(name
, attribute_name
);
779 Ssl::GetX509Fingerprint(X509
* cert
, const char *)
781 static char buf
[1024];
786 unsigned char md
[EVP_MAX_MD_SIZE
];
787 if (!X509_digest(cert
, EVP_sha1(), md
, &n
))
790 assert(3 * n
+ 1 < sizeof(buf
));
793 for (unsigned int i
=0; i
< n
; ++i
, s
+= 3) {
794 const char term
= (i
+ 1 < n
) ? ':' : '\0';
795 snprintf(s
, 4, "%02X%c", md
[i
], term
);
801 /// \ingroup ServerProtocolSSLInternal
803 Ssl::GetX509CAAttribute(X509
* cert
, const char *attribute_name
)
812 name
= X509_get_issuer_name(cert
);
814 ret
= ssl_get_attribute(name
, attribute_name
);
819 const char *sslGetUserAttribute(SSL
*ssl
, const char *attribute_name
)
824 X509
*cert
= SSL_get_peer_certificate(ssl
);
826 const char *attr
= Ssl::GetX509UserAttribute(cert
, attribute_name
);
832 const char *sslGetCAAttribute(SSL
*ssl
, const char *attribute_name
)
837 X509
*cert
= SSL_get_peer_certificate(ssl
);
839 const char *attr
= Ssl::GetX509CAAttribute(cert
, attribute_name
);
846 sslGetUserEmail(SSL
* ssl
)
848 return sslGetUserAttribute(ssl
, "emailAddress");
852 sslGetUserCertificatePEM(SSL
*ssl
)
856 static char *str
= NULL
;
865 cert
= SSL_get_peer_certificate(ssl
);
870 mem
= BIO_new(BIO_s_mem());
872 PEM_write_bio_X509(mem
, cert
);
874 len
= BIO_get_mem_data(mem
, &ptr
);
876 str
= (char *)xmalloc(len
+ 1);
878 memcpy(str
, ptr
, len
);
890 sslGetUserCertificateChainPEM(SSL
*ssl
)
892 STACK_OF(X509
) *chain
;
894 static char *str
= NULL
;
904 chain
= SSL_get_peer_cert_chain(ssl
);
907 return sslGetUserCertificatePEM(ssl
);
909 mem
= BIO_new(BIO_s_mem());
911 for (i
= 0; i
< sk_X509_num(chain
); ++i
) {
912 X509
*cert
= sk_X509_value(chain
, i
);
913 PEM_write_bio_X509(mem
, cert
);
916 len
= BIO_get_mem_data(mem
, &ptr
);
918 str
= (char *)xmalloc(len
+ 1);
919 memcpy(str
, ptr
, len
);
927 /// Create SSL context and apply ssl certificate and private key to it.
929 Ssl::createSSLContext(Security::CertPointer
& x509
, Ssl::EVP_PKEY_Pointer
& pkey
, AnyP::PortCfg
&port
)
931 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
932 Security::ContextPointer
sslContext(SSL_CTX_new(TLS_server_method()));
934 Security::ContextPointer
sslContext(SSL_CTX_new(SSLv23_server_method()));
937 if (!SSL_CTX_use_certificate(sslContext
.get(), x509
.get()))
940 if (!SSL_CTX_use_PrivateKey(sslContext
.get(), pkey
.get()))
943 if (!configureSslContext(sslContext
.get(), port
))
946 return sslContext
.release();
950 Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data
, AnyP::PortCfg
&port
)
952 Security::CertPointer cert
;
953 Ssl::EVP_PKEY_Pointer pkey
;
954 if (!readCertAndPrivateKeyFromMemory(cert
, pkey
, data
) || !cert
|| !pkey
)
957 return createSSLContext(cert
, pkey
, port
);
961 Ssl::generateSslContext(CertificateProperties
const &properties
, AnyP::PortCfg
&port
)
963 Security::CertPointer cert
;
964 Ssl::EVP_PKEY_Pointer pkey
;
965 if (!generateSslCertificate(cert
, pkey
, properties
) || !cert
|| !pkey
)
968 return createSSLContext(cert
, pkey
, port
);
972 Ssl::chainCertificatesToSSLContext(SSL_CTX
*sslContext
, AnyP::PortCfg
&port
)
974 assert(sslContext
!= NULL
);
975 // Add signing certificate to the certificates chain
976 X509
*signingCert
= port
.signingCert
.get();
977 if (SSL_CTX_add_extra_chain_cert(sslContext
, signingCert
)) {
978 // increase the certificate lock
979 CRYPTO_add(&(signingCert
->references
),1,CRYPTO_LOCK_X509
);
981 const int ssl_error
= ERR_get_error();
982 debugs(33, DBG_IMPORTANT
, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error
, NULL
));
984 Ssl::addChainToSslContext(sslContext
, port
.certsToChain
.get());
988 Ssl::configureUnconfiguredSslContext(SSL_CTX
*sslContext
, Ssl::CertSignAlgorithm signAlgorithm
,AnyP::PortCfg
&port
)
990 if (sslContext
&& signAlgorithm
== Ssl::algSignTrusted
) {
991 Ssl::chainCertificatesToSSLContext(sslContext
, port
);
996 Ssl::configureSSL(SSL
*ssl
, CertificateProperties
const &properties
, AnyP::PortCfg
&port
)
998 Security::CertPointer cert
;
999 Ssl::EVP_PKEY_Pointer pkey
;
1000 if (!generateSslCertificate(cert
, pkey
, properties
))
1009 if (!SSL_use_certificate(ssl
, cert
.get()))
1012 if (!SSL_use_PrivateKey(ssl
, pkey
.get()))
1019 Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL
*ssl
, const char *data
, AnyP::PortCfg
&port
)
1021 Security::CertPointer cert
;
1022 Ssl::EVP_PKEY_Pointer pkey
;
1023 if (!readCertAndPrivateKeyFromMemory(cert
, pkey
, data
))
1029 if (!SSL_use_certificate(ssl
, cert
.get()))
1032 if (!SSL_use_PrivateKey(ssl
, pkey
.get()))
1038 bool Ssl::verifySslCertificate(Security::ContextPtr sslContext
, CertificateProperties
const &properties
)
1040 // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
1041 // Try to retrieve certificate directly from Security::ContextPtr object
1042 #if SQUID_USE_SSLGETCERTIFICATE_HACK
1043 X509
***pCert
= (X509
***)sslContext
->cert
;
1044 X509
* cert
= pCert
&& *pCert
? **pCert
: NULL
;
1045 #elif SQUID_SSLGETCERTIFICATE_BUGGY
1049 // Temporary ssl for getting X509 certificate from SSL_CTX.
1050 Security::SessionPointer
ssl(SSL_new(sslContext
));
1051 X509
* cert
= SSL_get_certificate(ssl
.get());
1055 ASN1_TIME
* time_notBefore
= X509_get_notBefore(cert
);
1056 ASN1_TIME
* time_notAfter
= X509_get_notAfter(cert
);
1057 bool ret
= (X509_cmp_current_time(time_notBefore
) < 0 && X509_cmp_current_time(time_notAfter
) > 0);
1061 return certificateMatchesProperties(cert
, properties
);
1065 Ssl::setClientSNI(SSL
*ssl
, const char *fqdn
)
1067 //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
1068 // if the TLS servername extension (SNI) is enabled in openssl library.
1069 #if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
1070 if (!SSL_set_tlsext_host_name(ssl
, fqdn
)) {
1071 const int ssl_error
= ERR_get_error();
1072 debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
1073 ERR_error_string(ssl_error
, NULL
) << "\n");
1078 debugs(83, 7, "no support for TLS servername extension (SNI)\n");
1083 void Ssl::addChainToSslContext(Security::ContextPtr sslContext
, STACK_OF(X509
) *chain
)
1088 for (int i
= 0; i
< sk_X509_num(chain
); ++i
) {
1089 X509
*cert
= sk_X509_value(chain
, i
);
1090 if (SSL_CTX_add_extra_chain_cert(sslContext
, cert
)) {
1091 // increase the certificate lock
1092 CRYPTO_add(&(cert
->references
),1,CRYPTO_LOCK_X509
);
1094 const int ssl_error
= ERR_get_error();
1095 debugs(83, DBG_IMPORTANT
, "WARNING: can not add certificate to SSL context chain: " << ERR_error_string(ssl_error
, NULL
));
1101 hasAuthorityInfoAccessCaIssuers(X509
*cert
)
1103 AUTHORITY_INFO_ACCESS
*info
;
1106 info
= static_cast<AUTHORITY_INFO_ACCESS
*>(X509_get_ext_d2i(cert
, NID_info_access
, NULL
, NULL
));
1110 static char uri
[MAX_URL
];
1113 for (int i
= 0; i
< sk_ACCESS_DESCRIPTION_num(info
); i
++) {
1114 ACCESS_DESCRIPTION
*ad
= sk_ACCESS_DESCRIPTION_value(info
, i
);
1115 if (OBJ_obj2nid(ad
->method
) == NID_ad_ca_issuers
) {
1116 if (ad
->location
->type
== GEN_URI
) {
1117 xstrncpy(uri
, reinterpret_cast<char *>(ASN1_STRING_data(ad
->location
->d
.uniformResourceIdentifier
)), sizeof(uri
));
1122 AUTHORITY_INFO_ACCESS_free(info
);
1123 return uri
[0] != '\0' ? uri
: nullptr;
1127 Ssl::loadCerts(const char *certsFile
, Ssl::CertsIndexedList
&list
)
1129 BIO
*in
= BIO_new_file(certsFile
, "r");
1131 debugs(83, DBG_IMPORTANT
, "Failed to open '" << certsFile
<< "' to load certificates");
1136 while((aCert
= PEM_read_bio_X509(in
, NULL
, NULL
, NULL
))) {
1137 static char buffer
[2048];
1138 X509_NAME_oneline(X509_get_subject_name(aCert
), buffer
, sizeof(buffer
));
1139 list
.insert(std::pair
<SBuf
, X509
*>(SBuf(buffer
), aCert
));
1141 debugs(83, 4, "Loaded " << list
.size() << " certificates from file: '" << certsFile
<< "'");
1146 /// quickly find the issuer certificate of a certificate cert in the
1147 /// Ssl::CertsIndexedList list
1149 findCertIssuerFast(Ssl::CertsIndexedList
&list
, X509
*cert
)
1151 static char buffer
[2048];
1153 if (X509_NAME
*issuerName
= X509_get_issuer_name(cert
))
1154 X509_NAME_oneline(issuerName
, buffer
, sizeof(buffer
));
1158 const auto ret
= list
.equal_range(SBuf(buffer
));
1159 for (Ssl::CertsIndexedList::iterator it
= ret
.first
; it
!= ret
.second
; ++it
) {
1160 X509
*issuer
= it
->second
;
1161 if (X509_check_issued(cert
, issuer
)) {
1168 /// slowly find the issuer certificate of a given cert using linear search
1170 findCertIssuer(Security::CertList
const &list
, X509
*cert
)
1172 for (Security::CertList::const_iterator it
= list
.begin(); it
!= list
.end(); ++it
) {
1173 if (X509_check_issued(it
->get(), cert
) == X509_V_OK
)
1180 Ssl::uriOfIssuerIfMissing(X509
*cert
, Security::CertList
const &serverCertificates
)
1182 if (!cert
|| !serverCertificates
.size())
1185 if (!findCertIssuer(serverCertificates
, cert
)) {
1186 //if issuer is missing
1187 if (!findCertIssuerFast(SquidUntrustedCerts
, cert
)) {
1188 // and issuer not found in local untrusted certificates database
1189 if (const char *issuerUri
= hasAuthorityInfoAccessCaIssuers(cert
)) {
1190 // There is a URI where we can download a certificate.
1199 Ssl::missingChainCertificatesUrls(std::queue
<SBuf
> &URIs
, Security::CertList
const &serverCertificates
)
1201 if (!serverCertificates
.size())
1204 for (const auto &i
: serverCertificates
) {
1205 if (const char *issuerUri
= uriOfIssuerIfMissing(i
.get(), serverCertificates
))
1206 URIs
.push(SBuf(issuerUri
));
1211 Ssl::SSL_add_untrusted_cert(SSL
*ssl
, X509
*cert
)
1213 STACK_OF(X509
) *untrustedStack
= static_cast <STACK_OF(X509
) *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_untrusted_chain
));
1214 if (!untrustedStack
) {
1215 untrustedStack
= sk_X509_new_null();
1216 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_untrusted_chain
, untrustedStack
)) {
1217 sk_X509_pop_free(untrustedStack
, X509_free
);
1218 throw TextException("Failed to attach untrusted certificates chain");
1221 sk_X509_push(untrustedStack
, cert
);
1224 /// Search for the issuer certificate of cert in sk list.
1226 sk_x509_findIssuer(STACK_OF(X509
) *sk
, X509
*cert
)
1231 const int skItemsNum
= sk_X509_num(sk
);
1232 for (int i
= 0; i
< skItemsNum
; ++i
) {
1233 X509
*issuer
= sk_X509_value(sk
, i
);
1234 if (X509_check_issued(issuer
, cert
) == X509_V_OK
)
1240 /// add missing issuer certificates to untrustedCerts
1242 completeIssuers(X509_STORE_CTX
*ctx
, STACK_OF(X509
) *untrustedCerts
)
1244 debugs(83, 2, "completing " << sk_X509_num(untrustedCerts
) << " OpenSSL untrusted certs using " << SquidUntrustedCerts
.size() << " configured untrusted certificates");
1246 int depth
= ctx
->param
->depth
;
1247 X509
*current
= ctx
->cert
;
1249 for (i
= 0; current
&& (i
< depth
); ++i
) {
1250 if (X509_check_issued(current
, current
)) {
1251 // either ctx->cert is itself self-signed or untrustedCerts
1252 // aready contain the self-signed current certificate
1256 // untrustedCerts is short, not worth indexing
1257 X509
*issuer
= sk_x509_findIssuer(untrustedCerts
, current
);
1259 if ((issuer
= findCertIssuerFast(SquidUntrustedCerts
, current
)))
1260 sk_X509_push(untrustedCerts
, issuer
);
1266 debugs(83, 2, "exceeded the maximum certificate chain length: " << depth
);
1269 /// OpenSSL certificate validation callback.
1271 untrustedToStoreCtx_cb(X509_STORE_CTX
*ctx
,void *data
)
1273 debugs(83, 4, "Try to use pre-downloaded intermediate certificates\n");
1275 SSL
*ssl
= static_cast<SSL
*>(X509_STORE_CTX_get_ex_data(ctx
, SSL_get_ex_data_X509_STORE_CTX_idx()));
1276 STACK_OF(X509
) *sslUntrustedStack
= static_cast <STACK_OF(X509
) *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_untrusted_chain
));
1278 // OpenSSL already maintains ctx->untrusted but we cannot modify
1279 // internal OpenSSL list directly. We have to give OpenSSL our own
1280 // list, but it must include certificates on the OpenSSL ctx->untrusted
1281 STACK_OF(X509
) *oldUntrusted
= ctx
->untrusted
;
1282 STACK_OF(X509
) *sk
= sk_X509_dup(oldUntrusted
); // oldUntrusted is always not NULL
1284 for (int i
= 0; i
< sk_X509_num(sslUntrustedStack
); ++i
) {
1285 X509
*cert
= sk_X509_value(sslUntrustedStack
, i
);
1286 sk_X509_push(sk
, cert
);
1289 // If the local untrusted certificates internal database is used
1290 // run completeIssuers to add missing certificates if possible.
1291 if (SquidUntrustedCerts
.size() > 0)
1292 completeIssuers(ctx
, sk
);
1294 X509_STORE_CTX_set_chain(ctx
, sk
); // No locking/unlocking, just sets ctx->untrusted
1295 int ret
= X509_verify_cert(ctx
);
1296 X509_STORE_CTX_set_chain(ctx
, oldUntrusted
); // Set back the old untrusted list
1297 sk_X509_free(sk
); // Release sk list
1302 Ssl::useSquidUntrusted(SSL_CTX
*sslContext
)
1304 SSL_CTX_set_cert_verify_callback(sslContext
, untrustedToStoreCtx_cb
, NULL
);
1308 Ssl::loadSquidUntrusted(const char *path
)
1310 return Ssl::loadCerts(path
, SquidUntrustedCerts
);
1314 Ssl::unloadSquidUntrusted()
1316 if (SquidUntrustedCerts
.size()) {
1317 for (Ssl::CertsIndexedList::iterator it
= SquidUntrustedCerts
.begin(); it
!= SquidUntrustedCerts
.end(); ++it
) {
1318 X509_free(it
->second
);
1320 SquidUntrustedCerts
.clear();
1325 \ingroup ServerProtocolSSLInternal
1326 * Read certificate from file.
1327 * See also: static readSslX509Certificate function, gadgets.cc file
1329 static X509
* readSslX509CertificatesChain(char const * certFilename
, STACK_OF(X509
)* chain
)
1333 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
1336 if (!BIO_read_filename(bio
.get(), certFilename
))
1338 X509
*certificate
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
);
1340 if (certificate
&& chain
) {
1342 if (X509_check_issued(certificate
, certificate
) == X509_V_OK
)
1343 debugs(83, 5, "Certificate is self-signed, will not be chained");
1345 // and add to the chain any other certificate exist in the file
1346 while (X509
*ca
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
)) {
1347 if (!sk_X509_push(chain
, ca
))
1348 debugs(83, DBG_IMPORTANT
, "WARNING: unable to add CA certificate to cert chain");
1356 void Ssl::readCertChainAndPrivateKeyFromFiles(Security::CertPointer
& cert
, EVP_PKEY_Pointer
& pkey
, X509_STACK_Pointer
& chain
, char const * certFilename
, char const * keyFilename
)
1358 if (keyFilename
== NULL
)
1359 keyFilename
= certFilename
;
1361 if (certFilename
== NULL
)
1362 certFilename
= keyFilename
;
1364 debugs(83, DBG_IMPORTANT
, "Using certificate in " << certFilename
);
1367 chain
.reset(sk_X509_new_null());
1369 debugs(83, DBG_IMPORTANT
, "WARNING: unable to allocate memory for cert chain");
1370 // XXX: ssl_ask_password_cb needs SSL_CTX_set_default_passwd_cb_userdata()
1371 // so this may not fully work iff Config.Program.ssl_password is set.
1372 pem_password_cb
*cb
= ::Config
.Program
.ssl_password
? &ssl_ask_password_cb
: NULL
;
1373 pkey
.resetWithoutLocking(readSslPrivateKey(keyFilename
, cb
));
1374 cert
.resetWithoutLocking(readSslX509CertificatesChain(certFilename
, chain
.get()));
1375 if (!pkey
|| !cert
|| !X509_check_private_key(cert
.get(), pkey
.get())) {
1381 bool Ssl::generateUntrustedCert(Security::CertPointer
&untrustedCert
, EVP_PKEY_Pointer
&untrustedPkey
, Security::CertPointer
const &cert
, EVP_PKEY_Pointer
const & pkey
)
1383 // Generate the self-signed certificate, using a hard-coded subject prefix
1384 Ssl::CertificateProperties certProperties
;
1385 if (const char *cn
= CommonHostName(cert
.get())) {
1386 certProperties
.commonName
= "Not trusted by \"";
1387 certProperties
.commonName
+= cn
;
1388 certProperties
.commonName
+= "\"";
1389 } else if (const char *org
= getOrganization(cert
.get())) {
1390 certProperties
.commonName
= "Not trusted by \"";
1391 certProperties
.commonName
+= org
;
1392 certProperties
.commonName
+= "\"";
1394 certProperties
.commonName
= "Not trusted";
1395 certProperties
.setCommonName
= true;
1396 // O, OU, and other CA subject fields will be mimicked
1397 // Expiration date and other common properties will be mimicked
1398 certProperties
.signAlgorithm
= Ssl::algSignSelf
;
1399 certProperties
.signWithPkey
.resetAndLock(pkey
.get());
1400 certProperties
.mimicCert
.resetAndLock(cert
.get());
1401 return Ssl::generateSslCertificate(untrustedCert
, untrustedPkey
, certProperties
);
1405 SslCreate(Security::ContextPtr sslContext
, const Comm::ConnectionPointer
&conn
, Ssl::Bio::Type type
, const char *squidCtx
)
1407 if (!Comm::IsConnOpen(conn
)) {
1408 debugs(83, DBG_IMPORTANT
, "Gone connection");
1412 const char *errAction
= NULL
;
1414 if (auto ssl
= SSL_new(sslContext
)) {
1415 const int fd
= conn
->fd
;
1416 // without BIO, we would call SSL_set_fd(ssl, fd) instead
1417 if (BIO
*bio
= Ssl::Bio::Create(fd
, type
)) {
1418 Ssl::Bio::Link(ssl
, bio
); // cannot fail
1420 fd_table
[fd
].ssl
.resetWithoutLocking(ssl
);
1421 fd_table
[fd
].read_method
= &ssl_read_method
;
1422 fd_table
[fd
].write_method
= &ssl_write_method
;
1423 fd_note(fd
, squidCtx
);
1426 errCode
= ERR_get_error();
1427 errAction
= "failed to initialize I/O";
1430 errCode
= ERR_get_error();
1431 errAction
= "failed to allocate handle";
1434 debugs(83, DBG_IMPORTANT
, "ERROR: " << squidCtx
<< ' ' << errAction
<<
1435 ": " << ERR_error_string(errCode
, NULL
));
1440 Ssl::CreateClient(Security::ContextPtr sslContext
, const Comm::ConnectionPointer
&c
, const char *squidCtx
)
1442 return SslCreate(sslContext
, c
, Ssl::Bio::BIO_TO_SERVER
, squidCtx
);
1446 Ssl::CreateServer(Security::ContextPtr sslContext
, const Comm::ConnectionPointer
&c
, const char *squidCtx
)
1448 return SslCreate(sslContext
, c
, Ssl::Bio::BIO_TO_CLIENT
, squidCtx
);
1451 Ssl::CertError::CertError(ssl_error_t anErr
, X509
*aCert
, int aDepth
): code(anErr
), depth(aDepth
)
1453 cert
.resetAndLock(aCert
);
1456 Ssl::CertError::CertError(CertError
const &err
): code(err
.code
), depth(err
.depth
)
1458 cert
.resetAndLock(err
.cert
.get());
1462 Ssl::CertError::operator = (const CertError
&old
)
1465 cert
.resetAndLock(old
.cert
.get());
1470 Ssl::CertError::operator == (const CertError
&ce
) const
1472 return code
== ce
.code
&& cert
.get() == ce
.cert
.get();
1476 Ssl::CertError::operator != (const CertError
&ce
) const
1478 return code
!= ce
.code
|| cert
.get() != ce
.cert
.get();
1482 store_session_cb(SSL
*ssl
, SSL_SESSION
*session
)
1484 if (!Ssl::SessionCache
)
1487 debugs(83, 5, "Request to store SSL Session ");
1489 SSL_SESSION_set_timeout(session
, Config
.SSL
.session_ttl
);
1491 unsigned char *id
= session
->session_id
;
1492 unsigned int idlen
= session
->session_id_length
;
1493 unsigned char key
[MEMMAP_SLOT_KEY_SIZE
];
1494 // Session ids are of size 32bytes. They should always fit to a
1495 // MemMap::Slot::key
1496 assert(idlen
<= MEMMAP_SLOT_KEY_SIZE
);
1497 memset(key
, 0, sizeof(key
));
1498 memcpy(key
, id
, idlen
);
1500 Ipc::MemMap::Slot
*slotW
= Ssl::SessionCache
->openForWriting((const cache_key
*)key
, pos
);
1502 int lenRequired
= i2d_SSL_SESSION(session
, NULL
);
1503 if (lenRequired
< MEMMAP_SLOT_DATA_SIZE
) {
1504 unsigned char *p
= (unsigned char *)slotW
->p
;
1505 lenRequired
= i2d_SSL_SESSION(session
, &p
);
1506 slotW
->set(key
, NULL
, lenRequired
, squid_curtime
+ Config
.SSL
.session_ttl
);
1508 Ssl::SessionCache
->closeForWriting(pos
);
1509 debugs(83, 5, "wrote an ssl session entry of size " << lenRequired
<< " at pos " << pos
);
1515 remove_session_cb(SSL_CTX
*, SSL_SESSION
*sessionID
)
1517 if (!Ssl::SessionCache
)
1520 debugs(83, 5, "Request to remove corrupted or not valid SSL Session ");
1522 Ipc::MemMap::Slot
const *slot
= Ssl::SessionCache
->openForReading((const cache_key
*)sessionID
, pos
);
1525 Ssl::SessionCache
->closeForReading(pos
);
1527 // What if we are not able to remove the session?
1528 // Maybe schedule a job to remove it later?
1529 // For now we just have an invalid entry in cache until will be expired
1530 // The openSSL will reject it when we try to use it
1531 Ssl::SessionCache
->free(pos
);
1534 static SSL_SESSION
*
1535 get_session_cb(SSL
*, unsigned char *sessionID
, int len
, int *copy
)
1537 if (!Ssl::SessionCache
)
1540 SSL_SESSION
*session
= NULL
;
1541 const unsigned int *p
;
1542 p
= (unsigned int *)sessionID
;
1543 debugs(83, 5, "Request to search for SSL Session of len:" <<
1544 len
<< p
[0] << ":" << p
[1]);
1547 Ipc::MemMap::Slot
const *slot
= Ssl::SessionCache
->openForReading((const cache_key
*)sessionID
, pos
);
1549 if (slot
->expire
> squid_curtime
) {
1550 const unsigned char *ptr
= slot
->p
;
1551 session
= d2i_SSL_SESSION(NULL
, &ptr
, slot
->pSize
);
1552 debugs(83, 5, "Session retrieved from cache at pos " << pos
);
1554 debugs(83, 5, "Session in cache expired");
1555 Ssl::SessionCache
->closeForReading(pos
);
1559 debugs(83, 5, "Failed to retrieved from cache\n");
1561 // With the parameter copy the callback can require the SSL engine
1562 // to increment the reference count of the SSL_SESSION object, Normally
1563 // the reference count is not incremented and therefore the session must
1564 // not be explicitly freed with SSL_SESSION_free(3).
1570 Ssl::SetSessionCallbacks(Security::ContextPtr ctx
)
1572 if (Ssl::SessionCache
) {
1573 SSL_CTX_set_session_cache_mode(ctx
, SSL_SESS_CACHE_SERVER
|SSL_SESS_CACHE_NO_INTERNAL
);
1574 SSL_CTX_sess_set_new_cb(ctx
, store_session_cb
);
1575 SSL_CTX_sess_set_remove_cb(ctx
, remove_session_cb
);
1576 SSL_CTX_sess_set_get_cb(ctx
, get_session_cb
);
1580 #endif /* USE_OPENSSL */