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