]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/support.cc
Compat: cleanup several config.h hacks
[thirdparty/squid.git] / src / ssl / support.cc
CommitLineData
f484cdf5 1
2/*
262a0e14 3 * $Id$
f484cdf5 4 *
5 * AUTHOR: Benno Rice
27d8545c 6 * DEBUG: section 83 SSL accelerator support
f484cdf5 7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
26ac0430 24 *
f484cdf5 25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
26ac0430 29 *
f484cdf5 30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36#include "squid.h"
454e8283 37
38/* MS Visual Studio Projects are monolithic, so we need the following
39 * #if to exclude the SSL code from compile process when not needed.
40 */
41#if USE_SSL
42
528b2c61 43#include "fde.h"
c0941a6a 44#include "acl/FilledChecklist.h"
4db984be 45#include "ssl/support.h"
95d2589c 46#include "ssl/gadgets.h"
f484cdf5 47
63be0a78 48/**
49 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
50 \ingroup ServerProtocolSSLAPI
51 */
52
53/// \ingroup ServerProtocolSSLInternal
307b83b7 54static int
55ssl_ask_password_cb(char *buf, int size, int rwflag, void *userdata)
56{
57 FILE *in;
58 int len = 0;
59 char cmdline[1024];
60
61 snprintf(cmdline, sizeof(cmdline), "\"%s\" \"%s\"", Config.Program.ssl_password, (const char *)userdata);
62 in = popen(cmdline, "r");
63
64 if (fgets(buf, size, in))
65
66 len = strlen(buf);
67
68 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
69
70 len--;
71
72 buf[len] = '\0';
73
74 pclose(in);
75
76 return len;
77}
78
63be0a78 79/// \ingroup ServerProtocolSSLInternal
307b83b7 80static void
81ssl_ask_password(SSL_CTX * context, const char * prompt)
82{
83 if (Config.Program.ssl_password) {
84 SSL_CTX_set_default_passwd_cb(context, ssl_ask_password_cb);
85 SSL_CTX_set_default_passwd_cb_userdata(context, (void *)prompt);
86 }
87}
88
63be0a78 89/// \ingroup ServerProtocolSSLInternal
f484cdf5 90static RSA *
e6ccf245 91ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen)
f484cdf5 92{
e01f02ed 93 static RSA *rsa_512 = NULL;
94 static RSA *rsa_1024 = NULL;
95 RSA *rsa = NULL;
96 int newkey = 0;
f484cdf5 97
e01f02ed 98 switch (keylen) {
99
100 case 512:
101
102 if (!rsa_512) {
103 rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
104 newkey = 1;
105 }
106
107 rsa = rsa_512;
108 break;
109
110 case 1024:
111
112 if (!rsa_1024) {
113 rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
114 newkey = 1;
115 }
116
117 rsa = rsa_1024;
118 break;
119
120 default:
bf8fe701 121 debugs(83, 1, "ssl_temp_rsa_cb: Unexpected key length " << keylen);
e01f02ed 122 return NULL;
123 }
124
125 if (rsa == NULL) {
bf8fe701 126 debugs(83, 1, "ssl_temp_rsa_cb: Failed to generate key " << keylen);
e01f02ed 127 return NULL;
128 }
129
130 if (newkey) {
131 if (do_debug(83, 5))
132 PEM_write_RSAPrivateKey(debug_log, rsa, NULL, NULL, 0, NULL, NULL);
133
bf8fe701 134 debugs(83, 1, "Generated ephemeral RSA key of length " << keylen);
e01f02ed 135 }
62e76326 136
f484cdf5 137 return rsa;
138}
139
63be0a78 140/// \ingroup ServerProtocolSSLInternal
f484cdf5 141static int
142ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
143{
144 char buffer[256];
a7ad6e4e 145 SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
146 SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
147 const char *server = (const char *)SSL_get_ex_data(ssl, ssl_ex_index_server);
148 void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
815eaa44 149 ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
a7ad6e4e 150 X509 *peer_cert = ctx->cert;
f484cdf5 151
a7ad6e4e 152 X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
62e76326 153 sizeof(buffer));
a7ad6e4e 154
155 if (ok) {
bf8fe701 156 debugs(83, 5, "SSL Certificate signature OK: " << buffer);
62e76326 157
158 if (server) {
159 int i;
160 int found = 0;
161 char cn[1024];
8cd03ece
AJ
162
163 STACK_OF(GENERAL_NAME) * altnames;
531fc437 164 altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
8cd03ece
AJ
165 if (altnames) {
166 int numalts = sk_GENERAL_NAME_num(altnames);
167 debugs(83, 3, "Verifying server domain " << server << " to certificate subjectAltName");
168 for (i = 0; i < numalts; i++) {
169 const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
170 if (check->type != GEN_DNS) {
171 continue;
172 }
173 ASN1_STRING *data = check->d.dNSName;
174 if (data->length > (int)sizeof(cn) - 1) {
175 continue;
176 }
177 memcpy(cn, data->data, data->length);
178 cn[data->length] = '\0';
179 debugs(83, 4, "Verifying server domain " << server << " to certificate name " << cn);
180 if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
181 found = 1;
182 break;
183 }
184 }
185 }
186
62e76326 187 X509_NAME *name = X509_get_subject_name(peer_cert);
bf8fe701 188 debugs(83, 3, "Verifying server domain " << server << " to certificate dn " << buffer);
62e76326 189
190 for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
191 ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
192
193 if (data->length > (int)sizeof(cn) - 1)
194 continue;
195
196 memcpy(cn, data->data, data->length);
197
198 cn[data->length] = '\0';
199
bf8fe701 200 debugs(83, 4, "Verifying server domain " << server << " to certificate cn " << cn);
62e76326 201
202 if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
203 found = 1;
204 break;
205 }
206 }
207
208 if (!found) {
815eaa44 209 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
62e76326 210 ok = 0;
815eaa44 211 if (check)
c0941a6a 212 Filled(check)->ssl_error = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
62e76326 213 }
214 }
a7ad6e4e 215 } else {
62e76326 216 switch (ctx->error) {
217
218 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
bf8fe701 219 debugs(83, 5, "SSL Certficate error: CA not known: " << buffer);
62e76326 220 break;
221
222 case X509_V_ERR_CERT_NOT_YET_VALID:
bf8fe701 223 debugs(83, 5, "SSL Certficate not yet valid: " << buffer);
62e76326 224 break;
225
226 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
bf8fe701 227 debugs(83, 5, "SSL Certificate has illegal \'not before\' field: " <<
228 buffer);
26ac0430 229
62e76326 230 break;
231
232 case X509_V_ERR_CERT_HAS_EXPIRED:
bf8fe701 233 debugs(83, 5, "SSL Certificate expired: " << buffer);
62e76326 234 break;
235
236 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
bf8fe701 237 debugs(83, 5, "SSL Certificate has invalid \'not after\' field: " << buffer);
62e76326 238 break;
239
240 default:
bf8fe701 241 debugs(83, 1, "SSL unknown certificate error " << ctx->error << " in " << buffer);
62e76326 242 break;
243 }
815eaa44 244
245 if (check)
c0941a6a 246 Filled(check)->ssl_error = ctx->error;
815eaa44 247 }
248
249 if (!ok && check) {
250 if (check->fastCheck()) {
251 debugs(83, 3, "bypassing SSL error " << ctx->error << " in " << buffer);
252 ok = 1;
253 } else {
254 debugs(83, 5, "confirming SSL error " << ctx->error);
255 }
a7ad6e4e 256 }
62e76326 257
26ac0430 258 if (!dont_verify_domain && server) {}
62e76326 259
f484cdf5 260 return ok;
261}
262
63be0a78 263/// \ingroup ServerProtocolSSLInternal
26ac0430 264static struct ssl_option {
79d4ccdf 265 const char *name;
266 long value;
62e76326 267}
268
269ssl_options[] = {
79d4ccdf 270
32d002cb 271#if SSL_OP_MICROSOFT_SESS_ID_BUG
26ac0430
AJ
272 {
273 "MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG
274 },
673cd7db 275#endif
32d002cb 276#if SSL_OP_NETSCAPE_CHALLENGE_BUG
26ac0430
AJ
277 {
278 "NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG
279 },
673cd7db 280#endif
32d002cb 281#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
26ac0430
AJ
282 {
283 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
284 },
673cd7db 285#endif
32d002cb 286#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
26ac0430
AJ
287 {
288 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
289 },
673cd7db 290#endif
32d002cb 291#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
26ac0430
AJ
292 {
293 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
294 },
673cd7db 295#endif
32d002cb 296#if SSL_OP_MSIE_SSLV2_RSA_PADDING
26ac0430
AJ
297 {
298 "MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING
299 },
673cd7db 300#endif
32d002cb 301#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
26ac0430
AJ
302 {
303 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
304 },
673cd7db 305#endif
32d002cb 306#if SSL_OP_TLS_D5_BUG
26ac0430
AJ
307 {
308 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
309 },
673cd7db 310#endif
32d002cb 311#if SSL_OP_TLS_BLOCK_PADDING_BUG
26ac0430
AJ
312 {
313 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
314 },
673cd7db 315#endif
32d002cb 316#if SSL_OP_TLS_ROLLBACK_BUG
26ac0430
AJ
317 {
318 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
319 },
673cd7db 320#endif
32d002cb 321#if SSL_OP_ALL
26ac0430
AJ
322 {
323 "ALL", SSL_OP_ALL
324 },
673cd7db 325#endif
32d002cb 326#if SSL_OP_SINGLE_DH_USE
26ac0430
AJ
327 {
328 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
329 },
673cd7db 330#endif
32d002cb 331#if SSL_OP_EPHEMERAL_RSA
26ac0430
AJ
332 {
333 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
334 },
673cd7db 335#endif
32d002cb 336#if SSL_OP_PKCS1_CHECK_1
26ac0430
AJ
337 {
338 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
339 },
673cd7db 340#endif
32d002cb 341#if SSL_OP_PKCS1_CHECK_2
26ac0430
AJ
342 {
343 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
344 },
673cd7db 345#endif
32d002cb 346#if SSL_OP_NETSCAPE_CA_DN_BUG
26ac0430
AJ
347 {
348 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
349 },
673cd7db 350#endif
32d002cb 351#if SSL_OP_NON_EXPORT_FIRST
26ac0430
AJ
352 {
353 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
354 },
673cd7db 355#endif
32d002cb 356#if SSL_OP_CIPHER_SERVER_PREFERENCE
26ac0430
AJ
357 {
358 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
359 },
673cd7db 360#endif
32d002cb 361#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
26ac0430
AJ
362 {
363 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
364 },
673cd7db 365#endif
32d002cb 366#if SSL_OP_NO_SSLv2
26ac0430
AJ
367 {
368 "NO_SSLv2", SSL_OP_NO_SSLv2
369 },
673cd7db 370#endif
32d002cb 371#if SSL_OP_NO_SSLv3
26ac0430
AJ
372 {
373 "NO_SSLv3", SSL_OP_NO_SSLv3
374 },
673cd7db 375#endif
32d002cb 376#if SSL_OP_NO_TLSv1
26ac0430
AJ
377 {
378 "NO_TLSv1", SSL_OP_NO_TLSv1
379 },
673cd7db 380#endif
26ac0430
AJ
381 {
382 "", 0
383 },
384 {
385 NULL, 0
386 }
387};
79d4ccdf 388
63be0a78 389/// \ingroup ServerProtocolSSLInternal
84f2d773 390static long
79d4ccdf 391ssl_parse_options(const char *options)
392{
393 long op = SSL_OP_ALL;
394 char *tmp;
395 char *option;
396
397 if (!options)
62e76326 398 goto no_options;
79d4ccdf 399
400 tmp = xstrdup(options);
62e76326 401
79d4ccdf 402 option = strtok(tmp, ":,");
62e76326 403
79d4ccdf 404 while (option) {
62e76326 405
406 struct ssl_option *opt = NULL, *opttmp;
407 long value = 0;
408 enum {
409 MODE_ADD, MODE_REMOVE
410 } mode;
411
412 switch (*option) {
413
414 case '!':
415
416 case '-':
417 mode = MODE_REMOVE;
418 option++;
419 break;
420
421 case '+':
422 mode = MODE_ADD;
423 option++;
424 break;
425
426 default:
427 mode = MODE_ADD;
428 break;
429 }
430
431 for (opttmp = ssl_options; opttmp->name; opttmp++) {
432 if (strcmp(opttmp->name, option) == 0) {
433 opt = opttmp;
434 break;
435 }
436 }
437
438 if (opt)
439 value = opt->value;
440 else if (strncmp(option, "0x", 2) == 0) {
441 /* Special case.. hex specification */
442 value = strtol(option + 2, NULL, 16);
443 } else {
444 fatalf("Unknown SSL option '%s'", option);
445 value = 0; /* Keep GCC happy */
446 }
447
448 switch (mode) {
449
450 case MODE_ADD:
451 op |= value;
452 break;
453
454 case MODE_REMOVE:
455 op &= ~value;
456 break;
457 }
458
459 option = strtok(NULL, ":,");
79d4ccdf 460 }
461
462 safe_free(tmp);
62e76326 463
464no_options:
79d4ccdf 465 return op;
466}
467
63be0a78 468/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 469#define SSL_FLAG_NO_DEFAULT_CA (1<<0)
63be0a78 470/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 471#define SSL_FLAG_DELAYED_AUTH (1<<1)
63be0a78 472/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 473#define SSL_FLAG_DONT_VERIFY_PEER (1<<2)
63be0a78 474/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 475#define SSL_FLAG_DONT_VERIFY_DOMAIN (1<<3)
63be0a78 476/// \ingroup ServerProtocolSSLInternal
b13877cc 477#define SSL_FLAG_NO_SESSION_REUSE (1<<4)
63be0a78 478/// \ingroup ServerProtocolSSLInternal
a82a4fe4 479#define SSL_FLAG_VERIFY_CRL (1<<5)
63be0a78 480/// \ingroup ServerProtocolSSLInternal
a82a4fe4 481#define SSL_FLAG_VERIFY_CRL_ALL (1<<6)
a7ad6e4e 482
63be0a78 483/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 484static long
485ssl_parse_flags(const char *flags)
486{
487 long fl = 0;
488 char *tmp;
489 char *flag;
490
491 if (!flags)
62e76326 492 return 0;
a7ad6e4e 493
494 tmp = xstrdup(flags);
62e76326 495
a7ad6e4e 496 flag = strtok(tmp, ":,");
62e76326 497
a7ad6e4e 498 while (flag) {
62e76326 499 if (strcmp(flag, "NO_DEFAULT_CA") == 0)
500 fl |= SSL_FLAG_NO_DEFAULT_CA;
501 else if (strcmp(flag, "DELAYED_AUTH") == 0)
502 fl |= SSL_FLAG_DELAYED_AUTH;
503 else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
504 fl |= SSL_FLAG_DONT_VERIFY_PEER;
505 else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
506 fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
b13877cc 507 else if (strcmp(flag, "NO_SESSION_REUSE") == 0)
508 fl |= SSL_FLAG_NO_SESSION_REUSE;
a82a4fe4 509
32d002cb 510#if X509_V_FLAG_CRL_CHECK
a82a4fe4 511
512 else if (strcmp(flag, "VERIFY_CRL") == 0)
513 fl |= SSL_FLAG_VERIFY_CRL;
514 else if (strcmp(flag, "VERIFY_CRL_ALL") == 0)
515 fl |= SSL_FLAG_VERIFY_CRL_ALL;
516
517#endif
518
62e76326 519 else
520 fatalf("Unknown ssl flag '%s'", flag);
521
522 flag = strtok(NULL, ":,");
a7ad6e4e 523 }
62e76326 524
a7ad6e4e 525 safe_free(tmp);
526 return fl;
527}
528
26ac0430 529struct SslErrorMapEntry {
815eaa44 530 const char *name;
531 ssl_error_t value;
532};
533
534static SslErrorMapEntry TheSslErrorMap[] = {
535 { "SQUID_X509_V_ERR_DOMAIN_MISMATCH", SQUID_X509_V_ERR_DOMAIN_MISMATCH },
536 { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT },
537 { "X509_V_ERR_CERT_NOT_YET_VALID", X509_V_ERR_CERT_NOT_YET_VALID },
538 { "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD },
539 { "X509_V_ERR_CERT_HAS_EXPIRED", X509_V_ERR_CERT_HAS_EXPIRED },
540 { "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD },
541 { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY },
542 { "SSL_ERROR_NONE", SSL_ERROR_NONE },
543 { NULL, SSL_ERROR_NONE }
544};
545
546ssl_error_t
547sslParseErrorString(const char *name)
548{
549 assert(name);
550
551 for (int i = 0; TheSslErrorMap[i].name; ++i) {
552 if (strcmp(name, TheSslErrorMap[i].name) == 0)
553 return TheSslErrorMap[i].value;
554 }
555
556 if (xisdigit(*name)) {
557 const long int value = strtol(name, NULL, 0);
558 if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX)
559 return value;
560 fatalf("Too small or too bug SSL error code '%s'", name);
561 }
562
563 fatalf("Unknown SSL error name '%s'", name);
564 return SSL_ERROR_SSL; // not reached
565}
566
567const char *
568sslFindErrorString(ssl_error_t value)
569{
570 for (int i = 0; TheSslErrorMap[i].name; ++i) {
571 if (TheSslErrorMap[i].value == value)
572 return TheSslErrorMap[i].name;
573 }
574
575 return NULL;
576}
577
578// "dup" function for SSL_get_ex_new_index("cert_err_check")
579static int
580ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
26ac0430
AJ
581 int, long, void *)
582{
815eaa44 583 // We do not support duplication of ACLCheckLists.
584 // If duplication is needed, we can count copies with cbdata.
585 assert(false);
586 return 0;
587}
588
589// "free" function for SSL_get_ex_new_index("cert_err_check")
590static void
591ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
26ac0430
AJ
592 int, long, void *)
593{
815eaa44 594 delete static_cast<ACLChecklist *>(ptr); // may be NULL
595}
a7ad6e4e 596
63be0a78 597/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 598static void
599ssl_initialize(void)
f484cdf5 600{
d193a436 601 static int ssl_initialized = 0;
62e76326 602
d193a436 603 if (!ssl_initialized) {
62e76326 604 ssl_initialized = 1;
605 SSL_load_error_strings();
606 SSLeay_add_ssl_algorithms();
32d002cb 607#if HAVE_OPENSSL_ENGINE_H
62e76326 608
609 if (Config.SSL.ssl_engine) {
610 ENGINE *e;
611
612 if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
613 fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
614 }
615
616 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
617 int ssl_error = ERR_get_error();
618 fatalf("Failed to initialise SSL engine: %s\n",
619 ERR_error_string(ssl_error, NULL));
620 }
621 }
622
a7ad6e4e 623#else
62e76326 624 if (Config.SSL.ssl_engine) {
625 fatalf("Your OpenSSL has no SSL engine support\n");
626 }
627
a7ad6e4e 628#endif
62e76326 629
d193a436 630 }
62e76326 631
a7ad6e4e 632 ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
633 ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
815eaa44 634 ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
a7ad6e4e 635}
636
63be0a78 637/// \ingroup ServerProtocolSSLInternal
a82a4fe4 638static int
639ssl_load_crl(SSL_CTX *sslContext, const char *CRLfile)
640{
641 X509_STORE *st = SSL_CTX_get_cert_store(sslContext);
642 X509_CRL *crl;
643 BIO *in = BIO_new_file(CRLfile, "r");
644 int count = 0;
645
646 if (!in) {
bf8fe701 647 debugs(83, 2, "WARNING: Failed to open CRL file '" << CRLfile << "'");
a82a4fe4 648 return 0;
649 }
650
651 while ((crl = PEM_read_bio_X509_CRL(in,NULL,NULL,NULL))) {
652 if (!X509_STORE_add_crl(st, crl))
bf8fe701 653 debugs(83, 2, "WARNING: Failed to add CRL from file '" << CRLfile << "'");
a82a4fe4 654 else
655 count++;
656
657 X509_CRL_free(crl);
658 }
659
660 BIO_free(in);
661 return count;
662}
663
a7ad6e4e 664SSL_CTX *
a82a4fe4 665sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath, const char *CRLfile, const char *dhfile, const char *context)
a7ad6e4e 666{
667 int ssl_error;
f1c9c850 668#if OPENSSL_VERSION_NUMBER < 0x00909000L
a7ad6e4e 669 SSL_METHOD *method;
f1c9c850
AJ
670#else
671 const SSL_METHOD *method;
672#endif
a7ad6e4e 673 SSL_CTX *sslContext;
674 long fl = ssl_parse_flags(flags);
675
676 ssl_initialize();
677
f484cdf5 678 if (!keyfile)
62e76326 679 keyfile = certfile;
680
f484cdf5 681 if (!certfile)
62e76326 682 certfile = keyfile;
683
a7ad6e4e 684 if (!CAfile)
62e76326 685 CAfile = clientCA;
f484cdf5 686
79d4ccdf 687 switch (version) {
62e76326 688
f484cdf5 689 case 2:
bf8fe701 690 debugs(83, 5, "Using SSLv2.");
62e76326 691 method = SSLv2_server_method();
692 break;
693
f484cdf5 694 case 3:
bf8fe701 695 debugs(83, 5, "Using SSLv3.");
62e76326 696 method = SSLv3_server_method();
697 break;
698
f484cdf5 699 case 4:
bf8fe701 700 debugs(83, 5, "Using TLSv1.");
62e76326 701 method = TLSv1_server_method();
702 break;
703
f484cdf5 704 case 1:
62e76326 705
f484cdf5 706 default:
bf8fe701 707 debugs(83, 5, "Using SSLv2/SSLv3.");
62e76326 708 method = SSLv23_server_method();
709 break;
f484cdf5 710 }
711
712 sslContext = SSL_CTX_new(method);
62e76326 713
f484cdf5 714 if (sslContext == NULL) {
62e76326 715 ssl_error = ERR_get_error();
716 fatalf("Failed to allocate SSL context: %s\n",
717 ERR_error_string(ssl_error, NULL));
f484cdf5 718 }
62e76326 719
79d4ccdf 720 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
f484cdf5 721
6b2936d5 722 if (context && *context) {
3de409f0 723 SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)context, strlen(context));
6b2936d5 724 }
725
b13877cc 726 if (fl & SSL_FLAG_NO_SESSION_REUSE) {
727 SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
728 }
729
a9d79803 730 if (Config.SSL.unclean_shutdown) {
bf8fe701 731 debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
a9d79803 732
733 SSL_CTX_set_quiet_shutdown(sslContext, 1);
734 }
735
79d4ccdf 736 if (cipher) {
bf8fe701 737 debugs(83, 5, "Using chiper suite " << cipher << ".");
62e76326 738
739 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
740 ssl_error = ERR_get_error();
741 fatalf("Failed to set SSL cipher suite '%s': %s\n",
742 cipher, ERR_error_string(ssl_error, NULL));
743 }
79d4ccdf 744 }
62e76326 745
bf8fe701 746 debugs(83, 1, "Using certificate in " << certfile);
62e76326 747
a7ad6e4e 748 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
62e76326 749 ssl_error = ERR_get_error();
bf8fe701 750 debugs(83, 0, "Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL) );
62e76326 751 goto error;
f484cdf5 752 }
62e76326 753
bf8fe701 754 debugs(83, 1, "Using private key in " << keyfile);
307b83b7 755 ssl_ask_password(sslContext, keyfile);
62e76326 756
f484cdf5 757 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
62e76326 758 ssl_error = ERR_get_error();
bf8fe701 759 debugs(83, 0, "Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL) );
62e76326 760 goto error;
f484cdf5 761 }
62e76326 762
bf8fe701 763 debugs(83, 5, "Comparing private and public SSL keys.");
62e76326 764
a7ad6e4e 765 if (!SSL_CTX_check_private_key(sslContext)) {
62e76326 766 ssl_error = ERR_get_error();
26ac0430 767 debugs(83, 0, "SSL private key '" <<
bf8fe701 768 certfile << "' does not match public key '" <<
769 keyfile << "': " << ERR_error_string(ssl_error, NULL) );
62e76326 770 goto error;
a7ad6e4e 771 }
62e76326 772
bf8fe701 773 debugs(83, 9, "Setting RSA key generation callback.");
a7ad6e4e 774 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
775
bf8fe701 776 debugs(83, 9, "Setting CA certificate locations.");
62e76326 777
a82a4fe4 778 if ((CAfile || CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) {
62e76326 779 ssl_error = ERR_get_error();
bf8fe701 780 debugs(83, 1, "Error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL) );
781 debugs(83, 1, "continuing anyway..." );
a7ad6e4e 782 }
62e76326 783
a7ad6e4e 784 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 785 !SSL_CTX_set_default_verify_paths(sslContext)) {
786 ssl_error = ERR_get_error();
bf8fe701 787 debugs(83, 1, "Error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL) );
788 debugs(83, 1, "continuing anyway..." );
a7ad6e4e 789 }
62e76326 790
a7ad6e4e 791 if (clientCA) {
8c1ff4ef 792 STACK_OF(X509_NAME) *cert_names;
bf8fe701 793 debugs(83, 9, "Set client certifying authority list.");
8c1ff4ef 794 cert_names = SSL_load_client_CA_file(clientCA);
795
796 if (cert_names == NULL) {
26ac0430 797 debugs(83, 1, "Error loading the client CA certificates from '" << clientCA << "\': " << ERR_error_string(ERR_get_error(),NULL) );
8c1ff4ef 798 goto error;
799 }
800
801 ERR_clear_error();
802 SSL_CTX_set_client_CA_list(sslContext, cert_names);
62e76326 803
804 if (fl & SSL_FLAG_DELAYED_AUTH) {
bf8fe701 805 debugs(83, 9, "Not requesting client certificates until acl processing requires one");
62e76326 806 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
807 } else {
bf8fe701 808 debugs(83, 9, "Requiring client certificates.");
62e76326 809 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
810 }
a82a4fe4 811
812 if (CRLfile) {
813 ssl_load_crl(sslContext, CRLfile);
814 fl |= SSL_FLAG_VERIFY_CRL;
815 }
816
32d002cb 817#if X509_V_FLAG_CRL_CHECK
a82a4fe4 818 if (fl & SSL_FLAG_VERIFY_CRL_ALL)
819 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
820 else if (fl & SSL_FLAG_VERIFY_CRL)
821 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
822
823#endif
824
a7ad6e4e 825 } else {
bf8fe701 826 debugs(83, 9, "Not requiring any client certificates");
62e76326 827 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 828 }
f484cdf5 829
35105e4b 830 if (dhfile) {
831 FILE *in = fopen(dhfile, "r");
832 DH *dh = NULL;
833 int codes;
834
835 if (in) {
836 dh = PEM_read_DHparams(in, NULL, NULL, NULL);
837 fclose(in);
838 }
839
840 if (!dh)
bf8fe701 841 debugs(83, 1, "WARNING: Failed to read DH parameters '" << dhfile << "'");
35105e4b 842 else if (dh && DH_check(dh, &codes) == 0) {
843 if (codes) {
bf8fe701 844 debugs(83, 1, "WARNING: Failed to verify DH parameters '" << dhfile << "' (" << std::hex << codes << ")");
35105e4b 845 DH_free(dh);
846 dh = NULL;
847 }
848 }
849
850 if (dh)
851 SSL_CTX_set_tmp_dh(sslContext, dh);
852 }
853
a7ad6e4e 854 if (fl & SSL_FLAG_DONT_VERIFY_DOMAIN)
62e76326 855 SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
856
a7ad6e4e 857 return sslContext;
62e76326 858
859error:
a7ad6e4e 860 SSL_CTX_free(sslContext);
62e76326 861
a7ad6e4e 862 return NULL;
863}
864
865SSL_CTX *
a82a4fe4 866sslCreateClientContext(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 867{
868 int ssl_error;
f1c9c850 869#if OPENSSL_VERSION_NUMBER < 0x00909000L
a7ad6e4e 870 SSL_METHOD *method;
f1c9c850
AJ
871#else
872 const SSL_METHOD *method;
873#endif
a7ad6e4e 874 SSL_CTX *sslContext;
875 long fl = ssl_parse_flags(flags);
876
877 ssl_initialize();
878
879 if (!keyfile)
62e76326 880 keyfile = certfile;
881
a7ad6e4e 882 if (!certfile)
62e76326 883 certfile = keyfile;
a7ad6e4e 884
a7ad6e4e 885 switch (version) {
62e76326 886
a7ad6e4e 887 case 2:
bf8fe701 888 debugs(83, 5, "Using SSLv2.");
62e76326 889 method = SSLv2_client_method();
890 break;
891
a7ad6e4e 892 case 3:
bf8fe701 893 debugs(83, 5, "Using SSLv3.");
62e76326 894 method = SSLv3_client_method();
895 break;
896
a7ad6e4e 897 case 4:
bf8fe701 898 debugs(83, 5, "Using TLSv1.");
62e76326 899 method = TLSv1_client_method();
900 break;
901
a7ad6e4e 902 case 1:
62e76326 903
a7ad6e4e 904 default:
bf8fe701 905 debugs(83, 5, "Using SSLv2/SSLv3.");
62e76326 906 method = SSLv23_client_method();
907 break;
a7ad6e4e 908 }
909
910 sslContext = SSL_CTX_new(method);
62e76326 911
a7ad6e4e 912 if (sslContext == NULL) {
62e76326 913 ssl_error = ERR_get_error();
914 fatalf("Failed to allocate SSL context: %s\n",
915 ERR_error_string(ssl_error, NULL));
a7ad6e4e 916 }
62e76326 917
a7ad6e4e 918 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
919
920 if (cipher) {
bf8fe701 921 debugs(83, 5, "Using chiper suite " << cipher << ".");
62e76326 922
923 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
924 ssl_error = ERR_get_error();
925 fatalf("Failed to set SSL cipher suite '%s': %s\n",
926 cipher, ERR_error_string(ssl_error, NULL));
927 }
a7ad6e4e 928 }
62e76326 929
a7ad6e4e 930 if (certfile) {
bf8fe701 931 debugs(83, 1, "Using certificate in " << certfile);
62e76326 932
933 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
934 ssl_error = ERR_get_error();
935 fatalf("Failed to acquire SSL certificate '%s': %s\n",
936 certfile, ERR_error_string(ssl_error, NULL));
937 }
938
bf8fe701 939 debugs(83, 1, "Using private key in " << keyfile);
307b83b7 940 ssl_ask_password(sslContext, keyfile);
62e76326 941
942 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
943 ssl_error = ERR_get_error();
944 fatalf("Failed to acquire SSL private key '%s': %s\n",
945 keyfile, ERR_error_string(ssl_error, NULL));
946 }
947
bf8fe701 948 debugs(83, 5, "Comparing private and public SSL keys.");
62e76326 949
950 if (!SSL_CTX_check_private_key(sslContext)) {
951 ssl_error = ERR_get_error();
952 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
953 certfile, keyfile, ERR_error_string(ssl_error, NULL));
954 }
a7ad6e4e 955 }
62e76326 956
bf8fe701 957 debugs(83, 9, "Setting RSA key generation callback.");
f484cdf5 958 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
959
a7ad6e4e 960 if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
bf8fe701 961 debugs(83, 1, "NOTICE: Peer certificates are not verified for validity!");
62e76326 962 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 963 } else {
bf8fe701 964 debugs(83, 9, "Setting certificate verification callback.");
62e76326 965 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
a7ad6e4e 966 }
f484cdf5 967
bf8fe701 968 debugs(83, 9, "Setting CA certificate locations.");
62e76326 969
a82a4fe4 970 if ((CAfile || CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) {
971 ssl_error = ERR_get_error();
bf8fe701 972 debugs(83, 1, "Error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
973 debugs(83, 1, "continuing anyway..." );
a82a4fe4 974 }
975
976 if (CRLfile) {
977 ssl_load_crl(sslContext, CRLfile);
978 fl |= SSL_FLAG_VERIFY_CRL;
979 }
980
32d002cb 981#if X509_V_FLAG_CRL_CHECK
a82a4fe4 982 if (fl & SSL_FLAG_VERIFY_CRL_ALL)
983 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
984 else if (fl & SSL_FLAG_VERIFY_CRL)
985 X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
986
987#endif
62e76326 988
a7ad6e4e 989 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 990 !SSL_CTX_set_default_verify_paths(sslContext)) {
991 ssl_error = ERR_get_error();
bf8fe701 992 debugs(83, 1, "Error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL) );
993 debugs(83, 1, "continuing anyway...");
f484cdf5 994 }
62e76326 995
d193a436 996 return sslContext;
f484cdf5 997}
998
63be0a78 999/// \ingroup ServerProtocolSSLInternal
d193a436 1000int
e6ccf245 1001ssl_read_method(int fd, char *buf, int len)
f484cdf5 1002{
6de9e64b 1003 SSL *ssl = fd_table[fd].ssl;
79d4ccdf 1004 int i;
1005
6de9e64b 1006#if DONT_DO_THIS
1007
1008 if (!SSL_is_init_finished(ssl)) {
1009 errno = ENOTCONN;
1010 return -1;
1011 }
79d4ccdf 1012
6de9e64b 1013#endif
1014
1015 i = SSL_read(ssl, buf, len);
1016
1017 if (i > 0 && SSL_pending(ssl) > 0) {
bf8fe701 1018 debugs(83, 2, "SSL FD " << fd << " is pending");
62e76326 1019 fd_table[fd].flags.read_pending = 1;
79d4ccdf 1020 } else
62e76326 1021 fd_table[fd].flags.read_pending = 0;
79d4ccdf 1022
1023 return i;
f484cdf5 1024}
1025
63be0a78 1026/// \ingroup ServerProtocolSSLInternal
d193a436 1027int
e6ccf245 1028ssl_write_method(int fd, const char *buf, int len)
f484cdf5 1029{
6de9e64b 1030 SSL *ssl = fd_table[fd].ssl;
1031 int i;
1032
1033 if (!SSL_is_init_finished(ssl)) {
1034 errno = ENOTCONN;
1035 return -1;
1036 }
1037
1038 i = SSL_write(ssl, buf, len);
1039
1040 return i;
f484cdf5 1041}
79d4ccdf 1042
1043void
e6ccf245 1044ssl_shutdown_method(int fd)
79d4ccdf 1045{
1046 SSL *ssl = fd_table[fd].ssl;
62e76326 1047
79d4ccdf 1048 SSL_shutdown(ssl);
1049}
a7ad6e4e 1050
63be0a78 1051/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 1052static const char *
1053ssl_get_attribute(X509_NAME * name, const char *attribute_name)
1054{
1055 static char buffer[1024];
1056 int nid;
1057
1058 buffer[0] = '\0';
1059
1060 if (strcmp(attribute_name, "DN") == 0) {
62e76326 1061 X509_NAME_oneline(name, buffer, sizeof(buffer));
1062 goto done;
a7ad6e4e 1063 }
62e76326 1064
a7ad6e4e 1065 nid = OBJ_txt2nid((char *) attribute_name);
62e76326 1066
a7ad6e4e 1067 if (nid == 0) {
bf8fe701 1068 debugs(83, 1, "WARNING: Unknown SSL attribute name '" << attribute_name << "'");
62e76326 1069 return NULL;
a7ad6e4e 1070 }
62e76326 1071
a7ad6e4e 1072 X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
62e76326 1073
1074done:
a7ad6e4e 1075 return *buffer ? buffer : NULL;
1076}
1077
63be0a78 1078/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 1079const char *
1080sslGetUserAttribute(SSL * ssl, const char *attribute_name)
1081{
1082 X509 *cert;
1083 X509_NAME *name;
23e6c4ae 1084 const char *ret;
a7ad6e4e 1085
1086 if (!ssl)
62e76326 1087 return NULL;
a7ad6e4e 1088
1089 cert = SSL_get_peer_certificate(ssl);
62e76326 1090
a7ad6e4e 1091 if (!cert)
62e76326 1092 return NULL;
a7ad6e4e 1093
5a4684b6 1094 name = X509_get_subject_name(cert);
a7ad6e4e 1095
23e6c4ae 1096 ret = ssl_get_attribute(name, attribute_name);
1097
1098 X509_free(cert);
1099
23e6c4ae 1100 return ret;
a7ad6e4e 1101}
1102
63be0a78 1103/// \ingroup ServerProtocolSSLInternal
a7ad6e4e 1104const char *
1105sslGetCAAttribute(SSL * ssl, const char *attribute_name)
1106{
1107 X509 *cert;
1108 X509_NAME *name;
23e6c4ae 1109 const char *ret;
a7ad6e4e 1110
1111 if (!ssl)
62e76326 1112 return NULL;
a7ad6e4e 1113
1114 cert = SSL_get_peer_certificate(ssl);
62e76326 1115
a7ad6e4e 1116 if (!cert)
62e76326 1117 return NULL;
a7ad6e4e 1118
5a4684b6 1119 name = X509_get_issuer_name(cert);
a7ad6e4e 1120
23e6c4ae 1121 ret = ssl_get_attribute(name, attribute_name);
1122
1123 X509_free(cert);
1124
23e6c4ae 1125 return ret;
a7ad6e4e 1126}
1127
a7ad6e4e 1128const char *
1129sslGetUserEmail(SSL * ssl)
1130{
e6ceef10 1131 return sslGetUserAttribute(ssl, "emailAddress");
a7ad6e4e 1132}
4ac9968f 1133
1134const char *
1135sslGetUserCertificatePEM(SSL *ssl)
1136{
1137 X509 *cert;
1138 BIO *mem;
1139 static char *str = NULL;
1140 char *ptr;
1141 long len;
1142
1143 safe_free(str);
1144
1145 if (!ssl)
1146 return NULL;
1147
1148 cert = SSL_get_peer_certificate(ssl);
1149
1150 if (!cert)
1151 return NULL;
1152
1153 mem = BIO_new(BIO_s_mem());
1154
1155 PEM_write_bio_X509(mem, cert);
1156
1157
1158 len = BIO_get_mem_data(mem, &ptr);
1159
1160 str = (char *)xmalloc(len + 1);
1161
1162 memcpy(str, ptr, len);
1163
1164 str[len] = '\0';
1165
1166 X509_free(cert);
1167
1168 BIO_free(mem);
1169
1170 return str;
1171}
3d61c476 1172
1173const char *
1174sslGetUserCertificateChainPEM(SSL *ssl)
1175{
1176 STACK_OF(X509) *chain;
1177 BIO *mem;
1178 static char *str = NULL;
1179 char *ptr;
1180 long len;
1181 int i;
1182
1183 safe_free(str);
1184
1185 if (!ssl)
1186 return NULL;
1187
1188 chain = SSL_get_peer_cert_chain(ssl);
1189
1190 if (!chain)
1191 return sslGetUserCertificatePEM(ssl);
1192
1193 mem = BIO_new(BIO_s_mem());
1194
1195 for (i = 0; i < sk_X509_num(chain); i++) {
1196 X509 *cert = sk_X509_value(chain, i);
1197 PEM_write_bio_X509(mem, cert);
1198 }
1199
1200 len = BIO_get_mem_data(mem, &ptr);
1201
1202 str = (char *)xmalloc(len + 1);
1203 memcpy(str, ptr, len);
1204 str[len] = '\0';
1205
1206 BIO_free(mem);
1207
1208 return str;
1209}
454e8283 1210
95d2589c
CT
1211/// \ingroup ServerProtocolSSLInternal
1212/// Create SSL context and apply ssl certificate and private key to it.
1213static SSL_CTX * createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey)
1214{
1215 Ssl::SSL_CTX_Pointer sslContext(SSL_CTX_new(SSLv23_server_method()));
1216
1217 if (!SSL_CTX_use_certificate(sslContext.get(), x509.get()))
1218 return NULL;
1219
1220 if (!SSL_CTX_use_PrivateKey(sslContext.get(), pkey.get()))
1221 return NULL;
1222 return sslContext.release();
1223}
1224
1225SSL_CTX * Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data)
1226{
1227 Ssl::X509_Pointer cert;
1228 Ssl::EVP_PKEY_Pointer pkey;
1229 if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
1230 return NULL;
1231
1232 if (!cert || !pkey)
1233 return NULL;
1234
1235 return createSSLContext(cert, pkey);
1236}
1237
1238SSL_CTX * Ssl::generateSslContext(char const *host, Ssl::X509_Pointer const & signedX509, Ssl::EVP_PKEY_Pointer const & signedPkey)
1239{
1240 Ssl::X509_Pointer cert;
1241 Ssl::EVP_PKEY_Pointer pkey;
1242 if (!generateSslCertificateAndPrivateKey(host, signedX509, signedPkey, cert, pkey, NULL)) {
1243 return NULL;
1244 }
1245 if (!cert)
1246 return NULL;
1247
1248 if (!pkey)
1249 return NULL;
1250
1251 return createSSLContext(cert, pkey);
1252}
1253
1254bool Ssl::verifySslCertificateDate(SSL_CTX * sslContext)
1255{
1256 // Temporary ssl for getting X509 certificate from SSL_CTX.
1257 Ssl::SSL_Pointer ssl(SSL_new(sslContext));
1258 X509 * cert = SSL_get_certificate(ssl.get());
1259 ASN1_TIME * time_notBefore = X509_get_notBefore(cert);
1260 ASN1_TIME * time_notAfter = X509_get_notAfter(cert);
1261 bool ret = (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
1262 return ret;
1263}
1264
454e8283 1265#endif /* USE_SSL */