@@ -69,25 +69,29 @@ ssl_error_server (void *ptr)
69
69
ssl_stream = mongoc_stream_tls_new (sock_stream , data -> server , 0 );
70
70
assert (ssl_stream );
71
71
72
- if (data -> behavior != SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE ) {
72
+ switch (data -> behavior ) {
73
+ case SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE :
74
+ usleep (data -> handshake_stall_ms * 1000 );
75
+ break ;
76
+ case SSL_TEST_BEHAVIOR_HANGUP_AFTER_HANDSHAKE :
73
77
r = mongoc_stream_tls_do_handshake (ssl_stream , TIMEOUT );
74
78
assert (r );
75
79
76
80
r = mongoc_stream_readv (ssl_stream , & iov , 1 , 1 , TIMEOUT );
77
81
assert (r == 1 );
78
-
79
- /* this test function only implements two behaviors so far */
80
- ASSERT_CMPINT (data -> behavior ,
81
- = = ,
82
- SSL_TEST_BEHAVIOR_HANGUP_AFTER_HANDSHAKE );
83
-
84
- mongoc_stream_close (ssl_stream );
85
- mongoc_stream_destroy (ssl_stream );
86
- mongoc_socket_destroy (listen_sock );
82
+ break ;
83
+ case SSL_TEST_BEHAVIOR_NORMAL :
84
+ default :
85
+ fprintf (stderr , "unimplemented ssl_test_behavior_t\n" );
86
+ abort ();
87
87
}
88
88
89
89
data -> server_result -> result = SSL_TEST_SUCCESS ;
90
90
91
+ mongoc_stream_close (ssl_stream );
92
+ mongoc_stream_destroy (ssl_stream );
93
+ mongoc_socket_destroy (listen_sock );
94
+
91
95
return NULL ;
92
96
}
93
97
@@ -206,8 +210,118 @@ test_mongoc_tls_hangup (void)
206
210
ASSERT (sr .result == SSL_TEST_SUCCESS );
207
211
}
208
212
213
+
214
+ /** run as a child thread by test_mongoc_tls_handshake_stall
215
+ *
216
+ * It:
217
+ * 1. spins up
218
+ * 2. waits on a condvar until the server is up
219
+ * 3. connects to the server's port
220
+ * 4. attempts handshake
221
+ * 5. confirms that it times out
222
+ * 6. shuts down
223
+ */
224
+ static void *
225
+ handshake_stall_client (void * ptr )
226
+ {
227
+ ssl_test_data_t * data = (ssl_test_data_t * )ptr ;
228
+ char * uri_str ;
229
+ mongoc_client_t * client ;
230
+ bson_t reply ;
231
+ bson_error_t error ;
232
+ int64_t connect_timeout_ms = data -> handshake_stall_ms - 100 ;
233
+ int64_t duration_ms ;
234
+
235
+ int64_t start_time ;
236
+
237
+ mongoc_mutex_lock (& data -> cond_mutex );
238
+ while (!data -> server_port ) {
239
+ mongoc_cond_wait (& data -> cond , & data -> cond_mutex );
240
+ }
241
+ mongoc_mutex_unlock (& data -> cond_mutex );
242
+
243
+ uri_str = bson_strdup_printf (
244
+ "mongodb://localhost:%u/?ssl=true&connecttimeoutms=%" PRId64 ,
245
+ data -> server_port , connect_timeout_ms );
246
+
247
+ client = mongoc_client_new (uri_str );
248
+
249
+ /* we should time out after about 200ms */
250
+ start_time = bson_get_monotonic_time ();
251
+ mongoc_client_get_server_status (client ,
252
+ NULL ,
253
+ & reply ,
254
+ & error );
255
+
256
+ /* time is in microseconds */
257
+ duration_ms = (bson_get_monotonic_time () - start_time ) / 1000 ;
258
+
259
+ if (llabs (duration_ms - connect_timeout_ms ) > 100 ) {
260
+ fprintf (stderr ,
261
+ "expected timeout after about 200ms, not %" PRId64 "\n" ,
262
+ duration_ms );
263
+ abort ();
264
+ }
265
+
266
+ data -> client_result -> result = SSL_TEST_SUCCESS ;
267
+
268
+ bson_destroy (& reply );
269
+ mongoc_client_destroy (client );
270
+ bson_free (uri_str );
271
+
272
+ return NULL ;
273
+ }
274
+
275
+
276
+ static void
277
+ test_mongoc_tls_handshake_stall (void )
278
+ {
279
+ mongoc_ssl_opt_t sopt = { 0 };
280
+ mongoc_ssl_opt_t copt = { 0 };
281
+ ssl_test_result_t sr ;
282
+ ssl_test_result_t cr ;
283
+ ssl_test_data_t data = { 0 };
284
+ mongoc_thread_t threads [2 ];
285
+ int i , r ;
286
+
287
+ sopt .pem_file = PEMFILE_NOPASS ;
288
+ sopt .weak_cert_validation = 1 ;
289
+ copt .weak_cert_validation = 1 ;
290
+
291
+ data .server = & sopt ;
292
+ data .client = & copt ;
293
+ data .behavior = SSL_TEST_BEHAVIOR_STALL_BEFORE_HANDSHAKE ;
294
+ data .handshake_stall_ms = 300 ;
295
+ data .server_result = & sr ;
296
+ data .client_result = & cr ;
297
+ data .host = "localhost" ;
298
+
299
+ mongoc_mutex_init (& data .cond_mutex );
300
+ mongoc_cond_init (& data .cond );
301
+
302
+ r = mongoc_thread_create (threads , & ssl_error_server , & data );
303
+ assert (r == 0 );
304
+
305
+ r =
306
+ mongoc_thread_create (threads + 1 , & handshake_stall_client , & data );
307
+ assert (r == 0 );
308
+
309
+ for (i = 0 ; i < 2 ; i ++ ) {
310
+ r = mongoc_thread_join (threads [i ]);
311
+ assert (r == 0 );
312
+ }
313
+
314
+ mongoc_mutex_destroy (& data .cond_mutex );
315
+ mongoc_cond_destroy (& data .cond );
316
+
317
+ ASSERT (cr .result == SSL_TEST_SUCCESS );
318
+ ASSERT (sr .result == SSL_TEST_SUCCESS );
319
+ }
320
+
209
321
void
210
322
test_stream_tls_error_install (TestSuite * suite )
211
323
{
212
324
TestSuite_Add (suite , "/TLS/hangup" , test_mongoc_tls_hangup );
325
+ TestSuite_Add (suite , "/TLS/handshake_stall" ,
326
+ test_mongoc_tls_handshake_stall );
213
327
}
0 commit comments