]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/support.cc
Cleanup: replace USE_SSL wrapper macro with USE_OPENSSL
[thirdparty/squid.git] / src / ssl / support.cc
CommitLineData
f484cdf5 1
2/*
f484cdf5 3 * AUTHOR: Benno Rice
27d8545c 4 * DEBUG: section 83 SSL accelerator support
f484cdf5 5 *
6 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
7 * ----------------------------------------------------------
8 *
9 * Squid is the result of efforts by numerous individuals from the
10 * Internet community. Development is led by Duane Wessels of the
11 * National Laboratory for Applied Network Research and funded by the
12 * National Science Foundation. Squid is Copyrighted (C) 1998 by
13 * Duane Wessels and the University of California San Diego. Please
14 * see the COPYRIGHT file for full details. Squid incorporates
15 * software developed and/or copyrighted by other sources. Please see
16 * the CREDITS file for full details.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
26ac0430 22 *
f484cdf5 23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
26ac0430 27 *
f484cdf5 28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
31 *
32 */
33
582c2af2 34#include "squid.h"
454e8283 35
36/* MS Visual Studio Projects are monolithic, so we need the following
37 * #if to exclude the SSL code from compile process when not needed.
38 */
cb4f4424 39#if USE_OPENSSL
454e8283 40
c0941a6a 41#include "acl/FilledChecklist.h"
86660d64 42#include "anyp/PortCfg.h"
582c2af2
FC
43#include "fde.h"
44#include "globals.h"
86c63190 45#include "ipc/MemMap.h"
4d5904f7 46#include "SquidConfig.h"
10a69fc0 47#include "SquidTime.h"
2cef0ca6 48#include "ssl/Config.h"
4d16918e 49#include "ssl/ErrorDetail.h"
95d2589c 50#include "ssl/gadgets.h"
602d9612 51#include "ssl/support.h"
fc54b8d2 52#include "URL.h"
f484cdf5 53
21d845b1
FC
54#if HAVE_ERRNO_H
55#include <errno.h>
56#endif
57
10a69fc0
CT
58static void setSessionCallbacks(SSL_CTX *ctx);
59Ipc::MemMap *SslSessionCache = NULL;
60const char *SslSessionCacheName = "ssl_session_cache";
61
caf3666d
AR
62const char *Ssl::BumpModeStr[] = {
63 "none",
64 "client-first",
65 "server-first",
66 NULL
67};
68
63be0a78 69/**
70 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
71 \ingroup ServerProtocolSSLAPI
72 */
73
74/// \ingroup ServerProtocolSSLInternal
307b83b7 75static int
76ssl_ask_password_cb(char *buf, int size, int rwflag, void *userdata)
77{
78 FILE *in;
79 int len = 0;
80 char cmdline[1024];
81
82 snprintf(cmdline, sizeof(cmdline), "\"%s\" \"%s\"", Config.Program.ssl_password, (const char *)userdata);
83 in = popen(cmdline, "r");
84
85 if (fgets(buf, size, in))
86
87 len = strlen(buf);
88
89 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
5e263176 90 --len;
307b83b7 91
92 buf[len] = '\0';
93
94 pclose(in);
95
96 return len;
97}
98
63be0a78 99/// \ingroup ServerProtocolSSLInternal
307b83b7 100static void
101ssl_ask_password(SSL_CTX * context, const char * prompt)
102{
103 if (Config.Program.ssl_password) {
104 SSL_CTX_set_default_passwd_cb(context, ssl_ask_password_cb);
105 SSL_CTX_set_default_passwd_cb_userdata(context, (void *)prompt);
106 }
107}
108
63be0a78 109/// \ingroup ServerProtocolSSLInternal
f484cdf5 110static RSA *
e6ccf245 111ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen)
f484cdf5 112{
e01f02ed 113 static RSA *rsa_512 = NULL;
114 static RSA *rsa_1024 = NULL;
115 RSA *rsa = NULL;
116 int newkey = 0;
f484cdf5 117
e01f02ed 118 switch (keylen) {
119
120 case 512:
121
122 if (!rsa_512) {
123 rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
124 newkey = 1;
125 }
126
127 rsa = rsa_512;
128 break;
129
130 case 1024:
131
132 if (!rsa_1024) {
133 rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
134 newkey = 1;
135 }
136
137 rsa = rsa_1024;
138 break;
139
140 default:
e0236918 141 debugs(83, DBG_IMPORTANT, "ssl_temp_rsa_cb: Unexpected key length " << keylen);
e01f02ed 142 return NULL;
143 }
144
145 if (rsa == NULL) {
e0236918 146 debugs(83, DBG_IMPORTANT, "ssl_temp_rsa_cb: Failed to generate key " << keylen);
e01f02ed 147 return NULL;
148 }
149
150 if (newkey) {
151 if (do_debug(83, 5))
152 PEM_write_RSAPrivateKey(debug_log, rsa, NULL, NULL, 0, NULL, NULL);
153
e0236918 154 debugs(83, DBG_IMPORTANT, "Generated ephemeral RSA key of length " << keylen);
e01f02ed 155 }
62e76326 156
f484cdf5 157 return rsa;
158}
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
e34763f4 215 if (cn_data->length > (int)sizeof(cn) - 1) {
4d16918e
CT
216 return 1; //if does not fit our buffer just ignore
217 }
218 memcpy(cn, cn_data->data, cn_data->length);
219 cn[cn_data->length] = '\0';
220 debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn);
221 return matchDomainName(server, cn[0] == '*' ? cn + 1 : cn);
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
CT
233 // preserve original ctx->error before SSL_ calls can overwrite it
234 Ssl::ssl_error_t error_no = ok ? SSL_ERROR_NONE : ctx->error;
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());
238 SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
239 const char *server = (const char *)SSL_get_ex_data(ssl, ssl_ex_index_server);
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);
a7ad6e4e 243 X509 *peer_cert = ctx->cert;
f484cdf5 244
a7ad6e4e 245 X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
62e76326 246 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
CT
268 // Check for domain mismatch only if the current certificate is the peer certificate.
269 if (server && peer_cert == X509_STORE_CTX_get_current_cert(ctx)) {
8eb0a7ee 270 if (!Ssl::checkX509ServerValidity(peer_cert, server)) {
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.
e7bcc25f
CT
280 if (X509_cmp(peer_cert, peeked_cert) != 0) {
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) {
62a7607e
CT
288 X509 *broken_cert = X509_STORE_CTX_get_current_cert(ctx);
289 if (!broken_cert)
290 broken_cert = peer_cert;
291
292 Ssl::CertErrors *errs = static_cast<Ssl::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
7a957a93 293 if (!errs) {
62a7607e 294 errs = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert));
7a957a93 295 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) {
fb2178bb 296 debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer);
7a957a93
AR
297 delete errs;
298 errs = NULL;
fb2178bb 299 }
87f237a9 300 } else // remember another error number
62a7607e 301 errs->push_back_unique(Ssl::CertError(error_no, broken_cert));
fb2178bb 302
7698a79c 303 if (const char *err_descr = Ssl::GetErrorDescr(error_no))
cf09bec7
CT
304 debugs(83, 5, err_descr << ": " << buffer);
305 else
7698a79c
CT
306 debugs(83, DBG_IMPORTANT, "SSL unknown certificate error " << error_no << " in " << buffer);
307
0ad3ff51
CT
308 // Check if the certificate error can be bypassed.
309 // Infinity validation loop errors can not bypassed.
310 if (error_no != SQUID_X509_V_ERR_INFINITE_VALIDATION) {
311 if (check) {
312 ACLFilledChecklist *filledCheck = Filled(check);
313 assert(!filledCheck->sslErrors);
314 filledCheck->sslErrors = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert));
315 filledCheck->serverCert.resetAndLock(peer_cert);
316 if (check->fastCheck() == ACCESS_ALLOWED) {
317 debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
318 ok = 1;
319 } else {
320 debugs(83, 5, "confirming SSL error " << error_no);
321 }
322 delete filledCheck->sslErrors;
323 filledCheck->sslErrors = NULL;
324 filledCheck->serverCert.reset(NULL);
7698a79c 325 }
0ad3ff51
CT
326 // If the certificate validator is used then we need to allow all errors and
327 // pass them to certficate validator for more processing
328 else if (Ssl::TheConfig.ssl_crt_validator) {
329 ok = 1;
330 // Check if we have stored certificates chain. Store if not.
331 if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
332 STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
333 if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
334 sk_X509_pop_free(certStack, X509_free);
335 }
4747ea4c
CT
336 }
337 }
a7ad6e4e 338 }
62e76326 339
26ac0430 340 if (!dont_verify_domain && server) {}
62e76326 341
7698a79c 342 if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
f622c461
MF
343
344 // Find the broken certificate. It may be intermediate.
345 X509 *broken_cert = peer_cert; // reasonable default if search fails
346 // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
347 if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
348 if (X509 *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
349 broken_cert = last_used_cert;
350 }
351
352 Ssl::ErrorDetail *errDetail =
de878a55 353 new Ssl::ErrorDetail(error_no, peer_cert, broken_cert);
f622c461 354
e34763f4 355 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) {
4d16918e
CT
356 debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer);
357 delete errDetail;
358 }
359 }
360
f484cdf5 361 return ok;
362}
363
63be0a78 364/// \ingroup ServerProtocolSSLInternal
26ac0430 365static struct ssl_option {
79d4ccdf 366 const char *name;
367 long value;
62e76326 368}
369
370ssl_options[] = {
79d4ccdf 371
32d002cb 372#if SSL_OP_MICROSOFT_SESS_ID_BUG
26ac0430
AJ
373 {
374 "MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG
375 },
673cd7db 376#endif
32d002cb 377#if SSL_OP_NETSCAPE_CHALLENGE_BUG
26ac0430
AJ
378 {
379 "NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG
380 },
673cd7db 381#endif
32d002cb 382#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
26ac0430
AJ
383 {
384 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
385 },
673cd7db 386#endif
32d002cb 387#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
26ac0430
AJ
388 {
389 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
390 },
673cd7db 391#endif
32d002cb 392#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
26ac0430
AJ
393 {
394 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
395 },
673cd7db 396#endif
32d002cb 397#if SSL_OP_MSIE_SSLV2_RSA_PADDING
26ac0430
AJ
398 {
399 "MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING
400 },
673cd7db 401#endif
32d002cb 402#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
26ac0430
AJ
403 {
404 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
405 },
673cd7db 406#endif
32d002cb 407#if SSL_OP_TLS_D5_BUG
26ac0430
AJ
408 {
409 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
410 },
673cd7db 411#endif
32d002cb 412#if SSL_OP_TLS_BLOCK_PADDING_BUG
26ac0430
AJ
413 {
414 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
415 },
673cd7db 416#endif
32d002cb 417#if SSL_OP_TLS_ROLLBACK_BUG
26ac0430
AJ
418 {
419 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
420 },
673cd7db 421#endif
32d002cb 422#if SSL_OP_ALL
26ac0430 423 {
866eafc6 424 "ALL", (long)SSL_OP_ALL
26ac0430 425 },
673cd7db 426#endif
32d002cb 427#if SSL_OP_SINGLE_DH_USE
26ac0430
AJ
428 {
429 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
430 },
673cd7db 431#endif
32d002cb 432#if SSL_OP_EPHEMERAL_RSA
26ac0430
AJ
433 {
434 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
435 },
673cd7db 436#endif
32d002cb 437#if SSL_OP_PKCS1_CHECK_1
26ac0430
AJ
438 {
439 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
440 },
673cd7db 441#endif
32d002cb 442#if SSL_OP_PKCS1_CHECK_2
26ac0430
AJ
443 {
444 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
445 },
673cd7db 446#endif
32d002cb 447#if SSL_OP_NETSCAPE_CA_DN_BUG
26ac0430
AJ
448 {
449 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
450 },
673cd7db 451#endif
32d002cb 452#if SSL_OP_NON_EXPORT_FIRST
26ac0430
AJ
453 {
454 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
455 },
673cd7db 456#endif
32d002cb 457#if SSL_OP_CIPHER_SERVER_PREFERENCE
26ac0430
AJ
458 {
459 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
460 },
673cd7db 461#endif
32d002cb 462#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
26ac0430
AJ
463 {
464 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
465 },
673cd7db 466#endif
32d002cb 467#if SSL_OP_NO_SSLv2
26ac0430
AJ
468 {
469 "NO_SSLv2", SSL_OP_NO_SSLv2
470 },
673cd7db 471#endif
32d002cb 472#if SSL_OP_NO_SSLv3
26ac0430
AJ
473 {
474 "NO_SSLv3", SSL_OP_NO_SSLv3
475 },
673cd7db 476#endif
32d002cb 477#if SSL_OP_NO_TLSv1
26ac0430
AJ
478 {
479 "NO_TLSv1", SSL_OP_NO_TLSv1
480 },
3d96b0e8
AJ
481#endif
482#if SSL_OP_NO_TLSv1_1
483 {
484 "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
485 },
486#endif
487#if SSL_OP_NO_TLSv1_2
488 {
489 "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
490 },
71606c88
SW
491#endif
492#if SSL_OP_NO_COMPRESSION
493 {
494 "No_Compression", SSL_OP_NO_COMPRESSION
495 },
673cd7db 496#endif
26ac0430
AJ
497 {
498 "", 0
499 },
500 {
501 NULL, 0
502 }
503};
79d4ccdf 504
63be0a78 505/// \ingroup ServerProtocolSSLInternal
86660d64
CT
506long
507Ssl::parse_options(const char *options)
79d4ccdf 508{
943c5f16 509 long op = 0;
79d4ccdf 510 char *tmp;
511 char *option;
512
513 if (!options)
62e76326 514 goto no_options;
79d4ccdf 515
516 tmp = xstrdup(options);
62e76326 517
79d4ccdf 518 option = strtok(tmp, ":,");
62e76326 519
79d4ccdf 520 while (option) {
62e76326 521
522 struct ssl_option *opt = NULL, *opttmp;
523 long value = 0;
524 enum {
525 MODE_ADD, MODE_REMOVE
526 } mode;
527
528 switch (*option) {
529
530 case '!':
531
532 case '-':
533 mode = MODE_REMOVE;
d7ae3534 534 ++option;
62e76326 535 break;
536
537 case '+':
538 mode = MODE_ADD;
d7ae3534 539 ++option;
62e76326 540 break;
541
542 default:
543 mode = MODE_ADD;
544 break;
545 }
546
d7ae3534 547 for (opttmp = ssl_options; opttmp->name; ++opttmp) {
62e76326 548 if (strcmp(opttmp->name, option) == 0) {
549 opt = opttmp;
550 break;
551 }
552 }
553
554 if (opt)
555 value = opt->value;
556 else if (strncmp(option, "0x", 2) == 0) {
557 /* Special case.. hex specification */
558 value = strtol(option + 2, NULL, 16);
559 } else {
560 fatalf("Unknown SSL option '%s'", option);
561 value = 0; /* Keep GCC happy */
562 }
563
564 switch (mode) {
565
566 case MODE_ADD:
567 op |= value;
568 break;
569
570 case MODE_REMOVE:
571 op &= ~value;
572 break;
573 }
574
575 option = strtok(NULL, ":,");
79d4ccdf 576 }
577
578 safe_free(tmp);
62e76326 579
580no_options:
79d4ccdf 581 return op;
582}
583
63be0a78 584/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 585#define SSL_FLAG_NO_DEFAULT_CA (1<<0)
63be0a78 586/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 587#define SSL_FLAG_DELAYED_AUTH (1<<1)
63be0a78 588/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 589#define SSL_FLAG_DONT_VERIFY_PEER (1<<2)
63be0a78 590/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 591#define SSL_FLAG_DONT_VERIFY_DOMAIN (1<<3)
63be0a78 592/// \ingroup ServerProtocolSSLInternal
b13877cc 593#define SSL_FLAG_NO_SESSION_REUSE (1<<4)
63be0a78 594/// \ingroup ServerProtocolSSLInternal
a82a4fe4 595#define SSL_FLAG_VERIFY_CRL (1<<5)
63be0a78 596/// \ingroup ServerProtocolSSLInternal
a82a4fe4 597#define SSL_FLAG_VERIFY_CRL_ALL (1<<6)
a7ad6e4e 598
63be0a78 599/// \ingroup ServerProtocolSSLInternal
86660d64
CT
600long
601Ssl::parse_flags(const char *flags)
a7ad6e4e 602{
603 long fl = 0;
604 char *tmp;
605 char *flag;
606
607 if (!flags)
62e76326 608 return 0;
a7ad6e4e 609
610 tmp = xstrdup(flags);
62e76326 611
a7ad6e4e 612 flag = strtok(tmp, ":,");
62e76326 613
a7ad6e4e 614 while (flag) {
62e76326 615 if (strcmp(flag, "NO_DEFAULT_CA") == 0)
616 fl |= SSL_FLAG_NO_DEFAULT_CA;
617 else if (strcmp(flag, "DELAYED_AUTH") == 0)
618 fl |= SSL_FLAG_DELAYED_AUTH;
619 else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
620 fl |= SSL_FLAG_DONT_VERIFY_PEER;
621 else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
622 fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
b13877cc 623 else if (strcmp(flag, "NO_SESSION_REUSE") == 0)
624 fl |= SSL_FLAG_NO_SESSION_REUSE;
a82a4fe4 625
32d002cb 626#if X509_V_FLAG_CRL_CHECK
a82a4fe4 627
628 else if (strcmp(flag, "VERIFY_CRL") == 0)
629 fl |= SSL_FLAG_VERIFY_CRL;
630 else if (strcmp(flag, "VERIFY_CRL_ALL") == 0)
631 fl |= SSL_FLAG_VERIFY_CRL_ALL;
632
633#endif
634
62e76326 635 else
636 fatalf("Unknown ssl flag '%s'", flag);
637
638 flag = strtok(NULL, ":,");
a7ad6e4e 639 }
62e76326 640
a7ad6e4e 641 safe_free(tmp);
642 return fl;
643}
644
815eaa44 645// "dup" function for SSL_get_ex_new_index("cert_err_check")
646static int
647ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
26ac0430
AJ
648 int, long, void *)
649{
815eaa44 650 // We do not support duplication of ACLCheckLists.
651 // If duplication is needed, we can count copies with cbdata.
652 assert(false);
653 return 0;
654}
655
656// "free" function for SSL_get_ex_new_index("cert_err_check")
657static void
658ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
26ac0430
AJ
659 int, long, void *)
660{
815eaa44 661 delete static_cast<ACLChecklist *>(ptr); // may be NULL
662}
a7ad6e4e 663
4d16918e
CT
664// "free" function for SSL_get_ex_new_index("ssl_error_detail")
665static void
666ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *,
667 int, long, void *)
668{
669 Ssl::ErrorDetail *errDetail = static_cast <Ssl::ErrorDetail *>(ptr);
670 delete errDetail;
671}
672
fb2178bb 673static void
7a957a93 674ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
87f237a9 675 int, long, void *)
fb2178bb 676{
62a7607e 677 Ssl::CertErrors *errs = static_cast <Ssl::CertErrors*>(ptr);
7a957a93 678 delete errs;
fb2178bb
CT
679}
680
0ad3ff51
CT
681// "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
682static void
683ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *,
3cc296c4 684 int, long, void *)
0ad3ff51
CT
685{
686 uint32_t *counter = static_cast <uint32_t *>(ptr);
687 delete counter;
688}
689
4747ea4c
CT
690/// \ingroup ServerProtocolSSLInternal
691/// Callback handler function to release STACK_OF(X509) "ex" data stored
692/// in an SSL object.
693static void
694ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *,
695 int, long, void *)
696{
697 STACK_OF(X509) *certsChain = static_cast <STACK_OF(X509) *>(ptr);
698 sk_X509_pop_free(certsChain,X509_free);
699}
700
e7bcc25f
CT
701// "free" function for X509 certificates
702static void
703ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *,
87f237a9 704 int, long, void *)
e7bcc25f
CT
705{
706 X509 *cert = static_cast <X509 *>(ptr);
707 X509_free(cert);
708}
709
63be0a78 710/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 711static void
712ssl_initialize(void)
f484cdf5 713{
d193a436 714 static int ssl_initialized = 0;
62e76326 715
d193a436 716 if (!ssl_initialized) {
62e76326 717 ssl_initialized = 1;
718 SSL_load_error_strings();
719 SSLeay_add_ssl_algorithms();
32d002cb 720#if HAVE_OPENSSL_ENGINE_H
62e76326 721
722 if (Config.SSL.ssl_engine) {
723 ENGINE *e;
724
725 if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
726 fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
727 }
728
729 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
730 int ssl_error = ERR_get_error();
731 fatalf("Failed to initialise SSL engine: %s\n",
732 ERR_error_string(ssl_error, NULL));
733 }
734 }
735
a7ad6e4e 736#else
62e76326 737 if (Config.SSL.ssl_engine) {
738 fatalf("Your OpenSSL has no SSL engine support\n");
739 }
740
a7ad6e4e 741#endif
d193a436 742 }
62e76326 743
a7ad6e4e 744 ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
745 ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
815eaa44 746 ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
4d16918e 747 ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail);
e7bcc25f 748 ssl_ex_index_ssl_peeked_cert = SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL, NULL, &ssl_free_X509);
7a957a93 749 ssl_ex_index_ssl_errors = SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL, NULL, &ssl_free_SslErrors);
4747ea4c 750 ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL, NULL, &ssl_free_CertChain);
0ad3ff51 751 ssl_ex_index_ssl_validation_counter = SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL, NULL, &ssl_free_int);
a7ad6e4e 752}
753
63be0a78 754/// \ingroup ServerProtocolSSLInternal
a82a4fe4 755static int
756ssl_load_crl(SSL_CTX *sslContext, const char *CRLfile)
757{
758 X509_STORE *st = SSL_CTX_get_cert_store(sslContext);
759 X509_CRL *crl;
760 BIO *in = BIO_new_file(CRLfile, "r");
761 int count = 0;
762
763 if (!in) {
bf8fe701 764 debugs(83, 2, "WARNING: Failed to open CRL file '" << CRLfile << "'");
a82a4fe4 765 return 0;
766 }
767
768 while ((crl = PEM_read_bio_X509_CRL(in,NULL,NULL,NULL))) {
769 if (!X509_STORE_add_crl(st, crl))
bf8fe701 770 debugs(83, 2, "WARNING: Failed to add CRL from file '" << CRLfile << "'");
a82a4fe4 771 else
d7ae3534 772 ++count;
a82a4fe4 773
774 X509_CRL_free(crl);
775 }
776
777 BIO_free(in);
778 return count;
779}
780
86660d64
CT
781STACK_OF(X509_CRL) *
782Ssl::loadCrl(const char *CRLFile, long &flags)
a7ad6e4e 783{
86660d64
CT
784 X509_CRL *crl;
785 BIO *in = BIO_new_file(CRLFile, "r");
786 if (!in) {
787 debugs(83, 2, "WARNING: Failed to open CRL file '" << CRLFile << "'");
f4e4d4d6
CT
788 return NULL;
789 }
790
86660d64
CT
791 STACK_OF(X509_CRL) *CRLs = sk_X509_CRL_new_null();
792 if (!CRLs) {
793 debugs(83, 2, "WARNING: Failed to allocate X509_CRL stack to load file '" << CRLFile << "'");
50b4c080 794 return NULL;
86660d64 795 }
62e76326 796
86660d64
CT
797 int count = 0;
798 while ((crl = PEM_read_bio_X509_CRL(in,NULL,NULL,NULL))) {
799 if (!sk_X509_CRL_push(CRLs, crl))
800 debugs(83, 2, "WARNING: Failed to add CRL from file '" << CRLFile << "'");
801 else
802 ++count;
803 }
804 BIO_free(in);
62e76326 805
86660d64
CT
806 if (count)
807 flags |= SSL_FLAG_VERIFY_CRL;
3d96b0e8 808
86660d64
CT
809 return CRLs;
810}
3d96b0e8 811
86660d64
CT
812DH *
813Ssl::readDHParams(const char *dhfile)
814{
815 FILE *in = fopen(dhfile, "r");
816 DH *dh = NULL;
817 int codes;
62e76326 818
86660d64
CT
819 if (in) {
820 dh = PEM_read_DHparams(in, NULL, NULL, NULL);
821 fclose(in);
f484cdf5 822 }
823
86660d64
CT
824 if (!dh)
825 debugs(83, DBG_IMPORTANT, "WARNING: Failed to read DH parameters '" << dhfile << "'");
826 else if (dh && DH_check(dh, &codes) == 0) {
827 if (codes) {
828 debugs(83, DBG_IMPORTANT, "WARNING: Failed to verify DH parameters '" << dhfile << "' (" << std::hex << codes << ")");
829 DH_free(dh);
830 dh = NULL;
831 }
f484cdf5 832 }
86660d64
CT
833 return dh;
834}
62e76326 835
86660d64
CT
836static bool
837configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
838{
839 int ssl_error;
840 SSL_CTX_set_options(sslContext, port.sslOptions);
f484cdf5 841
86660d64
CT
842 if (port.sslContextSessionId)
843 SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
6b2936d5 844
86660d64 845 if (port.sslContextFlags & SSL_FLAG_NO_SESSION_REUSE) {
b13877cc 846 SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
847 }
848
a9d79803 849 if (Config.SSL.unclean_shutdown) {
bf8fe701 850 debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
a9d79803 851
852 SSL_CTX_set_quiet_shutdown(sslContext, 1);
853 }
854
86660d64
CT
855 if (port.cipher) {
856 debugs(83, 5, "Using chiper suite " << port.cipher << ".");
62e76326 857
86660d64 858 if (!SSL_CTX_set_cipher_list(sslContext, port.cipher)) {
62e76326 859 ssl_error = ERR_get_error();
86660d64
CT
860 debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.cipher << "': " << ERR_error_string(ssl_error, NULL));
861 return false;
62e76326 862 }
79d4ccdf 863 }
62e76326 864
bf8fe701 865 debugs(83, 9, "Setting RSA key generation callback.");
a7ad6e4e 866 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
867
bf8fe701 868 debugs(83, 9, "Setting CA certificate locations.");
62e76326 869
86660d64
CT
870 const char *cafile = port.cafile ? port.cafile : port.clientca;
871 if ((cafile || port.capath) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.capath)) {
62e76326 872 ssl_error = ERR_get_error();
48e7baac 873 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
a7ad6e4e 874 }
62e76326 875
86660d64 876 if (!(port.sslContextFlags & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 877 !SSL_CTX_set_default_verify_paths(sslContext)) {
878 ssl_error = ERR_get_error();
48e7baac 879 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
a7ad6e4e 880 }
62e76326 881
86660d64 882 if (port.clientCA.get()) {
8c1ff4ef 883 ERR_clear_error();
86660d64 884 SSL_CTX_set_client_CA_list(sslContext, port.clientCA.get());
62e76326 885
86660d64 886 if (port.sslContextFlags & SSL_FLAG_DELAYED_AUTH) {
bf8fe701 887 debugs(83, 9, "Not requesting client certificates until acl processing requires one");
62e76326 888 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
889 } else {
bf8fe701 890 debugs(83, 9, "Requiring client certificates.");
62e76326 891 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
892 }
a82a4fe4 893
86660d64
CT
894 if (port.clientVerifyCrls.get()) {
895 X509_STORE *st = SSL_CTX_get_cert_store(sslContext);
896 for (int i = 0; i < sk_X509_CRL_num(port.clientVerifyCrls.get()); ++i) {
897 X509_CRL *crl = sk_X509_CRL_value(port.clientVerifyCrls.get(), i);
898 if (!X509_STORE_add_crl(st, crl))
899 debugs(83, 2, "WARNING: Failed to add CRL");
900 }
a82a4fe4 901 }
902
32d002cb 903#if X509_V_FLAG_CRL_CHECK
86660d64 904 if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL_ALL)
a82a4fe4 905 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
86660d64 906 else if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL)
a82a4fe4 907 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
a82a4fe4 908#endif
909
a7ad6e4e 910 } else {
bf8fe701 911 debugs(83, 9, "Not requiring any client certificates");
62e76326 912 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 913 }
f484cdf5 914
86660d64
CT
915 if (port.dhParams.get()) {
916 SSL_CTX_set_tmp_dh(sslContext, port.dhParams.get());
917 }
35105e4b 918
86660d64
CT
919 if (port.sslContextFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
920 SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
921
10a69fc0
CT
922 setSessionCallbacks(sslContext);
923
86660d64
CT
924 return true;
925}
926
927SSL_CTX *
928sslCreateServerContext(AnyP::PortCfg &port)
929{
930 int ssl_error;
931 SSL_CTX *sslContext;
932 const char *keyfile, *certfile;
933 certfile = port.cert;
934 keyfile = port.key;
935
936 ssl_initialize();
937
938 if (!keyfile)
939 keyfile = certfile;
940
941 if (!certfile)
942 certfile = keyfile;
943
944 sslContext = SSL_CTX_new(port.contextMethod);
945
946 if (sslContext == NULL) {
947 ssl_error = ERR_get_error();
948 debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate SSL context: " << ERR_error_string(ssl_error, NULL));
949 return NULL;
950 }
951
952 if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) {
953 ssl_error = ERR_get_error();
954 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
955 SSL_CTX_free(sslContext);
956 return NULL;
957 }
958
959 if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) {
960 ssl_error = ERR_get_error();
961 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
962 SSL_CTX_free(sslContext);
963 return NULL;
964 }
965
966 Ssl::addChainToSslContext(sslContext, port.certsToChain.get());
967
968 /* Alternate code;
969 debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
970
971 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
972 ssl_error = ERR_get_error();
973 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
974 SSL_CTX_free(sslContext);
975 return NULL;
35105e4b 976 }
977
86660d64
CT
978 debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
979 ssl_ask_password(sslContext, keyfile);
980
981 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
982 ssl_error = ERR_get_error();
983 debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
984 SSL_CTX_free(sslContext);
985 return NULL;
35105e4b 986 }
987
86660d64 988 debugs(83, 5, "Comparing private and public SSL keys.");
35105e4b 989
86660d64
CT
990 if (!SSL_CTX_check_private_key(sslContext)) {
991 ssl_error = ERR_get_error();
992 debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
993 keyfile << "': " << ERR_error_string(ssl_error, NULL));
994 SSL_CTX_free(sslContext);
995 return NULL;
996 }
997 */
998
999 if (!configureSslContext(sslContext, port)) {
1000 debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
1001 SSL_CTX_free(sslContext);
1002 return NULL;
1003 }
62e76326 1004
a7ad6e4e 1005 return sslContext;
a7ad6e4e 1006}
1007
1008SSL_CTX *
a82a4fe4 1009sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile)
a7ad6e4e 1010{
1011 int ssl_error;
19179f7c
CT
1012 Ssl::ContextMethod method;
1013 SSL_CTX * sslContext;
86660d64 1014 long fl = Ssl::parse_flags(flags);
a7ad6e4e 1015
1016 ssl_initialize();
1017
1018 if (!keyfile)
62e76326 1019 keyfile = certfile;
1020
a7ad6e4e 1021 if (!certfile)
62e76326 1022 certfile = keyfile;
a7ad6e4e 1023
a7ad6e4e 1024 switch (version) {
62e76326 1025
a7ad6e4e 1026 case 2:
50b4c080 1027#ifndef OPENSSL_NO_SSL2
bf8fe701 1028 debugs(83, 5, "Using SSLv2.");
62e76326 1029 method = SSLv2_client_method();
50b4c080 1030#else
48e7baac 1031 debugs(83, DBG_IMPORTANT, "SSLv2 is not available in this Proxy.");
50b4c080
AJ
1032 return NULL;
1033#endif
62e76326 1034 break;
1035
a7ad6e4e 1036 case 3:
bf8fe701 1037 debugs(83, 5, "Using SSLv3.");
62e76326 1038 method = SSLv3_client_method();
1039 break;
1040
a7ad6e4e 1041 case 4:
bf8fe701 1042 debugs(83, 5, "Using TLSv1.");
62e76326 1043 method = TLSv1_client_method();
1044 break;
1045
3d96b0e8
AJ
1046 case 5:
1047#if OPENSSL_VERSION_NUMBER >= 0x10001000L // NP: not sure exactly which sub-version yet.
1048 debugs(83, 5, "Using TLSv1.1.");
1049 method = TLSv1_1_client_method();
1050#else
1051 debugs(83, DBG_IMPORTANT, "TLSv1.1 is not available in this Proxy.");
1052 return NULL;
1053#endif
1054 break;
1055
1056 case 6:
1057#if OPENSSL_VERSION_NUMBER >= 0x10001000L // NP: not sure exactly which sub-version yet.
1058 debugs(83, 5, "Using TLSv1.2");
1059 method = TLSv1_2_client_method();
1060#else
1061 debugs(83, DBG_IMPORTANT, "TLSv1.2 is not available in this Proxy.");
1062 return NULL;
1063#endif
1064 break;
1065
a7ad6e4e 1066 case 1:
62e76326 1067
a7ad6e4e 1068 default:
bf8fe701 1069 debugs(83, 5, "Using SSLv2/SSLv3.");
62e76326 1070 method = SSLv23_client_method();
1071 break;
a7ad6e4e 1072 }
1073
1074 sslContext = SSL_CTX_new(method);
62e76326 1075
a7ad6e4e 1076 if (sslContext == NULL) {
62e76326 1077 ssl_error = ERR_get_error();
1078 fatalf("Failed to allocate SSL context: %s\n",
1079 ERR_error_string(ssl_error, NULL));
a7ad6e4e 1080 }
62e76326 1081
86660d64 1082 SSL_CTX_set_options(sslContext, Ssl::parse_options(options));
a7ad6e4e 1083
1084 if (cipher) {
bf8fe701 1085 debugs(83, 5, "Using chiper suite " << cipher << ".");
62e76326 1086
1087 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
1088 ssl_error = ERR_get_error();
1089 fatalf("Failed to set SSL cipher suite '%s': %s\n",
1090 cipher, ERR_error_string(ssl_error, NULL));
1091 }
a7ad6e4e 1092 }
62e76326 1093
a7ad6e4e 1094 if (certfile) {
e0236918 1095 debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
62e76326 1096
1097 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
1098 ssl_error = ERR_get_error();
1099 fatalf("Failed to acquire SSL certificate '%s': %s\n",
1100 certfile, ERR_error_string(ssl_error, NULL));
1101 }
1102
e0236918 1103 debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
307b83b7 1104 ssl_ask_password(sslContext, keyfile);
62e76326 1105
1106 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
1107 ssl_error = ERR_get_error();
1108 fatalf("Failed to acquire SSL private key '%s': %s\n",
1109 keyfile, ERR_error_string(ssl_error, NULL));
1110 }
1111
bf8fe701 1112 debugs(83, 5, "Comparing private and public SSL keys.");
62e76326 1113
1114 if (!SSL_CTX_check_private_key(sslContext)) {
1115 ssl_error = ERR_get_error();
1116 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
1117 certfile, keyfile, ERR_error_string(ssl_error, NULL));
1118 }
a7ad6e4e 1119 }
62e76326 1120
bf8fe701 1121 debugs(83, 9, "Setting RSA key generation callback.");
f484cdf5 1122 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
1123
a7ad6e4e 1124 if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
48e7baac 1125 debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!");
62e76326 1126 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 1127 } else {
bf8fe701 1128 debugs(83, 9, "Setting certificate verification callback.");
62e76326 1129 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
a7ad6e4e 1130 }
f484cdf5 1131
bf8fe701 1132 debugs(83, 9, "Setting CA certificate locations.");
62e76326 1133
a82a4fe4 1134 if ((CAfile || CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) {
1135 ssl_error = ERR_get_error();
48e7baac 1136 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
a82a4fe4 1137 }
1138
1139 if (CRLfile) {
1140 ssl_load_crl(sslContext, CRLfile);
1141 fl |= SSL_FLAG_VERIFY_CRL;
1142 }
1143
32d002cb 1144#if X509_V_FLAG_CRL_CHECK
a82a4fe4 1145 if (fl & SSL_FLAG_VERIFY_CRL_ALL)
1146 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1147 else if (fl & SSL_FLAG_VERIFY_CRL)
1148 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
1149
1150#endif
62e76326 1151
a7ad6e4e 1152 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 1153 !SSL_CTX_set_default_verify_paths(sslContext)) {
1154 ssl_error = ERR_get_error();
48e7baac 1155 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
f484cdf5 1156 }
62e76326 1157
d193a436 1158 return sslContext;
f484cdf5 1159}
1160
63be0a78 1161/// \ingroup ServerProtocolSSLInternal
d193a436 1162int
e6ccf245 1163ssl_read_method(int fd, char *buf, int len)
f484cdf5 1164{
6de9e64b 1165 SSL *ssl = fd_table[fd].ssl;
79d4ccdf 1166 int i;
1167
6de9e64b 1168#if DONT_DO_THIS
1169
1170 if (!SSL_is_init_finished(ssl)) {
1171 errno = ENOTCONN;
1172 return -1;
1173 }
79d4ccdf 1174
6de9e64b 1175#endif
1176
1177 i = SSL_read(ssl, buf, len);
1178
1179 if (i > 0 && SSL_pending(ssl) > 0) {
bf8fe701 1180 debugs(83, 2, "SSL FD " << fd << " is pending");
be4d35dc 1181 fd_table[fd].flags.read_pending = true;
79d4ccdf 1182 } else
be4d35dc 1183 fd_table[fd].flags.read_pending = false;
79d4ccdf 1184
1185 return i;
f484cdf5 1186}
1187
63be0a78 1188/// \ingroup ServerProtocolSSLInternal
d193a436 1189int
e6ccf245 1190ssl_write_method(int fd, const char *buf, int len)
f484cdf5 1191{
6de9e64b 1192 SSL *ssl = fd_table[fd].ssl;
1193 int i;
1194
1195 if (!SSL_is_init_finished(ssl)) {
1196 errno = ENOTCONN;
1197 return -1;
1198 }
1199
1200 i = SSL_write(ssl, buf, len);
1201
1202 return i;
f484cdf5 1203}
79d4ccdf 1204
1205void
575d05c4 1206ssl_shutdown_method(SSL *ssl)
79d4ccdf 1207{
79d4ccdf 1208 SSL_shutdown(ssl);
1209}
a7ad6e4e 1210
63be0a78 1211/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 1212static const char *
1213ssl_get_attribute(X509_NAME * name, const char *attribute_name)
1214{
1215 static char buffer[1024];
1216 int nid;
1217
1218 buffer[0] = '\0';
1219
1220 if (strcmp(attribute_name, "DN") == 0) {
62e76326 1221 X509_NAME_oneline(name, buffer, sizeof(buffer));
1222 goto done;
a7ad6e4e 1223 }
62e76326 1224
a7ad6e4e 1225 nid = OBJ_txt2nid((char *) attribute_name);
62e76326 1226
a7ad6e4e 1227 if (nid == 0) {
e0236918 1228 debugs(83, DBG_IMPORTANT, "WARNING: Unknown SSL attribute name '" << attribute_name << "'");
62e76326 1229 return NULL;
a7ad6e4e 1230 }
62e76326 1231
a7ad6e4e 1232 X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
62e76326 1233
1234done:
a7ad6e4e 1235 return *buffer ? buffer : NULL;
1236}
1237
63be0a78 1238/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 1239const char *
00352183 1240Ssl::GetX509UserAttribute(X509 * cert, const char *attribute_name)
a7ad6e4e 1241{
a7ad6e4e 1242 X509_NAME *name;
23e6c4ae 1243 const char *ret;
a7ad6e4e 1244
a7ad6e4e 1245 if (!cert)
62e76326 1246 return NULL;
a7ad6e4e 1247
5a4684b6 1248 name = X509_get_subject_name(cert);
a7ad6e4e 1249
23e6c4ae 1250 ret = ssl_get_attribute(name, attribute_name);
1251
23e6c4ae 1252 return ret;
a7ad6e4e 1253}
1254
00352183
AR
1255const char *
1256Ssl::GetX509Fingerprint(X509 * cert, const char *)
1257{
1258 static char buf[1024];
1259 if (!cert)
1260 return NULL;
960e100b 1261
00352183
AR
1262 unsigned int n;
1263 unsigned char md[EVP_MAX_MD_SIZE];
1264 if (!X509_digest(cert, EVP_sha1(), md, &n))
1265 return NULL;
1266
1267 assert(3 * n + 1 < sizeof(buf));
1268
1269 char *s = buf;
1270 for (unsigned int i=0; i < n; ++i, s += 3) {
1271 const char term = (i + 1 < n) ? ':' : '\0';
1272 snprintf(s, 4, "%02X%c", md[i], term);
1273 }
1274
1275 return buf;
1276}
1277
63be0a78 1278/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 1279const char *
00352183 1280Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name)
a7ad6e4e 1281{
00352183 1282
a7ad6e4e 1283 X509_NAME *name;
23e6c4ae 1284 const char *ret;
a7ad6e4e 1285
a7ad6e4e 1286 if (!cert)
62e76326 1287 return NULL;
a7ad6e4e 1288
5a4684b6 1289 name = X509_get_issuer_name(cert);
a7ad6e4e 1290
23e6c4ae 1291 ret = ssl_get_attribute(name, attribute_name);
1292
00352183
AR
1293 return ret;
1294}
1295
1296const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name)
1297{
1298 if (!ssl)
1299 return NULL;
1300
1301 X509 *cert = SSL_get_peer_certificate(ssl);
1302
1303 const char *attr = Ssl::GetX509UserAttribute(cert, attribute_name);
1304
23e6c4ae 1305 X509_free(cert);
00352183
AR
1306 return attr;
1307}
23e6c4ae 1308
00352183
AR
1309const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name)
1310{
1311 if (!ssl)
1312 return NULL;
1313
1314 X509 *cert = SSL_get_peer_certificate(ssl);
1315
1316 const char *attr = Ssl::GetX509CAAttribute(cert, attribute_name);
1317
1318 X509_free(cert);
1319 return attr;
a7ad6e4e 1320}
1321
a7ad6e4e 1322const char *
1323sslGetUserEmail(SSL * ssl)
1324{
e6ceef10 1325 return sslGetUserAttribute(ssl, "emailAddress");
a7ad6e4e 1326}
4ac9968f 1327
1328const char *
1329sslGetUserCertificatePEM(SSL *ssl)
1330{
1331 X509 *cert;
1332 BIO *mem;
1333 static char *str = NULL;
1334 char *ptr;
1335 long len;
1336
1337 safe_free(str);
1338
1339 if (!ssl)
1340 return NULL;
1341
1342 cert = SSL_get_peer_certificate(ssl);
1343
1344 if (!cert)
1345 return NULL;
1346
1347 mem = BIO_new(BIO_s_mem());
1348
1349 PEM_write_bio_X509(mem, cert);
1350
4ac9968f 1351 len = BIO_get_mem_data(mem, &ptr);
1352
1353 str = (char *)xmalloc(len + 1);
1354
1355 memcpy(str, ptr, len);
1356
1357 str[len] = '\0';
1358
1359 X509_free(cert);
1360
1361 BIO_free(mem);
1362
1363 return str;
1364}
3d61c476 1365
1366const char *
1367sslGetUserCertificateChainPEM(SSL *ssl)
1368{
1369 STACK_OF(X509) *chain;
1370 BIO *mem;
1371 static char *str = NULL;
1372 char *ptr;
1373 long len;
1374 int i;
1375
1376 safe_free(str);
1377
1378 if (!ssl)
1379 return NULL;
1380
1381 chain = SSL_get_peer_cert_chain(ssl);
1382
1383 if (!chain)
1384 return sslGetUserCertificatePEM(ssl);
1385
1386 mem = BIO_new(BIO_s_mem());
1387
d7ae3534 1388 for (i = 0; i < sk_X509_num(chain); ++i) {
3d61c476 1389 X509 *cert = sk_X509_value(chain, i);
1390 PEM_write_bio_X509(mem, cert);
1391 }
1392
1393 len = BIO_get_mem_data(mem, &ptr);
1394
1395 str = (char *)xmalloc(len + 1);
1396 memcpy(str, ptr, len);
1397 str[len] = '\0';
1398
1399 BIO_free(mem);
1400
1401 return str;
1402}
454e8283 1403
86660d64
CT
1404Ssl::ContextMethod
1405Ssl::contextMethod(int version)
1406{
1407 Ssl::ContextMethod method;
1408
1409 switch (version) {
1410
1411 case 2:
1412#ifndef OPENSSL_NO_SSL2
1413 debugs(83, 5, "Using SSLv2.");
1414 method = SSLv2_server_method();
1415#else
1416 debugs(83, DBG_IMPORTANT, "SSLv2 is not available in this Proxy.");
1417 return NULL;
1418#endif
1419 break;
1420
1421 case 3:
1422 debugs(83, 5, "Using SSLv3.");
1423 method = SSLv3_server_method();
1424 break;
1425
1426 case 4:
1427 debugs(83, 5, "Using TLSv1.");
1428 method = TLSv1_server_method();
1429 break;
1430
1431 case 5:
1432#if OPENSSL_VERSION_NUMBER >= 0x10001000L // NP: not sure exactly which sub-version yet.
1433 debugs(83, 5, "Using TLSv1.1.");
1434 method = TLSv1_1_server_method();
1435#else
1436 debugs(83, DBG_IMPORTANT, "TLSv1.1 is not available in this Proxy.");
1437 return NULL;
1438#endif
1439 break;
1440
1441 case 6:
1442#if OPENSSL_VERSION_NUMBER >= 0x10001000L // NP: not sure exactly which sub-version yet.
1443 debugs(83, 5, "Using TLSv1.2");
1444 method = TLSv1_2_server_method();
1445#else
1446 debugs(83, DBG_IMPORTANT, "TLSv1.2 is not available in this Proxy.");
1447 return NULL;
1448#endif
1449 break;
1450
1451 case 1:
1452
1453 default:
1454 debugs(83, 5, "Using SSLv2/SSLv3.");
1455 method = SSLv23_server_method();
1456 break;
1457 }
1458 return method;
1459}
1460
95d2589c
CT
1461/// \ingroup ServerProtocolSSLInternal
1462/// Create SSL context and apply ssl certificate and private key to it.
86660d64
CT
1463static SSL_CTX *
1464createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port)
95d2589c 1465{
86660d64 1466 Ssl::SSL_CTX_Pointer sslContext(SSL_CTX_new(port.contextMethod));
95d2589c
CT
1467
1468 if (!SSL_CTX_use_certificate(sslContext.get(), x509.get()))
1469 return NULL;
1470
1471 if (!SSL_CTX_use_PrivateKey(sslContext.get(), pkey.get()))
1472 return NULL;
86660d64
CT
1473
1474 if (!configureSslContext(sslContext.get(), port))
1475 return NULL;
1476
95d2589c
CT
1477 return sslContext.release();
1478}
1479
86660d64
CT
1480SSL_CTX *
1481Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port)
95d2589c
CT
1482{
1483 Ssl::X509_Pointer cert;
1484 Ssl::EVP_PKEY_Pointer pkey;
1485 if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
1486 return NULL;
1487
1488 if (!cert || !pkey)
1489 return NULL;
1490
86660d64 1491 return createSSLContext(cert, pkey, port);
95d2589c
CT
1492}
1493
86660d64
CT
1494SSL_CTX *
1495Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port)
95d2589c
CT
1496{
1497 Ssl::X509_Pointer cert;
1498 Ssl::EVP_PKEY_Pointer pkey;
aebe6888 1499 if (!generateSslCertificate(cert, pkey, properties))
95d2589c 1500 return NULL;
9a90aace 1501
95d2589c
CT
1502 if (!cert)
1503 return NULL;
1504
1505 if (!pkey)
1506 return NULL;
1507
86660d64 1508 return createSSLContext(cert, pkey, port);
95d2589c
CT
1509}
1510
4ece76b2 1511bool Ssl::verifySslCertificate(SSL_CTX * sslContext, CertificateProperties const &properties)
95d2589c 1512{
b8658552
CT
1513 // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
1514 // Try to retrieve certificate directly from SSL_CTX object
fc321c30 1515#if SQUID_USE_SSLGETCERTIFICATE_HACK
b8658552
CT
1516 X509 ***pCert = (X509 ***)sslContext->cert;
1517 X509 * cert = pCert && *pCert ? **pCert : NULL;
fc321c30
CT
1518#elif SQUID_SSLGETCERTIFICATE_BUGGY
1519 X509 * cert = NULL;
1520 assert(0);
b8658552 1521#else
95d2589c
CT
1522 // Temporary ssl for getting X509 certificate from SSL_CTX.
1523 Ssl::SSL_Pointer ssl(SSL_new(sslContext));
1524 X509 * cert = SSL_get_certificate(ssl.get());
b8658552
CT
1525#endif
1526 if (!cert)
1527 return false;
95d2589c
CT
1528 ASN1_TIME * time_notBefore = X509_get_notBefore(cert);
1529 ASN1_TIME * time_notAfter = X509_get_notAfter(cert);
1530 bool ret = (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
e7bcc25f
CT
1531 if (!ret)
1532 return false;
1533
4ece76b2 1534 return certificateMatchesProperties(cert, properties);
95d2589c
CT
1535}
1536
253749a8
CT
1537bool
1538Ssl::setClientSNI(SSL *ssl, const char *fqdn)
1539{
1540 //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
1541 // if the TLS servername extension (SNI) is enabled in openssl library.
1542#if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
1543 if (!SSL_set_tlsext_host_name(ssl, fqdn)) {
1544 const int ssl_error = ERR_get_error();
1545 debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
1546 ERR_error_string(ssl_error, NULL) << "\n");
1547 return false;
1548 }
1549 return true;
1550#else
1551 debugs(83, 7, "no support for TLS servername extension (SNI)\n");
1552 return false;
1553#endif
1554}
1555
a594dbfa
CT
1556void Ssl::addChainToSslContext(SSL_CTX *sslContext, STACK_OF(X509) *chain)
1557{
1558 if (!chain)
1559 return;
1560
d7ae3534 1561 for (int i = 0; i < sk_X509_num(chain); ++i) {
a594dbfa
CT
1562 X509 *cert = sk_X509_value(chain, i);
1563 if (SSL_CTX_add_extra_chain_cert(sslContext, cert)) {
1564 // increase the certificate lock
1565 CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509);
1566 } else {
1567 const int ssl_error = ERR_get_error();
1568 debugs(83, DBG_IMPORTANT, "WARNING: can not add certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL));
1569 }
1570 }
1571}
1572
1573/**
1574 \ingroup ServerProtocolSSLInternal
1575 * Read certificate from file.
1576 * See also: static readSslX509Certificate function, gadgets.cc file
1577 */
1578static X509 * readSslX509CertificatesChain(char const * certFilename, STACK_OF(X509)* chain)
1579{
1580 if (!certFilename)
1581 return NULL;
1582 Ssl::BIO_Pointer bio(BIO_new(BIO_s_file_internal()));
1583 if (!bio)
1584 return NULL;
1585 if (!BIO_read_filename(bio.get(), certFilename))
1586 return NULL;
1587 X509 *certificate = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL);
1588
1589 if (certificate && chain) {
1590
c11211d9 1591 if (X509_check_issued(certificate, certificate) == X509_V_OK)
a594dbfa
CT
1592 debugs(83, 5, "Certificate is self-signed, will not be chained");
1593 else {
a411d213 1594 // and add to the chain any other certificate exist in the file
a594dbfa
CT
1595 while (X509 *ca = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL)) {
1596 if (!sk_X509_push(chain, ca))
1597 debugs(83, DBG_IMPORTANT, "WARNING: unable to add CA certificate to cert chain");
1598 }
1599 }
1600 }
c11211d9 1601
a594dbfa
CT
1602 return certificate;
1603}
1604
1605void Ssl::readCertChainAndPrivateKeyFromFiles(X509_Pointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename)
1606{
1607 if (keyFilename == NULL)
1608 keyFilename = certFilename;
86660d64
CT
1609
1610 if (certFilename == NULL)
1611 certFilename = keyFilename;
1612
1613 debugs(83, DBG_IMPORTANT, "Using certificate in " << certFilename);
1614
a594dbfa
CT
1615 if (!chain)
1616 chain.reset(sk_X509_new_null());
1617 if (!chain)
1618 debugs(83, DBG_IMPORTANT, "WARNING: unable to allocate memory for cert chain");
37144aca
AR
1619 // XXX: ssl_ask_password_cb needs SSL_CTX_set_default_passwd_cb_userdata()
1620 // so this may not fully work iff Config.Program.ssl_password is set.
1621 pem_password_cb *cb = ::Config.Program.ssl_password ? &ssl_ask_password_cb : NULL;
1622 pkey.reset(readSslPrivateKey(keyFilename, cb));
a594dbfa
CT
1623 cert.reset(readSslX509CertificatesChain(certFilename, chain.get()));
1624 if (!pkey || !cert || !X509_check_private_key(cert.get(), pkey.get())) {
1625 pkey.reset(NULL);
1626 cert.reset(NULL);
1627 }
1628}
1629
95588170
CT
1630bool Ssl::generateUntrustedCert(X509_Pointer &untrustedCert, EVP_PKEY_Pointer &untrustedPkey, X509_Pointer const &cert, EVP_PKEY_Pointer const & pkey)
1631{
1632 // Generate the self-signed certificate, using a hard-coded subject prefix
1633 Ssl::CertificateProperties certProperties;
1634 if (const char *cn = CommonHostName(cert.get())) {
1635 certProperties.commonName = "Not trusted by \"";
1636 certProperties.commonName += cn;
1637 certProperties.commonName += "\"";
87f237a9 1638 } else if (const char *org = getOrganization(cert.get())) {
95588170
CT
1639 certProperties.commonName = "Not trusted by \"";
1640 certProperties.commonName += org;
1641 certProperties.commonName += "\"";
87f237a9 1642 } else
95588170
CT
1643 certProperties.commonName = "Not trusted";
1644 certProperties.setCommonName = true;
1645 // O, OU, and other CA subject fields will be mimicked
1646 // Expiration date and other common properties will be mimicked
1647 certProperties.signAlgorithm = Ssl::algSignSelf;
1648 certProperties.signWithPkey.resetAndLock(pkey.get());
1649 certProperties.mimicCert.resetAndLock(cert.get());
1650 return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
1651}
1652
62a7607e 1653Ssl::CertError::CertError(ssl_error_t anErr, X509 *aCert): code(anErr)
170cb017 1654{
62a7607e
CT
1655 cert.resetAndLock(aCert);
1656}
1657
1658Ssl::CertError::CertError(CertError const &err): code(err.code)
1659{
1660 cert.resetAndLock(err.cert.get());
1661}
1662
1663Ssl::CertError &
170cb017 1664Ssl::CertError::operator = (const CertError &old)
62a7607e 1665{
170cb017 1666 code = old.code;
62a7607e
CT
1667 cert.resetAndLock(old.cert.get());
1668 return *this;
1669}
1670
1671bool
1672Ssl::CertError::operator == (const CertError &ce) const
1673{
1674 return code == ce.code && cert.get() == ce.cert.get();
1675}
1676
1677bool
1678Ssl::CertError::operator != (const CertError &ce) const
1679{
1680 return code != ce.code || cert.get() != ce.cert.get();
1681}
1682
10a69fc0
CT
1683static int
1684store_session_cb(SSL *ssl, SSL_SESSION *session)
1685{
1686 if (!SslSessionCache)
1687 return 0;
1688
1689 debugs(83, 5, "Request to store SSL Session ");
1690
1691 SSL_SESSION_set_timeout(session, Config.SSL.session_ttl);
1692
1693 unsigned char *id = session->session_id;
1694 unsigned int idlen = session->session_id_length;
1695 unsigned char key[MEMMAP_SLOT_KEY_SIZE];
1696 // Session ids are of size 32bytes. They should always fit to a
86c63190 1697 // MemMap::Slot::key
10a69fc0
CT
1698 assert(idlen <= MEMMAP_SLOT_KEY_SIZE);
1699 memset(key, 0, sizeof(key));
1700 memcpy(key, id, idlen);
1701 int pos;
1702 Ipc::MemMap::Slot *slotW = SslSessionCache->openForWriting((const cache_key*)key, pos);
1703 if (slotW) {
1704 int lenRequired = i2d_SSL_SESSION(session, NULL);
1705 if (lenRequired < MEMMAP_SLOT_DATA_SIZE) {
1706 unsigned char *p = (unsigned char *)slotW->p;
1707 lenRequired = i2d_SSL_SESSION(session, &p);
1708 slotW->set(key, NULL, lenRequired, squid_curtime + Config.SSL.session_ttl);
1709 }
1710 SslSessionCache->closeForWriting(pos);
1711 debugs(83, 5, "wrote an ssl session entry of size " << lenRequired << " at pos " << pos);
1712 }
1713 return 0;
1714}
1715
1716static void
1717remove_session_cb(SSL_CTX *, SSL_SESSION *sessionID)
1718{
1719 if (!SslSessionCache)
1720 return ;
1721
1722 debugs(83, 5, "Request to remove corrupted or not valid SSL Session ");
1723 int pos;
1724 Ipc::MemMap::Slot const *slot = SslSessionCache->openForReading((const cache_key*)sessionID, pos);
1725 if (slot == NULL)
1726 return;
1727 SslSessionCache->closeForReading(pos);
1728 // TODO:
1729 // What if we are not able to remove the session?
1730 // Maybe schedule a job to remove it later?
1731 // For now we just have an invalid entry in cache until will be expired
1732 // The openSSL will reject it when we try to use it
1733 SslSessionCache->free(pos);
1734}
1735
1736static SSL_SESSION *
1737get_session_cb(SSL *, unsigned char *sessionID, int len, int *copy)
1738{
1739 if (!SslSessionCache)
1740 return NULL;
1741
1742 SSL_SESSION *session = NULL;
1743 const unsigned int *p;
1744 p = (unsigned int *)sessionID;
1745 debugs(83, 5, "Request to search for SSL Session of len:" <<
1746 len << p[0] << ":" << p[1]);
1747
1748 int pos;
1749 Ipc::MemMap::Slot const *slot = SslSessionCache->openForReading((const cache_key*)sessionID, pos);
1750 if (slot != NULL) {
1751 if (slot->expire > squid_curtime) {
1752 const unsigned char *ptr = slot->p;
1753 session = d2i_SSL_SESSION(NULL, &ptr, slot->pSize);
1754 debugs(83, 5, "Session retrieved from cache at pos " << pos);
1755 } else
1756 debugs(83, 5, "Session in cache expired");
1757 SslSessionCache->closeForReading(pos);
1758 }
1759
1760 if (!session)
1761 debugs(83, 5, "Failed to retrieved from cache\n");
1762
1763 // With the parameter copy the callback can require the SSL engine
1764 // to increment the reference count of the SSL_SESSION object, Normally
1765 // the reference count is not incremented and therefore the session must
1766 // not be explicitly freed with SSL_SESSION_free(3).
1767 *copy = 0;
1768 return session;
1769}
1770
1771static void
1772setSessionCallbacks(SSL_CTX *ctx)
1773{
1774 if (SslSessionCache) {
1775 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL);
1776 SSL_CTX_sess_set_new_cb(ctx, store_session_cb);
1777 SSL_CTX_sess_set_remove_cb(ctx, remove_session_cb);
1778 SSL_CTX_sess_set_get_cb(ctx, get_session_cb);
1779 }
1780}
1781
1782static bool
1783isSslServer()
1784{
1785 if (Config.Sockaddr.https)
1786 return true;
1787
1788 for (AnyP::PortCfg *s = Config.Sockaddr.http; s; s = s->next) {
1789 if (s->flags.tunnelSslBumping)
1790 return true;
1791 }
1792
1793 return false;
1794}
1795
1796#define SSL_SESSION_ID_SIZE 32
1797#define SSL_SESSION_MAX_SIZE 10*1024
1798
1799void
1800Ssl::initialize_session_cache()
1801{
1802
1803 if (!isSslServer()) //no need to configure ssl session cache.
1804 return;
1805
86c63190 1806 // Check if the MemMap keys and data are enough big to hold
10a69fc0
CT
1807 // session ids and session data
1808 assert(SSL_SESSION_ID_SIZE >= MEMMAP_SLOT_KEY_SIZE);
1809 assert(SSL_SESSION_MAX_SIZE >= MEMMAP_SLOT_DATA_SIZE);
1810
1811 int configuredItems = ::Config.SSL.sessionCacheSize / sizeof(Ipc::MemMap::Slot);
1812 if (IamWorkerProcess() && configuredItems)
1813 SslSessionCache = new Ipc::MemMap(SslSessionCacheName);
1814 else {
1815 SslSessionCache = NULL;
1816 return;
1817 }
1818
1819 for (AnyP::PortCfg *s = ::Config.Sockaddr.https; s; s = s->next) {
1820 if (s->staticSslContext.get() != NULL)
1821 setSessionCallbacks(s->staticSslContext.get());
1822 }
1823
1824 for (AnyP::PortCfg *s = ::Config.Sockaddr.http; s; s = s->next) {
1825 if (s->staticSslContext.get() != NULL)
1826 setSessionCallbacks(s->staticSslContext.get());
1827 }
1828}
1829
1830void
1831destruct_session_cache()
1832{
1833 delete SslSessionCache;
1834}
1835
1836/// initializes shared memory segments used by MemStore
1837class SharedSessionCacheRr: public Ipc::Mem::RegisteredRunner
1838{
1839public:
1840 /* RegisteredRunner API */
1841 SharedSessionCacheRr(): owner(NULL) {}
21b7990f 1842 virtual void useConfig();
10a69fc0
CT
1843 virtual ~SharedSessionCacheRr();
1844
1845protected:
21b7990f 1846 virtual void create();
10a69fc0
CT
1847
1848private:
1849 Ipc::MemMap::Owner *owner;
1850};
1851
21b7990f 1852RunnerRegistrationEntry(SharedSessionCacheRr);
10a69fc0
CT
1853
1854void
21b7990f 1855SharedSessionCacheRr::useConfig()
10a69fc0 1856{
21b7990f 1857 Ipc::Mem::RegisteredRunner::useConfig();
10a69fc0
CT
1858}
1859
1860void
21b7990f 1861SharedSessionCacheRr::create()
10a69fc0
CT
1862{
1863 if (!isSslServer()) //no need to configure ssl session cache.
1864 return;
1865
1866 int items;
1867 items = Config.SSL.sessionCacheSize / sizeof(Ipc::MemMap::Slot);
1868 if (items)
1869 owner = Ipc::MemMap::Init(SslSessionCacheName, items);
1870}
1871
1872SharedSessionCacheRr::~SharedSessionCacheRr()
1873{
1874 delete owner;
1875}
1876
cb4f4424 1877#endif /* USE_OPENSSL */