UtilitySSL.cpp
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* ====================================================================
18 * Copyright (c) 1998-2006 Ralf S. Engelschall. All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 *
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 *
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following
29 * disclaimer in the documentation and/or other materials
30 * provided with the distribution.
31 *
32 * 3. All advertising materials mentioning features or use of this
33 * software must display the following acknowledgment:
34 * "This product includes software developed by
35 * Ralf S. Engelschall <rse@engelschall.com> for use in the
36 * mod_ssl project (http://www.modssl.org/)."
37 *
38 * 4. The names "mod_ssl" must not be used to endorse or promote
39 * products derived from this software without prior written
40 * permission. For written permission, please contact
41 * rse@engelschall.com.
42 *
43 * 5. Products derived from this software may not be called "mod_ssl"
44 * nor may "mod_ssl" appear in their names without prior
45 * written permission of Ralf S. Engelschall.
46 *
47 * 6. Redistributions of any form whatsoever must retain the following
48 * acknowledgment:
49 * "This product includes software developed by
50 * Ralf S. Engelschall <rse@engelschall.com> for use in the
51 * mod_ssl project (http://www.modssl.org/)."
52 *
53 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
54 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
57 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
64 * OF THE POSSIBILITY OF SUCH DAMAGE.
65 * ====================================================================
66 */
67
68/* ====================================================================
69 * Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
70 *
71 * Redistribution and use in source and binary forms, with or without
72 * modification, are permitted provided that the following conditions
73 * are met:
74 *
75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer.
77 *
78 * 2. Redistributions in binary form must reproduce the above copyright
79 * notice, this list of conditions and the following disclaimer in
80 * the documentation and/or other materials provided with the
81 * distribution.
82 *
83 * 3. All advertising materials mentioning features or use of this
84 * software must display the following acknowledgment:
85 * "This product includes software developed by Ben Laurie
86 * for use in the Apache-SSL HTTP server project."
87 *
88 * 4. The name "Apache-SSL Server" must not be used to
89 * endorse or promote products derived from this software without
90 * prior written permission.
91 *
92 * 5. Redistributions of any form whatsoever must retain the following
93 * acknowledgment:
94 * "This product includes software developed by Ben Laurie
95 * for use in the Apache-SSL HTTP server project."
96 *
97 * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
98 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
99 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
100 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
101 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
102 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
103 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
104 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
105 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
106 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
107 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
108 * OF THE POSSIBILITY OF SUCH DAMAGE.
109 * ====================================================================
110 */
111
112#ifdef _MSC_VER
113#include "stdafx.h"
114#else
115#include "config.h"
116#endif
117
118#if (HAVE_SSL > 0)
119
120#include <vector>
121
122#include "Mutex.h"
123#include "UtilitySSL.h"
124
125//#include "openssl/applink.c" // To prevent crashing (see the OpenSSL FAQ)
126
127#include "openssl/bio.h" // BIO objects for I/O
128#include "openssl/bn.h"
129#include "openssl/crypto.h"
130#include "openssl/err.h" // Error reporting
131#include "openssl/rand.h"
132#ifndef OPENSSL_NO_DH
133#include "openssl/dh.h"
134#endif
135
136#ifdef _MSC_VER
137
138#if !defined(strcasecmp)
139#define strcasecmp _stricmp
140#endif
141
142#if !defined(strncasecmp)
143#define strncasecmp _strnicmp
144#endif
145
146#endif
147
148namespace FIX
149{
150
151#ifndef OPENSSL_NO_DH
152static DH *load_dh_param(const char *dhfile)
153{
154 DH *ret = NULL;
155 BIO *bio;
156
157 if ((bio = BIO_new_file(dhfile, "r")) == NULL)
158 goto err;
159 ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
160err:
161 if (bio != NULL)
162 BIO_free(bio);
163 return (ret);
164}
165
166#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
167/* OpenSSL Pre-1.1.0 compatibility */
168/* Taken from OpenSSL 1.1.0 snapshot 20160410 */
169static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
170{
171 /* q is optional */
172 if (p == NULL || g == NULL)
173 return 0;
174 BN_free(dh->p);
175 BN_free(dh->q);
176 BN_free(dh->g);
177 dh->p = p;
178 dh->q = q;
179 dh->g = g;
180
181 if (q != NULL)
182 {
183 dh->length = BN_num_bits(q);
184 }
185
186 return 1;
187}
188#endif
189
190/*
191 * Grab well-defined DH parameters from OpenSSL, see the BN_get_rfc*
192 * functions in <openssl/bn.h> for all available primes.
193 */
194static DH *make_dh_params(BIGNUM *(*prime)(BIGNUM *))
195{
196 DH *dh = DH_new();
197 BIGNUM *p, *g;
198
199 if (!dh)
200 {
201 return NULL;
202 }
203 p = prime(NULL);
204 g = BN_new();
205 if (g != NULL)
206 {
207 BN_set_word(g, 2);
208 }
209 if (!p || !g || !DH_set0_pqg(dh, p, NULL, g))
210 {
211 DH_free(dh);
212 BN_free(p);
213 BN_free(g);
214 return NULL;
215 }
216 return dh;
217}
218
219/* Storage and initialization for DH parameters. */
220static struct dhparam
221{
222 BIGNUM *(*const prime)(BIGNUM *); /* function to generate... */
223 DH *dh; /* ...this, used for keys.... */
224 const unsigned int min; /* ...of length >= this. */
225} dhparams[] = {
226 {get_rfc3526_prime_8192, NULL, 6145}, {get_rfc3526_prime_6144, NULL, 4097},
227 {get_rfc3526_prime_4096, NULL, 3073}, {get_rfc3526_prime_3072, NULL, 2049},
228 {get_rfc3526_prime_2048, NULL, 1025}, {get_rfc2409_prime_1024, NULL, 0}};
229
230static void init_dh_params(void)
231{
232 unsigned n;
233
234 for (n = 0; n < sizeof(dhparams) / sizeof(dhparams[0]); n++)
235 dhparams[n].dh = make_dh_params(dhparams[n].prime);
236}
237
238static void free_dh_params(void)
239{
240 unsigned n;
241
242 /* DH_free() is a noop for a NULL parameter, so these are harmless
243 * in the (unexpected) case where these variables are already
244 * NULL. */
245 for (n = 0; n < sizeof(dhparams) / sizeof(dhparams[0]); n++)
246 {
247 DH_free(dhparams[n].dh);
248 dhparams[n].dh = NULL;
249 }
250}
251
252/* Hand out the same DH structure though once generated as we leak
253 * memory otherwise and freeing the structure up after use would be
254 * hard to track and in fact is not needed at all as it is safe to
255 * use the same parameters over and over again security wise (in
256 * contrast to the keys itself) and code safe as the returned structure
257 * is duplicated by OpenSSL anyway. Hence no modification happens
258 * to our copy. */
259DH *modssl_get_dh_params(unsigned keylen)
260{
261 unsigned n;
262
263 for (n = 0; n < sizeof(dhparams) / sizeof(dhparams[0]); n++)
264 if (keylen >= dhparams[n].min)
265 return dhparams[n].dh;
266
267 return NULL; /* impossible to reach. */
268}
269
270/*
271 * Hand out standard DH parameters, based on the authentication strength
272 */
273DH *ssl_callback_TmpDH(SSL *ssl, int exportvar, int keylen)
274{
275 EVP_PKEY *pkey;
276 int type;
277
278 pkey = SSL_get_privatekey(ssl);
279#if OPENSSL_VERSION_NUMBER < 0x10100000L
280 type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
281#else
282 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
283#endif
284
285 /*
286 * OpenSSL will call us with either keylen == 512 or keylen == 1024
287 * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
288 * Adjust the DH parameter length according to the size of the
289 * RSA/DSA private key used for the current connection, and always
290 * use at least 1024-bit parameters.
291 * Note: This may cause interoperability issues with implementations
292 * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
293 * In this case, SSLCertificateFile can be used to specify fixed
294 * 1024-bit DH parameters (with the effect that OpenSSL skips this
295 * callback).
296 */
297 if ((type == EVP_PKEY_RSA) || (type == EVP_PKEY_DSA))
298 {
299 keylen = EVP_PKEY_bits(pkey);
300 }
301
302 return modssl_get_dh_params(keylen);
303}
304#endif
305
306/* Mutex to protect ssl init and terminate */
307static Mutex ssl_mutex;
308/* Reference count of ssl users. Should always call ssl_init/ssl_term */
309static int ssl_users = 0;
310static int ssl_initialized = 0;
311/* This array will store all of the mutexes available to OpenSSL. */
312#ifdef _MSC_VER
313static HANDLE *lock_cs = 0;
314#else
315static pthread_mutex_t *lock_cs = 0;
316#endif
317
318static void thread_setup(void); // For thread safety.
319static void thread_cleanup(void);
320static void ssl_rand_seed(void);
321
322void ssl_init()
323{
324
325 Locker locker(ssl_mutex);
326 ++ssl_users;
327
328 thread_setup();
329
330 if (ssl_initialized)
331 return;
332
333#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
334 CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
335#else
336 OPENSSL_malloc_init();
337#endif
338 SSL_library_init(); // Initialize OpenSSL's SSL libraries
339 SSL_load_error_strings(); // Load SSL error strings
340 ERR_load_BIO_strings(); // Load BIO error strings
341 OpenSSL_add_all_algorithms(); // Load all available encryption algorithms
342
343 ssl_rand_seed();
344
345 ssl_initialized = 1;
346
347#ifndef OPENSSL_NO_DH
348 init_dh_params();
349#endif
350
351 return;
352}
353
354void ssl_term()
355{
356
357 Locker locker(ssl_mutex);
358 --ssl_users;
359
360 if (ssl_users > 0)
361 return;
362
363 thread_cleanup();
364
365#ifndef OPENSSL_NO_DH
366 free_dh_params();
367#endif
368}
369
370void ssl_socket_close(int socket, SSL *ssl)
371{
372
373 if (ssl == 0)
374 {
375 socket_close(socket);
376 return;
377 }
378
379 int i;
380 int rc = 0;
381
382 for (i = 0; i < 4; i++)
383 {
384 if ((rc = SSL_shutdown(ssl)) == 1)
385 break;
386 }
387}
388
389static void locking_callback(int mode, int type, const char *file, int line)
390{
391#ifdef _MSC_VER
392 if (mode & CRYPTO_LOCK)
393 WaitForSingleObject(lock_cs[type], INFINITE);
394 else
395 ReleaseMutex(lock_cs[type]);
396#else
397 if (mode & CRYPTO_LOCK)
398 pthread_mutex_lock(&(lock_cs[type]));
399 else
400 pthread_mutex_unlock(&(lock_cs[type]));
401#endif
402}
403
404static unsigned long thread_id_func()
405{
406#ifdef _MSC_VER
407 return (unsigned)GetCurrentThread();
408#else
409 return (unsigned long)pthread_self();
410#endif
411}
412
413static void thread_setup(void)
414{
415
416 if (lock_cs != 0)
417 return;
418
419 int i;
420#ifdef _MSC_VER
421 lock_cs = (HANDLE *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
422 for (i = 0; i < CRYPTO_num_locks(); i++)
423 lock_cs[i] = CreateMutex(0, FALSE, 0);
424#else
425 lock_cs = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
426 sizeof(pthread_mutex_t));
427 for (i = 0; i < CRYPTO_num_locks(); i++)
428 {
429 pthread_mutex_init(&(lock_cs[i]), 0);
430 }
431#endif
432
433#ifndef _MSC_VER
434 CRYPTO_set_id_callback((unsigned long (*)(void))thread_id_func);
435#endif
436 CRYPTO_set_locking_callback(
437 (void (*)(int, int, const char *, int))locking_callback);
438}
439
440static void thread_cleanup(void)
441{
442
443 if (lock_cs == 0)
444 return;
445
446#ifndef _MSC_VER
447 CRYPTO_set_id_callback(0);
448#endif
449 CRYPTO_set_locking_callback(0);
450
451 int i;
452#ifdef _MSC_VER
453 for (i = 0; i < CRYPTO_num_locks(); i++)
454 CloseHandle(lock_cs[i]);
455 OPENSSL_free(lock_cs);
456#else
457 for (i = 0; i < CRYPTO_num_locks(); i++)
458 pthread_mutex_destroy(&(lock_cs[i]));
459 OPENSSL_free(lock_cs);
460#endif
461
462 lock_cs = 0;
463}
464
465static int ssl_rand_choose_num(int l, int h)
466{
467 int i;
468 char buf[50];
469
470 srand((unsigned int)time(0));
471 snprintf(buf, sizeof(buf), "%.0f",
472 (((double)(rand() % RAND_MAX) / RAND_MAX) * (h - l)));
473 buf[sizeof(buf) - 1] = 0;
474 i = atoi(buf) + 1;
475 if (i < l)
476 i = l;
477 if (i > h)
478 i = h;
479 return i;
480}
481
482static void ssl_rand_seed(void)
483{
484#ifdef _MSC_VER
485 int pid;
486#else
487 pid_t pid;
488#endif
489 int n, l;
490 unsigned char stackdata[256];
491 time_t t = time(0);
492
493 /*
494 * seed in the current time (usually just 4 bytes)
495 */
496 l = sizeof(time_t);
497 RAND_seed((unsigned char *)&t, l);
498 /*
499 * seed in the current process id (usually just 4 bytes)
500 */
501 pid = getpid();
502 l = sizeof(pid);
503 RAND_seed((unsigned char *)&pid, l);
504 /*
505 * seed in some current state of the run-time stack (128 bytes)
506 */
507 n = ssl_rand_choose_num(0, sizeof(stackdata) - 128 - 1);
508 RAND_seed(stackdata + n, 128);
509}
510
511const char *socket_error(char *tempbuf, int buflen)
512{
513#ifdef _MSC_VER
514 int code = WSAGetLastError();
515 snprintf(tempbuf, buflen, "%s(%d)", WSAErrString(code), code);
516#else /* UNIX */
517 snprintf(tempbuf, buflen, "%s(errno=%d)", strerror(errno), errno);
518#endif
519 tempbuf[buflen - 1] = 0;
520
521 return tempbuf;
522}
523
524int caListX509NameCmp(const X509_NAME *const *a, const X509_NAME *const *b)
525{
526 return (X509_NAME_cmp(*a, *b));
527}
528
529#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
530int lookupX509Store(X509_STORE *pStore, int nType, X509_NAME *pName,
531 X509_OBJECT *pObj)
532{
533 X509_STORE_CTX pStoreCtx;
534 int rc;
535
536 X509_STORE_CTX_init(&pStoreCtx, pStore, 0, 0);
537 rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
538 X509_STORE_CTX_cleanup(&pStoreCtx);
539 return rc;
540}
541
542int callbackVerifyCRL(int ok, X509_STORE_CTX *ctx, X509_STORE *revStore)
543{
544 X509_OBJECT obj;
545 X509_NAME *subject;
546 X509_NAME *issuer;
547 X509 *xs;
548 X509_CRL *crl;
549 X509_REVOKED *revoked;
550 long serial;
551 BIO *bio;
552 int i, n, rc;
553 char *cp;
554 char *cp2;
555
556 if (revStore == 0)
557 return ok;
558
559 /*
560 * Determine certificate ingredients in advance
561 */
562 xs = X509_STORE_CTX_get_current_cert(ctx);
563 subject = X509_get_subject_name(xs);
564 issuer = X509_get_issuer_name(xs);
565
566 /*
567 * Try to retrieve a CRL corresponding to the _subject_ of
568 * the current certificate in order to verify it's integrity.
569 */
570 memset((char *)&obj, 0, sizeof(obj));
571 rc = lookupX509Store(revStore, X509_LU_CRL, subject, &obj);
572 crl = obj.data.crl;
573 if (rc > 0 && crl != 0)
574 {
575 bio = BIO_new(BIO_s_mem());
576 BIO_printf(bio, "lastUpdate: ");
577 ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl));
578 BIO_printf(bio, ", nextUpdate: ");
579 ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl));
580 n = BIO_pending(bio);
581 cp = (char *)malloc(n + 1);
582 n = BIO_read(bio, cp, n);
583 cp[n] = 0;
584 BIO_free(bio);
585 cp2 = X509_NAME_oneline(subject, NULL, 0);
586 printf("CA CRL: Issuer: %s, %s\n", cp2, cp);
587 free(cp2);
588 free(cp);
589
590 /*
591 * Verify the signature on this CRL
592 */
593 if (X509_CRL_verify(crl, X509_get_pubkey(xs)) <= 0)
594 {
595 printf("Invalid signature on CRL\n");
596 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
597 X509_OBJECT_free_contents(&obj);
598 return 0;
599 }
600
601 /*
602 * Check date of CRL to make sure it's not expired
603 */
604 i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
605 if (i == 0)
606 {
607 printf("Found CRL has invalid nextUpdate field\n");
608 X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
609 X509_OBJECT_free_contents(&obj);
610 return 0;
611 }
612 if (i < 0)
613 {
614 printf("Found CRL is expired - revoking all certificates until you get "
615 "updated CRL\n");
616 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
617 X509_OBJECT_free_contents(&obj);
618 return false;
619 }
620 X509_OBJECT_free_contents(&obj);
621 }
622
623 /*
624 * Try to retrieve a CRL corresponding to the _issuer_ of
625 * the current certificate in order to check for revocation.
626 */
627 memset((char *)&obj, 0, sizeof(obj));
628 rc = lookupX509Store(revStore, X509_LU_CRL, issuer, &obj);
629 crl = obj.data.crl;
630 if (rc > 0 && crl != NULL)
631 {
632 /*
633 * Check if the current certificate is revoked by this CRL
634 */
635 n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
636 for (i = 0; i < n; i++)
637 {
638 revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
639 if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(xs)) ==
640 0)
641 {
642 serial = ASN1_INTEGER_get(revoked->serialNumber);
643 cp = X509_NAME_oneline(issuer, NULL, 0);
644 printf("Certificate with serial %ld (0x%lX) revoked per CRL from "
645 "issuer %s\n",
646 serial, serial, cp);
647 free(cp);
648 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
649 X509_OBJECT_free_contents(&obj);
650 return 0;
651 }
652 }
653 X509_OBJECT_free_contents(&obj);
654 }
655 return ok;
656}
657#endif
658
659int callbackVerify(int ok, X509_STORE_CTX *ctx)
660{
661 X509 *xs;
662 int errnum;
663 int errdepth;
664 char *cp;
665 char *cp2;
666
667 /*
668 * Get verify ingredients
669 */
670 xs = X509_STORE_CTX_get_current_cert(ctx);
671 errnum = X509_STORE_CTX_get_error(ctx);
672 errdepth = X509_STORE_CTX_get_error_depth(ctx);
673
674 /*
675 * Log verification information
676 */
677 cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
678 cp2 = X509_NAME_oneline(X509_get_issuer_name(xs), NULL, 0);
679 printf("Certificate Verification: depth: %d, subject: %s, issuer: %s\n",
680 errdepth, cp != NULL ? cp : "-unknown-",
681 cp2 != NULL ? cp2 : "-unknown");
682
683 if (cp)
684 free(cp);
685 if (cp2)
686 free(cp2);
687
688#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
689 /*
690 * Additionally perform CRL-based revocation checks
691 */
692 if (ok)
693 {
694 SSL *ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx);
695 X509_STORE *revStore = (X509_STORE *)SSL_get_app_data(ssl);
696 ok = callbackVerifyCRL(ok, ctx, revStore);
697 if (!ok)
698 errnum = X509_STORE_CTX_get_error(ctx);
699 }
700#endif
701
702 /*
703 * If we already know it's not ok, log the real reason
704 */
705 if (!ok)
706 {
707 printf("Certificate Verification: Error (%d): %s\n", errnum,
708 X509_verify_cert_error_string(errnum));
709 ERR_print_errors_fp(stderr);
710 }
711
712 return (ok);
713}
714
715int typeofSSLAlgo(X509 *pCert, EVP_PKEY *pKey)
716{
717
718 int t;
719
720 t = SSL_ALGO_UNKNOWN;
721 if (pCert != 0)
722 pKey = X509_get_pubkey(pCert);
723 if (pKey != 0)
724 {
725 #if OPENSSL_VERSION_NUMBER < 0x10100000L
726 switch (EVP_PKEY_type(pKey->type))
727#else
728 switch (EVP_PKEY_base_id(pKey))
729#endif
730 {
731 case EVP_PKEY_RSA:
732 t = SSL_ALGO_RSA;
733 break;
734 case EVP_PKEY_DSA:
735 t = SSL_ALGO_DSA;
736 break;
737 default:
738 break;
739 }
740 }
741 return t;
742}
743
744STACK_OF(X509_NAME) * findCAList(const char *cpCAfile, const char *cpCApath)
745{
746 STACK_OF(X509_NAME) * skCAList;
747 STACK_OF(X509_NAME) * sk;
748#ifndef HAVE_ACE_DIRENT
749 DIR *dir;
750 struct dirent *direntry;
751#else
752 ACE_DIR *dir;
753 struct ACE_DIRENT *direntry;
754#endif
755 char *cp;
756 int n;
757
758/*
759 * Start with a empty stack/list where new
760 * entries get added in sorted order.
761 */
762#ifndef __SUNPRO_CC
763 skCAList = sk_X509_NAME_new(caListX509NameCmp);
764#else
765 skCAList =
766 sk_X509_NAME_new((int (*)(const X509_name_st *const *,
767 const X509_name_st *const *))caListX509NameCmp);
768#endif
769
770 /*
771 * Process CA certificate bundle file
772 */
773 if (cpCAfile != 0)
774 {
775 sk = SSL_load_client_CA_file(cpCAfile);
776 for (n = 0; sk != 0 && n < sk_X509_NAME_num(sk); n++)
777 {
778 // TODO log->onEvent(std::string("CA certificate: ") +
779 // X509_NAME_oneline(sk_X509_NAME_value(sk, n), 0, 0));
780 if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0)
781 sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n));
782 }
783 }
784
785 /*
786 * Process CA certificate path files
787 */
788 if (cpCApath != 0)
789 {
790#ifndef HAVE_ACE_DIRENT
791 dir = opendir(cpCApath);
792#else
793 dir = ACE_OS::opendir(cpCApath);
794#endif
795
796#ifndef HAVE_ACE_DIRENT
797 while ((direntry = readdir(dir)) != 0)
798 {
799#else
800 while ((direntry = ACE_OS::readdir(dir)) != 0)
801 {
802#endif
803 cp = strCat(cpCApath, SLASH, direntry->d_name, 0);
804 sk = SSL_load_client_CA_file(cp);
805 for (n = 0; sk != 0 && n < sk_X509_NAME_num(sk); n++)
806 {
807 // TODO log->onEvent(std::string("CA certificate: %s") +
808 // X509_NAME_oneline(sk_X509_NAME_value(sk, n), 0, 0));
809 if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0)
810 sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n));
811 }
812 }
813#ifndef HAVE_ACE_DIRENT
814 closedir(dir);
815#else
816 ACE_OS::closedir(dir);
817#endif
818 }
819
820 /*
821 * Cleanup
822 */
823 sk_X509_NAME_set_cmp_func(skCAList, 0);
824 return skCAList;
825}
826
827X509_STORE *createX509Store(const char *cpFile, const char *cpPath)
828{
829 X509_STORE *pStore;
830 X509_LOOKUP *pLookup;
831
832 if (cpFile == 0 && cpPath == 0)
833 return 0;
834 if ((pStore = X509_STORE_new()) == 0)
835 return 0;
836 if (cpFile != 0)
837 {
838 if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file())) == 0)
839 {
840 X509_STORE_free(pStore);
841 return 0;
842 }
843 X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
844 }
845 if (cpPath != 0)
846 {
847 if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir())) == 0)
848 {
849 X509_STORE_free(pStore);
850 return 0;
851 }
852 X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
853 }
854 return pStore;
855}
856X509 *readX509(FILE *fp, X509 **x509, passPhraseHandleCallbackType cb)
857{
858 X509 *rc;
859 BIO *bioS;
860 BIO *bioF;
861
862 rc = PEM_read_X509(fp, x509, cb, 0);
863 if (rc == 0)
864 {
865 /* 2. try DER+Base64 */
866 fseek(fp, 0L, SEEK_SET);
867 if ((bioS = BIO_new(BIO_s_fd())) == 0)
868 return 0;
869 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
870 if ((bioF = BIO_new(BIO_f_base64())) == 0)
871 {
872 BIO_free(bioS);
873 return 0;
874 }
875 bioS = BIO_push(bioF, bioS);
876 rc = d2i_X509_bio(bioS, 0);
877 BIO_free_all(bioS);
878 if (rc == 0)
879 {
880 /* 3. try plain DER */
881 fseek(fp, 0L, SEEK_SET);
882 if ((bioS = BIO_new(BIO_s_fd())) == 0)
883 return 0;
884 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
885 rc = d2i_X509_bio(bioS, 0);
886 BIO_free(bioS);
887 }
888 }
889 if (rc != 0 && x509 != 0)
890 {
891 if (*x509 != 0)
892 X509_free(*x509);
893 *x509 = rc;
894 }
895 return rc;
896}
897
898EVP_PKEY *readPrivateKey(FILE *fp, EVP_PKEY **key,
899 passPhraseHandleCallbackType cb)
900{
901 EVP_PKEY *rc;
902 BIO *bioS;
903 BIO *bioF;
904
905 rc = PEM_read_PrivateKey(fp, key, cb, 0);
906 if (rc == 0)
907 {
908 /* 2. try DER+Base64 */
909 fseek(fp, 0L, SEEK_SET);
910 if ((bioS = BIO_new(BIO_s_fd())) == 0)
911 return 0;
912 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
913 if ((bioF = BIO_new(BIO_f_base64())) == 0)
914 {
915 BIO_free(bioS);
916 return 0;
917 }
918 bioS = BIO_push(bioF, bioS);
919 rc = d2i_PrivateKey_bio(bioS, 0);
920 BIO_free_all(bioS);
921 if (rc == 0)
922 {
923 fseek(fp, 0L, SEEK_SET);
924 if ((bioS = BIO_new(BIO_s_fd())) == 0)
925 return 0;
926 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
927 rc = d2i_PrivateKey_bio(bioS, 0);
928 BIO_free(bioS);
929 }
930 }
931 if (rc != 0 && key != 0)
932 {
933 if (*key != 0)
934 EVP_PKEY_free(*key);
935 *key = rc;
936 }
937 return rc;
938}
939
940char *strCat(const char *a, ...)
941{
942 char *cp, *argp, *res;
943
944 /* Pass one --- find length of required string */
945
946 int len = 0;
947 va_list adummy;
948
949 if (a == 0)
950 return 0;
951
952 va_start(adummy, a);
953
954 len = strlen(a);
955 while ((cp = va_arg(adummy, char *)) != 0)
956 len += strlen(cp);
957
958 va_end(adummy);
959
960 /* Allocate the required string */
961
962 res = new char[len + 1];
963 cp = res;
964 *cp = '\0';
965
966 /* Pass two --- copy the argument strings into the result space */
967
968 va_start(adummy, a);
969
970 strcpy(cp, a);
971 cp += strlen(a);
972 while ((argp = va_arg(adummy, char *)) != 0)
973 {
974 strcpy(cp, argp);
975 cp += strlen(argp);
976 }
977
978 va_end(adummy);
979
980 /* Return the result string */
981
982 return res;
983}
984
985int setSocketNonBlocking(int pSocket)
986/********************************************************************************
987* switch socket to non-blocking mode
988* Returns: 0 in the case of success, -1 in the case of error
989*
990*/
991{
992#ifdef _MSC_VER
993 {
994 unsigned long arg = 1; /* ie enable non-blocking mode */
995
996 if (ioctlsocket(pSocket, FIONBIO, &arg) == SOCKET_ERROR)
997 {
998 int ecode = WSAGetLastError();
999
1000 /* EINVAL returned when an attempt is made to set non-blocking a socket
1001 * accepted on a non-blocking listen socket. dont know why */
1002
1003 if (ecode != WSAEINVAL)
1004 {
1005 // TODO LogEvent(
1006 // ERROR_ID,
1007 //"SetSocketNonBlocking:ioctlsocket(%d,FIONBIO,0) failed: %s(%d)",
1008 // pSocket, WSAErrString(ecode), ecode);
1009 return -1;
1010 }
1011 }
1012 return 0;
1013 }
1014
1015#else /* unix */
1016 {
1017 int f = fcntl(pSocket, F_GETFL);
1018
1019 if (f == -1)
1020 // TODO LogEvent(ERROR_ID,
1021 // "SetSocketNonBlocking: fcntl(%d,F_GETFL) failed: %s(errno=%d)",
1022 // pSocket, strerror(errno), errno);
1023
1024 f |= O_NONBLOCK;
1025 if (fcntl(pSocket, F_SETFL, f) == -1)
1026 {
1027 // TODO LogEvent(ERROR_ID,
1028 //"SetSocketNonBlocking: fcntl(%d,F_SETFL) failed: %s(errno=%d)",
1029 // pSocket, strerror(errno), errno);
1030 return -1;
1031 }
1032 return 0;
1033 }
1034#endif
1035}
1036
1037long protocolOptions(const char *opt)
1038{
1039 long options = SSL_PROTOCOL_NONE, thisopt;
1040 char action;
1041 const char *w, *e;
1042
1043 if (*opt)
1044 {
1045 w = opt;
1046 e = w + strlen(w);
1047 while (w && (w < e))
1048 {
1049 action = '\0';
1050 while ((*w == ' ') || (*w == '\t'))
1051 w++;
1052 if (*w == '+' || *w == '-')
1053 action = *(w++);
1054
1055 if (!strncasecmp(w, "SSLv2", 5 /* strlen("SSLv2") */))
1056 {
1057 thisopt = SSL_PROTOCOL_SSLV2;
1058 w += 5 /* strlen("SSLv2")*/;
1059 }
1060 else if (!strncasecmp(w, "SSLv3", 5 /* strlen("SSLv3") */))
1061 {
1062 thisopt = SSL_PROTOCOL_SSLV3;
1063 w += 5 /*strlen("SSLv3") */;
1064 }
1065 else if (!strncasecmp(w, "TLSv1_1", 7 /* strlen("TLSv1_1") */))
1066 {
1067 thisopt = SSL_PROTOCOL_TLSV1_1;
1068 w += 7 /* strlen("TLSv1_1") */;
1069 }
1070 else if (!strncasecmp(w, "TLSv1_2", 7 /* strlen("TLSv1_2") */))
1071 {
1072 thisopt = SSL_PROTOCOL_TLSV1_2;
1073 w += 7 /* strlen("TLSv1_2") */;
1074 }
1075 else if (!strncasecmp(w, "TLSv1", 5 /* strlen("TLSv1") */))
1076 {
1077 thisopt = SSL_PROTOCOL_TLSV1;
1078 w += 5 /* strlen("TLSv1") */;
1079 }
1080 else if (!strncasecmp(w, "all", 3 /* strlen("all") */))
1081 {
1082 thisopt = SSL_PROTOCOL_ALL;
1083 w += 3 /* strlen("all") */;
1084 }
1085 else
1086 return -1;
1087
1088 if (action == '-')
1089 options &= ~thisopt;
1090 else if (action == '+')
1091 options |= thisopt;
1092 else
1093 options = thisopt;
1094 }
1095 }
1096 else
1097 { /* default all except SSLv2 */
1098 options = SSL_PROTOCOL_ALL;
1099 thisopt = SSL_PROTOCOL_SSLV2;
1100 options &= ~thisopt;
1101 }
1102
1103 return options;
1104}
1105
1106void setCtxOptions(SSL_CTX *ctx, long options)
1107{
1108 SSL_CTX_set_options(ctx, SSL_OP_ALL);
1109 if (!(options & SSL_PROTOCOL_SSLV2))
1110 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
1111 if (!(options & SSL_PROTOCOL_SSLV3))
1112 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
1113 if (!(options & SSL_PROTOCOL_TLSV1))
1114 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
1115 if (!(options & SSL_PROTOCOL_TLSV1_1))
1116 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1);
1117 if (!(options & SSL_PROTOCOL_TLSV1_2))
1118 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2);
1119}
1120
1121int enable_DH_ECDH(SSL_CTX *ctx, const char *certFile)
1122{
1123#ifndef OPENSSL_NO_DH
1124 int no_dhe = 0;
1125 if (!no_dhe)
1126 {
1127 DH *dh = NULL;
1128
1129 if (certFile)
1130 dh = load_dh_param(certFile);
1131
1132 if (dh != NULL)
1133 {
1134 SSL_CTX_set_tmp_dh(ctx, dh);
1135
1136 DH_free(dh);
1137 }
1138 else
1139 {
1140 SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
1141 }
1142 //(void)BIO_flush(bio_s_out);
1143 }
1144#endif
1145
1146#ifndef OPENSSL_NO_ECDH
1147 EC_KEY *ecdh;
1148 ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1149 if (ecdh == NULL)
1150 {
1151 return 2;
1152 }
1153 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
1154 EC_KEY_free(ecdh);
1155#endif
1156
1157 return 0;
1158}
1159
1160SSL_CTX *createSSLContext(bool server, const SessionSettings &settings,
1161 std::string &errStr)
1162{
1163 errStr.erase();
1164
1165 SSL_CTX *ctx = 0;
1166
1167 std::string strOptions;
1168 if (settings.get().has(SSL_PROTOCOL))
1169 {
1170 strOptions = settings.get().getString(SSL_PROTOCOL);
1171 }
1172
1173 long options = protocolOptions(strOptions.c_str());
1174
1175 /* set up the application context */
1176#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1177 if (server)
1178 {
1179 ctx = SSL_CTX_new(TLS_server_method());
1180 }
1181 else
1182 {
1183 ctx = SSL_CTX_new(TLS_client_method());
1184 }
1185#else
1186 if (server)
1187 {
1188 ctx = SSL_CTX_new(SSLv23_server_method());
1189 }
1190 else
1191 {
1192 ctx = SSL_CTX_new(SSLv23_client_method());
1193 }
1194#endif
1195
1196 if (ctx == 0)
1197 {
1198 errStr.append("Unable to get context");
1199 return ctx;
1200 }
1201
1202 setCtxOptions(ctx, options);
1203
1204 SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
1205 if (server)
1206 {
1207 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
1208 }
1209
1210 SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |
1211 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
1212
1213 if (settings.get().has(SSL_CIPHER_SUITE))
1214 {
1215 std::string strCipherSuite = settings.get().getString(SSL_CIPHER_SUITE);
1216
1217 if (!strCipherSuite.empty() &&
1218 !SSL_CTX_set_cipher_list(ctx, strCipherSuite.c_str()))
1219 {
1220 errStr.append("Unable to configure permitted SSL ciphers");
1221 SSL_CTX_free(ctx);
1222 return 0;
1223 }
1224 }
1225
1226 return ctx;
1227}
1228
1229bool loadSSLCert(SSL_CTX *ctx, bool server, const SessionSettings &settings,
1230 Log *log, passPhraseHandleCallbackType cb, std::string &errStr)
1231{
1232 errStr.erase();
1233
1234 log->onEvent("Loading SSL certificate");
1235
1236 std::string cert;
1237 std::string key;
1238
1239 if (server)
1240 {
1241 if (!settings.get().has(SERVER_CERT_FILE))
1242 {
1243 errStr.assign(SERVER_CERT_FILE);
1244 errStr.append(" parameter not found");
1245 return false;
1246 }
1247
1248 cert.assign(settings.get().getString(SERVER_CERT_FILE));
1249
1250 if (settings.get().has(SERVER_CERT_KEY_FILE))
1251 key.assign(settings.get().getString(SERVER_CERT_KEY_FILE));
1252 else
1253 key.assign(cert);
1254 }
1255 else
1256 {
1257 if (!settings.get().has(CLIENT_CERT_FILE))
1258 {
1259 log->onEvent("No SSL certificate configured for client.");
1260
1261 int ret = enable_DH_ECDH(ctx, 0);
1262 if (ret != 0)
1263 {
1264 if (ret == 1)
1265 errStr.assign("Could not enable DH");
1266 else if (ret == 2)
1267 errStr.assign("Could not enable ECDH");
1268 else
1269 errStr.assign("Unknown error enabling DH, ECDH");
1270
1271 return false;
1272 }
1273
1274 return true;
1275 }
1276
1277 cert.assign(settings.get().getString(CLIENT_CERT_FILE));
1278
1279 if (settings.get().has(CLIENT_CERT_KEY_FILE))
1280 key.assign(settings.get().getString(CLIENT_CERT_KEY_FILE));
1281 else
1282 key.assign(cert);
1283 }
1284
1285 SSL_CTX_set_default_passwd_cb(ctx, cb);
1286
1287 FILE *fp;
1288
1289 if ((fp = fopen(cert.c_str(), "r")) == 0)
1290 {
1291 errStr.assign(cert);
1292 errStr.append(" file could not be opened");
1293 return false;
1294 }
1295
1296 X509 *X509Cert = readX509(fp, 0, 0);
1297
1298 fclose(fp);
1299
1300 if (X509Cert == 0)
1301 {
1302 errStr.assign(cert);
1303 errStr.append(" readX509 failed");
1304 return false;
1305 }
1306
1307 switch (typeofSSLAlgo(X509Cert, 0))
1308 {
1309 case SSL_ALGO_RSA:
1310 log->onEvent("Configuring RSA client certificate");
1311
1312 if (SSL_CTX_use_certificate(ctx, X509Cert) <= 0)
1313 {
1314 errStr.assign("Unable to configure RSA client certificate");
1315 return false;
1316 }
1317 break;
1318
1319 case SSL_ALGO_DSA:
1320 log->onEvent("Configuring DSA client certificate");
1321 if (SSL_CTX_use_certificate(ctx, X509Cert) <= 0)
1322 {
1323 errStr.assign("Unable to configure DSA client certificate");
1324 return false;
1325 }
1326 break;
1327
1328 default:
1329 errStr.assign("Unable to configure client certificate");
1330 return false;
1331 break;
1332 }
1333 X509_free(X509Cert);
1334
1335 if ((fp = fopen(key.c_str(), "r")) == 0)
1336 {
1337 errStr.assign(key);
1338 errStr.append(" file could not be opened");
1339 return false;
1340 }
1341
1342 EVP_PKEY *privateKey = readPrivateKey(fp, 0, cb);
1343
1344 fclose(fp);
1345
1346 if (privateKey == 0)
1347 {
1348 errStr.assign(key);
1349 errStr.append(" readPrivateKey failed");
1350 return false;
1351 }
1352
1353 switch (typeofSSLAlgo(0, privateKey))
1354 {
1355 case SSL_ALGO_RSA:
1356 log->onEvent("Configuring RSA client private key");
1357 if (SSL_CTX_use_PrivateKey(ctx, privateKey) <= 0)
1358 {
1359 errStr.assign("Unable to configure RSA server private key");
1360 return false;
1361 }
1362 break;
1363
1364 case SSL_ALGO_DSA:
1365 log->onEvent("Configuring DSA client private key");
1366 if (SSL_CTX_use_PrivateKey(ctx, privateKey) <= 0)
1367 {
1368 errStr.assign("Unable to configure DSA server private key");
1369 return false;
1370 }
1371 break;
1372 default:
1373
1374 errStr.assign("Unable to configure client certificate");
1375 return false;
1376 break;
1377 }
1378 EVP_PKEY_free(privateKey);
1379
1380 /* Now we know that a key and cert have been set against
1381 * the SSL context */
1382 if (!SSL_CTX_check_private_key(ctx))
1383 {
1384 errStr.assign("Private key does not match the certificate public key");
1385 return false;
1386 }
1387
1388 int ret = enable_DH_ECDH(ctx, cert.c_str());
1389 if (ret != 0)
1390 {
1391 if (ret == 1)
1392 errStr.assign("Could not enable DH");
1393 else if (ret == 2)
1394 errStr.assign("Could not enable ECDH");
1395 else
1396 errStr.assign("Unknown error enabling DH, ECDH");
1397
1398 return false;
1399 }
1400
1401 return true;
1402 ;
1403}
1404
1405bool loadCAInfo(SSL_CTX *ctx, bool server, const SessionSettings &settings,
1406 Log *log, std::string &errStr, int &verifyLevel)
1407{
1408 errStr.erase();
1409
1410 log->onEvent("Loading CA info");
1411
1412 std::string caFile;
1413 if (settings.get().has(CERT_AUTH_FILE))
1414 caFile.assign(settings.get().getString(CERT_AUTH_FILE));
1415
1416 std::string caDir;
1417 if (settings.get().has(CERT_AUTH_DIR))
1418 caDir.assign(settings.get().getString(CERT_AUTH_DIR));
1419
1420 if (caFile.empty() && caDir.empty())
1421 return true;
1422
1423 if (!SSL_CTX_load_verify_locations(ctx, caFile.empty() ? 0 : caFile.c_str(),
1424 caDir.empty() ? 0 : caDir.c_str()) ||
1425 !SSL_CTX_set_default_verify_paths(ctx))
1426 {
1427 errStr.assign(
1428 "Unable to configure verify locations for client authentication");
1429 return false;
1430 }
1431
1432 STACK_OF(X509_NAME) * caList;
1433 if ((caList = findCAList(caFile.empty() ? 0 : caFile.c_str(),
1434 caDir.empty() ? 0 : caDir.c_str())) == 0)
1435 {
1436 errStr.assign("Unable to determine list of available CA certificates "
1437 "for client authentication");
1438 return false;
1439 }
1440 SSL_CTX_set_client_CA_list(ctx, caList);
1441
1442 if (server)
1443 {
1444 if (settings.get().has(VERIFY_LEVEL))
1445 verifyLevel = (settings.get().getInt(VERIFY_LEVEL));
1446
1447 if (verifyLevel != SSL_CLIENT_VERIFY_NOTSET)
1448 {
1449 /* configure new state */
1450 int cVerify = SSL_VERIFY_NONE;
1451 if (verifyLevel == SSL_CLIENT_VERIFY_REQUIRE)
1452 cVerify |= SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1453 else if (verifyLevel == SSL_CLIENT_VERIFY_OPTIONAL)
1454 cVerify |= SSL_VERIFY_PEER;
1455
1456 SSL_CTX_set_verify(ctx, cVerify, callbackVerify);
1457 }
1458 }
1459 else
1460 {
1461 /* Set the certificate verification callback */
1462 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, callbackVerify);
1463 }
1464
1465 return true;
1466}
1467
1468X509_STORE *loadCRLInfo(SSL_CTX *ctx, const SessionSettings &settings, Log *log,
1469 std::string &errStr)
1470{
1471 errStr.erase();
1472
1473 X509_STORE *revocationStore = 0;
1474
1475 log->onEvent("Loading CRL information");
1476
1477 errStr.erase();
1478
1479 std::string crlFile;
1480 if (settings.get().has(CRL_FILE))
1481 crlFile.assign(settings.get().getString(CRL_FILE));
1482
1483 std::string crlDir;
1484 if (settings.get().has(CRL_DIR))
1485 crlDir.assign(settings.get().getString(CRL_DIR));
1486
1487 if (crlFile.empty() && crlDir.empty())
1488 return revocationStore;
1489
1490#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
1491 revocationStore =
1492 createX509Store(crlFile.c_str(), crlDir.empty() ? 0 : crlDir.c_str());
1493 if (revocationStore == 0)
1494 {
1495 errStr.assign("Unable to create revocation store");
1496 }
1497#else
1498 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
1499 if (!store || !X509_STORE_load_locations(store, crlFile.c_str(),
1500 crlDir.c_str()))
1501 {
1502 errStr.assign("Unable to create revocation store");
1503 return 0;
1504 }
1505 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1506#endif
1507
1508 return revocationStore;
1509}
1510
1511int doAccept(SSL *ssl, int &result)
1512{
1513 int rc = SSL_accept(ssl);
1514 if (rc <= 0)
1515 {
1516 result = SSL_get_error(ssl, rc);
1517 }
1518
1519 return rc;
1520}
1521
1522int acceptSSLConnection(int socket, SSL *ssl, Log *log, int verify)
1523{
1524 int rc;
1525 int result = -1;
1526 char *subjName = 0;
1527 time_t timeout = time(0) + 10;
1528#ifdef __TOS_AIX__
1529 int retries = 0;
1530#endif
1531 /*
1532 * Now enter the SSL Handshake Phase
1533 */
1534 while (!SSL_is_init_finished(ssl))
1535 {
1536 ERR_clear_error();
1537 while ((rc = doAccept(ssl, result)) <= 0)
1538 {
1539
1540 if (result == SSL_ERROR_WANT_READ)
1541 ;
1542 else if (result == SSL_ERROR_WANT_WRITE)
1543 ;
1544 else if (result == SSL_ERROR_ZERO_RETURN)
1545 {
1546 /*
1547 * The case where the connection was closed before any data
1548 * was transferred. That's not a real error and can occur
1549 * sporadically with some clients.
1550 */
1551 if (log)
1552 log->onEvent("SSL handshake stopped: connection was closed");
1553 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1554 ssl_socket_close(socket, ssl);
1555 return result;
1556 }
1557 else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST)
1558 {
1559 /*
1560 * The case where OpenSSL has recognized a HTTP request:
1561 * This means the client speaks plain HTTP on our HTTPS
1562 * port. Hmmmm... At least for this error we can be more friendly
1563 * and try to provide him with a HTML error page. We have only one
1564 * problem: OpenSSL has already read some bytes from the HTTP
1565 * request. So we have to skip the request line manually and
1566 * instead provide a faked one in order to continue the internal
1567 * Apache processing.
1568 *
1569 */
1570 char ca[2];
1571 int rv;
1572
1573 /* log the situation */
1574 if (log)
1575 log->onEvent("SSL handshake failed: HTTP spoken on HTTPS port");
1576
1577 /* first: skip the remaining bytes of the request line */
1578 do
1579 {
1580#ifndef _MSC_VER // Unix
1581 do
1582 {
1583 rv = read(socket, ca, 1);
1584 } while (rv == -1 && errno == EINTR);
1585#else // Windows
1586 do
1587 {
1588 rv = recv(socket, ca, 1, 0);
1589 } while (rv == -1 && errno == EINTR);
1590#endif
1591 } while (rv > 0 && ca[0] != '\012' /*LF*/);
1592
1593 SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
1594 ssl_socket_close(socket, ssl);
1595 ;
1596 return result;
1597 }
1598 else if (result == SSL_ERROR_SYSCALL)
1599 {
1600#ifdef __TOS_AIX__
1601 if (errno == EINTR)
1602 continue;
1603 else if (errno == EAGAIN)
1604 {
1605 // Please refer:
1606 // http://community.emailogy.com/scripts/wa-COMMUNITY.exe?A2=ind0303&L=lstsrv-l&O=A&P=19558
1607 // http://mirt.net/pipermail/stunnel-users/2007-May/001570.html
1608 ++retries;
1609 if (retries <= 100)
1610 {
1611 if (log)
1612 log->onEvent(
1613 "EAGAIN received during SSL handshake, trying again");
1614 process_sleep(0.005);
1615 continue;
1616 }
1617 }
1618 if (errno > 0)
1619 {
1620 if (log)
1621 log->onEvent(
1622 std::string("SSL handshake interrupted by system, errno " +
1623 IntConvertor::convert(errno)));
1624 }
1625 else if (log)
1626 log->onEvent("Spurious SSL handshake interrupt");
1627#elif defined(_MSC_VER)
1628 // MS Windows will not set errno, but WSEGetLastError() must be queried
1629 int lastSocketError = WSAGetLastError();
1630 if ((lastSocketError == WSAEINTR) ||
1631 (lastSocketError == WSAEWOULDBLOCK))
1632 continue;
1633 if (log)
1634 log->onEvent(
1635 std::string(
1636 "SSL handshake interrupted by system, system error ") +
1637 IntConvertor::convert(lastSocketError) + " socket " +
1638 IntConvertor::convert(socket));
1639
1640#else
1641 if (errno == EINTR)
1642 continue;
1643 if (errno > 0)
1644 {
1645 if (log)
1646 log->onEvent(
1647 std::string("SSL handshake interrupted by system, errno ") +
1648 IntConvertor::convert(errno));
1649 }
1650 else if (log)
1651 log->onEvent("Spurious SSL handshake interrupt");
1652#endif
1653 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1654 ssl_socket_close(socket, ssl);
1655 return result;
1656 }
1657 else
1658 {
1659 /*
1660 * Ok, anything else is a fatal error
1661 */
1662 unsigned long err = ERR_get_error();
1663 if (log)
1664 log->onEvent("SSL handshake failed");
1665
1666 while (err)
1667 {
1668 if (log)
1669 log->onEvent(std::string("SSL failure reason: ") +
1670 ERR_reason_error_string(err));
1671 err = ERR_get_error();
1672 }
1673
1674 /*
1675 * try to gracefully shutdown the connection:
1676 * - send an own shutdown message (be gracefully)
1677 * - don't wait for peer's shutdown message (deadloop)
1678 * - kick away the SSL stuff immediately
1679 */
1680 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1681 ssl_socket_close(socket, ssl);
1682 return result;
1683 }
1684 if (time(0) > timeout)
1685 {
1686 if (log)
1687 log->onEvent("SSL handshake stopped: connection was closed");
1688 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1689 ssl_socket_close(socket, ssl);
1690 return result;
1691 }
1692 process_sleep(0.01);
1693 }
1694
1695 X509 *xs = 0;
1696
1697 /*
1698 * Check for failed client authentication
1699 */
1700 if ((result = SSL_get_verify_result(ssl)) != X509_V_OK)
1701 {
1702 if (log)
1703 log->onEvent("SSL client authentication failed: ");
1704 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1705 ssl_socket_close(socket, ssl);
1706 return result;
1707 }
1708 else
1709 {
1710 if ((xs = SSL_get_peer_certificate(ssl)) != 0)
1711 {
1712 subjName = X509_NAME_oneline(X509_get_subject_name(xs), 0, 0);
1713 }
1714 }
1715 }
1716
1717 if ((verify == SSL_CLIENT_VERIFY_REQUIRE) && subjName == 0)
1718 {
1719 if (log)
1720 log->onEvent("No acceptable peer certificate available");
1721 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1722 ssl_socket_close(socket, ssl);
1723 result = 2;
1724 }
1725
1726 if (subjName)
1727 free(subjName);
1728
1729 return result;
1730}
1731}
1732
1733#endif
static DIR * opendir(const char *dirname)
static int closedir(DIR *dirp)
static struct dirent * readdir(DIR *dirp)
const char SERVER_CERT_KEY_FILE[]
const char SSL_PROTOCOL[]
const char CLIENT_CERT_FILE[]
const char CLIENT_CERT_KEY_FILE[]
const char CERT_AUTH_DIR[]
void socket_close(int s)
Definition Utility.cpp:180
void process_sleep(double s)
Definition Utility.cpp:466
const char SSL_CIPHER_SUITE[]
const char VERIFY_LEVEL[]
const char CERT_AUTH_FILE[]
const char CRL_FILE[]
const char CRL_DIR[]
const char SERVER_CERT_FILE[]
static std::string convert(signed_int value)
char d_name[PATH_MAX]

Generated on Thu Feb 29 2024 22:38:19 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001