quickfix_ruby 1.14.3.1 → 1.15.1

Sign up to get free protection for your applications and to get access to all the features.
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