quickfix_ruby 1.14.3.1 → 1.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/ext/quickfix/Acceptor.h +2 -0
  3. data/ext/quickfix/AtomicCount.h +82 -12
  4. data/ext/quickfix/DOMDocument.h +9 -7
  5. data/ext/quickfix/DataDictionary.cpp +77 -14
  6. data/ext/quickfix/DataDictionary.h +90 -16
  7. data/ext/quickfix/Dictionary.cpp +1 -2
  8. data/ext/quickfix/Exceptions.h +3 -5
  9. data/ext/quickfix/Field.h +83 -32
  10. data/ext/quickfix/FieldConvertors.cpp +93 -0
  11. data/ext/quickfix/FieldConvertors.h +129 -275
  12. data/ext/quickfix/FieldMap.cpp +53 -13
  13. data/ext/quickfix/FieldMap.h +200 -62
  14. data/ext/quickfix/FieldTypes.cpp +10 -10
  15. data/ext/quickfix/FieldTypes.h +293 -44
  16. data/ext/quickfix/FileLog.cpp +6 -10
  17. data/ext/quickfix/FileLog.h +4 -10
  18. data/ext/quickfix/FileStore.cpp +19 -6
  19. data/ext/quickfix/FileStore.h +4 -0
  20. data/ext/quickfix/FixFieldNumbers.h +1462 -1461
  21. data/ext/quickfix/FixFields.h +1462 -1461
  22. data/ext/quickfix/FixValues.h +3230 -3227
  23. data/ext/quickfix/HttpConnection.cpp +1 -1
  24. data/ext/quickfix/Initiator.cpp +7 -1
  25. data/ext/quickfix/Initiator.h +2 -0
  26. data/ext/quickfix/Log.h +6 -12
  27. data/ext/quickfix/Message.cpp +186 -57
  28. data/ext/quickfix/Message.h +109 -47
  29. data/ext/quickfix/MySQLConnection.h +1 -1
  30. data/ext/quickfix/PostgreSQLConnection.h +1 -1
  31. data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
  32. data/ext/quickfix/QuickfixRuby.h +1 -1
  33. data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
  34. data/ext/quickfix/SSLSocketAcceptor.h +185 -0
  35. data/ext/quickfix/SSLSocketConnection.cpp +427 -0
  36. data/ext/quickfix/SSLSocketConnection.h +206 -0
  37. data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
  38. data/ext/quickfix/SSLSocketInitiator.h +196 -0
  39. data/ext/quickfix/Session.cpp +113 -20
  40. data/ext/quickfix/Session.h +18 -4
  41. data/ext/quickfix/SessionFactory.cpp +10 -3
  42. data/ext/quickfix/SessionSettings.cpp +5 -3
  43. data/ext/quickfix/SessionSettings.h +97 -5
  44. data/ext/quickfix/Settings.cpp +72 -2
  45. data/ext/quickfix/Settings.h +3 -0
  46. data/ext/quickfix/SharedArray.h +140 -6
  47. data/ext/quickfix/SocketConnection.cpp +2 -2
  48. data/ext/quickfix/SocketConnector.cpp +5 -2
  49. data/ext/quickfix/SocketConnector.h +3 -2
  50. data/ext/quickfix/SocketInitiator.cpp +28 -4
  51. data/ext/quickfix/SocketInitiator.h +1 -1
  52. data/ext/quickfix/SocketMonitor.cpp +5 -5
  53. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
  54. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
  55. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
  56. data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
  57. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
  58. data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
  59. data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
  60. data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
  61. data/ext/quickfix/ThreadedSocketConnection.h +4 -1
  62. data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
  63. data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
  64. data/ext/quickfix/Utility.cpp +23 -1
  65. data/ext/quickfix/Utility.h +28 -2
  66. data/ext/quickfix/UtilitySSL.cpp +1733 -0
  67. data/ext/quickfix/UtilitySSL.h +277 -0
  68. data/ext/quickfix/config-all.h +10 -0
  69. data/ext/quickfix/dirent_windows.h +838 -0
  70. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  71. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  72. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  73. data/ext/quickfix/double-conversion/bignum.h +144 -0
  74. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  75. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  76. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  77. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  78. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  79. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  80. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  81. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  82. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  83. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  84. data/ext/quickfix/double-conversion/ieee.h +402 -0
  85. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  86. data/ext/quickfix/double-conversion/strtod.h +45 -0
  87. data/ext/quickfix/double-conversion/utils.h +372 -0
  88. data/ext/quickfix/stdint_msvc.h +254 -0
  89. data/lib/quickfix44.rb +3329 -10
  90. data/lib/quickfix50.rb +6649 -81
  91. data/lib/quickfix50sp1.rb +8054 -142
  92. data/lib/quickfix50sp2.rb +10900 -234
  93. data/lib/quickfix_fields.rb +7662 -7649
  94. data/spec/FIX40.xml +28 -28
  95. data/spec/FIX41.xml +29 -29
  96. data/spec/FIX42.xml +47 -47
  97. data/spec/FIX43.xml +148 -148
  98. data/spec/FIX44.xml +1078 -1081
  99. data/spec/FIX50.xml +1292 -1289
  100. data/spec/FIX50SP1.xml +1811 -1802
  101. data/spec/FIX50SP2.xml +1948 -1939
  102. data/spec/FIXT11.xml +5 -8
  103. data/test/test_FieldBaseTestCase.rb +1 -1
  104. data/test/test_MessageTestCase.rb +2 -2
  105. metadata +42 -6
@@ -0,0 +1,1733 @@
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