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