quickfix_ruby_ud 2.0.7-x86_64-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.
- checksums.yaml +7 -0
- data/ext/quickfix/Acceptor.cpp +257 -0
- data/ext/quickfix/Acceptor.h +127 -0
- data/ext/quickfix/Allocator.h +9 -0
- data/ext/quickfix/Application.h +137 -0
- data/ext/quickfix/DOMDocument.h +70 -0
- data/ext/quickfix/DataDictionary.cpp +679 -0
- data/ext/quickfix/DataDictionary.h +607 -0
- data/ext/quickfix/DataDictionaryProvider.cpp +66 -0
- data/ext/quickfix/DataDictionaryProvider.h +67 -0
- data/ext/quickfix/DatabaseConnectionID.h +98 -0
- data/ext/quickfix/DatabaseConnectionPool.h +84 -0
- data/ext/quickfix/Dictionary.cpp +157 -0
- data/ext/quickfix/Dictionary.h +89 -0
- data/ext/quickfix/Event.h +89 -0
- data/ext/quickfix/Except.h +39 -0
- data/ext/quickfix/Exceptions.h +257 -0
- data/ext/quickfix/Field.h +654 -0
- data/ext/quickfix/FieldConvertors.cpp +86 -0
- data/ext/quickfix/FieldConvertors.h +800 -0
- data/ext/quickfix/FieldMap.cpp +254 -0
- data/ext/quickfix/FieldMap.h +327 -0
- data/ext/quickfix/FieldNumbers.h +44 -0
- data/ext/quickfix/FieldTypes.cpp +62 -0
- data/ext/quickfix/FieldTypes.h +817 -0
- data/ext/quickfix/Fields.h +30 -0
- data/ext/quickfix/FileLog.cpp +176 -0
- data/ext/quickfix/FileLog.h +110 -0
- data/ext/quickfix/FileStore.cpp +369 -0
- data/ext/quickfix/FileStore.h +131 -0
- data/ext/quickfix/FixCommonFields.h +13 -0
- data/ext/quickfix/FixFieldNumbers.h +6132 -0
- data/ext/quickfix/FixFields.h +6133 -0
- data/ext/quickfix/FixValues.h +5790 -0
- data/ext/quickfix/Group.cpp +44 -0
- data/ext/quickfix/Group.h +78 -0
- data/ext/quickfix/HostDetailsProvider.cpp +79 -0
- data/ext/quickfix/HostDetailsProvider.h +44 -0
- data/ext/quickfix/HtmlBuilder.h +178 -0
- data/ext/quickfix/HttpConnection.cpp +914 -0
- data/ext/quickfix/HttpConnection.h +74 -0
- data/ext/quickfix/HttpMessage.cpp +229 -0
- data/ext/quickfix/HttpMessage.h +112 -0
- data/ext/quickfix/HttpParser.cpp +49 -0
- data/ext/quickfix/HttpParser.h +49 -0
- data/ext/quickfix/HttpServer.cpp +152 -0
- data/ext/quickfix/HttpServer.h +76 -0
- data/ext/quickfix/Initiator.cpp +310 -0
- data/ext/quickfix/Initiator.h +151 -0
- data/ext/quickfix/Log.cpp +71 -0
- data/ext/quickfix/Log.h +254 -0
- data/ext/quickfix/Message.cpp +617 -0
- data/ext/quickfix/Message.h +419 -0
- data/ext/quickfix/MessageCracker.h +171 -0
- data/ext/quickfix/MessageSorters.cpp +101 -0
- data/ext/quickfix/MessageSorters.h +185 -0
- data/ext/quickfix/MessageStore.cpp +182 -0
- data/ext/quickfix/MessageStore.h +164 -0
- data/ext/quickfix/Mutex.h +120 -0
- data/ext/quickfix/MySQLConnection.h +187 -0
- data/ext/quickfix/MySQLLog.cpp +262 -0
- data/ext/quickfix/MySQLLog.h +158 -0
- data/ext/quickfix/MySQLStore.cpp +323 -0
- data/ext/quickfix/MySQLStore.h +161 -0
- data/ext/quickfix/MySQLStubs.h +203 -0
- data/ext/quickfix/NullStore.cpp +40 -0
- data/ext/quickfix/NullStore.h +89 -0
- data/ext/quickfix/OdbcConnection.h +241 -0
- data/ext/quickfix/OdbcLog.cpp +230 -0
- data/ext/quickfix/OdbcLog.h +109 -0
- data/ext/quickfix/OdbcStore.cpp +313 -0
- data/ext/quickfix/OdbcStore.h +124 -0
- data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
- data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
- data/ext/quickfix/Parser.cpp +111 -0
- data/ext/quickfix/Parser.h +50 -0
- data/ext/quickfix/PostgreSQLConnection.h +163 -0
- data/ext/quickfix/PostgreSQLLog.cpp +263 -0
- data/ext/quickfix/PostgreSQLLog.h +157 -0
- data/ext/quickfix/PostgreSQLStore.cpp +327 -0
- data/ext/quickfix/PostgreSQLStore.h +160 -0
- data/ext/quickfix/PostgreSQLStubs.h +203 -0
- data/ext/quickfix/Queue.h +66 -0
- data/ext/quickfix/QuickfixRuby.cpp +131900 -0
- data/ext/quickfix/QuickfixRuby.h +56 -0
- data/ext/quickfix/Responder.h +41 -0
- data/ext/quickfix/SSLSocketAcceptor.cpp +409 -0
- data/ext/quickfix/SSLSocketAcceptor.h +186 -0
- data/ext/quickfix/SSLSocketConnection.cpp +434 -0
- data/ext/quickfix/SSLSocketConnection.h +221 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +558 -0
- data/ext/quickfix/SSLSocketInitiator.h +203 -0
- data/ext/quickfix/SSLStubs.h +129 -0
- data/ext/quickfix/Session.cpp +1437 -0
- data/ext/quickfix/Session.h +343 -0
- data/ext/quickfix/SessionFactory.cpp +314 -0
- data/ext/quickfix/SessionFactory.h +84 -0
- data/ext/quickfix/SessionID.h +136 -0
- data/ext/quickfix/SessionSettings.cpp +165 -0
- data/ext/quickfix/SessionSettings.h +283 -0
- data/ext/quickfix/SessionState.h +260 -0
- data/ext/quickfix/Settings.cpp +160 -0
- data/ext/quickfix/Settings.h +56 -0
- data/ext/quickfix/SharedArray.h +274 -0
- data/ext/quickfix/SocketAcceptor.cpp +216 -0
- data/ext/quickfix/SocketAcceptor.h +77 -0
- data/ext/quickfix/SocketConnection.cpp +256 -0
- data/ext/quickfix/SocketConnection.h +102 -0
- data/ext/quickfix/SocketConnector.cpp +112 -0
- data/ext/quickfix/SocketConnector.h +76 -0
- data/ext/quickfix/SocketInitiator.cpp +241 -0
- data/ext/quickfix/SocketInitiator.h +76 -0
- data/ext/quickfix/SocketMonitor.h +26 -0
- data/ext/quickfix/SocketMonitor_UNIX.cpp +238 -0
- data/ext/quickfix/SocketMonitor_UNIX.h +101 -0
- data/ext/quickfix/SocketMonitor_WIN32.cpp +248 -0
- data/ext/quickfix/SocketMonitor_WIN32.h +99 -0
- data/ext/quickfix/SocketServer.cpp +163 -0
- data/ext/quickfix/SocketServer.h +100 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +436 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +209 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +364 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +191 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +434 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +193 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +242 -0
- data/ext/quickfix/ThreadedSocketAcceptor.h +95 -0
- data/ext/quickfix/ThreadedSocketConnection.cpp +227 -0
- data/ext/quickfix/ThreadedSocketConnection.h +89 -0
- data/ext/quickfix/ThreadedSocketInitiator.cpp +238 -0
- data/ext/quickfix/ThreadedSocketInitiator.h +78 -0
- data/ext/quickfix/TimeRange.cpp +227 -0
- data/ext/quickfix/TimeRange.h +215 -0
- data/ext/quickfix/Utility.cpp +639 -0
- data/ext/quickfix/Utility.h +255 -0
- data/ext/quickfix/UtilitySSL.cpp +1612 -0
- data/ext/quickfix/UtilitySSL.h +274 -0
- data/ext/quickfix/Values.h +63 -0
- data/ext/quickfix/config-all.h +10 -0
- data/ext/quickfix/config.h +10 -0
- data/ext/quickfix/config_unix.h +178 -0
- data/ext/quickfix/config_windows.h +0 -0
- data/ext/quickfix/dirent_windows.h +838 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
- data/ext/quickfix/double-conversion/bignum.cc +766 -0
- data/ext/quickfix/double-conversion/bignum.h +144 -0
- data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
- data/ext/quickfix/double-conversion/cached-powers.h +64 -0
- data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
- data/ext/quickfix/double-conversion/diy-fp.h +118 -0
- data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
- data/ext/quickfix/double-conversion/double-conversion.h +543 -0
- data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
- data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
- data/ext/quickfix/double-conversion/ieee.h +402 -0
- data/ext/quickfix/double-conversion/strtod.cc +557 -0
- data/ext/quickfix/double-conversion/strtod.h +45 -0
- data/ext/quickfix/double-conversion/utils.h +374 -0
- data/ext/quickfix/extconf.rb +76 -0
- data/ext/quickfix/index.h +37 -0
- data/ext/quickfix/pugiconfig.hpp +77 -0
- data/ext/quickfix/pugixml.cpp +13237 -0
- data/ext/quickfix/pugixml.hpp +1516 -0
- data/ext/quickfix/scope_guard.hpp +215 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/ext/quickfix/strptime.h +7 -0
- data/lib/2.4/quickfix.so +0 -0
- data/lib/2.5/quickfix.so +0 -0
- data/lib/2.6/quickfix.so +0 -0
- data/lib/2.7/quickfix.so +0 -0
- data/lib/3.0/quickfix.so +0 -0
- data/lib/3.1/quickfix.so +0 -0
- data/lib/3.2/quickfix.so +0 -0
- data/lib/3.3/quickfix.so +0 -0
- data/lib/3.4/quickfix.so +0 -0
- data/lib/quickfix40.rb +274 -0
- data/lib/quickfix41.rb +351 -0
- data/lib/quickfix42.rb +1184 -0
- data/lib/quickfix43.rb +3504 -0
- data/lib/quickfix44.rb +14040 -0
- data/lib/quickfix50.rb +20051 -0
- data/lib/quickfix50sp1.rb +23596 -0
- data/lib/quickfix50sp2.rb +412444 -0
- data/lib/quickfix_fields.rb +79393 -0
- data/lib/quickfix_ruby.rb +82 -0
- data/lib/quickfixt11.rb +65 -0
- data/spec/FIX40.xml +862 -0
- data/spec/FIX41.xml +1282 -0
- data/spec/FIX42.xml +2743 -0
- data/spec/FIX43.xml +4230 -0
- data/spec/FIX44.xml +6600 -0
- data/spec/FIX50.xml +8142 -0
- data/spec/FIX50SP1.xml +9506 -0
- data/spec/FIX50SP2.xml +26069 -0
- data/spec/FIXT11.xml +252 -0
- data/test/DataDictionaryTestCase.rb +268 -0
- data/test/DictionaryTestCase.rb +112 -0
- data/test/FieldBaseTestCase.rb +24 -0
- data/test/MessageStoreTestCase.rb +19 -0
- data/test/MessageTestCase.rb +368 -0
- data/test/SessionSettingsTestCase.rb +41 -0
- 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
|