]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/support.cc
Bug 4599 pt5: various OpenSSL-1.x API compatibility fixes
[thirdparty/squid.git] / src / ssl / support.cc
CommitLineData
f484cdf5 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
f484cdf5 3 *
bbc27441
AJ
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.
f484cdf5 7 */
8
bbc27441
AJ
9/* DEBUG: section 83 SSL accelerator support */
10
582c2af2 11#include "squid.h"
454e8283 12
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.
15 */
cb4f4424 16#if USE_OPENSSL
454e8283 17
c0941a6a 18#include "acl/FilledChecklist.h"
86660d64 19#include "anyp/PortCfg.h"
ed6e9fb9 20#include "fatal.h"
b3a8ae1b 21#include "fd.h"
582c2af2
FC
22#include "fde.h"
23#include "globals.h"
86c63190 24#include "ipc/MemMap.h"
92e3827b 25#include "security/CertError.h"
4d5904f7 26#include "SquidConfig.h"
10a69fc0 27#include "SquidTime.h"
b3a8ae1b 28#include "ssl/bio.h"
2cef0ca6 29#include "ssl/Config.h"
4d16918e 30#include "ssl/ErrorDetail.h"
95d2589c 31#include "ssl/gadgets.h"
602d9612 32#include "ssl/support.h"
fc54b8d2 33#include "URL.h"
f484cdf5 34
1a30fdf5 35#include <cerrno>
21d845b1 36
55369ae6
AR
37// TODO: Move ssl_ex_index_* global variables from global.cc here.
38int ssl_ex_index_ssl_untrusted_chain = -1;
39
824d4656
AJ
40Ipc::MemMap *Ssl::SessionCache = NULL;
41const char *Ssl::SessionCacheName = "ssl_session_cache";
10a69fc0 42
55369ae6
AR
43static Ssl::CertsIndexedList SquidUntrustedCerts;
44
3c26b00a
CT
45const EVP_MD *Ssl::DefaultSignHash = NULL;
46
ba6fffba 47std::vector<const char *> Ssl::BumpModeStr = {
caf3666d
AR
48 "none",
49 "client-first",
50 "server-first",
5d65362c
CT
51 "peek",
52 "stare",
53 "bump",
7f4e9b73 54 "splice",
ba6fffba
EB
55 "terminate"
56 /*,"err"*/
caf3666d
AR
57};
58
63be0a78 59/**
60 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
61 \ingroup ServerProtocolSSLAPI
62 */
63
64/// \ingroup ServerProtocolSSLInternal
307b83b7 65static int
66ssl_ask_password_cb(char *buf, int size, int rwflag, void *userdata)
67{
68 FILE *in;
69 int len = 0;
70 char cmdline[1024];
71
72 snprintf(cmdline, sizeof(cmdline), "\"%s\" \"%s\"", Config.Program.ssl_password, (const char *)userdata);
73 in = popen(cmdline, "r");
74
75 if (fgets(buf, size, in))
76
77 len = strlen(buf);
78
79 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
5e263176 80 --len;
307b83b7 81
82 buf[len] = '\0';
83
84 pclose(in);
85
86 return len;
87}
88
63be0a78 89/// \ingroup ServerProtocolSSLInternal
307b83b7 90static void
91ssl_ask_password(SSL_CTX * context, const char * prompt)
92{
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);
96 }
97}
98
b7afb10f 99#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
f484cdf5 100static RSA *
e6ccf245 101ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen)
f484cdf5 102{
e01f02ed 103 static RSA *rsa_512 = NULL;
104 static RSA *rsa_1024 = NULL;
105 RSA *rsa = NULL;
106 int newkey = 0;
f484cdf5 107
e01f02ed 108 switch (keylen) {
109
110 case 512:
111
112 if (!rsa_512) {
113 rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
114 newkey = 1;
115 }
116
117 rsa = rsa_512;
118 break;
119
120 case 1024:
121
122 if (!rsa_1024) {
123 rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
124 newkey = 1;
125 }
126
127 rsa = rsa_1024;
128 break;
129
130 default:
e0236918 131 debugs(83, DBG_IMPORTANT, "ssl_temp_rsa_cb: Unexpected key length " << keylen);
e01f02ed 132 return NULL;
133 }
134
135 if (rsa == NULL) {
e0236918 136 debugs(83, DBG_IMPORTANT, "ssl_temp_rsa_cb: Failed to generate key " << keylen);
e01f02ed 137 return NULL;
138 }
139
140 if (newkey) {
014adac1 141 if (Debug::Enabled(83, 5))
e01f02ed 142 PEM_write_RSAPrivateKey(debug_log, rsa, NULL, NULL, 0, NULL, NULL);
143
e0236918 144 debugs(83, DBG_IMPORTANT, "Generated ephemeral RSA key of length " << keylen);
e01f02ed 145 }
62e76326 146
f484cdf5 147 return rsa;
148}
b7afb10f
CT
149#endif
150
151static void
152maybeSetupRsaCallback(Security::ContextPointer &ctx)
153{
154#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
155 debugs(83, 9, "Setting RSA key generation callback.");
156 SSL_CTX_set_tmp_rsa_callback(ctx.get(), ssl_temp_rsa_cb);
157#endif
158}
f484cdf5 159
4d16918e
CT
160int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len)
161{
162 BIO *bio;
163 int write = 0;
164 bio = BIO_new(BIO_s_mem());
165 if (bio) {
e34763f4
A
166 if (ASN1_TIME_print(bio, tm))
167 write = BIO_read(bio, buf, len-1);
168 BIO_free(bio);
4d16918e
CT
169 }
170 buf[write]='\0';
171 return write;
172}
173
174int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data))
175{
176 assert(peer_cert);
177
178 X509_NAME *name = X509_get_subject_name(peer_cert);
179
180 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)) {
e34763f4 181
4d16918e
CT
182 ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
183
184 if ( (*check_func)(check_data, cn_data) == 0)
185 return 1;
186 }
187
188 STACK_OF(GENERAL_NAME) * altnames;
189 altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
190
191 if (altnames) {
192 int numalts = sk_GENERAL_NAME_num(altnames);
d7ae3534 193 for (int i = 0; i < numalts; ++i) {
4d16918e
CT
194 const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
195 if (check->type != GEN_DNS) {
196 continue;
197 }
198 ASN1_STRING *cn_data = check->d.dNSName;
e34763f4 199
40dd2b59
CT
200 if ( (*check_func)(check_data, cn_data) == 0) {
201 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
4d16918e 202 return 1;
40dd2b59 203 }
4d16918e
CT
204 }
205 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
206 }
207 return 0;
208}
209
210static int check_domain( void *check_data, ASN1_STRING *cn_data)
211{
212 char cn[1024];
213 const char *server = (const char *)check_data;
214
abbd7825
CT
215 if (cn_data->length == 0)
216 return 1; // zero length cn, ignore
217
218 if (cn_data->length > (int)sizeof(cn) - 1)
4d16918e 219 return 1; //if does not fit our buffer just ignore
abbd7825 220
0f7f4cfc
AJ
221 char *s = reinterpret_cast<char*>(cn_data->data);
222 char *d = cn;
223 for (int i = 0; i < cn_data->length; ++i, ++d, ++s) {
224 if (*s == '\0')
225 return 1; // always a domain mismatch. contains 0x00
226 *d = *s;
227 }
4d16918e
CT
228 cn[cn_data->length] = '\0';
229 debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn);
abbd7825 230 return matchDomainName(server, (cn[0] == '*' ? cn + 1 : cn), mdnRejectSubsubDomains);
4d16918e
CT
231}
232
8eb0a7ee
CT
233bool Ssl::checkX509ServerValidity(X509 *cert, const char *server)
234{
235 return matchX509CommonNames(cert, (void *)server, check_domain);
236}
237
2a268a06
CT
238#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
239static inline X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
240{
241 return ctx->cert;
242}
243#endif
244
63be0a78 245/// \ingroup ServerProtocolSSLInternal
f484cdf5 246static int
247ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
248{
7698a79c 249 // preserve original ctx->error before SSL_ calls can overwrite it
2a268a06 250 Security::ErrorCode error_no = ok ? SSL_ERROR_NONE : X509_STORE_CTX_get_error(ctx);
7698a79c
CT
251
252 char buffer[256] = "";
a7ad6e4e 253 SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
0476ec45 254 SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
68920ad8 255 SBuf *server = (SBuf *)SSL_get_ex_data(ssl, ssl_ex_index_server);
a7ad6e4e 256 void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
815eaa44 257 ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
e7bcc25f 258 X509 *peeked_cert = (X509 *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_peeked_cert);
92e3827b 259 Security::CertPointer peer_cert;
2a268a06 260 peer_cert.resetAndLock(X509_STORE_CTX_get0_cert(ctx));
f484cdf5 261
92e3827b 262 X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), buffer, sizeof(buffer));
a7ad6e4e 263
0ad3ff51
CT
264 // detect infinite loops
265 uint32_t *validationCounter = static_cast<uint32_t *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_validation_counter));
266 if (!validationCounter) {
267 validationCounter = new uint32_t(1);
268 SSL_set_ex_data(ssl, ssl_ex_index_ssl_validation_counter, validationCounter);
269 } else {
270 // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
271 (*validationCounter)++;
272 }
273
274 if ((*validationCounter) >= SQUID_CERT_VALIDATION_ITERATION_MAX) {
275 ok = 0; // or the validation loop will never stop
276 error_no = SQUID_X509_V_ERR_INFINITE_VALIDATION;
277 debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
278 *validationCounter << " iterations while checking " << buffer);
279 }
280
a7ad6e4e 281 if (ok) {
bf8fe701 282 debugs(83, 5, "SSL Certificate signature OK: " << buffer);
62e76326 283
4747ea4c 284 // Check for domain mismatch only if the current certificate is the peer certificate.
92e3827b
AJ
285 if (!dont_verify_domain && server && peer_cert.get() == X509_STORE_CTX_get_current_cert(ctx)) {
286 if (!Ssl::checkX509ServerValidity(peer_cert.get(), server->c_str())) {
815eaa44 287 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
62e76326 288 ok = 0;
4d16918e 289 error_no = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
62e76326 290 }
291 }
7698a79c 292 }
0db46e4f 293
e7bcc25f 294 if (ok && peeked_cert) {
7a957a93 295 // Check whether the already peeked certificate matches the new one.
92e3827b 296 if (X509_cmp(peer_cert.get(), peeked_cert) != 0) {
e7bcc25f
CT
297 debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer << " does not match peeked certificate");
298 ok = 0;
299 error_no = SQUID_X509_V_ERR_CERT_CHANGE;
300 }
301 }
302
7698a79c 303 if (!ok) {
92e3827b
AJ
304 Security::CertPointer broken_cert;
305 broken_cert.resetAndLock(X509_STORE_CTX_get_current_cert(ctx));
62a7607e
CT
306 if (!broken_cert)
307 broken_cert = peer_cert;
308
92e3827b 309 Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
e36bc333 310 const int depth = X509_STORE_CTX_get_error_depth(ctx);
7a957a93 311 if (!errs) {
92e3827b 312 errs = new Security::CertErrors(Security::CertError(error_no, broken_cert, depth));
7a957a93 313 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) {
fb2178bb 314 debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer);
7a957a93
AR
315 delete errs;
316 errs = NULL;
fb2178bb 317 }
87f237a9 318 } else // remember another error number
92e3827b 319 errs->push_back_unique(Security::CertError(error_no, broken_cert, depth));
fb2178bb 320
7698a79c 321 if (const char *err_descr = Ssl::GetErrorDescr(error_no))
cf09bec7
CT
322 debugs(83, 5, err_descr << ": " << buffer);
323 else
7698a79c
CT
324 debugs(83, DBG_IMPORTANT, "SSL unknown certificate error " << error_no << " in " << buffer);
325
0ad3ff51
CT
326 // Check if the certificate error can be bypassed.
327 // Infinity validation loop errors can not bypassed.
328 if (error_no != SQUID_X509_V_ERR_INFINITE_VALIDATION) {
329 if (check) {
330 ACLFilledChecklist *filledCheck = Filled(check);
331 assert(!filledCheck->sslErrors);
92e3827b
AJ
332 filledCheck->sslErrors = new Security::CertErrors(Security::CertError(error_no, broken_cert));
333 filledCheck->serverCert = peer_cert;
0ad3ff51
CT
334 if (check->fastCheck() == ACCESS_ALLOWED) {
335 debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
336 ok = 1;
337 } else {
338 debugs(83, 5, "confirming SSL error " << error_no);
339 }
340 delete filledCheck->sslErrors;
341 filledCheck->sslErrors = NULL;
58a5291c 342 filledCheck->serverCert.reset();
7698a79c 343 }
0ad3ff51
CT
344 // If the certificate validator is used then we need to allow all errors and
345 // pass them to certficate validator for more processing
346 else if (Ssl::TheConfig.ssl_crt_validator) {
7698a79c 347 ok = 1;
7698a79c 348 }
815eaa44 349 }
a7ad6e4e 350 }
62e76326 351
081be7eb
CT
352 if (Ssl::TheConfig.ssl_crt_validator) {
353 // Check if we have stored certificates chain. Store if not.
354 if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
355 STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
356 if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
357 sk_X509_pop_free(certStack, X509_free);
358 }
359 }
360
7698a79c 361 if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
f622c461
MF
362
363 // Find the broken certificate. It may be intermediate.
92e3827b 364 Security::CertPointer broken_cert(peer_cert); // reasonable default if search fails
f622c461
MF
365 // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
366 if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
92e3827b
AJ
367 if (auto *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
368 broken_cert.resetAndLock(last_used_cert);
f622c461
MF
369 }
370
92e3827b
AJ
371 auto *errDetail = new Ssl::ErrorDetail(error_no, peer_cert.get(), broken_cert.get());
372 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) {
4d16918e
CT
373 debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer);
374 delete errDetail;
375 }
376 }
377
f484cdf5 378 return ok;
379}
380
815eaa44 381// "dup" function for SSL_get_ex_new_index("cert_err_check")
2a268a06
CT
382#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
383static int
384ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *,
385 int, long, void *)
386#else
815eaa44 387static int
388ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
26ac0430 389 int, long, void *)
2a268a06 390#endif
26ac0430 391{
815eaa44 392 // We do not support duplication of ACLCheckLists.
393 // If duplication is needed, we can count copies with cbdata.
394 assert(false);
395 return 0;
396}
397
398// "free" function for SSL_get_ex_new_index("cert_err_check")
399static void
400ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
26ac0430
AJ
401 int, long, void *)
402{
815eaa44 403 delete static_cast<ACLChecklist *>(ptr); // may be NULL
404}
a7ad6e4e 405
4d16918e
CT
406// "free" function for SSL_get_ex_new_index("ssl_error_detail")
407static void
408ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *,
409 int, long, void *)
410{
411 Ssl::ErrorDetail *errDetail = static_cast <Ssl::ErrorDetail *>(ptr);
412 delete errDetail;
413}
414
fb2178bb 415static void
7a957a93 416ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
87f237a9 417 int, long, void *)
fb2178bb 418{
92e3827b 419 Security::CertErrors *errs = static_cast <Security::CertErrors*>(ptr);
7a957a93 420 delete errs;
fb2178bb
CT
421}
422
0ad3ff51
CT
423// "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
424static void
425ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *,
3cc296c4 426 int, long, void *)
0ad3ff51
CT
427{
428 uint32_t *counter = static_cast <uint32_t *>(ptr);
429 delete counter;
430}
431
4747ea4c
CT
432/// \ingroup ServerProtocolSSLInternal
433/// Callback handler function to release STACK_OF(X509) "ex" data stored
434/// in an SSL object.
435static void
436ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *,
437 int, long, void *)
438{
439 STACK_OF(X509) *certsChain = static_cast <STACK_OF(X509) *>(ptr);
440 sk_X509_pop_free(certsChain,X509_free);
441}
442
e7bcc25f
CT
443// "free" function for X509 certificates
444static void
445ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *,
87f237a9 446 int, long, void *)
e7bcc25f
CT
447{
448 X509 *cert = static_cast <X509 *>(ptr);
449 X509_free(cert);
450}
451
c1d50c01 452// "free" function for SBuf
68920ad8
CT
453static void
454ssl_free_SBuf(void *, void *ptr, CRYPTO_EX_DATA *,
455 int, long, void *)
456{
457 SBuf *buf = static_cast <SBuf *>(ptr);
458 delete buf;
459}
460
0a28c16a
AJ
461void
462Ssl::Initialize(void)
f484cdf5 463{
56a35ad1
AR
464 static bool initialized = false;
465 if (initialized)
466 return;
467 initialized = true;
62e76326 468
56a35ad1
AR
469 SSL_load_error_strings();
470 SSLeay_add_ssl_algorithms();
62e76326 471
56a35ad1 472#if HAVE_OPENSSL_ENGINE_H
0a28c16a 473 if (::Config.SSL.ssl_engine) {
56a35ad1 474 ENGINE *e;
0a28c16a
AJ
475 if (!(e = ENGINE_by_id(::Config.SSL.ssl_engine)))
476 fatalf("Unable to find SSL engine '%s'\n", ::Config.SSL.ssl_engine);
56a35ad1
AR
477
478 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
f5518dca 479 const int ssl_error = ERR_get_error();
ea574635 480 fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error));
62e76326 481 }
56a35ad1 482 }
a7ad6e4e 483#else
0a28c16a 484 if (::Config.SSL.ssl_engine)
56a35ad1 485 fatalf("Your OpenSSL has no SSL engine support\n");
a7ad6e4e 486#endif
62e76326 487
0a28c16a 488 const char *defName = ::Config.SSL.certSignHash ? ::Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE;
3c26b00a
CT
489 Ssl::DefaultSignHash = EVP_get_digestbyname(defName);
490 if (!Ssl::DefaultSignHash)
491 fatalf("Sign hash '%s' is not supported\n", defName);
492
fa1cf51e 493 ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, ssl_free_SBuf);
a7ad6e4e 494 ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
815eaa44 495 ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
4d16918e 496 ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail);
e7bcc25f 497 ssl_ex_index_ssl_peeked_cert = SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL, NULL, &ssl_free_X509);
7a957a93 498 ssl_ex_index_ssl_errors = SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL, NULL, &ssl_free_SslErrors);
4747ea4c 499 ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL, NULL, &ssl_free_CertChain);
0ad3ff51 500 ssl_ex_index_ssl_validation_counter = SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL, NULL, &ssl_free_int);
55369ae6
AR
501 ssl_ex_index_ssl_untrusted_chain = SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL, NULL, &ssl_free_CertChain);
502}
503
3834ada4
PM
504#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
505static void
506ssl_info_cb(const SSL *ssl, int where, int ret)
507{
508 (void)ret;
509 if ((where & SSL_CB_HANDSHAKE_DONE) != 0) {
510 // disable renegotiation (CVE-2009-3555)
511 ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
512 }
513}
514#endif
515
86660d64 516static bool
b23f5f9c 517configureSslContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
86660d64
CT
518{
519 int ssl_error;
b23f5f9c 520 SSL_CTX_set_options(ctx.get(), port.secure.parsedOptions);
f484cdf5 521
3834ada4 522#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
b23f5f9c 523 SSL_CTX_set_info_callback(ctx.get(), ssl_info_cb);
3834ada4
PM
524#endif
525
86660d64 526 if (port.sslContextSessionId)
b23f5f9c 527 SSL_CTX_set_session_id_context(ctx.get(), (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
6b2936d5 528
9a622f3e 529 if (port.secure.parsedFlags & SSL_FLAG_NO_SESSION_REUSE) {
b23f5f9c 530 SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_OFF);
b13877cc 531 }
532
a9d79803 533 if (Config.SSL.unclean_shutdown) {
bf8fe701 534 debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
a9d79803 535
b23f5f9c 536 SSL_CTX_set_quiet_shutdown(ctx.get(), 1);
a9d79803 537 }
538
9a622f3e
AJ
539 if (!port.secure.sslCipher.isEmpty()) {
540 debugs(83, 5, "Using chiper suite " << port.secure.sslCipher << ".");
62e76326 541
b23f5f9c 542 if (!SSL_CTX_set_cipher_list(ctx.get(), port.secure.sslCipher.c_str())) {
62e76326 543 ssl_error = ERR_get_error();
ea574635 544 debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << Security::ErrorString(ssl_error));
86660d64 545 return false;
62e76326 546 }
79d4ccdf 547 }
62e76326 548
b7afb10f 549 maybeSetupRsaCallback(ctx);
a7ad6e4e 550
b23f5f9c
AJ
551 port.secure.updateContextEecdh(ctx);
552 port.secure.updateContextCa(ctx);
62e76326 553
86660d64 554 if (port.clientCA.get()) {
8c1ff4ef 555 ERR_clear_error();
e0f4e4e0 556 if (STACK_OF(X509_NAME) *clientca = SSL_dup_CA_list(port.clientCA.get())) {
b23f5f9c 557 SSL_CTX_set_client_CA_list(ctx.get(), clientca);
e0f4e4e0
AR
558 } else {
559 ssl_error = ERR_get_error();
ea574635 560 debugs(83, DBG_CRITICAL, "ERROR: Failed to dupe the client CA list: " << Security::ErrorString(ssl_error));
e0f4e4e0
AR
561 return false;
562 }
62e76326 563
9a622f3e 564 if (port.secure.parsedFlags & SSL_FLAG_DELAYED_AUTH) {
bf8fe701 565 debugs(83, 9, "Not requesting client certificates until acl processing requires one");
b23f5f9c 566 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL);
62e76326 567 } else {
bf8fe701 568 debugs(83, 9, "Requiring client certificates.");
b23f5f9c 569 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
62e76326 570 }
a82a4fe4 571
b23f5f9c 572 port.secure.updateContextCrl(ctx);
a82a4fe4 573
a7ad6e4e 574 } else {
bf8fe701 575 debugs(83, 9, "Not requiring any client certificates");
b23f5f9c 576 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL);
a7ad6e4e 577 }
f484cdf5 578
9a622f3e 579 if (port.secure.parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
b23f5f9c 580 SSL_CTX_set_ex_data(ctx.get(), ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
86660d64 581
b23f5f9c 582 Ssl::SetSessionCallbacks(ctx);
10a69fc0 583
86660d64
CT
584 return true;
585}
586
c75aba02 587bool
b23f5f9c 588Ssl::InitServerContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
86660d64 589{
9ad528b8 590 if (!ctx)
c75aba02 591 return false;
86660d64 592
9ad528b8 593 if (!SSL_CTX_use_certificate(ctx.get(), port.signingCert.get())) {
f5518dca 594 const int ssl_error = ERR_get_error();
d1d72d43 595 const auto &keys = port.secure.certs.front();
ea574635 596 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS certificate '" << keys.certFile << "': " << Security::ErrorString(ssl_error));
c75aba02 597 return false;
86660d64
CT
598 }
599
9ad528b8 600 if (!SSL_CTX_use_PrivateKey(ctx.get(), port.signPkey.get())) {
f5518dca 601 const int ssl_error = ERR_get_error();
d1d72d43 602 const auto &keys = port.secure.certs.front();
ea574635 603 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS private key '" << keys.privateKeyFile << "': " << Security::ErrorString(ssl_error));
c75aba02 604 return false;
86660d64
CT
605 }
606
b23f5f9c 607 Ssl::addChainToSslContext(ctx, port.certsToChain.get());
86660d64
CT
608
609 /* Alternate code;
610 debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
611
9ad528b8 612 if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
86660d64 613 ssl_error = ERR_get_error();
ea574635 614 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << Security::ErrorString(ssl_error));
c75aba02 615 return false;
35105e4b 616 }
617
86660d64 618 debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
9ad528b8 619 ssl_ask_password(ctx.get(), keyfile);
86660d64 620
9ad528b8 621 if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
86660d64 622 ssl_error = ERR_get_error();
ea574635 623 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << Security::ErrorString(ssl_error));
c75aba02 624 return false;
35105e4b 625 }
626
86660d64 627 debugs(83, 5, "Comparing private and public SSL keys.");
35105e4b 628
9ad528b8 629 if (!SSL_CTX_check_private_key(ctx.get())) {
86660d64
CT
630 ssl_error = ERR_get_error();
631 debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
ea574635 632 keyfile << "': " << Security::ErrorString(ssl_error));
c75aba02 633 return false;
86660d64
CT
634 }
635 */
636
b23f5f9c 637 if (!configureSslContext(ctx, port)) {
86660d64 638 debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
c75aba02 639 return false;
86660d64 640 }
62e76326 641
c75aba02 642 return true;
a7ad6e4e 643}
644
c75aba02 645bool
64769c79 646Ssl::InitClientContext(Security::ContextPointer &ctx, Security::PeerOptions &peer, long options, long fl)
d620ae0e 647{
64769c79 648 if (!ctx)
c75aba02 649 return false;
62e76326 650
64769c79 651 SSL_CTX_set_options(ctx.get(), options);
a7ad6e4e 652
3834ada4 653#if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
64769c79 654 SSL_CTX_set_info_callback(ctx.get(), ssl_info_cb);
3834ada4
PM
655#endif
656
d1d72d43
AJ
657 if (!peer.sslCipher.isEmpty()) {
658 debugs(83, 5, "Using chiper suite " << peer.sslCipher << ".");
62e76326 659
d1d72d43 660 const char *cipher = peer.sslCipher.c_str();
64769c79 661 if (!SSL_CTX_set_cipher_list(ctx.get(), cipher)) {
f5518dca 662 const int ssl_error = ERR_get_error();
62e76326 663 fatalf("Failed to set SSL cipher suite '%s': %s\n",
ea574635 664 cipher, Security::ErrorString(ssl_error));
62e76326 665 }
a7ad6e4e 666 }
62e76326 667
332c979d
AJ
668 if (!peer.certs.empty()) {
669 // TODO: support loading multiple cert/key pairs
670 auto &keys = peer.certs.front();
671 if (!keys.certFile.isEmpty()) {
672 debugs(83, DBG_IMPORTANT, "Using certificate in " << keys.certFile);
673
674 const char *certfile = keys.certFile.c_str();
64769c79 675 if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
332c979d
AJ
676 const int ssl_error = ERR_get_error();
677 fatalf("Failed to acquire SSL certificate '%s': %s\n",
ea574635 678 certfile, Security::ErrorString(ssl_error));
332c979d 679 }
62e76326 680
332c979d
AJ
681 debugs(83, DBG_IMPORTANT, "Using private key in " << keys.privateKeyFile);
682 const char *keyfile = keys.privateKeyFile.c_str();
64769c79 683 ssl_ask_password(ctx.get(), keyfile);
62e76326 684
64769c79 685 if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
332c979d
AJ
686 const int ssl_error = ERR_get_error();
687 fatalf("Failed to acquire SSL private key '%s': %s\n",
ea574635 688 keyfile, Security::ErrorString(ssl_error));
332c979d 689 }
62e76326 690
332c979d 691 debugs(83, 5, "Comparing private and public SSL keys.");
62e76326 692
64769c79 693 if (!SSL_CTX_check_private_key(ctx.get())) {
332c979d
AJ
694 const int ssl_error = ERR_get_error();
695 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
ea574635 696 certfile, keyfile, Security::ErrorString(ssl_error));
332c979d 697 }
62e76326 698 }
a7ad6e4e 699 }
62e76326 700
b7afb10f 701 maybeSetupRsaCallback(ctx);
f484cdf5 702
a7ad6e4e 703 if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
48e7baac 704 debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!");
64769c79 705 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL);
a7ad6e4e 706 } else {
bf8fe701 707 debugs(83, 9, "Setting certificate verification callback.");
64769c79 708 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
a7ad6e4e 709 }
f484cdf5 710
c75aba02 711 return true;
f484cdf5 712}
713
63be0a78 714/// \ingroup ServerProtocolSSLInternal
d193a436 715int
e6ccf245 716ssl_read_method(int fd, char *buf, int len)
f484cdf5 717{
33cc0629 718 auto ssl = fd_table[fd].ssl.get();
79d4ccdf 719
6de9e64b 720#if DONT_DO_THIS
721
722 if (!SSL_is_init_finished(ssl)) {
723 errno = ENOTCONN;
724 return -1;
725 }
79d4ccdf 726
6de9e64b 727#endif
728
33cc0629 729 int i = SSL_read(ssl, buf, len);
afc199f9
AR
730 if (i > 0) {
731 (void)VALGRIND_MAKE_MEM_DEFINED(buf, i);
732 }
6de9e64b 733
734 if (i > 0 && SSL_pending(ssl) > 0) {
bf8fe701 735 debugs(83, 2, "SSL FD " << fd << " is pending");
be4d35dc 736 fd_table[fd].flags.read_pending = true;
79d4ccdf 737 } else
be4d35dc 738 fd_table[fd].flags.read_pending = false;
79d4ccdf 739
740 return i;
f484cdf5 741}
742
63be0a78 743/// \ingroup ServerProtocolSSLInternal
d193a436 744int
e6ccf245 745ssl_write_method(int fd, const char *buf, int len)
f484cdf5 746{
33cc0629 747 auto ssl = fd_table[fd].ssl.get();
6de9e64b 748 if (!SSL_is_init_finished(ssl)) {
749 errno = ENOTCONN;
750 return -1;
751 }
752
33cc0629 753 int i = SSL_write(ssl, buf, len);
6de9e64b 754 return i;
f484cdf5 755}
79d4ccdf 756
757void
575d05c4 758ssl_shutdown_method(SSL *ssl)
79d4ccdf 759{
79d4ccdf 760 SSL_shutdown(ssl);
761}
a7ad6e4e 762
63be0a78 763/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 764static const char *
765ssl_get_attribute(X509_NAME * name, const char *attribute_name)
766{
767 static char buffer[1024];
a7ad6e4e 768 buffer[0] = '\0';
769
770 if (strcmp(attribute_name, "DN") == 0) {
62e76326 771 X509_NAME_oneline(name, buffer, sizeof(buffer));
627059a5
AJ
772 } else {
773 int nid = OBJ_txt2nid(const_cast<char *>(attribute_name));
774 if (nid == 0) {
775 debugs(83, DBG_IMPORTANT, "WARNING: Unknown SSL attribute name '" << attribute_name << "'");
776 return nullptr;
777 }
778 X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
a7ad6e4e 779 }
62e76326 780
627059a5 781 return *buffer ? buffer : nullptr;
a7ad6e4e 782}
783
63be0a78 784/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 785const char *
00352183 786Ssl::GetX509UserAttribute(X509 * cert, const char *attribute_name)
a7ad6e4e 787{
a7ad6e4e 788 X509_NAME *name;
23e6c4ae 789 const char *ret;
a7ad6e4e 790
a7ad6e4e 791 if (!cert)
62e76326 792 return NULL;
a7ad6e4e 793
5a4684b6 794 name = X509_get_subject_name(cert);
a7ad6e4e 795
23e6c4ae 796 ret = ssl_get_attribute(name, attribute_name);
797
23e6c4ae 798 return ret;
a7ad6e4e 799}
800
00352183
AR
801const char *
802Ssl::GetX509Fingerprint(X509 * cert, const char *)
803{
804 static char buf[1024];
805 if (!cert)
806 return NULL;
960e100b 807
00352183
AR
808 unsigned int n;
809 unsigned char md[EVP_MAX_MD_SIZE];
810 if (!X509_digest(cert, EVP_sha1(), md, &n))
811 return NULL;
812
813 assert(3 * n + 1 < sizeof(buf));
814
815 char *s = buf;
816 for (unsigned int i=0; i < n; ++i, s += 3) {
817 const char term = (i + 1 < n) ? ':' : '\0';
818 snprintf(s, 4, "%02X%c", md[i], term);
819 }
820
821 return buf;
822}
823
63be0a78 824/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 825const char *
00352183 826Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name)
a7ad6e4e 827{
00352183 828
a7ad6e4e 829 X509_NAME *name;
23e6c4ae 830 const char *ret;
a7ad6e4e 831
a7ad6e4e 832 if (!cert)
62e76326 833 return NULL;
a7ad6e4e 834
5a4684b6 835 name = X509_get_issuer_name(cert);
a7ad6e4e 836
23e6c4ae 837 ret = ssl_get_attribute(name, attribute_name);
838
00352183
AR
839 return ret;
840}
841
842const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name)
843{
844 if (!ssl)
845 return NULL;
846
847 X509 *cert = SSL_get_peer_certificate(ssl);
848
849 const char *attr = Ssl::GetX509UserAttribute(cert, attribute_name);
850
23e6c4ae 851 X509_free(cert);
00352183
AR
852 return attr;
853}
23e6c4ae 854
00352183
AR
855const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name)
856{
857 if (!ssl)
858 return NULL;
859
860 X509 *cert = SSL_get_peer_certificate(ssl);
861
862 const char *attr = Ssl::GetX509CAAttribute(cert, attribute_name);
863
864 X509_free(cert);
865 return attr;
a7ad6e4e 866}
867
a7ad6e4e 868const char *
869sslGetUserEmail(SSL * ssl)
870{
e6ceef10 871 return sslGetUserAttribute(ssl, "emailAddress");
a7ad6e4e 872}
4ac9968f 873
874const char *
875sslGetUserCertificatePEM(SSL *ssl)
876{
877 X509 *cert;
878 BIO *mem;
879 static char *str = NULL;
880 char *ptr;
881 long len;
882
883 safe_free(str);
884
885 if (!ssl)
886 return NULL;
887
888 cert = SSL_get_peer_certificate(ssl);
889
890 if (!cert)
891 return NULL;
892
893 mem = BIO_new(BIO_s_mem());
894
895 PEM_write_bio_X509(mem, cert);
896
4ac9968f 897 len = BIO_get_mem_data(mem, &ptr);
898
899 str = (char *)xmalloc(len + 1);
900
901 memcpy(str, ptr, len);
902
903 str[len] = '\0';
904
905 X509_free(cert);
906
907 BIO_free(mem);
908
909 return str;
910}
3d61c476 911
912const char *
913sslGetUserCertificateChainPEM(SSL *ssl)
914{
915 STACK_OF(X509) *chain;
916 BIO *mem;
917 static char *str = NULL;
918 char *ptr;
919 long len;
920 int i;
921
922 safe_free(str);
923
924 if (!ssl)
925 return NULL;
926
927 chain = SSL_get_peer_cert_chain(ssl);
928
929 if (!chain)
930 return sslGetUserCertificatePEM(ssl);
931
932 mem = BIO_new(BIO_s_mem());
933
d7ae3534 934 for (i = 0; i < sk_X509_num(chain); ++i) {
3d61c476 935 X509 *cert = sk_X509_value(chain, i);
936 PEM_write_bio_X509(mem, cert);
937 }
938
939 len = BIO_get_mem_data(mem, &ptr);
940
941 str = (char *)xmalloc(len + 1);
942 memcpy(str, ptr, len);
943 str[len] = '\0';
944
945 BIO_free(mem);
946
947 return str;
948}
454e8283 949
95d2589c 950/// Create SSL context and apply ssl certificate and private key to it.
0476ec45 951Security::ContextPointer
f97700a0 952Ssl::createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port)
95d2589c 953{
0476ec45 954 Security::ContextPointer ctx(port.secure.createBlankContext());
95d2589c 955
0476ec45
AJ
956 if (!SSL_CTX_use_certificate(ctx.get(), x509.get()))
957 return Security::ContextPointer();
95d2589c 958
0476ec45
AJ
959 if (!SSL_CTX_use_PrivateKey(ctx.get(), pkey.get()))
960 return Security::ContextPointer();
86660d64 961
b23f5f9c 962 if (!configureSslContext(ctx, port))
0476ec45 963 return Security::ContextPointer();
86660d64 964
0476ec45 965 return ctx;
95d2589c
CT
966}
967
0476ec45 968Security::ContextPointer
86660d64 969Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port)
95d2589c 970{
f97700a0 971 Security::CertPointer cert;
95d2589c 972 Ssl::EVP_PKEY_Pointer pkey;
96993ee0 973 if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey)
0476ec45 974 return Security::ContextPointer();
95d2589c 975
86660d64 976 return createSSLContext(cert, pkey, port);
95d2589c
CT
977}
978
0476ec45 979Security::ContextPointer
86660d64 980Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port)
95d2589c 981{
f97700a0 982 Security::CertPointer cert;
95d2589c 983 Ssl::EVP_PKEY_Pointer pkey;
96993ee0 984 if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey)
0476ec45 985 return Security::ContextPointer();
95d2589c 986
86660d64 987 return createSSLContext(cert, pkey, port);
95d2589c
CT
988}
989
d8f0ceab 990void
b23f5f9c 991Ssl::chainCertificatesToSSLContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
d8f0ceab 992{
b23f5f9c 993 assert(ctx);
d8f0ceab
CT
994 // Add signing certificate to the certificates chain
995 X509 *signingCert = port.signingCert.get();
b23f5f9c 996 if (SSL_CTX_add_extra_chain_cert(ctx.get(), signingCert)) {
d8f0ceab 997 // increase the certificate lock
6f2b8700 998 X509_up_ref(signingCert);
d8f0ceab
CT
999 } else {
1000 const int ssl_error = ERR_get_error();
ea574635 1001 debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << Security::ErrorString(ssl_error));
d8f0ceab 1002 }
b23f5f9c 1003 Ssl::addChainToSslContext(ctx, port.certsToChain.get());
d8f0ceab
CT
1004}
1005
1006void
b23f5f9c 1007Ssl::configureUnconfiguredSslContext(Security::ContextPointer &ctx, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port)
d8f0ceab 1008{
b23f5f9c
AJ
1009 if (ctx && signAlgorithm == Ssl::algSignTrusted)
1010 Ssl::chainCertificatesToSSLContext(ctx, port);
d8f0ceab
CT
1011}
1012
d620ae0e
CT
1013bool
1014Ssl::configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
1015{
f97700a0 1016 Security::CertPointer cert;
d620ae0e
CT
1017 Ssl::EVP_PKEY_Pointer pkey;
1018 if (!generateSslCertificate(cert, pkey, properties))
1019 return false;
1020
1021 if (!cert)
1022 return false;
1023
1024 if (!pkey)
1025 return false;
1026
1027 if (!SSL_use_certificate(ssl, cert.get()))
1028 return false;
1029
1030 if (!SSL_use_PrivateKey(ssl, pkey.get()))
1031 return false;
1032
1033 return true;
1034}
1035
1036bool
1037Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port)
1038{
f97700a0 1039 Security::CertPointer cert;
d620ae0e
CT
1040 Ssl::EVP_PKEY_Pointer pkey;
1041 if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
1042 return false;
1043
1044 if (!cert || !pkey)
1045 return false;
1046
1047 if (!SSL_use_certificate(ssl, cert.get()))
1048 return false;
1049
1050 if (!SSL_use_PrivateKey(ssl, pkey.get()))
1051 return false;
1052
1053 return true;
1054}
1055
b23f5f9c
AJ
1056bool
1057Ssl::verifySslCertificate(Security::ContextPointer &ctx, CertificateProperties const &properties)
95d2589c 1058{
b8658552 1059 // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
b23f5f9c 1060 // Try to retrieve certificate directly from Security::ContextPointer object
fc321c30 1061#if SQUID_USE_SSLGETCERTIFICATE_HACK
b23f5f9c 1062 X509 ***pCert = (X509 ***)ctx->cert;
b8658552 1063 X509 * cert = pCert && *pCert ? **pCert : NULL;
fc321c30
CT
1064#elif SQUID_SSLGETCERTIFICATE_BUGGY
1065 X509 * cert = NULL;
1066 assert(0);
b8658552 1067#else
95d2589c 1068 // Temporary ssl for getting X509 certificate from SSL_CTX.
b23f5f9c 1069 Security::SessionPointer ssl(SSL_new(ctx.get()));
95d2589c 1070 X509 * cert = SSL_get_certificate(ssl.get());
b8658552
CT
1071#endif
1072 if (!cert)
1073 return false;
95d2589c
CT
1074 ASN1_TIME * time_notBefore = X509_get_notBefore(cert);
1075 ASN1_TIME * time_notAfter = X509_get_notAfter(cert);
1076 bool ret = (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
e7bcc25f
CT
1077 if (!ret)
1078 return false;
1079
4ece76b2 1080 return certificateMatchesProperties(cert, properties);
95d2589c
CT
1081}
1082
253749a8
CT
1083bool
1084Ssl::setClientSNI(SSL *ssl, const char *fqdn)
1085{
1086 //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
1087 // if the TLS servername extension (SNI) is enabled in openssl library.
1088#if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
1089 if (!SSL_set_tlsext_host_name(ssl, fqdn)) {
1090 const int ssl_error = ERR_get_error();
1091 debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
ea574635 1092 Security::ErrorString(ssl_error) << "\n");
253749a8
CT
1093 return false;
1094 }
1095 return true;
1096#else
1097 debugs(83, 7, "no support for TLS servername extension (SNI)\n");
1098 return false;
1099#endif
1100}
1101
b23f5f9c
AJ
1102void
1103Ssl::addChainToSslContext(Security::ContextPointer &ctx, STACK_OF(X509) *chain)
a594dbfa
CT
1104{
1105 if (!chain)
1106 return;
1107
d7ae3534 1108 for (int i = 0; i < sk_X509_num(chain); ++i) {
a594dbfa 1109 X509 *cert = sk_X509_value(chain, i);
b23f5f9c 1110 if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert)) {
a594dbfa 1111 // increase the certificate lock
6f2b8700 1112 X509_up_ref(cert);
a594dbfa
CT
1113 } else {
1114 const int ssl_error = ERR_get_error();
ea574635 1115 debugs(83, DBG_IMPORTANT, "WARNING: can not add certificate to SSL context chain: " << Security::ErrorString(ssl_error));
a594dbfa
CT
1116 }
1117 }
1118}
1119
55369ae6
AR
1120static const char *
1121hasAuthorityInfoAccessCaIssuers(X509 *cert)
1122{
1123 AUTHORITY_INFO_ACCESS *info;
1124 if (!cert)
168d2b30 1125 return nullptr;
4b5ea8a6 1126 info = static_cast<AUTHORITY_INFO_ACCESS *>(X509_get_ext_d2i(cert, NID_info_access, NULL, NULL));
55369ae6 1127 if (!info)
168d2b30 1128 return nullptr;
55369ae6
AR
1129
1130 static char uri[MAX_URL];
1131 uri[0] = '\0';
1132
1133 for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
1134 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
1135 if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers) {
1136 if (ad->location->type == GEN_URI) {
2a268a06
CT
1137 xstrncpy(uri,
1138 reinterpret_cast<const char *>(
1139#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
1140 ASN1_STRING_data(ad->location->d.uniformResourceIdentifier)
1141#else
1142 ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier)
1143#endif
1144 ),
1145 sizeof(uri));
55369ae6
AR
1146 }
1147 break;
1148 }
1149 }
1150 AUTHORITY_INFO_ACCESS_free(info);
168d2b30 1151 return uri[0] != '\0' ? uri : nullptr;
55369ae6
AR
1152}
1153
866be11c
CT
1154bool
1155Ssl::loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
1156{
1157 BIO *in = BIO_new_file(certsFile, "r");
1158 if (!in) {
1159 debugs(83, DBG_IMPORTANT, "Failed to open '" << certsFile << "' to load certificates");
1160 return false;
1161 }
1162
1163 X509 *aCert;
1164 while((aCert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
1165 static char buffer[2048];
1166 X509_NAME_oneline(X509_get_subject_name(aCert), buffer, sizeof(buffer));
1167 list.insert(std::pair<SBuf, X509 *>(SBuf(buffer), aCert));
1168 }
1169 debugs(83, 4, "Loaded " << list.size() << " certificates from file: '" << certsFile << "'");
1170 BIO_free(in);
1171 return true;
1172}
1173
6c4905ef
CT
1174/// quickly find the issuer certificate of a certificate cert in the
1175/// Ssl::CertsIndexedList list
55369ae6 1176static X509 *
6c4905ef 1177findCertIssuerFast(Ssl::CertsIndexedList &list, X509 *cert)
55369ae6
AR
1178{
1179 static char buffer[2048];
1180
1181 if (X509_NAME *issuerName = X509_get_issuer_name(cert))
1182 X509_NAME_oneline(issuerName, buffer, sizeof(buffer));
1183 else
1184 return NULL;
1185
1186 const auto ret = list.equal_range(SBuf(buffer));
1187 for (Ssl::CertsIndexedList::iterator it = ret.first; it != ret.second; ++it) {
1188 X509 *issuer = it->second;
1189 if (X509_check_issued(cert, issuer)) {
1190 return issuer;
1191 }
1192 }
1193 return NULL;
1194}
1195
6c4905ef 1196/// slowly find the issuer certificate of a given cert using linear search
a34d1d2d
CT
1197static bool
1198findCertIssuer(Security::CertList const &list, X509 *cert)
55369ae6 1199{
a34d1d2d
CT
1200 for (Security::CertList::const_iterator it = list.begin(); it != list.end(); ++it) {
1201 if (X509_check_issued(it->get(), cert) == X509_V_OK)
1202 return true;
55369ae6 1203 }
a34d1d2d 1204 return false;
55369ae6
AR
1205}
1206
1207const char *
a34d1d2d 1208Ssl::uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates)
55369ae6 1209{
a34d1d2d 1210 if (!cert || !serverCertificates.size())
168d2b30 1211 return nullptr;
55369ae6 1212
a34d1d2d 1213 if (!findCertIssuer(serverCertificates, cert)) {
168d2b30 1214 //if issuer is missing
6c4905ef 1215 if (!findCertIssuerFast(SquidUntrustedCerts, cert)) {
3945c91d 1216 // and issuer not found in local untrusted certificates database
55369ae6
AR
1217 if (const char *issuerUri = hasAuthorityInfoAccessCaIssuers(cert)) {
1218 // There is a URI where we can download a certificate.
55369ae6
AR
1219 return issuerUri;
1220 }
1221 }
1222 }
168d2b30 1223 return nullptr;
55369ae6
AR
1224}
1225
1226void
a34d1d2d 1227Ssl::missingChainCertificatesUrls(std::queue<SBuf> &URIs, Security::CertList const &serverCertificates)
55369ae6 1228{
a34d1d2d 1229 if (!serverCertificates.size())
55369ae6
AR
1230 return;
1231
4b5ea8a6
CT
1232 for (const auto &i : serverCertificates) {
1233 if (const char *issuerUri = uriOfIssuerIfMissing(i.get(), serverCertificates))
55369ae6
AR
1234 URIs.push(SBuf(issuerUri));
1235 }
1236}
1237
1238void
1239Ssl::SSL_add_untrusted_cert(SSL *ssl, X509 *cert)
1240{
1241 STACK_OF(X509) *untrustedStack = static_cast <STACK_OF(X509) *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
1242 if (!untrustedStack) {
1243 untrustedStack = sk_X509_new_null();
1244 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain, untrustedStack)) {
168d2b30
CT
1245 sk_X509_pop_free(untrustedStack, X509_free);
1246 throw TextException("Failed to attach untrusted certificates chain");
55369ae6
AR
1247 }
1248 }
1249 sk_X509_push(untrustedStack, cert);
1250}
1251
6c4905ef 1252/// Search for the issuer certificate of cert in sk list.
a34d1d2d 1253static X509 *
6c4905ef 1254sk_x509_findIssuer(STACK_OF(X509) *sk, X509 *cert)
a34d1d2d
CT
1255{
1256 if (!sk)
1257 return NULL;
1258
1259 const int skItemsNum = sk_X509_num(sk);
1260 for (int i = 0; i < skItemsNum; ++i) {
1261 X509 *issuer = sk_X509_value(sk, i);
1262 if (X509_check_issued(issuer, cert) == X509_V_OK)
1263 return issuer;
1264 }
1265 return NULL;
1266}
1267
55369ae6
AR
1268/// add missing issuer certificates to untrustedCerts
1269static void
1270completeIssuers(X509_STORE_CTX *ctx, STACK_OF(X509) *untrustedCerts)
1271{
1272 debugs(83, 2, "completing " << sk_X509_num(untrustedCerts) << " OpenSSL untrusted certs using " << SquidUntrustedCerts.size() << " configured untrusted certificates");
1273
2a268a06 1274#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
55369ae6 1275 int depth = ctx->param->depth;
2a268a06
CT
1276#else
1277 const X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx);
1278 int depth = X509_VERIFY_PARAM_get_depth(param);
1279#endif
1280 X509 *current = X509_STORE_CTX_get0_cert(ctx);
55369ae6
AR
1281 int i = 0;
1282 for (i = 0; current && (i < depth); ++i) {
1283 if (X509_check_issued(current, current)) {
1284 // either ctx->cert is itself self-signed or untrustedCerts
1285 // aready contain the self-signed current certificate
1286 break;
1287 }
1288
1289 // untrustedCerts is short, not worth indexing
6c4905ef 1290 X509 *issuer = sk_x509_findIssuer(untrustedCerts, current);
55369ae6 1291 if (!issuer) {
6c4905ef 1292 if ((issuer = findCertIssuerFast(SquidUntrustedCerts, current)))
55369ae6
AR
1293 sk_X509_push(untrustedCerts, issuer);
1294 }
1295 current = issuer;
1296 }
1297
1298 if (i >= depth)
1299 debugs(83, 2, "exceeded the maximum certificate chain length: " << depth);
1300}
1301
1302/// OpenSSL certificate validation callback.
1303static int
1304untrustedToStoreCtx_cb(X509_STORE_CTX *ctx,void *data)
1305{
1306 debugs(83, 4, "Try to use pre-downloaded intermediate certificates\n");
1307
4b5ea8a6 1308 SSL *ssl = static_cast<SSL *>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
55369ae6
AR
1309 STACK_OF(X509) *sslUntrustedStack = static_cast <STACK_OF(X509) *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
1310
1311 // OpenSSL already maintains ctx->untrusted but we cannot modify
1312 // internal OpenSSL list directly. We have to give OpenSSL our own
1313 // list, but it must include certificates on the OpenSSL ctx->untrusted
2a268a06 1314#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
55369ae6 1315 STACK_OF(X509) *oldUntrusted = ctx->untrusted;
2a268a06
CT
1316#else
1317 STACK_OF(X509) *oldUntrusted = X509_STORE_CTX_get0_untrusted(ctx);
1318#endif
55369ae6
AR
1319 STACK_OF(X509) *sk = sk_X509_dup(oldUntrusted); // oldUntrusted is always not NULL
1320
1321 for (int i = 0; i < sk_X509_num(sslUntrustedStack); ++i) {
1322 X509 *cert = sk_X509_value(sslUntrustedStack, i);
1323 sk_X509_push(sk, cert);
1324 }
1325
1326 // If the local untrusted certificates internal database is used
1327 // run completeIssuers to add missing certificates if possible.
1328 if (SquidUntrustedCerts.size() > 0)
1329 completeIssuers(ctx, sk);
1330
1331 X509_STORE_CTX_set_chain(ctx, sk); // No locking/unlocking, just sets ctx->untrusted
1332 int ret = X509_verify_cert(ctx);
2a268a06 1333#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
55369ae6 1334 X509_STORE_CTX_set_chain(ctx, oldUntrusted); // Set back the old untrusted list
2a268a06
CT
1335#else
1336 X509_STORE_CTX_set0_untrusted(ctx, oldUntrusted);
1337#endif
55369ae6
AR
1338 sk_X509_free(sk); // Release sk list
1339 return ret;
1340}
1341
1342void
1343Ssl::useSquidUntrusted(SSL_CTX *sslContext)
1344{
1345 SSL_CTX_set_cert_verify_callback(sslContext, untrustedToStoreCtx_cb, NULL);
1346}
1347
1348bool
1349Ssl::loadSquidUntrusted(const char *path)
1350{
1351 return Ssl::loadCerts(path, SquidUntrustedCerts);
1352}
1353
1354void
1355Ssl::unloadSquidUntrusted()
1356{
1357 if (SquidUntrustedCerts.size()) {
1358 for (Ssl::CertsIndexedList::iterator it = SquidUntrustedCerts.begin(); it != SquidUntrustedCerts.end(); ++it) {
1359 X509_free(it->second);
1360 }
1361 SquidUntrustedCerts.clear();
1362 }
1363}
1364
a594dbfa
CT
1365/**
1366 \ingroup ServerProtocolSSLInternal
1367 * Read certificate from file.
1368 * See also: static readSslX509Certificate function, gadgets.cc file
1369 */
1370static X509 * readSslX509CertificatesChain(char const * certFilename, STACK_OF(X509)* chain)
1371{
1372 if (!certFilename)
1373 return NULL;
093deea9 1374 Ssl::BIO_Pointer bio(BIO_new(BIO_s_file()));
a594dbfa
CT
1375 if (!bio)
1376 return NULL;
1377 if (!BIO_read_filename(bio.get(), certFilename))
1378 return NULL;
1379 X509 *certificate = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL);
1380
1381 if (certificate && chain) {
1382
c11211d9 1383 if (X509_check_issued(certificate, certificate) == X509_V_OK)
a594dbfa
CT
1384 debugs(83, 5, "Certificate is self-signed, will not be chained");
1385 else {
a411d213 1386 // and add to the chain any other certificate exist in the file
a594dbfa
CT
1387 while (X509 *ca = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL)) {
1388 if (!sk_X509_push(chain, ca))
1389 debugs(83, DBG_IMPORTANT, "WARNING: unable to add CA certificate to cert chain");
1390 }
1391 }
1392 }
c11211d9 1393
a594dbfa
CT
1394 return certificate;
1395}
1396
f97700a0 1397void Ssl::readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename)
a594dbfa
CT
1398{
1399 if (keyFilename == NULL)
1400 keyFilename = certFilename;
86660d64
CT
1401
1402 if (certFilename == NULL)
1403 certFilename = keyFilename;
1404
1405 debugs(83, DBG_IMPORTANT, "Using certificate in " << certFilename);
1406
a594dbfa
CT
1407 if (!chain)
1408 chain.reset(sk_X509_new_null());
1409 if (!chain)
1410 debugs(83, DBG_IMPORTANT, "WARNING: unable to allocate memory for cert chain");
37144aca
AR
1411 // XXX: ssl_ask_password_cb needs SSL_CTX_set_default_passwd_cb_userdata()
1412 // so this may not fully work iff Config.Program.ssl_password is set.
1413 pem_password_cb *cb = ::Config.Program.ssl_password ? &ssl_ask_password_cb : NULL;
35b3559c
AJ
1414 pkey.resetWithoutLocking(readSslPrivateKey(keyFilename, cb));
1415 cert.resetWithoutLocking(readSslX509CertificatesChain(certFilename, chain.get()));
599111be
AJ
1416 if (!cert) {
1417 debugs(83, DBG_IMPORTANT, "WARNING: missing cert in '" << certFilename << "'");
1418 } else if (!pkey) {
1419 debugs(83, DBG_IMPORTANT, "WARNING: missing private key in '" << keyFilename << "'");
1420 } else if (!X509_check_private_key(cert.get(), pkey.get())) {
1421 debugs(83, DBG_IMPORTANT, "WARNING: X509_check_private_key() failed to verify signing cert");
1422 } else
1423 return; // everything is okay
1424
1425 pkey.reset();
1426 cert.reset();
a594dbfa
CT
1427}
1428
f97700a0 1429bool Ssl::generateUntrustedCert(Security::CertPointer &untrustedCert, EVP_PKEY_Pointer &untrustedPkey, Security::CertPointer const &cert, EVP_PKEY_Pointer const & pkey)
95588170
CT
1430{
1431 // Generate the self-signed certificate, using a hard-coded subject prefix
1432 Ssl::CertificateProperties certProperties;
1433 if (const char *cn = CommonHostName(cert.get())) {
1434 certProperties.commonName = "Not trusted by \"";
1435 certProperties.commonName += cn;
1436 certProperties.commonName += "\"";
87f237a9 1437 } else if (const char *org = getOrganization(cert.get())) {
95588170
CT
1438 certProperties.commonName = "Not trusted by \"";
1439 certProperties.commonName += org;
1440 certProperties.commonName += "\"";
87f237a9 1441 } else
95588170
CT
1442 certProperties.commonName = "Not trusted";
1443 certProperties.setCommonName = true;
1444 // O, OU, and other CA subject fields will be mimicked
1445 // Expiration date and other common properties will be mimicked
1446 certProperties.signAlgorithm = Ssl::algSignSelf;
1447 certProperties.signWithPkey.resetAndLock(pkey.get());
1448 certProperties.mimicCert.resetAndLock(cert.get());
1449 return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
1450}
1451
157c5ace 1452static bool
b23f5f9c 1453SslCreate(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Ssl::Bio::Type type, const char *squidCtx)
b3a8ae1b 1454{
157c5ace 1455 if (!Comm::IsConnOpen(conn)) {
b418d9c8 1456 debugs(83, DBG_IMPORTANT, "Gone connection");
157c5ace 1457 return false;
b418d9c8
CT
1458 }
1459
b3a8ae1b
AR
1460 const char *errAction = NULL;
1461 int errCode = 0;
b23f5f9c 1462 if (auto ssl = SSL_new(ctx.get())) {
157c5ace 1463 const int fd = conn->fd;
b3a8ae1b 1464 // without BIO, we would call SSL_set_fd(ssl, fd) instead
d620ae0e 1465 if (BIO *bio = Ssl::Bio::Create(fd, type)) {
b3a8ae1b
AR
1466 Ssl::Bio::Link(ssl, bio); // cannot fail
1467
35b3559c 1468 fd_table[fd].ssl.resetWithoutLocking(ssl);
b3a8ae1b
AR
1469 fd_table[fd].read_method = &ssl_read_method;
1470 fd_table[fd].write_method = &ssl_write_method;
1471 fd_note(fd, squidCtx);
157c5ace 1472 return true;
b3a8ae1b
AR
1473 }
1474 errCode = ERR_get_error();
1475 errAction = "failed to initialize I/O";
1476 SSL_free(ssl);
1477 } else {
1478 errCode = ERR_get_error();
1479 errAction = "failed to allocate handle";
1480 }
1481
1482 debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
ea574635 1483 ": " << Security::ErrorString(errCode));
157c5ace 1484 return false;
b3a8ae1b
AR
1485}
1486
157c5ace 1487bool
b23f5f9c 1488Ssl::CreateClient(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
d620ae0e 1489{
b23f5f9c 1490 return SslCreate(ctx, c, Ssl::Bio::BIO_TO_SERVER, squidCtx);
d620ae0e
CT
1491}
1492
157c5ace 1493bool
0476ec45 1494Ssl::CreateServer(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
d620ae0e 1495{
b23f5f9c 1496 return SslCreate(ctx, c, Ssl::Bio::BIO_TO_CLIENT, squidCtx);
d620ae0e
CT
1497}
1498
10a69fc0
CT
1499static int
1500store_session_cb(SSL *ssl, SSL_SESSION *session)
1501{
824d4656 1502 if (!Ssl::SessionCache)
10a69fc0
CT
1503 return 0;
1504
1505 debugs(83, 5, "Request to store SSL Session ");
1506
1507 SSL_SESSION_set_timeout(session, Config.SSL.session_ttl);
1508
2a268a06 1509#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
10a69fc0
CT
1510 unsigned char *id = session->session_id;
1511 unsigned int idlen = session->session_id_length;
2a268a06
CT
1512#else
1513 unsigned int idlen;
1514 const unsigned char *id = SSL_SESSION_get_id(session, &idlen);
1515#endif
10a69fc0
CT
1516 unsigned char key[MEMMAP_SLOT_KEY_SIZE];
1517 // Session ids are of size 32bytes. They should always fit to a
86c63190 1518 // MemMap::Slot::key
10a69fc0
CT
1519 assert(idlen <= MEMMAP_SLOT_KEY_SIZE);
1520 memset(key, 0, sizeof(key));
1521 memcpy(key, id, idlen);
1522 int pos;
824d4656 1523 Ipc::MemMap::Slot *slotW = Ssl::SessionCache->openForWriting((const cache_key*)key, pos);
10a69fc0
CT
1524 if (slotW) {
1525 int lenRequired = i2d_SSL_SESSION(session, NULL);
1526 if (lenRequired < MEMMAP_SLOT_DATA_SIZE) {
1527 unsigned char *p = (unsigned char *)slotW->p;
1528 lenRequired = i2d_SSL_SESSION(session, &p);
1529 slotW->set(key, NULL, lenRequired, squid_curtime + Config.SSL.session_ttl);
1530 }
824d4656 1531 Ssl::SessionCache->closeForWriting(pos);
10a69fc0
CT
1532 debugs(83, 5, "wrote an ssl session entry of size " << lenRequired << " at pos " << pos);
1533 }
1534 return 0;
1535}
1536
1537static void
1538remove_session_cb(SSL_CTX *, SSL_SESSION *sessionID)
1539{
824d4656 1540 if (!Ssl::SessionCache)
10a69fc0
CT
1541 return ;
1542
1543 debugs(83, 5, "Request to remove corrupted or not valid SSL Session ");
1544 int pos;
824d4656 1545 Ipc::MemMap::Slot const *slot = Ssl::SessionCache->openForReading((const cache_key*)sessionID, pos);
10a69fc0
CT
1546 if (slot == NULL)
1547 return;
824d4656 1548 Ssl::SessionCache->closeForReading(pos);
10a69fc0
CT
1549 // TODO:
1550 // What if we are not able to remove the session?
1551 // Maybe schedule a job to remove it later?
1552 // For now we just have an invalid entry in cache until will be expired
1553 // The openSSL will reject it when we try to use it
824d4656 1554 Ssl::SessionCache->free(pos);
10a69fc0
CT
1555}
1556
1557static SSL_SESSION *
2a268a06 1558#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
10a69fc0 1559get_session_cb(SSL *, unsigned char *sessionID, int len, int *copy)
2a268a06
CT
1560#else
1561get_session_cb(SSL *, const unsigned char *sessionID, int len, int *copy)
1562#endif
10a69fc0 1563{
824d4656 1564 if (!Ssl::SessionCache)
10a69fc0
CT
1565 return NULL;
1566
1567 SSL_SESSION *session = NULL;
1568 const unsigned int *p;
1569 p = (unsigned int *)sessionID;
1570 debugs(83, 5, "Request to search for SSL Session of len:" <<
1571 len << p[0] << ":" << p[1]);
1572
1573 int pos;
824d4656 1574 Ipc::MemMap::Slot const *slot = Ssl::SessionCache->openForReading((const cache_key*)sessionID, pos);
10a69fc0
CT
1575 if (slot != NULL) {
1576 if (slot->expire > squid_curtime) {
1577 const unsigned char *ptr = slot->p;
1578 session = d2i_SSL_SESSION(NULL, &ptr, slot->pSize);
1579 debugs(83, 5, "Session retrieved from cache at pos " << pos);
1580 } else
1581 debugs(83, 5, "Session in cache expired");
824d4656 1582 Ssl::SessionCache->closeForReading(pos);
10a69fc0
CT
1583 }
1584
1585 if (!session)
1586 debugs(83, 5, "Failed to retrieved from cache\n");
1587
1588 // With the parameter copy the callback can require the SSL engine
1589 // to increment the reference count of the SSL_SESSION object, Normally
1590 // the reference count is not incremented and therefore the session must
1591 // not be explicitly freed with SSL_SESSION_free(3).
1592 *copy = 0;
1593 return session;
1594}
1595
824d4656 1596void
b23f5f9c 1597Ssl::SetSessionCallbacks(Security::ContextPointer &ctx)
10a69fc0 1598{
824d4656 1599 if (Ssl::SessionCache) {
b23f5f9c
AJ
1600 SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL);
1601 SSL_CTX_sess_set_new_cb(ctx.get(), store_session_cb);
1602 SSL_CTX_sess_set_remove_cb(ctx.get(), remove_session_cb);
1603 SSL_CTX_sess_set_get_cb(ctx.get(), get_session_cb);
10a69fc0
CT
1604 }
1605}
1606
cb4f4424 1607#endif /* USE_OPENSSL */
f53969cc 1608