View | Details | Raw Unified | Return to bug 229021 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile (-1 / +1 lines)
Lines 3-9 Link Here
3
3
4
PORTNAME=	p4
4
PORTNAME=	p4
5
PORTVERSION=	${YEAR}.${MAJOR}.${MINOR}
5
PORTVERSION=	${YEAR}.${MAJOR}.${MINOR}
6
PORTREVISION=	2
6
PORTREVISION=	3
7
CATEGORIES=	devel
7
CATEGORIES=	devel
8
# Perforce stupidly rerolls their distfiles on a regular basis, updating the
8
# Perforce stupidly rerolls their distfiles on a regular basis, updating the
9
# files' timestamps when they do, which changes the zip file's checksum.  Work
9
# files' timestamps when they do, which changes the zip file's checksum.  Work
(-)files/patch-netssltransport.cc (+439 lines)
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] );

Return to bug 229021