Line 0
Link Here
|
|
|
1 |
--- net/netssltransport.cc.orig 2018-10-28 00:15:23 UTC |
2 |
+++ net/netssltransport.cc |
3 |
@@ -112,11 +112,37 @@ unsigned long sCompileVersion = OPENSSL |
4 |
unsigned long sVersion1_0_0 = 0x1000000f; |
5 |
const char *sVerStr1_0_0 = "1.0.0"; |
6 |
# ifdef OS_NT |
7 |
-static HANDLE *mutexArray = NULL; |
8 |
+static HANDLE mutexArray[ CRYPTO_NUM_LOCKS ]; |
9 |
# else |
10 |
-static pthread_mutex_t *mutexArray = NULL; |
11 |
+static pthread_mutex_t mutexArray[ CRYPTO_NUM_LOCKS ]; |
12 |
# endif |
13 |
|
14 |
+typedef struct { |
15 |
+ int value; |
16 |
+ const char *name; |
17 |
+} SslErrorNames; |
18 |
+ |
19 |
+SslErrorNames sslErrorNames[] = { |
20 |
+ {SSL_ERROR_NONE, " (None)"}, // 0 |
21 |
+ {SSL_ERROR_SSL, " (SSL)"}, // 1 |
22 |
+ {SSL_ERROR_WANT_READ, " (Want_Read)"}, // 2 |
23 |
+ {SSL_ERROR_WANT_WRITE, " (Want_Write)"}, // 3 |
24 |
+ {SSL_ERROR_WANT_X509_LOOKUP, " (Want_X509_Lookup)"}, // 4 |
25 |
+ {SSL_ERROR_SYSCALL, " (Syscall)"}, // 5 |
26 |
+ {SSL_ERROR_ZERO_RETURN, " (Zero_Return)"}, // 6 |
27 |
+ {SSL_ERROR_WANT_CONNECT, " (Want_Connect)"}, // 7 |
28 |
+ {SSL_ERROR_WANT_ACCEPT, " (Want_Accept)"} // 8 |
29 |
+}; |
30 |
+ |
31 |
+const char * |
32 |
+GetSslErrorName(int err) |
33 |
+{ |
34 |
+ if( err < SSL_ERROR_NONE || err > SSL_ERROR_WANT_ACCEPT ) |
35 |
+ return ""; |
36 |
+ |
37 |
+ return sslErrorNames[err].name; |
38 |
+} |
39 |
+ |
40 |
//////////////////////////////////////////////////////////////////////////// |
41 |
// MutexLocker // |
42 |
//////////////////////////////////////////////////////////////////////////// |
43 |
@@ -220,6 +246,147 @@ NetSslTransport::~NetSslTransport() |
44 |
Close(); |
45 |
} |
46 |
|
47 |
+// MS Visual Studio didn't implement snprintf until VS 2015. Sigh. |
48 |
+# ifdef _MSC_VER |
49 |
+ #define SNPRINTF1(buf, len, msg, arg1) sprintf(buf, msg, arg1) |
50 |
+ #define SNPRINTF2(buf, len, msg, arg1, arg2) sprintf(buf, msg, arg1, arg2) |
51 |
+# else |
52 |
+ #define SNPRINTF1(buf, len, msg, arg1) snprintf(buf, len, msg, arg1) |
53 |
+ #define SNPRINTF2(buf, len, msg, arg1, arg2) snprintf(buf, len, msg, arg1, arg2) |
54 |
+# endif |
55 |
+ |
56 |
+SSL_CTX * |
57 |
+NetSslTransport::CreateAndInitializeSslContext(const char *conntypename) |
58 |
+{ |
59 |
+ char msgbuf[128]; |
60 |
+ size_t bufsize = sizeof(msgbuf) - 1; |
61 |
+ |
62 |
+ SNPRINTF1( msgbuf, bufsize, |
63 |
+ "NetSslTransport::Ssl%sInit - Initializing CTX structure.", |
64 |
+ conntypename ); |
65 |
+ TRANSPORT_PRINT_VAR( SSLDEBUG_FUNCTION, msgbuf ); |
66 |
+ |
67 |
+ /* |
68 |
+ * In OpenSSL v1.1.0 we can use |
69 |
+ * TLS_method() |
70 |
+ * SSL_CTX_set_min_proto_version() |
71 |
+ * SSL_CTX_set_max_proto_version() |
72 |
+ * instead of the deprecated |
73 |
+ * SSLv23_method() |
74 |
+ * and the not-recommended |
75 |
+ * SSL_CTX_set_options( SSL_OP_NO_xxx ) |
76 |
+ * but we still build with OpenSSL v1.0.x, so for now we'll stay |
77 |
+ * with the old way of doing things. |
78 |
+ * |
79 |
+ * See https://www.openssl.org/docs/man1.1.0/ssl/SSLv23_method.html |
80 |
+ * Note: |
81 |
+ * "Clients should avoid creating "holes" in the set of protocols they support. |
82 |
+ * When disabling a protocol, make sure that you also disable either all |
83 |
+ * previous or all subsequent protocol versions. In clients, when a protocol |
84 |
+ * version is disabled without disabling all previous protocol versions, |
85 |
+ * the effect is to also disable all subsequent protocol versions." |
86 |
+ */ |
87 |
+ |
88 |
+ /* |
89 |
+ * Start by allowing all protocol versions |
90 |
+ */ |
91 |
+ |
92 |
+ SSL_CTX *ctxp = SSL_CTX_new( SSLv23_method() ); |
93 |
+ SNPRINTF1( msgbuf, bufsize, "NetSslTransport::Ssl%sInit SSL_CTX_new", conntypename ); |
94 |
+ TRANSPORT_PRINT_VAR( SSLDEBUG_FUNCTION, msgbuf ); |
95 |
+ |
96 |
+ SSL_CTX_set_mode( |
97 |
+ ctxp, |
98 |
+ SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); |
99 |
+ SNPRINTF1( msgbuf, bufsize, "NetSslTransport::Ssl%sInit SSL_CTX_set_mode", conntypename ); |
100 |
+ SSLLOGFUNCTION( msgbuf ); |
101 |
+ |
102 |
+ /* |
103 |
+ * Now disable SSLv2 and SSLv3 (but still allow TLSv1.0 and later) |
104 |
+ */ |
105 |
+ |
106 |
+ SSL_CTX_set_options( ctxp, SSL_OP_NO_SSLv2 ); |
107 |
+ SNPRINTF1( msgbuf, bufsize, "NetSslTransport::Ssl%sInit SSL_CTX_set_options(NO_SSLv2)", conntypename ); |
108 |
+ SSLLOGFUNCTION( msgbuf ); |
109 |
+ |
110 |
+ SSL_CTX_set_options( ctxp, SSL_OP_NO_SSLv3 ); |
111 |
+ SNPRINTF1( msgbuf, bufsize, "NetSslTransport::Ssl%sInit SSL_CTX_set_options(NO_SSLv3)", conntypename ); |
112 |
+ SSLLOGFUNCTION( msgbuf ); |
113 |
+ |
114 |
+ /* |
115 |
+ * Let the customer disable any protocols they don't want. |
116 |
+ * Allow only TLS versions in the (closed) range [tlsmin, tlsmax]. |
117 |
+ */ |
118 |
+ int tlsmin = p4tunable.Get( P4TUNE_SSL_TLS_VERSION_MIN ); |
119 |
+ int tlsmax = p4tunable.Get( P4TUNE_SSL_TLS_VERSION_MAX ); |
120 |
+ |
121 |
+ struct TlsVersion { |
122 |
+ int value; // tunable value |
123 |
+ int proto; // OpenSSL protocol version value |
124 |
+ const char *name; // OpenSSL protocol version name |
125 |
+ }; |
126 |
+ |
127 |
+ /* |
128 |
+ * Expand this table if and when new TLS protocol versions are available. |
129 |
+ * This table *must* be ordered by the "value" field |
130 |
+ * and terminated by a "value" of 0. |
131 |
+ */ |
132 |
+ static TlsVersion tlsVersions[] = { |
133 |
+ { 10, SSL_OP_NO_TLSv1, "NO_TLSv1.0" }, |
134 |
+ { 11, SSL_OP_NO_TLSv1_1, "NO_TLSv1.1" }, |
135 |
+ { 12, SSL_OP_NO_TLSv1_2, "NO_TLSv1.2" }, |
136 |
+ { 0, 0, NULL} |
137 |
+ }; |
138 |
+ |
139 |
+ /* |
140 |
+ * Pin the value to the legal range. |
141 |
+ * Update this code if new values are added to tlsVersions[]. |
142 |
+ */ |
143 |
+ if( tlsmin < 10 ) |
144 |
+ tlsmin = 10; |
145 |
+ if( tlsmin > 12 ) |
146 |
+ tlsmin = 12; |
147 |
+ |
148 |
+ if( tlsmax < 10 ) |
149 |
+ tlsmax = 10; |
150 |
+ if( tlsmax > 12 ) |
151 |
+ tlsmax = 12; |
152 |
+ |
153 |
+ if( SSLDEBUG_FUNCTION ) |
154 |
+ { |
155 |
+ p4debug.printf( "NetSslTransport::Ssl%sInit tlsmin=%d, tlsmax=%d\n", |
156 |
+ conntypename, tlsmin, tlsmax ); |
157 |
+ } |
158 |
+ |
159 |
+ // disallow protocols below the requested minimum |
160 |
+ for( TlsVersion *vp = tlsVersions; vp->value; vp++ ) |
161 |
+ { |
162 |
+ if( vp->value < tlsmin ) |
163 |
+ { |
164 |
+ SSL_CTX_set_options( ctxp, vp->proto ); |
165 |
+ SNPRINTF2( msgbuf, bufsize, |
166 |
+ "NetSslTransport::Ssl%sInit SSL_CTX_set_options(%s)", |
167 |
+ conntypename, vp->name ); |
168 |
+ SSLLOGFUNCTION( msgbuf ); |
169 |
+ } |
170 |
+ } |
171 |
+ |
172 |
+ // disallow protocols above the requested maximum |
173 |
+ for( TlsVersion *vp = tlsVersions; vp->value; vp++ ) |
174 |
+ { |
175 |
+ if( vp->value > tlsmax ) |
176 |
+ { |
177 |
+ SSL_CTX_set_options( ctxp, vp->proto ); |
178 |
+ SNPRINTF2( msgbuf, bufsize, |
179 |
+ "NetSslTransport::Ssl%sInit SSL_CTX_set_options(%s)", |
180 |
+ conntypename, vp->name ); |
181 |
+ SSLLOGFUNCTION( msgbuf ); |
182 |
+ } |
183 |
+ } |
184 |
+ |
185 |
+ return ctxp; |
186 |
+} |
187 |
+ |
188 |
/** |
189 |
* NetSslTransport::SslClientInit |
190 |
* |
191 |
@@ -255,10 +422,6 @@ NetSslTransport::SslClientInit(Error *e) |
192 |
return; |
193 |
#endif // OS_NT |
194 |
|
195 |
- TRANSPORT_PRINT( SSLDEBUG_FUNCTION, |
196 |
- "NetSslTransport::SslClientInit - Initializing client CTX structure." ); |
197 |
- |
198 |
- |
199 |
ValidateRuntimeVsCompiletimeSSLVersion( e ); |
200 |
if( e->Test() ) |
201 |
{ |
202 |
@@ -298,15 +461,12 @@ NetSslTransport::SslClientInit(Error *e) |
203 |
|
204 |
// WSAstartup code in NetTcpEndPoint constructor |
205 |
|
206 |
- sClientCtx = SSL_CTX_new( TLSv1_method() ); |
207 |
- SSLNULLHANDLER( sClientCtx, e, |
208 |
- "NetSslTransport::SslClientInit SSL_CTX_new", |
209 |
- fail ); |
210 |
- |
211 |
- SSL_CTX_set_mode( |
212 |
- sClientCtx, |
213 |
- SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); |
214 |
- SSLLOGFUNCTION( "NetSslTransport::SslClientInit SSL_CTX_set_mode" ); |
215 |
+ /* |
216 |
+ * Allow TLSv1.0 and later but disable SSLv2 and SSLv3 |
217 |
+ * - Allow customers to further filter TLS protocol versions |
218 |
+ */ |
219 |
+ if( (sClientCtx = CreateAndInitializeSslContext("Client")) == NULL ) |
220 |
+ goto fail; |
221 |
} |
222 |
return; |
223 |
|
224 |
@@ -362,9 +522,6 @@ NetSslTransport::SslServerInit(StrPtr *h |
225 |
return; |
226 |
#endif // OS_NT |
227 |
|
228 |
- TRANSPORT_PRINT( SSLDEBUG_FUNCTION, |
229 |
- "NetSslTransport::SslServerInit - Initializing server CTX structure." ); |
230 |
- |
231 |
/* |
232 |
* Added due to job084753: Swarm is a web app that reuses client processes. |
233 |
* See the SslClientInit code for more info. |
234 |
@@ -407,17 +564,12 @@ NetSslTransport::SslServerInit(StrPtr *h |
235 |
credentials.ReadCredentials(e); |
236 |
P4CHECKERROR( e, "NetSslTransport::SslServerInit ReadCredentials", fail ); |
237 |
|
238 |
- |
239 |
- sServerCtx = SSL_CTX_new( TLSv1_method() ); |
240 |
- SSLNULLHANDLER( sServerCtx, e, |
241 |
- "NetSslTransport::SslServerInit SSL_CTX_new", |
242 |
- fail ); |
243 |
- |
244 |
- SSL_CTX_set_mode( |
245 |
- sServerCtx, |
246 |
- SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); |
247 |
- SSLLOGFUNCTION( "NetSslTransport::SslServerInit SSL_CTX_set_mode" ); |
248 |
- |
249 |
+ /* |
250 |
+ * Allow TLSv1.0 and later but disable SSLv2 and SSLv3 |
251 |
+ * - Allow customers to further filter TLS protocol versions |
252 |
+ */ |
253 |
+ if( (sServerCtx = CreateAndInitializeSslContext("Server")) == NULL ) |
254 |
+ goto fail; |
255 |
|
256 |
SSL_CTX_use_PrivateKey( sServerCtx, credentials.GetPrivateKey() ); |
257 |
SSLLOGFUNCTION( |
258 |
@@ -471,8 +623,6 @@ fail: |
259 |
void |
260 |
NetSslTransport::DoHandshake( Error *e ) |
261 |
{ |
262 |
- int sslRetval; |
263 |
- |
264 |
if(ssl) |
265 |
return; |
266 |
|
267 |
@@ -624,8 +774,8 @@ bool |
268 |
NetSslTransport::SslHandshake( Error *e ) |
269 |
{ |
270 |
bool done = false; |
271 |
- int readable = isAccepted? 1 : 0; |
272 |
- int writable = isAccepted? 0 : 1; |
273 |
+ int readable; |
274 |
+ int writable; |
275 |
int counter = 0; |
276 |
/* select timeout */ |
277 |
const int tv = HALF_SECOND; |
278 |
@@ -651,6 +801,8 @@ NetSslTransport::SslHandshake( Error *e |
279 |
{ |
280 |
case SSL_ERROR_NONE: |
281 |
done = true; |
282 |
+ TRANSPORT_PRINTF( SSLDEBUG_CONNECT, |
283 |
+ "NetSslTransport::SslHandshake protocol=%s", SSL_get_version(ssl) ); |
284 |
break; |
285 |
|
286 |
case SSL_ERROR_WANT_READ: |
287 |
@@ -730,10 +882,12 @@ NetSslTransport::SslHandshake( Error *e |
288 |
/* underlying protocol error dump error to |
289 |
* debug output |
290 |
*/ |
291 |
- char sslError[256]; |
292 |
- ERR_error_string( ERR_get_error(), sslError ); |
293 |
- TRANSPORT_PRINTF( SSLDEBUG_ERROR, "Handshake Failed: %s", sslError ); |
294 |
- e->Net( "ssl handshake", sslError); |
295 |
+ |
296 |
+ // buffer for ssl protocol errors |
297 |
+ char sslErrorBuf[256]; |
298 |
+ ERR_error_string( ERR_get_error(), sslErrorBuf ); |
299 |
+ TRANSPORT_PRINTF( SSLDEBUG_ERROR, "Handshake Failed: %s", sslErrorBuf ); |
300 |
+ e->Set( MsgRpc::SslProtocolError ) << sslErrorBuf; |
301 |
return false; |
302 |
break; |
303 |
default: |
304 |
@@ -746,18 +900,26 @@ NetSslTransport::SslHandshake( Error *e |
305 |
errBuf.Append( &tmp ); |
306 |
errBuf.Append( ")" ); |
307 |
} |
308 |
+ else |
309 |
+ { |
310 |
+ StrBuf tmp; |
311 |
+ Error::StrError( tmp ); |
312 |
+ errBuf.Set( " (" ); |
313 |
+ errBuf.Append( &tmp ); |
314 |
+ errBuf.Append( ")" ); |
315 |
+ } |
316 |
if( isAccepted ) |
317 |
{ |
318 |
TRANSPORT_PRINTF( SSLDEBUG_ERROR, |
319 |
- "NetSslTransport::SslHandshake failed on server side: %d", |
320 |
- errorRet ); |
321 |
+ "NetSslTransport::SslHandshake failed on server side: %d%s", |
322 |
+ errorRet, GetSslErrorName(errorRet) ); |
323 |
e->Set( MsgRpc::SslAccept) << errBuf; |
324 |
} |
325 |
else |
326 |
{ |
327 |
TRANSPORT_PRINTF( SSLDEBUG_ERROR, |
328 |
- "NetSslTransport::SslHandshake failed on client side: %d", |
329 |
- errorRet); |
330 |
+ "NetSslTransport::SslHandshake failed on client side: %d%s", |
331 |
+ errorRet, GetSslErrorName(errorRet) ); |
332 |
e->Set( MsgRpc::SslConnect) << GetPortParser().String() << errBuf; |
333 |
} |
334 |
return false; |
335 |
@@ -819,10 +981,6 @@ NetSslTransport::SendOrReceive( NetIoPtr |
336 |
int readable = 0; |
337 |
int writable = 0; |
338 |
|
339 |
- /* flags set by check_availability( ) that poll for I/O status */ |
340 |
- bool can_read = false; |
341 |
- bool can_write = false; |
342 |
- |
343 |
/* flags to mark all the combinations of why we're blocking */ |
344 |
bool read_waiton_write = false; |
345 |
bool read_waiton_read = false; |
346 |
@@ -843,17 +1001,13 @@ NetSslTransport::SendOrReceive( NetIoPtr |
347 |
{ |
348 |
DoHandshake( se ); |
349 |
if( se->Test() ) |
350 |
- { |
351 |
- re = se; |
352 |
goto end; |
353 |
- } |
354 |
} |
355 |
|
356 |
for ( ;; ) |
357 |
{ |
358 |
doRead = io.recvPtr != io.recvEnd && !re->Test(); |
359 |
doWrite = io.sendPtr != io.sendEnd && !se->Test(); |
360 |
- sslPending = 0; |
361 |
|
362 |
if( !doRead && !doWrite ) |
363 |
{ |
364 |
@@ -892,7 +1046,15 @@ NetSslTransport::SendOrReceive( NetIoPtr |
365 |
if (readable && sslPending) |
366 |
tv = 0; |
367 |
else if( (readable && breakCallback) || maxwait ) |
368 |
+ { |
369 |
tv = HALF_SECOND; |
370 |
+ if( breakCallback ) |
371 |
+ { |
372 |
+ int p = breakCallback->PollMs(); |
373 |
+ if( p >= 1 ) |
374 |
+ tv = p; |
375 |
+ } |
376 |
+ } |
377 |
else |
378 |
tv = -1; |
379 |
|
380 |
@@ -1222,7 +1384,6 @@ end: |
381 |
void |
382 |
NetSslTransport::Close( void ) |
383 |
{ |
384 |
- int ret; |
385 |
if( t < 0 ) |
386 |
return; |
387 |
|
388 |
@@ -1476,23 +1637,7 @@ static void DynDestroyFunction( |
389 |
|
390 |
static int InitLockCallbacks( Error *e ) |
391 |
{ |
392 |
- int i; |
393 |
- int numlocks = CRYPTO_num_locks(); |
394 |
- |
395 |
- /* static locks area */ |
396 |
-# ifdef OS_NT |
397 |
- mutexArray = (HANDLE *) malloc( CRYPTO_num_locks() * sizeof(HANDLE) ); |
398 |
-# else |
399 |
- mutexArray = (pthread_mutex_t *) malloc( CRYPTO_num_locks() * sizeof(pthread_mutex_t) ); |
400 |
-# endif // OS_NT |
401 |
- |
402 |
- if( mutexArray == NULL ) |
403 |
- { |
404 |
- e->Set(MsgRpc::Operat) << "malloc"; |
405 |
- return -1; |
406 |
- } |
407 |
- |
408 |
- for ( i = 0; i < numlocks; i++ ) |
409 |
+ for ( int i = 0; i < CRYPTO_num_locks(); i++ ) |
410 |
{ |
411 |
# ifdef OS_NT |
412 |
mutexArray[i] = CreateMutex( NULL, FALSE, NULL ); |
413 |
@@ -1516,16 +1661,8 @@ static int InitLockCallbacks( Error *e ) |
414 |
* |
415 |
* @return 0 |
416 |
*/ |
417 |
-static int ShudownLockCallbacks( void ) |
418 |
+static int ShutdownLockCallbacks( void ) |
419 |
{ |
420 |
- int i; |
421 |
- int numlocks = CRYPTO_num_locks(); |
422 |
- |
423 |
- if( mutexArray == NULL ) |
424 |
- { |
425 |
- return (0); |
426 |
- } |
427 |
- |
428 |
CRYPTO_set_dynlock_create_callback( NULL ); |
429 |
CRYPTO_set_dynlock_lock_callback( NULL ); |
430 |
CRYPTO_set_dynlock_destroy_callback( NULL ); |
431 |
@@ -1533,7 +1670,7 @@ static int ShudownLockCallbacks( void ) |
432 |
CRYPTO_set_locking_callback( NULL ); |
433 |
CRYPTO_set_id_callback( NULL ); |
434 |
|
435 |
- for ( i = 0; i < numlocks; i++ ) |
436 |
+ for ( int i = 0; i < CRYPTO_num_locks(); i++ ) |
437 |
{ |
438 |
# ifdef OS_NT |
439 |
CloseHandle( mutexArray[i] ); |