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