]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl_support.cc
From ssl-2.5 2004/04/18 01:09:07
[thirdparty/squid.git] / src / ssl_support.cc
CommitLineData
f484cdf5 1
2/*
e01f02ed 3 * $Id: ssl_support.cc,v 1.23 2005/03/18 15:26:30 hno Exp $
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.
24 *
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.
29 *
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"
528b2c61 37#include "fde.h"
f484cdf5 38
307b83b7 39static int
40ssl_ask_password_cb(char *buf, int size, int rwflag, void *userdata)
41{
42 FILE *in;
43 int len = 0;
44 char cmdline[1024];
45
46 snprintf(cmdline, sizeof(cmdline), "\"%s\" \"%s\"", Config.Program.ssl_password, (const char *)userdata);
47 in = popen(cmdline, "r");
48
49 if (fgets(buf, size, in))
50
51 len = strlen(buf);
52
53 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
54
55 len--;
56
57 buf[len] = '\0';
58
59 pclose(in);
60
61 return len;
62}
63
64static void
65ssl_ask_password(SSL_CTX * context, const char * prompt)
66{
67 if (Config.Program.ssl_password) {
68 SSL_CTX_set_default_passwd_cb(context, ssl_ask_password_cb);
69 SSL_CTX_set_default_passwd_cb_userdata(context, (void *)prompt);
70 }
71}
72
f484cdf5 73static RSA *
e6ccf245 74ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen)
f484cdf5 75{
e01f02ed 76 static RSA *rsa_512 = NULL;
77 static RSA *rsa_1024 = NULL;
78 RSA *rsa = NULL;
79 int newkey = 0;
f484cdf5 80
e01f02ed 81 switch (keylen) {
82
83 case 512:
84
85 if (!rsa_512) {
86 rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
87 newkey = 1;
88 }
89
90 rsa = rsa_512;
91 break;
92
93 case 1024:
94
95 if (!rsa_1024) {
96 rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
97 newkey = 1;
98 }
99
100 rsa = rsa_1024;
101 break;
102
103 default:
104 debug(83,1)("ssl_temp_rsa_cb: Unexpected key length %d\n", keylen);
105 return NULL;
106 }
107
108 if (rsa == NULL) {
109 debug(83,1)("ssl_temp_rsa_cb: Failed to generate key %d\n", keylen);
110 return NULL;
111 }
112
113 if (newkey) {
114 if (do_debug(83, 5))
115 PEM_write_RSAPrivateKey(debug_log, rsa, NULL, NULL, 0, NULL, NULL);
116
117 debug(83,1)("Generated ephemeral RSA key of length %d\n", keylen);
118 }
62e76326 119
f484cdf5 120 return rsa;
121}
122
123static int
124ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
125{
126 char buffer[256];
a7ad6e4e 127 SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
128 SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
129 const char *server = (const char *)SSL_get_ex_data(ssl, ssl_ex_index_server);
130 void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
131 X509 *peer_cert = ctx->cert;
f484cdf5 132
a7ad6e4e 133 X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
62e76326 134 sizeof(buffer));
a7ad6e4e 135
136 if (ok) {
62e76326 137 debug(83, 5) ("SSL Certificate signature OK: %s\n", buffer);
138
139 if (server) {
140 int i;
141 int found = 0;
142 char cn[1024];
143 X509_NAME *name = X509_get_subject_name(peer_cert);
144 debug(83, 3) ("Verifying server domain %s to certificate dn %s\n",
145 server, buffer);
146
147 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)) {
148 ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
149
150 if (data->length > (int)sizeof(cn) - 1)
151 continue;
152
153 memcpy(cn, data->data, data->length);
154
155 cn[data->length] = '\0';
156
157 debug(83, 4) ("Verifying server domain %s to certificate cn %s\n",
158 server, cn);
159
160 if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
161 found = 1;
162 break;
163 }
164 }
165
166 if (!found) {
167 debug(83, 2) ("ERROR: Certificate %s does not match domainname %s\n", buffer, server);
168 ok = 0;
169 }
170 }
a7ad6e4e 171 } else {
62e76326 172 switch (ctx->error) {
173
174 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
175 debug(83, 5) ("SSL Certficate error: CA not known: %s\n", buffer);
176 break;
177
178 case X509_V_ERR_CERT_NOT_YET_VALID:
179 debug(83, 5) ("SSL Certficate not yet valid: %s\n", buffer);
180 break;
181
182 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
183 debug(83, 5) ("SSL Certificate has illegal \'not before\' field: %s\n", buffer);
184 break;
185
186 case X509_V_ERR_CERT_HAS_EXPIRED:
187 debug(83, 5) ("SSL Certificate expired: %s\n", buffer);
188 break;
189
190 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
191 debug(83, 5) ("SSL Certificate has invalid \'not after\' field: %s\n", buffer);
192 break;
193
194 default:
195 debug(83, 1) ("SSL unknown certificate error %d in %s\n",
196 ctx->error, buffer);
197 break;
198 }
a7ad6e4e 199 }
62e76326 200
201if (!dont_verify_domain && server) {}
202
f484cdf5 203 return ok;
204}
205
62e76326 206static struct ssl_option
207{
79d4ccdf 208 const char *name;
209 long value;
62e76326 210}
211
212ssl_options[] = {
79d4ccdf 213
673cd7db 214#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
62e76326 215 {
216 "MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG
217 },
673cd7db 218#endif
219#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
62e76326 220 {
221 "NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG
222 },
673cd7db 223#endif
224#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
62e76326 225 {
226 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
227 },
673cd7db 228#endif
229#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
62e76326 230 {
231 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
232 },
673cd7db 233#endif
234#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
62e76326 235 {
236 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
237 },
673cd7db 238#endif
239#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
62e76326 240 {
241 "MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING
242 },
673cd7db 243#endif
244#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
62e76326 245 {
246 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
247 },
673cd7db 248#endif
249#ifdef SSL_OP_TLS_D5_BUG
62e76326 250 {
251 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
252 },
673cd7db 253#endif
254#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
62e76326 255 {
256 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
257 },
673cd7db 258#endif
259#ifdef SSL_OP_TLS_ROLLBACK_BUG
62e76326 260 {
261 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
262 },
673cd7db 263#endif
264#ifdef SSL_OP_ALL
62e76326 265 {
266 "ALL", SSL_OP_ALL
267 },
673cd7db 268#endif
269#ifdef SSL_OP_SINGLE_DH_USE
62e76326 270 {
271 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
272 },
673cd7db 273#endif
274#ifdef SSL_OP_EPHEMERAL_RSA
62e76326 275 {
276 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
277 },
673cd7db 278#endif
279#ifdef SSL_OP_PKCS1_CHECK_1
62e76326 280 {
281 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
282 },
673cd7db 283#endif
284#ifdef SSL_OP_PKCS1_CHECK_2
62e76326 285 {
286 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
287 },
673cd7db 288#endif
289#ifdef SSL_OP_NETSCAPE_CA_DN_BUG
62e76326 290 {
291 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
292 },
673cd7db 293#endif
294#ifdef SSL_OP_NON_EXPORT_FIRST
62e76326 295 {
296 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
297 },
673cd7db 298#endif
299#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
62e76326 300 {
301 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
302 },
673cd7db 303#endif
304#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
62e76326 305 {
306 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
307 },
673cd7db 308#endif
309#ifdef SSL_OP_NO_SSLv2
62e76326 310 {
311 "NO_SSLv2", SSL_OP_NO_SSLv2
312 },
673cd7db 313#endif
314#ifdef SSL_OP_NO_SSLv3
62e76326 315 {
316 "NO_SSLv3", SSL_OP_NO_SSLv3
317 },
673cd7db 318#endif
319#ifdef SSL_OP_NO_TLSv1
62e76326 320 {
321 "NO_TLSv1", SSL_OP_NO_TLSv1
322 },
673cd7db 323#endif
62e76326 324 {
325 "", 0
326 },
327 {
328 NULL, 0
329 }
330 };
79d4ccdf 331
84f2d773 332static long
79d4ccdf 333ssl_parse_options(const char *options)
334{
335 long op = SSL_OP_ALL;
336 char *tmp;
337 char *option;
338
339 if (!options)
62e76326 340 goto no_options;
79d4ccdf 341
342 tmp = xstrdup(options);
62e76326 343
79d4ccdf 344 option = strtok(tmp, ":,");
62e76326 345
79d4ccdf 346 while (option) {
62e76326 347
348 struct ssl_option *opt = NULL, *opttmp;
349 long value = 0;
350 enum {
351 MODE_ADD, MODE_REMOVE
352 } mode;
353
354 switch (*option) {
355
356 case '!':
357
358 case '-':
359 mode = MODE_REMOVE;
360 option++;
361 break;
362
363 case '+':
364 mode = MODE_ADD;
365 option++;
366 break;
367
368 default:
369 mode = MODE_ADD;
370 break;
371 }
372
373 for (opttmp = ssl_options; opttmp->name; opttmp++) {
374 if (strcmp(opttmp->name, option) == 0) {
375 opt = opttmp;
376 break;
377 }
378 }
379
380 if (opt)
381 value = opt->value;
382 else if (strncmp(option, "0x", 2) == 0) {
383 /* Special case.. hex specification */
384 value = strtol(option + 2, NULL, 16);
385 } else {
386 fatalf("Unknown SSL option '%s'", option);
387 value = 0; /* Keep GCC happy */
388 }
389
390 switch (mode) {
391
392 case MODE_ADD:
393 op |= value;
394 break;
395
396 case MODE_REMOVE:
397 op &= ~value;
398 break;
399 }
400
401 option = strtok(NULL, ":,");
79d4ccdf 402 }
403
404 safe_free(tmp);
62e76326 405
406no_options:
79d4ccdf 407 return op;
408}
409
a7ad6e4e 410#define SSL_FLAG_NO_DEFAULT_CA (1<<0)
411#define SSL_FLAG_DELAYED_AUTH (1<<1)
412#define SSL_FLAG_DONT_VERIFY_PEER (1<<2)
413#define SSL_FLAG_DONT_VERIFY_DOMAIN (1<<3)
414
415static long
416ssl_parse_flags(const char *flags)
417{
418 long fl = 0;
419 char *tmp;
420 char *flag;
421
422 if (!flags)
62e76326 423 return 0;
a7ad6e4e 424
425 tmp = xstrdup(flags);
62e76326 426
a7ad6e4e 427 flag = strtok(tmp, ":,");
62e76326 428
a7ad6e4e 429 while (flag) {
62e76326 430 if (strcmp(flag, "NO_DEFAULT_CA") == 0)
431 fl |= SSL_FLAG_NO_DEFAULT_CA;
432 else if (strcmp(flag, "DELAYED_AUTH") == 0)
433 fl |= SSL_FLAG_DELAYED_AUTH;
434 else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
435 fl |= SSL_FLAG_DONT_VERIFY_PEER;
436 else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
437 fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
438 else
439 fatalf("Unknown ssl flag '%s'", flag);
440
441 flag = strtok(NULL, ":,");
a7ad6e4e 442 }
62e76326 443
a7ad6e4e 444 safe_free(tmp);
445 return fl;
446}
447
448
449static void
450ssl_initialize(void)
f484cdf5 451{
d193a436 452 static int ssl_initialized = 0;
62e76326 453
d193a436 454 if (!ssl_initialized) {
62e76326 455 ssl_initialized = 1;
456 SSL_load_error_strings();
457 SSLeay_add_ssl_algorithms();
a7ad6e4e 458#ifdef HAVE_OPENSSL_ENGINE_H
62e76326 459
460 if (Config.SSL.ssl_engine) {
461 ENGINE *e;
462
463 if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
464 fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
465 }
466
467 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
468 int ssl_error = ERR_get_error();
469 fatalf("Failed to initialise SSL engine: %s\n",
470 ERR_error_string(ssl_error, NULL));
471 }
472 }
473
a7ad6e4e 474#else
62e76326 475 if (Config.SSL.ssl_engine) {
476 fatalf("Your OpenSSL has no SSL engine support\n");
477 }
478
a7ad6e4e 479#endif
62e76326 480
d193a436 481 }
62e76326 482
a7ad6e4e 483 ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
484 ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
485
486}
487
488SSL_CTX *
35105e4b 489sslCreateServerContext(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 *dhfile)
a7ad6e4e 490{
491 int ssl_error;
492 SSL_METHOD *method;
493 SSL_CTX *sslContext;
494 long fl = ssl_parse_flags(flags);
495
496 ssl_initialize();
497
f484cdf5 498 if (!keyfile)
62e76326 499 keyfile = certfile;
500
f484cdf5 501 if (!certfile)
62e76326 502 certfile = keyfile;
503
a7ad6e4e 504 if (!CAfile)
62e76326 505 CAfile = clientCA;
f484cdf5 506
79d4ccdf 507 switch (version) {
62e76326 508
f484cdf5 509 case 2:
62e76326 510 debug(83, 5) ("Using SSLv2.\n");
511 method = SSLv2_server_method();
512 break;
513
f484cdf5 514 case 3:
62e76326 515 debug(83, 5) ("Using SSLv3.\n");
516 method = SSLv3_server_method();
517 break;
518
f484cdf5 519 case 4:
62e76326 520 debug(83, 5) ("Using TLSv1.\n");
521 method = TLSv1_server_method();
522 break;
523
f484cdf5 524 case 1:
62e76326 525
f484cdf5 526 default:
62e76326 527 debug(83, 5) ("Using SSLv2/SSLv3.\n");
528 method = SSLv23_server_method();
529 break;
f484cdf5 530 }
531
532 sslContext = SSL_CTX_new(method);
62e76326 533
f484cdf5 534 if (sslContext == NULL) {
62e76326 535 ssl_error = ERR_get_error();
536 fatalf("Failed to allocate SSL context: %s\n",
537 ERR_error_string(ssl_error, NULL));
f484cdf5 538 }
62e76326 539
79d4ccdf 540 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
f484cdf5 541
a9d79803 542 if (Config.SSL.unclean_shutdown) {
543 debug(83, 5) ("Enabling quiet SSL shutdowns (RFC violation).\n");
544
545 SSL_CTX_set_quiet_shutdown(sslContext, 1);
546 }
547
79d4ccdf 548 if (cipher) {
62e76326 549 debug(83, 5) ("Using chiper suite %s.\n", cipher);
550
551 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
552 ssl_error = ERR_get_error();
553 fatalf("Failed to set SSL cipher suite '%s': %s\n",
554 cipher, ERR_error_string(ssl_error, NULL));
555 }
79d4ccdf 556 }
62e76326 557
27d8545c 558 debug(83, 1) ("Using certificate in %s\n", certfile);
62e76326 559
a7ad6e4e 560 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
62e76326 561 ssl_error = ERR_get_error();
562 debug(83, 0) ("Failed to acquire SSL certificate '%s': %s\n",
563 certfile, ERR_error_string(ssl_error, NULL));
564 goto error;
f484cdf5 565 }
62e76326 566
27d8545c 567 debug(83, 1) ("Using private key in %s\n", keyfile);
307b83b7 568 ssl_ask_password(sslContext, keyfile);
62e76326 569
f484cdf5 570 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
62e76326 571 ssl_error = ERR_get_error();
572 debug(83, 0) ("Failed to acquire SSL private key '%s': %s\n",
573 keyfile, ERR_error_string(ssl_error, NULL));
574 goto error;
f484cdf5 575 }
62e76326 576
27d8545c 577 debug(83, 5) ("Comparing private and public SSL keys.\n");
62e76326 578
a7ad6e4e 579 if (!SSL_CTX_check_private_key(sslContext)) {
62e76326 580 ssl_error = ERR_get_error();
581 debug(83, 0) ("SSL private key '%s' does not match public key '%s': %s\n",
582 certfile, keyfile, ERR_error_string(ssl_error, NULL));
583 goto error;
a7ad6e4e 584 }
62e76326 585
a7ad6e4e 586 debug(83, 9) ("Setting RSA key generation callback.\n");
587 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
588
589 debug(83, 9) ("Setting CA certificate locations.\n");
62e76326 590
a7ad6e4e 591 if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
62e76326 592 ssl_error = ERR_get_error();
ac6298a7 593 debug(83, 1) ("Error setting CA certificate locations: %s\n",
62e76326 594 ERR_error_string(ssl_error, NULL));
595 debug(83, 1) ("continuing anyway...\n");
a7ad6e4e 596 }
62e76326 597
a7ad6e4e 598 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 599 !SSL_CTX_set_default_verify_paths(sslContext)) {
600 ssl_error = ERR_get_error();
ac6298a7 601 debug(83, 1) ("Error setting default CA certificate location: %s\n",
62e76326 602 ERR_error_string(ssl_error, NULL));
603 debug(83, 1) ("continuing anyway...\n");
a7ad6e4e 604 }
62e76326 605
a7ad6e4e 606 if (clientCA) {
62e76326 607 debug(83, 9) ("Set client certifying authority list.\n");
608 SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(clientCA));
609
610 if (fl & SSL_FLAG_DELAYED_AUTH) {
611 debug(83, 9) ("Not requesting client certificates until acl processing requires one\n");
612 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
613 } else {
614 debug(83, 9) ("Requiring client certificates.\n");
615 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
616 }
a7ad6e4e 617 } else {
62e76326 618 debug(83, 9) ("Not requiring any client certificates\n");
619 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 620 }
f484cdf5 621
35105e4b 622 if (dhfile) {
623 FILE *in = fopen(dhfile, "r");
624 DH *dh = NULL;
625 int codes;
626
627 if (in) {
628 dh = PEM_read_DHparams(in, NULL, NULL, NULL);
629 fclose(in);
630 }
631
632 if (!dh)
633 debug(83, 1) ("WARNING: Failed to read DH parameters '%s'\n", dhfile);
634 else if (dh && DH_check(dh, &codes) == 0) {
635 if (codes) {
636 debug(83, 1) ("WARNING: Failed to verify DH parameters '%s' (%x)\n", dhfile, codes);
637 DH_free(dh);
638 dh = NULL;
639 }
640 }
641
642 if (dh)
643 SSL_CTX_set_tmp_dh(sslContext, dh);
644 }
645
a7ad6e4e 646 if (fl & SSL_FLAG_DONT_VERIFY_DOMAIN)
62e76326 647 SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
648
a7ad6e4e 649 return sslContext;
62e76326 650
651error:
a7ad6e4e 652 SSL_CTX_free(sslContext);
62e76326 653
a7ad6e4e 654 return NULL;
655}
656
657SSL_CTX *
658sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath)
659{
660 int ssl_error;
661 SSL_METHOD *method;
662 SSL_CTX *sslContext;
663 long fl = ssl_parse_flags(flags);
664
665 ssl_initialize();
666
667 if (!keyfile)
62e76326 668 keyfile = certfile;
669
a7ad6e4e 670 if (!certfile)
62e76326 671 certfile = keyfile;
a7ad6e4e 672
a7ad6e4e 673 switch (version) {
62e76326 674
a7ad6e4e 675 case 2:
62e76326 676 debug(83, 5) ("Using SSLv2.\n");
677 method = SSLv2_client_method();
678 break;
679
a7ad6e4e 680 case 3:
62e76326 681 debug(83, 5) ("Using SSLv3.\n");
682 method = SSLv3_client_method();
683 break;
684
a7ad6e4e 685 case 4:
62e76326 686 debug(83, 5) ("Using TLSv1.\n");
687 method = TLSv1_client_method();
688 break;
689
a7ad6e4e 690 case 1:
62e76326 691
a7ad6e4e 692 default:
62e76326 693 debug(83, 5) ("Using SSLv2/SSLv3.\n");
694 method = SSLv23_client_method();
695 break;
a7ad6e4e 696 }
697
698 sslContext = SSL_CTX_new(method);
62e76326 699
a7ad6e4e 700 if (sslContext == NULL) {
62e76326 701 ssl_error = ERR_get_error();
702 fatalf("Failed to allocate SSL context: %s\n",
703 ERR_error_string(ssl_error, NULL));
a7ad6e4e 704 }
62e76326 705
a7ad6e4e 706 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
707
708 if (cipher) {
62e76326 709 debug(83, 5) ("Using chiper suite %s.\n", cipher);
710
711 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
712 ssl_error = ERR_get_error();
713 fatalf("Failed to set SSL cipher suite '%s': %s\n",
714 cipher, ERR_error_string(ssl_error, NULL));
715 }
a7ad6e4e 716 }
62e76326 717
a7ad6e4e 718 if (certfile) {
62e76326 719 debug(83, 1) ("Using certificate in %s\n", certfile);
720
721 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
722 ssl_error = ERR_get_error();
723 fatalf("Failed to acquire SSL certificate '%s': %s\n",
724 certfile, ERR_error_string(ssl_error, NULL));
725 }
726
727 debug(83, 1) ("Using private key in %s\n", keyfile);
307b83b7 728 ssl_ask_password(sslContext, keyfile);
62e76326 729
730 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
731 ssl_error = ERR_get_error();
732 fatalf("Failed to acquire SSL private key '%s': %s\n",
733 keyfile, ERR_error_string(ssl_error, NULL));
734 }
735
736 debug(83, 5) ("Comparing private and public SSL keys.\n");
737
738 if (!SSL_CTX_check_private_key(sslContext)) {
739 ssl_error = ERR_get_error();
740 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
741 certfile, keyfile, ERR_error_string(ssl_error, NULL));
742 }
a7ad6e4e 743 }
62e76326 744
27d8545c 745 debug(83, 9) ("Setting RSA key generation callback.\n");
f484cdf5 746 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
747
a7ad6e4e 748 if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
62e76326 749 debug(83, 1) ("NOTICE: Peer certificates are not verified for validity!\n");
750 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 751 } else {
62e76326 752 debug(83, 9) ("Setting certificate verification callback.\n");
753 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
a7ad6e4e 754 }
f484cdf5 755
a7ad6e4e 756 debug(83, 9) ("Setting CA certificate locations.\n");
62e76326 757
ac6298a7 758 if (CAfile || CApath)
759 if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
760 ssl_error = ERR_get_error();
761 debug(83, 1) ("Error setting CA certificate locations: %s\n",
762 ERR_error_string(ssl_error, NULL));
763 debug(83, 1) ("continuing anyway...\n");
764 }
62e76326 765
a7ad6e4e 766 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 767 !SSL_CTX_set_default_verify_paths(sslContext)) {
768 ssl_error = ERR_get_error();
ac6298a7 769 debug(83, 1) ("Error setting default CA certificate location: %s\n",
62e76326 770 ERR_error_string(ssl_error, NULL));
771 debug(83, 1) ("continuing anyway...\n");
f484cdf5 772 }
62e76326 773
d193a436 774 return sslContext;
f484cdf5 775}
776
d193a436 777int
e6ccf245 778ssl_read_method(int fd, char *buf, int len)
f484cdf5 779{
79d4ccdf 780 int i;
781
782 i = SSL_read(fd_table[fd].ssl, buf, len);
783
784 if (i > 0 && SSL_pending(fd_table[fd].ssl) > 0) {
62e76326 785 debug(83, 2) ("SSL fd %d is pending\n", fd);
786 fd_table[fd].flags.read_pending = 1;
79d4ccdf 787 } else
62e76326 788 fd_table[fd].flags.read_pending = 0;
79d4ccdf 789
790 return i;
f484cdf5 791}
792
d193a436 793int
e6ccf245 794ssl_write_method(int fd, const char *buf, int len)
f484cdf5 795{
796 return (SSL_write(fd_table[fd].ssl, buf, len));
797}
79d4ccdf 798
799void
e6ccf245 800ssl_shutdown_method(int fd)
79d4ccdf 801{
802 SSL *ssl = fd_table[fd].ssl;
62e76326 803
79d4ccdf 804 SSL_shutdown(ssl);
805}
a7ad6e4e 806
807static const char *
808ssl_get_attribute(X509_NAME * name, const char *attribute_name)
809{
810 static char buffer[1024];
811 int nid;
812
813 buffer[0] = '\0';
814
815 if (strcmp(attribute_name, "DN") == 0) {
62e76326 816 X509_NAME_oneline(name, buffer, sizeof(buffer));
817 goto done;
a7ad6e4e 818 }
62e76326 819
a7ad6e4e 820 nid = OBJ_txt2nid((char *) attribute_name);
62e76326 821
a7ad6e4e 822 if (nid == 0) {
62e76326 823 debug(83, 1) ("WARNING: Unknown SSL attribute name '%s'\n", attribute_name);
824 return NULL;
a7ad6e4e 825 }
62e76326 826
a7ad6e4e 827 X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
62e76326 828
829done:
a7ad6e4e 830 return *buffer ? buffer : NULL;
831}
832
833const char *
834sslGetUserAttribute(SSL * ssl, const char *attribute_name)
835{
836 X509 *cert;
837 X509_NAME *name;
838
839 if (!ssl)
62e76326 840 return NULL;
a7ad6e4e 841
842 cert = SSL_get_peer_certificate(ssl);
62e76326 843
a7ad6e4e 844 if (!cert)
62e76326 845 return NULL;
a7ad6e4e 846
5a4684b6 847 name = X509_get_subject_name(cert);
a7ad6e4e 848
849 return ssl_get_attribute(name, attribute_name);
850}
851
852const char *
853sslGetCAAttribute(SSL * ssl, const char *attribute_name)
854{
855 X509 *cert;
856 X509_NAME *name;
857
858 if (!ssl)
62e76326 859 return NULL;
a7ad6e4e 860
861 cert = SSL_get_peer_certificate(ssl);
62e76326 862
a7ad6e4e 863 if (!cert)
62e76326 864 return NULL;
a7ad6e4e 865
5a4684b6 866 name = X509_get_issuer_name(cert);
a7ad6e4e 867
868 return ssl_get_attribute(name, attribute_name);
869}
870
a7ad6e4e 871const char *
872sslGetUserEmail(SSL * ssl)
873{
874 return sslGetUserAttribute(ssl, "Email");
875}