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 static void setSessionCallbacks(Security::ContextPtr ctx
);
37 Ipc::MemMap
*SslSessionCache
= NULL
;
38 const char *SslSessionCacheName
= "ssl_session_cache";
40 static Ssl::CertsIndexedList SquidUntrustedCerts
;
42 const EVP_MD
*Ssl::DefaultSignHash
= NULL
;
44 const char *Ssl::BumpModeStr
[] = {
58 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
59 \ingroup ServerProtocolSSLAPI
62 /// \ingroup ServerProtocolSSLInternal
64 ssl_ask_password_cb(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_ask_password_cb
);
93 SSL_CTX_set_default_passwd_cb_userdata(context
, (void *)prompt
);
97 /// \ingroup ServerProtocolSSLInternal
99 ssl_temp_rsa_cb(SSL
* ssl
, int anInt
, int keylen
)
101 static RSA
*rsa_512
= NULL
;
102 static RSA
*rsa_1024
= NULL
;
111 rsa_512
= RSA_generate_key(512, RSA_F4
, NULL
, NULL
);
121 rsa_1024
= RSA_generate_key(1024, RSA_F4
, NULL
, NULL
);
129 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Unexpected key length " << keylen
);
134 debugs(83, DBG_IMPORTANT
, "ssl_temp_rsa_cb: Failed to generate key " << keylen
);
140 PEM_write_RSAPrivateKey(debug_log
, rsa
, NULL
, NULL
, 0, NULL
, NULL
);
142 debugs(83, DBG_IMPORTANT
, "Generated ephemeral RSA key of length " << keylen
);
148 int Ssl::asn1timeToString(ASN1_TIME
*tm
, char *buf
, int len
)
152 bio
= BIO_new(BIO_s_mem());
154 if (ASN1_TIME_print(bio
, tm
))
155 write
= BIO_read(bio
, buf
, len
-1);
162 int Ssl::matchX509CommonNames(X509
*peer_cert
, void *check_data
, int (*check_func
)(void *check_data
, ASN1_STRING
*cn_data
))
166 X509_NAME
*name
= X509_get_subject_name(peer_cert
);
168 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
)) {
170 ASN1_STRING
*cn_data
= X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name
, i
));
172 if ( (*check_func
)(check_data
, cn_data
) == 0)
176 STACK_OF(GENERAL_NAME
) * altnames
;
177 altnames
= (STACK_OF(GENERAL_NAME
)*)X509_get_ext_d2i(peer_cert
, NID_subject_alt_name
, NULL
, NULL
);
180 int numalts
= sk_GENERAL_NAME_num(altnames
);
181 for (int i
= 0; i
< numalts
; ++i
) {
182 const GENERAL_NAME
*check
= sk_GENERAL_NAME_value(altnames
, i
);
183 if (check
->type
!= GEN_DNS
) {
186 ASN1_STRING
*cn_data
= check
->d
.dNSName
;
188 if ( (*check_func
)(check_data
, cn_data
) == 0) {
189 sk_GENERAL_NAME_pop_free(altnames
, GENERAL_NAME_free
);
193 sk_GENERAL_NAME_pop_free(altnames
, GENERAL_NAME_free
);
198 static int check_domain( void *check_data
, ASN1_STRING
*cn_data
)
201 const char *server
= (const char *)check_data
;
203 if (cn_data
->length
> (int)sizeof(cn
) - 1) {
204 return 1; //if does not fit our buffer just ignore
206 char *s
= reinterpret_cast<char*>(cn_data
->data
);
208 for (int i
= 0; i
< cn_data
->length
; ++i
, ++d
, ++s
) {
210 return 1; // always a domain mismatch. contains 0x00
213 cn
[cn_data
->length
] = '\0';
214 debugs(83, 4, "Verifying server domain " << server
<< " to certificate name/subjectAltName " << cn
);
215 return matchDomainName(server
, cn
[0] == '*' ? cn
+ 1 : cn
);
218 bool Ssl::checkX509ServerValidity(X509
*cert
, const char *server
)
220 return matchX509CommonNames(cert
, (void *)server
, check_domain
);
223 /// \ingroup ServerProtocolSSLInternal
225 ssl_verify_cb(int ok
, X509_STORE_CTX
* ctx
)
227 // preserve original ctx->error before SSL_ calls can overwrite it
228 Ssl::ssl_error_t error_no
= ok
? SSL_ERROR_NONE
: ctx
->error
;
230 char buffer
[256] = "";
231 SSL
*ssl
= (SSL
*)X509_STORE_CTX_get_ex_data(ctx
, SSL_get_ex_data_X509_STORE_CTX_idx());
232 Security::ContextPtr sslctx
= SSL_get_SSL_CTX(ssl
);
233 SBuf
*server
= (SBuf
*)SSL_get_ex_data(ssl
, ssl_ex_index_server
);
234 void *dont_verify_domain
= SSL_CTX_get_ex_data(sslctx
, ssl_ctx_ex_index_dont_verify_domain
);
235 ACLChecklist
*check
= (ACLChecklist
*)SSL_get_ex_data(ssl
, ssl_ex_index_cert_error_check
);
236 X509
*peeked_cert
= (X509
*)SSL_get_ex_data(ssl
, ssl_ex_index_ssl_peeked_cert
);
237 X509
*peer_cert
= ctx
->cert
;
239 X509_NAME_oneline(X509_get_subject_name(peer_cert
), buffer
,
242 // detect infinite loops
243 uint32_t *validationCounter
= static_cast<uint32_t *>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_validation_counter
));
244 if (!validationCounter
) {
245 validationCounter
= new uint32_t(1);
246 SSL_set_ex_data(ssl
, ssl_ex_index_ssl_validation_counter
, validationCounter
);
248 // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
249 (*validationCounter
)++;
252 if ((*validationCounter
) >= SQUID_CERT_VALIDATION_ITERATION_MAX
) {
253 ok
= 0; // or the validation loop will never stop
254 error_no
= SQUID_X509_V_ERR_INFINITE_VALIDATION
;
255 debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
256 *validationCounter
<< " iterations while checking " << buffer
);
260 debugs(83, 5, "SSL Certificate signature OK: " << buffer
);
262 // Check for domain mismatch only if the current certificate is the peer certificate.
263 if (!dont_verify_domain
&& server
&& peer_cert
== X509_STORE_CTX_get_current_cert(ctx
)) {
264 if (!Ssl::checkX509ServerValidity(peer_cert
, server
->c_str())) {
265 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer
<< " does not match domainname " << server
);
267 error_no
= SQUID_X509_V_ERR_DOMAIN_MISMATCH
;
272 if (ok
&& peeked_cert
) {
273 // Check whether the already peeked certificate matches the new one.
274 if (X509_cmp(peer_cert
, peeked_cert
) != 0) {
275 debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer
<< " does not match peeked certificate");
277 error_no
= SQUID_X509_V_ERR_CERT_CHANGE
;
282 X509
*broken_cert
= X509_STORE_CTX_get_current_cert(ctx
);
284 broken_cert
= peer_cert
;
286 Ssl::CertErrors
*errs
= static_cast<Ssl::CertErrors
*>(SSL_get_ex_data(ssl
, ssl_ex_index_ssl_errors
));
288 const int depth
= X509_STORE_CTX_get_error_depth(ctx
);
289 errs
= new Ssl::CertErrors(Ssl::CertError(error_no
, broken_cert
, depth
));
290 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_errors
, (void *)errs
)) {
291 debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer
);
295 } else // remember another error number
296 errs
->push_back_unique(Ssl::CertError(error_no
, broken_cert
));
298 if (const char *err_descr
= Ssl::GetErrorDescr(error_no
))
299 debugs(83, 5, err_descr
<< ": " << buffer
);
301 debugs(83, DBG_IMPORTANT
, "SSL unknown certificate error " << error_no
<< " in " << buffer
);
303 // Check if the certificate error can be bypassed.
304 // Infinity validation loop errors can not bypassed.
305 if (error_no
!= SQUID_X509_V_ERR_INFINITE_VALIDATION
) {
307 ACLFilledChecklist
*filledCheck
= Filled(check
);
308 assert(!filledCheck
->sslErrors
);
309 filledCheck
->sslErrors
= new Ssl::CertErrors(Ssl::CertError(error_no
, broken_cert
));
310 filledCheck
->serverCert
.resetAndLock(peer_cert
);
311 if (check
->fastCheck() == ACCESS_ALLOWED
) {
312 debugs(83, 3, "bypassing SSL error " << error_no
<< " in " << buffer
);
315 debugs(83, 5, "confirming SSL error " << error_no
);
317 delete filledCheck
->sslErrors
;
318 filledCheck
->sslErrors
= NULL
;
319 filledCheck
->serverCert
.reset(NULL
);
321 // If the certificate validator is used then we need to allow all errors and
322 // pass them to certficate validator for more processing
323 else if (Ssl::TheConfig
.ssl_crt_validator
) {
329 if (Ssl::TheConfig
.ssl_crt_validator
) {
330 // Check if we have stored certificates chain. Store if not.
331 if (!SSL_get_ex_data(ssl
, ssl_ex_index_ssl_cert_chain
)) {
332 STACK_OF(X509
) *certStack
= X509_STORE_CTX_get1_chain(ctx
);
333 if (certStack
&& !SSL_set_ex_data(ssl
, ssl_ex_index_ssl_cert_chain
, certStack
))
334 sk_X509_pop_free(certStack
, X509_free
);
338 if (!ok
&& !SSL_get_ex_data(ssl
, ssl_ex_index_ssl_error_detail
) ) {
340 // Find the broken certificate. It may be intermediate.
341 X509
*broken_cert
= peer_cert
; // reasonable default if search fails
342 // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
343 if (error_no
!= SQUID_X509_V_ERR_DOMAIN_MISMATCH
) {
344 if (X509
*last_used_cert
= X509_STORE_CTX_get_current_cert(ctx
))
345 broken_cert
= last_used_cert
;
348 Ssl::ErrorDetail
*errDetail
=
349 new Ssl::ErrorDetail(error_no
, peer_cert
, broken_cert
);
351 if (!SSL_set_ex_data(ssl
, ssl_ex_index_ssl_error_detail
, errDetail
)) {
352 debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer
);
360 // "dup" function for SSL_get_ex_new_index("cert_err_check")
362 ssl_dupAclChecklist(CRYPTO_EX_DATA
*, CRYPTO_EX_DATA
*, void *,
365 // We do not support duplication of ACLCheckLists.
366 // If duplication is needed, we can count copies with cbdata.
371 // "free" function for SSL_get_ex_new_index("cert_err_check")
373 ssl_freeAclChecklist(void *, void *ptr
, CRYPTO_EX_DATA
*,
376 delete static_cast<ACLChecklist
*>(ptr
); // may be NULL
379 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
381 ssl_free_ErrorDetail(void *, void *ptr
, CRYPTO_EX_DATA
*,
384 Ssl::ErrorDetail
*errDetail
= static_cast <Ssl::ErrorDetail
*>(ptr
);
389 ssl_free_SslErrors(void *, void *ptr
, CRYPTO_EX_DATA
*,
392 Ssl::CertErrors
*errs
= static_cast <Ssl::CertErrors
*>(ptr
);
396 // "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
398 ssl_free_int(void *, void *ptr
, CRYPTO_EX_DATA
*,
401 uint32_t *counter
= static_cast <uint32_t *>(ptr
);
405 /// \ingroup ServerProtocolSSLInternal
406 /// Callback handler function to release STACK_OF(X509) "ex" data stored
407 /// in an SSL object.
409 ssl_free_CertChain(void *, void *ptr
, CRYPTO_EX_DATA
*,
412 STACK_OF(X509
) *certsChain
= static_cast <STACK_OF(X509
) *>(ptr
);
413 sk_X509_pop_free(certsChain
,X509_free
);
416 // "free" function for X509 certificates
418 ssl_free_X509(void *, void *ptr
, CRYPTO_EX_DATA
*,
421 X509
*cert
= static_cast <X509
*>(ptr
);
425 // "free" function for SBuf
427 ssl_free_SBuf(void *, void *ptr
, CRYPTO_EX_DATA
*,
430 SBuf
*buf
= static_cast <SBuf
*>(ptr
);
435 Ssl::Initialize(void)
437 static bool initialized
= false;
442 SSL_load_error_strings();
443 SSLeay_add_ssl_algorithms();
445 #if HAVE_OPENSSL_ENGINE_H
446 if (::Config
.SSL
.ssl_engine
) {
448 if (!(e
= ENGINE_by_id(::Config
.SSL
.ssl_engine
)))
449 fatalf("Unable to find SSL engine '%s'\n", ::Config
.SSL
.ssl_engine
);
451 if (!ENGINE_set_default(e
, ENGINE_METHOD_ALL
)) {
452 const int ssl_error
= ERR_get_error();
453 fatalf("Failed to initialise SSL engine: %s\n", ERR_error_string(ssl_error
, NULL
));
457 if (::Config
.SSL
.ssl_engine
)
458 fatalf("Your OpenSSL has no SSL engine support\n");
461 const char *defName
= ::Config
.SSL
.certSignHash
? ::Config
.SSL
.certSignHash
: SQUID_SSL_SIGN_HASH_IF_NONE
;
462 Ssl::DefaultSignHash
= EVP_get_digestbyname(defName
);
463 if (!Ssl::DefaultSignHash
)
464 fatalf("Sign hash '%s' is not supported\n", defName
);
466 ssl_ex_index_server
= SSL_get_ex_new_index(0, (void *) "server", NULL
, NULL
, ssl_free_SBuf
);
467 ssl_ctx_ex_index_dont_verify_domain
= SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL
, NULL
, NULL
);
468 ssl_ex_index_cert_error_check
= SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL
, &ssl_dupAclChecklist
, &ssl_freeAclChecklist
);
469 ssl_ex_index_ssl_error_detail
= SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL
, NULL
, &ssl_free_ErrorDetail
);
470 ssl_ex_index_ssl_peeked_cert
= SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL
, NULL
, &ssl_free_X509
);
471 ssl_ex_index_ssl_errors
= SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL
, NULL
, &ssl_free_SslErrors
);
472 ssl_ex_index_ssl_cert_chain
= SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL
, NULL
, &ssl_free_CertChain
);
473 ssl_ex_index_ssl_validation_counter
= SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL
, NULL
, &ssl_free_int
);
476 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
478 ssl_info_cb(const SSL
*ssl
, int where
, int ret
)
481 if ((where
& SSL_CB_HANDSHAKE_DONE
) != 0) {
482 // disable renegotiation (CVE-2009-3555)
483 ssl
->s3
->flags
|= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
;
489 configureSslContext(Security::ContextPtr sslContext
, AnyP::PortCfg
&port
)
492 SSL_CTX_set_options(sslContext
, port
.secure
.parsedOptions
);
494 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
495 SSL_CTX_set_info_callback(sslContext
, ssl_info_cb
);
498 if (port
.sslContextSessionId
)
499 SSL_CTX_set_session_id_context(sslContext
, (const unsigned char *)port
.sslContextSessionId
, strlen(port
.sslContextSessionId
));
501 if (port
.secure
.parsedFlags
& SSL_FLAG_NO_SESSION_REUSE
) {
502 SSL_CTX_set_session_cache_mode(sslContext
, SSL_SESS_CACHE_OFF
);
505 if (Config
.SSL
.unclean_shutdown
) {
506 debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
508 SSL_CTX_set_quiet_shutdown(sslContext
, 1);
511 if (!port
.secure
.sslCipher
.isEmpty()) {
512 debugs(83, 5, "Using chiper suite " << port
.secure
.sslCipher
<< ".");
514 if (!SSL_CTX_set_cipher_list(sslContext
, port
.secure
.sslCipher
.c_str())) {
515 ssl_error
= ERR_get_error();
516 debugs(83, DBG_CRITICAL
, "ERROR: Failed to set SSL cipher suite '" << port
.secure
.sslCipher
<< "': " << ERR_error_string(ssl_error
, NULL
));
521 debugs(83, 9, "Setting RSA key generation callback.");
522 SSL_CTX_set_tmp_rsa_callback(sslContext
, ssl_temp_rsa_cb
);
524 port
.secure
.updateContextEecdh(sslContext
);
525 port
.secure
.updateContextCa(sslContext
);
527 if (port
.clientCA
.get()) {
529 if (STACK_OF(X509_NAME
) *clientca
= SSL_dup_CA_list(port
.clientCA
.get())) {
530 SSL_CTX_set_client_CA_list(sslContext
, clientca
);
532 ssl_error
= ERR_get_error();
533 debugs(83, DBG_CRITICAL
, "ERROR: Failed to dupe the client CA list: " << ERR_error_string(ssl_error
, NULL
));
537 if (port
.secure
.parsedFlags
& SSL_FLAG_DELAYED_AUTH
) {
538 debugs(83, 9, "Not requesting client certificates until acl processing requires one");
539 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, NULL
);
541 debugs(83, 9, "Requiring client certificates.");
542 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, ssl_verify_cb
);
545 port
.secure
.updateContextCrl(sslContext
);
548 debugs(83, 9, "Not requiring any client certificates");
549 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, NULL
);
552 if (port
.secure
.parsedFlags
& SSL_FLAG_DONT_VERIFY_DOMAIN
)
553 SSL_CTX_set_ex_data(sslContext
, ssl_ctx_ex_index_dont_verify_domain
, (void *) -1);
555 setSessionCallbacks(sslContext
);
561 sslCreateServerContext(AnyP::PortCfg
&port
)
563 Security::ContextPtr
sslContext(port
.secure
.createBlankContext());
567 if (!SSL_CTX_use_certificate(sslContext
, port
.signingCert
.get())) {
568 const int ssl_error
= ERR_get_error();
569 const auto &keys
= port
.secure
.certs
.front();
570 debugs(83, DBG_CRITICAL
, "ERROR: Failed to acquire TLS certificate '" << keys
.certFile
<< "': " << ERR_error_string(ssl_error
, NULL
));
571 SSL_CTX_free(sslContext
);
575 if (!SSL_CTX_use_PrivateKey(sslContext
, port
.signPkey
.get())) {
576 const int ssl_error
= ERR_get_error();
577 const auto &keys
= port
.secure
.certs
.front();
578 debugs(83, DBG_CRITICAL
, "ERROR: Failed to acquire TLS private key '" << keys
.privateKeyFile
<< "': " << ERR_error_string(ssl_error
, NULL
));
579 SSL_CTX_free(sslContext
);
583 Ssl::addChainToSslContext(sslContext
, port
.certsToChain
.get());
586 debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
588 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
589 ssl_error = ERR_get_error();
590 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
591 SSL_CTX_free(sslContext);
595 debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
596 ssl_ask_password(sslContext, keyfile);
598 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
599 ssl_error = ERR_get_error();
600 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
601 SSL_CTX_free(sslContext);
605 debugs(83, 5, "Comparing private and public SSL keys.");
607 if (!SSL_CTX_check_private_key(sslContext)) {
608 ssl_error = ERR_get_error();
609 debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
610 keyfile << "': " << ERR_error_string(ssl_error, NULL));
611 SSL_CTX_free(sslContext);
616 if (!configureSslContext(sslContext
, port
)) {
617 debugs(83, DBG_CRITICAL
, "ERROR: Configuring static SSL context");
618 SSL_CTX_free(sslContext
);
626 sslCreateClientContext(Security::PeerOptions
&peer
, long options
, long fl
)
628 Security::ContextPtr
sslContext(peer
.createBlankContext());
632 SSL_CTX_set_options(sslContext
, options
);
634 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
635 SSL_CTX_set_info_callback(sslContext
, ssl_info_cb
);
638 if (!peer
.sslCipher
.isEmpty()) {
639 debugs(83, 5, "Using chiper suite " << peer
.sslCipher
<< ".");
641 const char *cipher
= peer
.sslCipher
.c_str();
642 if (!SSL_CTX_set_cipher_list(sslContext
, cipher
)) {
643 const int ssl_error
= ERR_get_error();
644 fatalf("Failed to set SSL cipher suite '%s': %s\n",
645 cipher
, ERR_error_string(ssl_error
, NULL
));
649 if (!peer
.certs
.empty()) {
650 // TODO: support loading multiple cert/key pairs
651 auto &keys
= peer
.certs
.front();
652 if (!keys
.certFile
.isEmpty()) {
653 debugs(83, DBG_IMPORTANT
, "Using certificate in " << keys
.certFile
);
655 const char *certfile
= keys
.certFile
.c_str();
656 if (!SSL_CTX_use_certificate_chain_file(sslContext
, certfile
)) {
657 const int ssl_error
= ERR_get_error();
658 fatalf("Failed to acquire SSL certificate '%s': %s\n",
659 certfile
, ERR_error_string(ssl_error
, NULL
));
662 debugs(83, DBG_IMPORTANT
, "Using private key in " << keys
.privateKeyFile
);
663 const char *keyfile
= keys
.privateKeyFile
.c_str();
664 ssl_ask_password(sslContext
, keyfile
);
666 if (!SSL_CTX_use_PrivateKey_file(sslContext
, keyfile
, SSL_FILETYPE_PEM
)) {
667 const int ssl_error
= ERR_get_error();
668 fatalf("Failed to acquire SSL private key '%s': %s\n",
669 keyfile
, ERR_error_string(ssl_error
, NULL
));
672 debugs(83, 5, "Comparing private and public SSL keys.");
674 if (!SSL_CTX_check_private_key(sslContext
)) {
675 const int ssl_error
= ERR_get_error();
676 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
677 certfile
, keyfile
, ERR_error_string(ssl_error
, NULL
));
682 debugs(83, 9, "Setting RSA key generation callback.");
683 SSL_CTX_set_tmp_rsa_callback(sslContext
, ssl_temp_rsa_cb
);
685 if (fl
& SSL_FLAG_DONT_VERIFY_PEER
) {
686 debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!");
687 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, NULL
);
689 debugs(83, 9, "Setting certificate verification callback.");
690 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, ssl_verify_cb
);
696 /// \ingroup ServerProtocolSSLInternal
698 ssl_read_method(int fd
, char *buf
, int len
)
700 SSL
*ssl
= fd_table
[fd
].ssl
;
705 if (!SSL_is_init_finished(ssl
)) {
712 i
= SSL_read(ssl
, buf
, len
);
714 if (i
> 0 && SSL_pending(ssl
) > 0) {
715 debugs(83, 2, "SSL FD " << fd
<< " is pending");
716 fd_table
[fd
].flags
.read_pending
= true;
718 fd_table
[fd
].flags
.read_pending
= false;
723 /// \ingroup ServerProtocolSSLInternal
725 ssl_write_method(int fd
, const char *buf
, int len
)
727 SSL
*ssl
= fd_table
[fd
].ssl
;
730 if (!SSL_is_init_finished(ssl
)) {
735 i
= SSL_write(ssl
, buf
, len
);
741 ssl_shutdown_method(SSL
*ssl
)
746 /// \ingroup ServerProtocolSSLInternal
748 ssl_get_attribute(X509_NAME
* name
, const char *attribute_name
)
750 static char buffer
[1024];
755 if (strcmp(attribute_name
, "DN") == 0) {
756 X509_NAME_oneline(name
, buffer
, sizeof(buffer
));
760 nid
= OBJ_txt2nid((char *) attribute_name
);
763 debugs(83, DBG_IMPORTANT
, "WARNING: Unknown SSL attribute name '" << attribute_name
<< "'");
767 X509_NAME_get_text_by_NID(name
, nid
, buffer
, sizeof(buffer
));
770 return *buffer
? buffer
: NULL
;
773 /// \ingroup ServerProtocolSSLInternal
775 Ssl::GetX509UserAttribute(X509
* cert
, const char *attribute_name
)
783 name
= X509_get_subject_name(cert
);
785 ret
= ssl_get_attribute(name
, attribute_name
);
791 Ssl::GetX509Fingerprint(X509
* cert
, const char *)
793 static char buf
[1024];
798 unsigned char md
[EVP_MAX_MD_SIZE
];
799 if (!X509_digest(cert
, EVP_sha1(), md
, &n
))
802 assert(3 * n
+ 1 < sizeof(buf
));
805 for (unsigned int i
=0; i
< n
; ++i
, s
+= 3) {
806 const char term
= (i
+ 1 < n
) ? ':' : '\0';
807 snprintf(s
, 4, "%02X%c", md
[i
], term
);
813 /// \ingroup ServerProtocolSSLInternal
815 Ssl::GetX509CAAttribute(X509
* cert
, const char *attribute_name
)
824 name
= X509_get_issuer_name(cert
);
826 ret
= ssl_get_attribute(name
, attribute_name
);
831 const char *sslGetUserAttribute(SSL
*ssl
, const char *attribute_name
)
836 X509
*cert
= SSL_get_peer_certificate(ssl
);
838 const char *attr
= Ssl::GetX509UserAttribute(cert
, attribute_name
);
844 const char *sslGetCAAttribute(SSL
*ssl
, const char *attribute_name
)
849 X509
*cert
= SSL_get_peer_certificate(ssl
);
851 const char *attr
= Ssl::GetX509CAAttribute(cert
, attribute_name
);
858 sslGetUserEmail(SSL
* ssl
)
860 return sslGetUserAttribute(ssl
, "emailAddress");
864 sslGetUserCertificatePEM(SSL
*ssl
)
868 static char *str
= NULL
;
877 cert
= SSL_get_peer_certificate(ssl
);
882 mem
= BIO_new(BIO_s_mem());
884 PEM_write_bio_X509(mem
, cert
);
886 len
= BIO_get_mem_data(mem
, &ptr
);
888 str
= (char *)xmalloc(len
+ 1);
890 memcpy(str
, ptr
, len
);
902 sslGetUserCertificateChainPEM(SSL
*ssl
)
904 STACK_OF(X509
) *chain
;
906 static char *str
= NULL
;
916 chain
= SSL_get_peer_cert_chain(ssl
);
919 return sslGetUserCertificatePEM(ssl
);
921 mem
= BIO_new(BIO_s_mem());
923 for (i
= 0; i
< sk_X509_num(chain
); ++i
) {
924 X509
*cert
= sk_X509_value(chain
, i
);
925 PEM_write_bio_X509(mem
, cert
);
928 len
= BIO_get_mem_data(mem
, &ptr
);
930 str
= (char *)xmalloc(len
+ 1);
931 memcpy(str
, ptr
, len
);
939 /// Create SSL context and apply ssl certificate and private key to it.
941 Ssl::createSSLContext(Security::CertPointer
& x509
, Ssl::EVP_PKEY_Pointer
& pkey
, AnyP::PortCfg
&port
)
943 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
944 Ssl::SSL_CTX_Pointer
sslContext(SSL_CTX_new(TLS_server_method()));
946 Ssl::SSL_CTX_Pointer
sslContext(SSL_CTX_new(SSLv23_server_method()));
949 if (!SSL_CTX_use_certificate(sslContext
.get(), x509
.get()))
952 if (!SSL_CTX_use_PrivateKey(sslContext
.get(), pkey
.get()))
955 if (!configureSslContext(sslContext
.get(), port
))
958 return sslContext
.release();
962 Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data
, AnyP::PortCfg
&port
)
964 Security::CertPointer cert
;
965 Ssl::EVP_PKEY_Pointer pkey
;
966 if (!readCertAndPrivateKeyFromMemory(cert
, pkey
, data
) || !cert
|| !pkey
)
969 return createSSLContext(cert
, pkey
, port
);
973 Ssl::generateSslContext(CertificateProperties
const &properties
, AnyP::PortCfg
&port
)
975 Security::CertPointer cert
;
976 Ssl::EVP_PKEY_Pointer pkey
;
977 if (!generateSslCertificate(cert
, pkey
, properties
) || !cert
|| !pkey
)
980 return createSSLContext(cert
, pkey
, port
);
984 Ssl::configureSSL(SSL
*ssl
, CertificateProperties
const &properties
, AnyP::PortCfg
&port
)
986 Security::CertPointer cert
;
987 Ssl::EVP_PKEY_Pointer pkey
;
988 if (!generateSslCertificate(cert
, pkey
, properties
))
997 if (!SSL_use_certificate(ssl
, cert
.get()))
1000 if (!SSL_use_PrivateKey(ssl
, pkey
.get()))
1007 Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL
*ssl
, const char *data
, AnyP::PortCfg
&port
)
1009 Security::CertPointer cert
;
1010 Ssl::EVP_PKEY_Pointer pkey
;
1011 if (!readCertAndPrivateKeyFromMemory(cert
, pkey
, data
))
1017 if (!SSL_use_certificate(ssl
, cert
.get()))
1020 if (!SSL_use_PrivateKey(ssl
, pkey
.get()))
1026 bool Ssl::verifySslCertificate(Security::ContextPtr sslContext
, CertificateProperties
const &properties
)
1028 // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
1029 // Try to retrieve certificate directly from Security::ContextPtr object
1030 #if SQUID_USE_SSLGETCERTIFICATE_HACK
1031 X509
***pCert
= (X509
***)sslContext
->cert
;
1032 X509
* cert
= pCert
&& *pCert
? **pCert
: NULL
;
1033 #elif SQUID_SSLGETCERTIFICATE_BUGGY
1037 // Temporary ssl for getting X509 certificate from SSL_CTX.
1038 Ssl::SSL_Pointer
ssl(SSL_new(sslContext
));
1039 X509
* cert
= SSL_get_certificate(ssl
.get());
1043 ASN1_TIME
* time_notBefore
= X509_get_notBefore(cert
);
1044 ASN1_TIME
* time_notAfter
= X509_get_notAfter(cert
);
1045 bool ret
= (X509_cmp_current_time(time_notBefore
) < 0 && X509_cmp_current_time(time_notAfter
) > 0);
1049 return certificateMatchesProperties(cert
, properties
);
1053 Ssl::setClientSNI(SSL
*ssl
, const char *fqdn
)
1055 //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
1056 // if the TLS servername extension (SNI) is enabled in openssl library.
1057 #if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
1058 if (!SSL_set_tlsext_host_name(ssl
, fqdn
)) {
1059 const int ssl_error
= ERR_get_error();
1060 debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
1061 ERR_error_string(ssl_error
, NULL
) << "\n");
1066 debugs(83, 7, "no support for TLS servername extension (SNI)\n");
1071 void Ssl::addChainToSslContext(Security::ContextPtr sslContext
, STACK_OF(X509
) *chain
)
1076 for (int i
= 0; i
< sk_X509_num(chain
); ++i
) {
1077 X509
*cert
= sk_X509_value(chain
, i
);
1078 if (SSL_CTX_add_extra_chain_cert(sslContext
, cert
)) {
1079 // increase the certificate lock
1080 CRYPTO_add(&(cert
->references
),1,CRYPTO_LOCK_X509
);
1082 const int ssl_error
= ERR_get_error();
1083 debugs(83, DBG_IMPORTANT
, "WARNING: can not add certificate to SSL context chain: " << ERR_error_string(ssl_error
, NULL
));
1089 Ssl::loadCerts(const char *certsFile
, Ssl::CertsIndexedList
&list
)
1091 BIO
*in
= BIO_new_file(certsFile
, "r");
1093 debugs(83, DBG_IMPORTANT
, "Failed to open '" << certsFile
<< "' to load certificates");
1098 while((aCert
= PEM_read_bio_X509(in
, NULL
, NULL
, NULL
))) {
1099 static char buffer
[2048];
1100 X509_NAME_oneline(X509_get_subject_name(aCert
), buffer
, sizeof(buffer
));
1101 list
.insert(std::pair
<SBuf
, X509
*>(SBuf(buffer
), aCert
));
1103 debugs(83, 4, "Loaded " << list
.size() << " certificates from file: '" << certsFile
<< "'");
1108 /// quickly find a certificate with a given issuer in Ssl::CertsIndexedList.
1110 findCertByIssuerFast(X509_STORE_CTX
*ctx
, Ssl::CertsIndexedList
&list
, X509
*cert
)
1112 static char buffer
[2048];
1114 if (X509_NAME
*issuerName
= X509_get_issuer_name(cert
))
1115 X509_NAME_oneline(issuerName
, buffer
, sizeof(buffer
));
1119 const auto ret
= list
.equal_range(SBuf(buffer
));
1120 for (Ssl::CertsIndexedList::iterator it
= ret
.first
; it
!= ret
.second
; ++it
) {
1121 X509
*issuer
= it
->second
;
1122 if (ctx
->check_issued(ctx
, cert
, issuer
)) {
1129 /// slowly find a certificate with a given issuer using linear search
1131 findCertByIssuerSlowly(X509_STORE_CTX
*ctx
, STACK_OF(X509
) *sk
, X509
*cert
)
1133 const int skItemsNum
= sk_X509_num(sk
);
1134 for (int i
= 0; i
< skItemsNum
; ++i
) {
1135 X509
*issuer
= sk_X509_value(sk
, i
);
1136 if (ctx
->check_issued(ctx
, cert
, issuer
))
1142 /// add missing issuer certificates to untrustedCerts
1144 completeIssuers(X509_STORE_CTX
*ctx
, STACK_OF(X509
) *untrustedCerts
)
1146 debugs(83, 2, "completing " << sk_X509_num(untrustedCerts
) << " OpenSSL untrusted certs using " << SquidUntrustedCerts
.size() << " configured untrusted certificates");
1148 int depth
= ctx
->param
->depth
;
1149 X509
*current
= ctx
->cert
;
1151 for (i
= 0; current
&& (i
< depth
); ++i
) {
1152 if (ctx
->check_issued(ctx
, current
, current
)) {
1153 // either ctx->cert is itself self-signed or untrustedCerts
1154 // aready contain the self-signed current certificate
1158 // untrustedCerts is short, not worth indexing
1159 X509
*issuer
= findCertByIssuerSlowly(ctx
, untrustedCerts
, current
);
1161 if ((issuer
= findCertByIssuerFast(ctx
, SquidUntrustedCerts
, current
)))
1162 sk_X509_push(untrustedCerts
, issuer
);
1168 debugs(83, 2, "exceeded the maximum certificate chain length: " << depth
);
1171 /// OpenSSL certificate validation callback.
1173 untrustedToStoreCtx_cb(X509_STORE_CTX
*ctx
,void *data
)
1175 debugs(83, 4, "Try to use pre-downloaded intermediate certificates\n");
1177 // OpenSSL already maintains ctx->untrusted but we cannot modify
1178 // internal OpenSSL list directly. We have to give OpenSSL our own
1179 // list, but it must include certificates on the OpenSSL ctx->untrusted
1180 STACK_OF(X509
) *oldUntrusted
= ctx
->untrusted
;
1181 STACK_OF(X509
) *sk
= sk_X509_dup(oldUntrusted
); // oldUntrusted is always not NULL
1182 completeIssuers(ctx
, sk
);
1183 X509_STORE_CTX_set_chain(ctx
, sk
); // No locking/unlocking, just sets ctx->untrusted
1184 int ret
= X509_verify_cert(ctx
);
1185 X509_STORE_CTX_set_chain(ctx
, oldUntrusted
); // Set back the old untrusted list
1186 sk_X509_free(sk
); // Release sk list
1191 Ssl::useSquidUntrusted(SSL_CTX
*sslContext
)
1193 if (SquidUntrustedCerts
.size() > 0)
1194 SSL_CTX_set_cert_verify_callback(sslContext
, untrustedToStoreCtx_cb
, NULL
);
1196 SSL_CTX_set_cert_verify_callback(sslContext
, NULL
, NULL
);
1200 Ssl::loadSquidUntrusted(const char *path
)
1202 return Ssl::loadCerts(path
, SquidUntrustedCerts
);
1206 Ssl::unloadSquidUntrusted()
1208 if (SquidUntrustedCerts
.size()) {
1209 for (Ssl::CertsIndexedList::iterator it
= SquidUntrustedCerts
.begin(); it
!= SquidUntrustedCerts
.end(); ++it
) {
1210 X509_free(it
->second
);
1212 SquidUntrustedCerts
.clear();
1217 \ingroup ServerProtocolSSLInternal
1218 * Read certificate from file.
1219 * See also: static readSslX509Certificate function, gadgets.cc file
1221 static X509
* readSslX509CertificatesChain(char const * certFilename
, STACK_OF(X509
)* chain
)
1225 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
1228 if (!BIO_read_filename(bio
.get(), certFilename
))
1230 X509
*certificate
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
);
1232 if (certificate
&& chain
) {
1234 if (X509_check_issued(certificate
, certificate
) == X509_V_OK
)
1235 debugs(83, 5, "Certificate is self-signed, will not be chained");
1237 // and add to the chain any other certificate exist in the file
1238 while (X509
*ca
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
)) {
1239 if (!sk_X509_push(chain
, ca
))
1240 debugs(83, DBG_IMPORTANT
, "WARNING: unable to add CA certificate to cert chain");
1248 void Ssl::readCertChainAndPrivateKeyFromFiles(Security::CertPointer
& cert
, EVP_PKEY_Pointer
& pkey
, X509_STACK_Pointer
& chain
, char const * certFilename
, char const * keyFilename
)
1250 if (keyFilename
== NULL
)
1251 keyFilename
= certFilename
;
1253 if (certFilename
== NULL
)
1254 certFilename
= keyFilename
;
1256 debugs(83, DBG_IMPORTANT
, "Using certificate in " << certFilename
);
1259 chain
.reset(sk_X509_new_null());
1261 debugs(83, DBG_IMPORTANT
, "WARNING: unable to allocate memory for cert chain");
1262 // XXX: ssl_ask_password_cb needs SSL_CTX_set_default_passwd_cb_userdata()
1263 // so this may not fully work iff Config.Program.ssl_password is set.
1264 pem_password_cb
*cb
= ::Config
.Program
.ssl_password
? &ssl_ask_password_cb
: NULL
;
1265 pkey
.reset(readSslPrivateKey(keyFilename
, cb
));
1266 cert
.reset(readSslX509CertificatesChain(certFilename
, chain
.get()));
1267 if (!pkey
|| !cert
|| !X509_check_private_key(cert
.get(), pkey
.get())) {
1273 bool Ssl::generateUntrustedCert(Security::CertPointer
&untrustedCert
, EVP_PKEY_Pointer
&untrustedPkey
, Security::CertPointer
const &cert
, EVP_PKEY_Pointer
const & pkey
)
1275 // Generate the self-signed certificate, using a hard-coded subject prefix
1276 Ssl::CertificateProperties certProperties
;
1277 if (const char *cn
= CommonHostName(cert
.get())) {
1278 certProperties
.commonName
= "Not trusted by \"";
1279 certProperties
.commonName
+= cn
;
1280 certProperties
.commonName
+= "\"";
1281 } else if (const char *org
= getOrganization(cert
.get())) {
1282 certProperties
.commonName
= "Not trusted by \"";
1283 certProperties
.commonName
+= org
;
1284 certProperties
.commonName
+= "\"";
1286 certProperties
.commonName
= "Not trusted";
1287 certProperties
.setCommonName
= true;
1288 // O, OU, and other CA subject fields will be mimicked
1289 // Expiration date and other common properties will be mimicked
1290 certProperties
.signAlgorithm
= Ssl::algSignSelf
;
1291 certProperties
.signWithPkey
.resetAndLock(pkey
.get());
1292 certProperties
.mimicCert
.resetAndLock(cert
.get());
1293 return Ssl::generateSslCertificate(untrustedCert
, untrustedPkey
, certProperties
);
1297 SslCreate(Security::ContextPtr sslContext
, const int fd
, Ssl::Bio::Type type
, const char *squidCtx
)
1300 debugs(83, DBG_IMPORTANT
, "Gone connection");
1304 const char *errAction
= NULL
;
1306 if (SSL
*ssl
= SSL_new(sslContext
)) {
1307 // without BIO, we would call SSL_set_fd(ssl, fd) instead
1308 if (BIO
*bio
= Ssl::Bio::Create(fd
, type
)) {
1309 Ssl::Bio::Link(ssl
, bio
); // cannot fail
1311 fd_table
[fd
].ssl
= ssl
;
1312 fd_table
[fd
].read_method
= &ssl_read_method
;
1313 fd_table
[fd
].write_method
= &ssl_write_method
;
1314 fd_note(fd
, squidCtx
);
1318 errCode
= ERR_get_error();
1319 errAction
= "failed to initialize I/O";
1322 errCode
= ERR_get_error();
1323 errAction
= "failed to allocate handle";
1326 debugs(83, DBG_IMPORTANT
, "ERROR: " << squidCtx
<< ' ' << errAction
<<
1327 ": " << ERR_error_string(errCode
, NULL
));
1332 Ssl::CreateClient(Security::ContextPtr sslContext
, const int fd
, const char *squidCtx
)
1334 return SslCreate(sslContext
, fd
, Ssl::Bio::BIO_TO_SERVER
, squidCtx
);
1338 Ssl::CreateServer(Security::ContextPtr sslContext
, const int fd
, const char *squidCtx
)
1340 return SslCreate(sslContext
, fd
, Ssl::Bio::BIO_TO_CLIENT
, squidCtx
);
1343 Ssl::CertError::CertError(ssl_error_t anErr
, X509
*aCert
, int aDepth
): code(anErr
), depth(aDepth
)
1345 cert
.resetAndLock(aCert
);
1348 Ssl::CertError::CertError(CertError
const &err
): code(err
.code
), depth(err
.depth
)
1350 cert
.resetAndLock(err
.cert
.get());
1354 Ssl::CertError::operator = (const CertError
&old
)
1357 cert
.resetAndLock(old
.cert
.get());
1362 Ssl::CertError::operator == (const CertError
&ce
) const
1364 return code
== ce
.code
&& cert
.get() == ce
.cert
.get();
1368 Ssl::CertError::operator != (const CertError
&ce
) const
1370 return code
!= ce
.code
|| cert
.get() != ce
.cert
.get();
1374 store_session_cb(SSL
*ssl
, SSL_SESSION
*session
)
1376 if (!SslSessionCache
)
1379 debugs(83, 5, "Request to store SSL Session ");
1381 SSL_SESSION_set_timeout(session
, Config
.SSL
.session_ttl
);
1383 unsigned char *id
= session
->session_id
;
1384 unsigned int idlen
= session
->session_id_length
;
1385 unsigned char key
[MEMMAP_SLOT_KEY_SIZE
];
1386 // Session ids are of size 32bytes. They should always fit to a
1387 // MemMap::Slot::key
1388 assert(idlen
<= MEMMAP_SLOT_KEY_SIZE
);
1389 memset(key
, 0, sizeof(key
));
1390 memcpy(key
, id
, idlen
);
1392 Ipc::MemMap::Slot
*slotW
= SslSessionCache
->openForWriting((const cache_key
*)key
, pos
);
1394 int lenRequired
= i2d_SSL_SESSION(session
, NULL
);
1395 if (lenRequired
< MEMMAP_SLOT_DATA_SIZE
) {
1396 unsigned char *p
= (unsigned char *)slotW
->p
;
1397 lenRequired
= i2d_SSL_SESSION(session
, &p
);
1398 slotW
->set(key
, NULL
, lenRequired
, squid_curtime
+ Config
.SSL
.session_ttl
);
1400 SslSessionCache
->closeForWriting(pos
);
1401 debugs(83, 5, "wrote an ssl session entry of size " << lenRequired
<< " at pos " << pos
);
1407 remove_session_cb(SSL_CTX
*, SSL_SESSION
*sessionID
)
1409 if (!SslSessionCache
)
1412 debugs(83, 5, "Request to remove corrupted or not valid SSL Session ");
1414 Ipc::MemMap::Slot
const *slot
= SslSessionCache
->openForReading((const cache_key
*)sessionID
, pos
);
1417 SslSessionCache
->closeForReading(pos
);
1419 // What if we are not able to remove the session?
1420 // Maybe schedule a job to remove it later?
1421 // For now we just have an invalid entry in cache until will be expired
1422 // The openSSL will reject it when we try to use it
1423 SslSessionCache
->free(pos
);
1426 static SSL_SESSION
*
1427 get_session_cb(SSL
*, unsigned char *sessionID
, int len
, int *copy
)
1429 if (!SslSessionCache
)
1432 SSL_SESSION
*session
= NULL
;
1433 const unsigned int *p
;
1434 p
= (unsigned int *)sessionID
;
1435 debugs(83, 5, "Request to search for SSL Session of len:" <<
1436 len
<< p
[0] << ":" << p
[1]);
1439 Ipc::MemMap::Slot
const *slot
= SslSessionCache
->openForReading((const cache_key
*)sessionID
, pos
);
1441 if (slot
->expire
> squid_curtime
) {
1442 const unsigned char *ptr
= slot
->p
;
1443 session
= d2i_SSL_SESSION(NULL
, &ptr
, slot
->pSize
);
1444 debugs(83, 5, "Session retrieved from cache at pos " << pos
);
1446 debugs(83, 5, "Session in cache expired");
1447 SslSessionCache
->closeForReading(pos
);
1451 debugs(83, 5, "Failed to retrieved from cache\n");
1453 // With the parameter copy the callback can require the SSL engine
1454 // to increment the reference count of the SSL_SESSION object, Normally
1455 // the reference count is not incremented and therefore the session must
1456 // not be explicitly freed with SSL_SESSION_free(3).
1462 setSessionCallbacks(Security::ContextPtr ctx
)
1464 if (SslSessionCache
) {
1465 SSL_CTX_set_session_cache_mode(ctx
, SSL_SESS_CACHE_SERVER
|SSL_SESS_CACHE_NO_INTERNAL
);
1466 SSL_CTX_sess_set_new_cb(ctx
, store_session_cb
);
1467 SSL_CTX_sess_set_remove_cb(ctx
, remove_session_cb
);
1468 SSL_CTX_sess_set_get_cb(ctx
, get_session_cb
);
1475 for (AnyP::PortCfgPointer s
= HttpPortList
; s
!= NULL
; s
= s
->next
) {
1476 if (s
->secure
.encryptTransport
)
1478 if (s
->flags
.tunnelSslBumping
)
1485 #define SSL_SESSION_ID_SIZE 32
1486 #define SSL_SESSION_MAX_SIZE 10*1024
1489 Ssl::initialize_session_cache()
1492 if (!isSslServer()) //no need to configure ssl session cache.
1495 // Check if the MemMap keys and data are enough big to hold
1496 // session ids and session data
1497 assert(SSL_SESSION_ID_SIZE
>= MEMMAP_SLOT_KEY_SIZE
);
1498 assert(SSL_SESSION_MAX_SIZE
>= MEMMAP_SLOT_DATA_SIZE
);
1500 int configuredItems
= ::Config
.SSL
.sessionCacheSize
/ sizeof(Ipc::MemMap::Slot
);
1501 if (IamWorkerProcess() && configuredItems
)
1502 SslSessionCache
= new Ipc::MemMap(SslSessionCacheName
);
1504 SslSessionCache
= NULL
;
1508 for (AnyP::PortCfgPointer s
= HttpPortList
; s
!= NULL
; s
= s
->next
) {
1509 if (s
->secure
.staticContext
.get())
1510 setSessionCallbacks(s
->secure
.staticContext
.get());
1515 destruct_session_cache()
1517 delete SslSessionCache
;
1520 /// initializes shared memory segments used by MemStore
1521 class SharedSessionCacheRr
: public Ipc::Mem::RegisteredRunner
1524 /* RegisteredRunner API */
1525 SharedSessionCacheRr(): owner(NULL
) {}
1526 virtual void useConfig();
1527 virtual ~SharedSessionCacheRr();
1530 virtual void create();
1533 Ipc::MemMap::Owner
*owner
;
1536 RunnerRegistrationEntry(SharedSessionCacheRr
);
1539 SharedSessionCacheRr::useConfig()
1541 Ipc::Mem::RegisteredRunner::useConfig();
1545 SharedSessionCacheRr::create()
1547 if (!isSslServer()) //no need to configure ssl session cache.
1551 items
= Config
.SSL
.sessionCacheSize
/ sizeof(Ipc::MemMap::Slot
);
1553 owner
= Ipc::MemMap::Init(SslSessionCacheName
, items
);
1556 SharedSessionCacheRr::~SharedSessionCacheRr()
1561 #endif /* USE_OPENSSL */