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