]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl_support.cc
Plug memory leak in certificate based ACLs
[thirdparty/squid.git] / src / ssl_support.cc
CommitLineData
f484cdf5 1
2/*
23e6c4ae 3 * $Id: ssl_support.cc,v 1.27 2005/03/18 16:46:44 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)
b13877cc 414#define SSL_FLAG_NO_SESSION_REUSE (1<<4)
a7ad6e4e 415
416static long
417ssl_parse_flags(const char *flags)
418{
419 long fl = 0;
420 char *tmp;
421 char *flag;
422
423 if (!flags)
62e76326 424 return 0;
a7ad6e4e 425
426 tmp = xstrdup(flags);
62e76326 427
a7ad6e4e 428 flag = strtok(tmp, ":,");
62e76326 429
a7ad6e4e 430 while (flag) {
62e76326 431 if (strcmp(flag, "NO_DEFAULT_CA") == 0)
432 fl |= SSL_FLAG_NO_DEFAULT_CA;
433 else if (strcmp(flag, "DELAYED_AUTH") == 0)
434 fl |= SSL_FLAG_DELAYED_AUTH;
435 else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
436 fl |= SSL_FLAG_DONT_VERIFY_PEER;
437 else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
438 fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
b13877cc 439 else if (strcmp(flag, "NO_SESSION_REUSE") == 0)
440 fl |= SSL_FLAG_NO_SESSION_REUSE;
62e76326 441 else
442 fatalf("Unknown ssl flag '%s'", flag);
443
444 flag = strtok(NULL, ":,");
a7ad6e4e 445 }
62e76326 446
a7ad6e4e 447 safe_free(tmp);
448 return fl;
449}
450
451
452static void
453ssl_initialize(void)
f484cdf5 454{
d193a436 455 static int ssl_initialized = 0;
62e76326 456
d193a436 457 if (!ssl_initialized) {
62e76326 458 ssl_initialized = 1;
459 SSL_load_error_strings();
460 SSLeay_add_ssl_algorithms();
a7ad6e4e 461#ifdef HAVE_OPENSSL_ENGINE_H
62e76326 462
463 if (Config.SSL.ssl_engine) {
464 ENGINE *e;
465
466 if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
467 fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
468 }
469
470 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
471 int ssl_error = ERR_get_error();
472 fatalf("Failed to initialise SSL engine: %s\n",
473 ERR_error_string(ssl_error, NULL));
474 }
475 }
476
a7ad6e4e 477#else
62e76326 478 if (Config.SSL.ssl_engine) {
479 fatalf("Your OpenSSL has no SSL engine support\n");
480 }
481
a7ad6e4e 482#endif
62e76326 483
d193a436 484 }
62e76326 485
a7ad6e4e 486 ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
487 ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
488
489}
490
491SSL_CTX *
6b2936d5 492sslCreateServerContext(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, const char *context)
a7ad6e4e 493{
494 int ssl_error;
495 SSL_METHOD *method;
496 SSL_CTX *sslContext;
497 long fl = ssl_parse_flags(flags);
498
499 ssl_initialize();
500
f484cdf5 501 if (!keyfile)
62e76326 502 keyfile = certfile;
503
f484cdf5 504 if (!certfile)
62e76326 505 certfile = keyfile;
506
a7ad6e4e 507 if (!CAfile)
62e76326 508 CAfile = clientCA;
f484cdf5 509
79d4ccdf 510 switch (version) {
62e76326 511
f484cdf5 512 case 2:
62e76326 513 debug(83, 5) ("Using SSLv2.\n");
514 method = SSLv2_server_method();
515 break;
516
f484cdf5 517 case 3:
62e76326 518 debug(83, 5) ("Using SSLv3.\n");
519 method = SSLv3_server_method();
520 break;
521
f484cdf5 522 case 4:
62e76326 523 debug(83, 5) ("Using TLSv1.\n");
524 method = TLSv1_server_method();
525 break;
526
f484cdf5 527 case 1:
62e76326 528
f484cdf5 529 default:
62e76326 530 debug(83, 5) ("Using SSLv2/SSLv3.\n");
531 method = SSLv23_server_method();
532 break;
f484cdf5 533 }
534
535 sslContext = SSL_CTX_new(method);
62e76326 536
f484cdf5 537 if (sslContext == NULL) {
62e76326 538 ssl_error = ERR_get_error();
539 fatalf("Failed to allocate SSL context: %s\n",
540 ERR_error_string(ssl_error, NULL));
f484cdf5 541 }
62e76326 542
79d4ccdf 543 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
f484cdf5 544
6b2936d5 545 if (context && *context) {
546 SSL_CTX_set_session_id_context(sslContext, context, strlen(context));
547 }
548
b13877cc 549 if (fl & SSL_FLAG_NO_SESSION_REUSE) {
550 SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
551 }
552
a9d79803 553 if (Config.SSL.unclean_shutdown) {
554 debug(83, 5) ("Enabling quiet SSL shutdowns (RFC violation).\n");
555
556 SSL_CTX_set_quiet_shutdown(sslContext, 1);
557 }
558
79d4ccdf 559 if (cipher) {
62e76326 560 debug(83, 5) ("Using chiper suite %s.\n", cipher);
561
562 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
563 ssl_error = ERR_get_error();
564 fatalf("Failed to set SSL cipher suite '%s': %s\n",
565 cipher, ERR_error_string(ssl_error, NULL));
566 }
79d4ccdf 567 }
62e76326 568
27d8545c 569 debug(83, 1) ("Using certificate in %s\n", certfile);
62e76326 570
a7ad6e4e 571 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
62e76326 572 ssl_error = ERR_get_error();
573 debug(83, 0) ("Failed to acquire SSL certificate '%s': %s\n",
574 certfile, ERR_error_string(ssl_error, NULL));
575 goto error;
f484cdf5 576 }
62e76326 577
27d8545c 578 debug(83, 1) ("Using private key in %s\n", keyfile);
307b83b7 579 ssl_ask_password(sslContext, keyfile);
62e76326 580
f484cdf5 581 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
62e76326 582 ssl_error = ERR_get_error();
583 debug(83, 0) ("Failed to acquire SSL private key '%s': %s\n",
584 keyfile, ERR_error_string(ssl_error, NULL));
585 goto error;
f484cdf5 586 }
62e76326 587
27d8545c 588 debug(83, 5) ("Comparing private and public SSL keys.\n");
62e76326 589
a7ad6e4e 590 if (!SSL_CTX_check_private_key(sslContext)) {
62e76326 591 ssl_error = ERR_get_error();
592 debug(83, 0) ("SSL private key '%s' does not match public key '%s': %s\n",
593 certfile, keyfile, ERR_error_string(ssl_error, NULL));
594 goto error;
a7ad6e4e 595 }
62e76326 596
a7ad6e4e 597 debug(83, 9) ("Setting RSA key generation callback.\n");
598 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
599
600 debug(83, 9) ("Setting CA certificate locations.\n");
62e76326 601
a7ad6e4e 602 if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
62e76326 603 ssl_error = ERR_get_error();
ac6298a7 604 debug(83, 1) ("Error setting CA certificate locations: %s\n",
62e76326 605 ERR_error_string(ssl_error, NULL));
606 debug(83, 1) ("continuing anyway...\n");
a7ad6e4e 607 }
62e76326 608
a7ad6e4e 609 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 610 !SSL_CTX_set_default_verify_paths(sslContext)) {
611 ssl_error = ERR_get_error();
ac6298a7 612 debug(83, 1) ("Error setting default CA certificate location: %s\n",
62e76326 613 ERR_error_string(ssl_error, NULL));
614 debug(83, 1) ("continuing anyway...\n");
a7ad6e4e 615 }
62e76326 616
a7ad6e4e 617 if (clientCA) {
62e76326 618 debug(83, 9) ("Set client certifying authority list.\n");
619 SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(clientCA));
620
621 if (fl & SSL_FLAG_DELAYED_AUTH) {
622 debug(83, 9) ("Not requesting client certificates until acl processing requires one\n");
623 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
624 } else {
625 debug(83, 9) ("Requiring client certificates.\n");
626 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
627 }
a7ad6e4e 628 } else {
62e76326 629 debug(83, 9) ("Not requiring any client certificates\n");
630 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 631 }
f484cdf5 632
35105e4b 633 if (dhfile) {
634 FILE *in = fopen(dhfile, "r");
635 DH *dh = NULL;
636 int codes;
637
638 if (in) {
639 dh = PEM_read_DHparams(in, NULL, NULL, NULL);
640 fclose(in);
641 }
642
643 if (!dh)
644 debug(83, 1) ("WARNING: Failed to read DH parameters '%s'\n", dhfile);
645 else if (dh && DH_check(dh, &codes) == 0) {
646 if (codes) {
647 debug(83, 1) ("WARNING: Failed to verify DH parameters '%s' (%x)\n", dhfile, codes);
648 DH_free(dh);
649 dh = NULL;
650 }
651 }
652
653 if (dh)
654 SSL_CTX_set_tmp_dh(sslContext, dh);
655 }
656
a7ad6e4e 657 if (fl & SSL_FLAG_DONT_VERIFY_DOMAIN)
62e76326 658 SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
659
a7ad6e4e 660 return sslContext;
62e76326 661
662error:
a7ad6e4e 663 SSL_CTX_free(sslContext);
62e76326 664
a7ad6e4e 665 return NULL;
666}
667
668SSL_CTX *
669sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath)
670{
671 int ssl_error;
672 SSL_METHOD *method;
673 SSL_CTX *sslContext;
674 long fl = ssl_parse_flags(flags);
675
676 ssl_initialize();
677
678 if (!keyfile)
62e76326 679 keyfile = certfile;
680
a7ad6e4e 681 if (!certfile)
62e76326 682 certfile = keyfile;
a7ad6e4e 683
a7ad6e4e 684 switch (version) {
62e76326 685
a7ad6e4e 686 case 2:
62e76326 687 debug(83, 5) ("Using SSLv2.\n");
688 method = SSLv2_client_method();
689 break;
690
a7ad6e4e 691 case 3:
62e76326 692 debug(83, 5) ("Using SSLv3.\n");
693 method = SSLv3_client_method();
694 break;
695
a7ad6e4e 696 case 4:
62e76326 697 debug(83, 5) ("Using TLSv1.\n");
698 method = TLSv1_client_method();
699 break;
700
a7ad6e4e 701 case 1:
62e76326 702
a7ad6e4e 703 default:
62e76326 704 debug(83, 5) ("Using SSLv2/SSLv3.\n");
705 method = SSLv23_client_method();
706 break;
a7ad6e4e 707 }
708
709 sslContext = SSL_CTX_new(method);
62e76326 710
a7ad6e4e 711 if (sslContext == NULL) {
62e76326 712 ssl_error = ERR_get_error();
713 fatalf("Failed to allocate SSL context: %s\n",
714 ERR_error_string(ssl_error, NULL));
a7ad6e4e 715 }
62e76326 716
a7ad6e4e 717 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
718
719 if (cipher) {
62e76326 720 debug(83, 5) ("Using chiper suite %s.\n", cipher);
721
722 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
723 ssl_error = ERR_get_error();
724 fatalf("Failed to set SSL cipher suite '%s': %s\n",
725 cipher, ERR_error_string(ssl_error, NULL));
726 }
a7ad6e4e 727 }
62e76326 728
a7ad6e4e 729 if (certfile) {
62e76326 730 debug(83, 1) ("Using certificate in %s\n", certfile);
731
732 if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
733 ssl_error = ERR_get_error();
734 fatalf("Failed to acquire SSL certificate '%s': %s\n",
735 certfile, ERR_error_string(ssl_error, NULL));
736 }
737
738 debug(83, 1) ("Using private key in %s\n", keyfile);
307b83b7 739 ssl_ask_password(sslContext, keyfile);
62e76326 740
741 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
742 ssl_error = ERR_get_error();
743 fatalf("Failed to acquire SSL private key '%s': %s\n",
744 keyfile, ERR_error_string(ssl_error, NULL));
745 }
746
747 debug(83, 5) ("Comparing private and public SSL keys.\n");
748
749 if (!SSL_CTX_check_private_key(sslContext)) {
750 ssl_error = ERR_get_error();
751 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
752 certfile, keyfile, ERR_error_string(ssl_error, NULL));
753 }
a7ad6e4e 754 }
62e76326 755
27d8545c 756 debug(83, 9) ("Setting RSA key generation callback.\n");
f484cdf5 757 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
758
a7ad6e4e 759 if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
62e76326 760 debug(83, 1) ("NOTICE: Peer certificates are not verified for validity!\n");
761 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
a7ad6e4e 762 } else {
62e76326 763 debug(83, 9) ("Setting certificate verification callback.\n");
764 SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
a7ad6e4e 765 }
f484cdf5 766
a7ad6e4e 767 debug(83, 9) ("Setting CA certificate locations.\n");
62e76326 768
ac6298a7 769 if (CAfile || CApath)
770 if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
771 ssl_error = ERR_get_error();
772 debug(83, 1) ("Error setting CA certificate locations: %s\n",
773 ERR_error_string(ssl_error, NULL));
774 debug(83, 1) ("continuing anyway...\n");
775 }
62e76326 776
a7ad6e4e 777 if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
62e76326 778 !SSL_CTX_set_default_verify_paths(sslContext)) {
779 ssl_error = ERR_get_error();
ac6298a7 780 debug(83, 1) ("Error setting default CA certificate location: %s\n",
62e76326 781 ERR_error_string(ssl_error, NULL));
782 debug(83, 1) ("continuing anyway...\n");
f484cdf5 783 }
62e76326 784
d193a436 785 return sslContext;
f484cdf5 786}
787
d193a436 788int
e6ccf245 789ssl_read_method(int fd, char *buf, int len)
f484cdf5 790{
6de9e64b 791 SSL *ssl = fd_table[fd].ssl;
79d4ccdf 792 int i;
793
6de9e64b 794#if DONT_DO_THIS
795
796 if (!SSL_is_init_finished(ssl)) {
797 errno = ENOTCONN;
798 return -1;
799 }
79d4ccdf 800
6de9e64b 801#endif
802
803 i = SSL_read(ssl, buf, len);
804
805 if (i > 0 && SSL_pending(ssl) > 0) {
62e76326 806 debug(83, 2) ("SSL fd %d is pending\n", fd);
807 fd_table[fd].flags.read_pending = 1;
79d4ccdf 808 } else
62e76326 809 fd_table[fd].flags.read_pending = 0;
79d4ccdf 810
811 return i;
f484cdf5 812}
813
d193a436 814int
e6ccf245 815ssl_write_method(int fd, const char *buf, int len)
f484cdf5 816{
6de9e64b 817 SSL *ssl = fd_table[fd].ssl;
818 int i;
819
820 if (!SSL_is_init_finished(ssl)) {
821 errno = ENOTCONN;
822 return -1;
823 }
824
825 i = SSL_write(ssl, buf, len);
826
827 return i;
f484cdf5 828}
79d4ccdf 829
830void
e6ccf245 831ssl_shutdown_method(int fd)
79d4ccdf 832{
833 SSL *ssl = fd_table[fd].ssl;
62e76326 834
79d4ccdf 835 SSL_shutdown(ssl);
836}
a7ad6e4e 837
838static const char *
839ssl_get_attribute(X509_NAME * name, const char *attribute_name)
840{
841 static char buffer[1024];
842 int nid;
843
844 buffer[0] = '\0';
845
846 if (strcmp(attribute_name, "DN") == 0) {
62e76326 847 X509_NAME_oneline(name, buffer, sizeof(buffer));
848 goto done;
a7ad6e4e 849 }
62e76326 850
a7ad6e4e 851 nid = OBJ_txt2nid((char *) attribute_name);
62e76326 852
a7ad6e4e 853 if (nid == 0) {
62e76326 854 debug(83, 1) ("WARNING: Unknown SSL attribute name '%s'\n", attribute_name);
855 return NULL;
a7ad6e4e 856 }
62e76326 857
a7ad6e4e 858 X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
62e76326 859
860done:
a7ad6e4e 861 return *buffer ? buffer : NULL;
862}
863
864const char *
865sslGetUserAttribute(SSL * ssl, const char *attribute_name)
866{
867 X509 *cert;
868 X509_NAME *name;
23e6c4ae 869 const char *ret;
a7ad6e4e 870
871 if (!ssl)
62e76326 872 return NULL;
a7ad6e4e 873
874 cert = SSL_get_peer_certificate(ssl);
62e76326 875
a7ad6e4e 876 if (!cert)
62e76326 877 return NULL;
a7ad6e4e 878
5a4684b6 879 name = X509_get_subject_name(cert);
a7ad6e4e 880
23e6c4ae 881 ret = ssl_get_attribute(name, attribute_name);
882
883 X509_free(cert);
884
885 CRYPTO_free(name);
886
887 return ret;
a7ad6e4e 888}
889
890const char *
891sslGetCAAttribute(SSL * ssl, const char *attribute_name)
892{
893 X509 *cert;
894 X509_NAME *name;
23e6c4ae 895 const char *ret;
a7ad6e4e 896
897 if (!ssl)
62e76326 898 return NULL;
a7ad6e4e 899
900 cert = SSL_get_peer_certificate(ssl);
62e76326 901
a7ad6e4e 902 if (!cert)
62e76326 903 return NULL;
a7ad6e4e 904
5a4684b6 905 name = X509_get_issuer_name(cert);
a7ad6e4e 906
23e6c4ae 907 ret = ssl_get_attribute(name, attribute_name);
908
909 X509_free(cert);
910
911 CRYPTO_free(name);
912
913 return ret;
a7ad6e4e 914}
915
a7ad6e4e 916const char *
917sslGetUserEmail(SSL * ssl)
918{
919 return sslGetUserAttribute(ssl, "Email");
920}