quickfix_ruby_ud 2.0.7-aarch64-linux

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