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