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 
148 namespace FIX
149 {
150 
151 #ifndef OPENSSL_NO_DH
152 static 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);
160 err:
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 */
169 static 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  */
194 static 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. */
220 static 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 
230 static 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 
238 static 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. */
259 DH *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  */
273 DH *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 */
307 static Mutex ssl_mutex;
308 /* Reference count of ssl users. Should always call ssl_init/ssl_term */
309 static int ssl_users = 0;
310 static int ssl_initialized = 0;
311 /* This array will store all of the mutexes available to OpenSSL. */
312 #ifdef _MSC_VER
313 static HANDLE *lock_cs = 0;
314 #else
315 static pthread_mutex_t *lock_cs = 0;
316 #endif
317 
318 static void thread_setup(void); // For thread safety.
319 static void thread_cleanup(void);
320 static void ssl_rand_seed(void);
321 
322 void 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 
354 void 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 
370 void 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 
389 static 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 
404 static 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 
413 static 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 
440 static 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 
465 static 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 
482 static 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 
511 const 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 
524 int 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)
530 int 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 
542 int 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 
659 int 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 
715 int 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 
744 STACK_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 
827 X509_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 }
856 X509 *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 
898 EVP_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 
940 char *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 
985 int 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 
1037 long 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 
1106 void 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 
1121 int 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 
1160 SSL_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 
1229 bool 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 
1405 bool 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 
1468 X509_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 
1511 int 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 
1522 int 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
opendir
static DIR * opendir(const char *dirname)
Definition: dirent_windows.h:522
FIX::CLIENT_CERT_KEY_FILE
const char CLIENT_CERT_KEY_FILE[]
Definition: SessionSettings.h:153
FIX::SSL_PROTOCOL
const char SSL_PROTOCOL[]
Definition: SessionSettings.h:203
FIX::CRL_DIR
const char CRL_DIR[]
Definition: SessionSettings.h:157
FIX::CERT_AUTH_FILE
const char CERT_AUTH_FILE[]
Definition: SessionSettings.h:154
UtilitySSL.h
FIX::SSL_CIPHER_SUITE
const char SSL_CIPHER_SUITE[]
Definition: SessionSettings.h:233
FIX::SERVER_CERT_KEY_FILE
const char SERVER_CERT_KEY_FILE[]
Definition: SessionSettings.h:151
Mutex.h
FIX::IntConvertor::convert
static std::string convert(signed_int value)
Definition: FieldConvertors.h:170
dirent
Definition: dirent_windows.h:201
FIX::CRL_FILE
const char CRL_FILE[]
Definition: SessionSettings.h:156
FIX::SERVER_CERT_FILE
const char SERVER_CERT_FILE[]
Definition: SessionSettings.h:150
FIX::VERIFY_LEVEL
const char VERIFY_LEVEL[]
Definition: SessionSettings.h:158
readdir
static struct dirent * readdir(DIR *dirp)
Definition: dirent_windows.h:592
FIX::process_sleep
void process_sleep(double s)
Definition: Utility.cpp:483
FIX
Definition: Acceptor.cpp:34
FIX::CLIENT_CERT_FILE
const char CLIENT_CERT_FILE[]
Definition: SessionSettings.h:152
FIX::socket_close
void socket_close(int s)
Definition: Utility.cpp:197
DIR
Definition: dirent_windows.h:210
FIX::CERT_AUTH_DIR
const char CERT_AUTH_DIR[]
Definition: SessionSettings.h:155
closedir
static int closedir(DIR *dirp)
Definition: dirent_windows.h:675

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001