@@ -484,6 +484,134 @@ test_mongoc_client_authenticate (void *context)
484484}
485485
486486
487+ static void
488+ test_mongoc_client_speculative_auth_failure (bool pooled )
489+ {
490+ mongoc_client_t * admin_client ;
491+ char * username ;
492+ bson_t roles ;
493+ mongoc_database_t * database ;
494+ char * uri_str_no_auth ;
495+ char * uri_str_auth ;
496+ mongoc_collection_t * collection ;
497+ mongoc_client_t * auth_client ;
498+ mongoc_client_pool_t * pool ;
499+ mongoc_uri_t * uri ;
500+ mongoc_cursor_t * cursor ;
501+ const bson_t * doc ;
502+ bson_error_t error ;
503+ bool r ;
504+ bson_t q ;
505+
506+ /*
507+ * Log in as admin.
508+ */
509+ admin_client = test_framework_client_new ();
510+
511+ /*
512+ * Add a user to the test database.
513+ */
514+ username = gen_test_user ();
515+ database = mongoc_client_get_database (admin_client , "test" );
516+ (void ) mongoc_database_remove_user (database , username , & error );
517+ bson_init (& roles );
518+ BCON_APPEND (& roles , "0" , "{" , "role" , "read" , "db" , "test" , "}" );
519+
520+ r = mongoc_database_add_user (database ,
521+ username ,
522+ "testpass" ,
523+ tmp_bson ("[{'role': 'read', 'db': 'test'}]" ),
524+ NULL ,
525+ & error );
526+
527+ ASSERT_OR_PRINT (r , error );
528+ mongoc_database_destroy (database );
529+
530+ bson_init (& q );
531+ uri_str_no_auth = test_framework_get_uri_str_no_auth ("test" );
532+ uri_str_auth =
533+ test_framework_add_user_password (uri_str_no_auth , username , "testpass" );
534+
535+ if (pooled ) {
536+ uri = mongoc_uri_new (uri_str_auth );
537+ pool = mongoc_client_pool_new (uri );
538+ mongoc_uri_destroy (uri );
539+
540+ test_framework_set_pool_ssl_opts (pool );
541+ auth_client = mongoc_client_pool_pop (pool );
542+ } else {
543+ auth_client = mongoc_client_new (uri_str_auth );
544+ test_framework_set_ssl_opts (auth_client );
545+ }
546+
547+ collection = mongoc_client_get_collection (auth_client , "test" , "test" );
548+
549+ database = mongoc_client_get_database (admin_client , "admin" );
550+
551+ /* Enable failpoint to break saslContinue */
552+ r = mongoc_database_command_simple (
553+ database ,
554+ tmp_bson ("{'configureFailPoint': 'failCommand', "
555+ "'mode': {'times': 1}, "
556+ "'data': {'failCommands': ['saslContinue'], 'closeConnection': "
557+ "true, 'errorCode': 10107}}" ),
558+ NULL ,
559+ NULL ,
560+ & error );
561+ ASSERT_OR_PRINT (r , error );
562+ mongoc_database_destroy (database );
563+
564+ /* Try authenticating by running a find operation */
565+ cursor = mongoc_collection_find_with_opts (collection , & q , NULL , NULL );
566+ r = mongoc_cursor_next (cursor , & doc );
567+ if (!r ) {
568+ r = mongoc_cursor_error (cursor , & error );
569+ BSON_ASSERT (r );
570+ ASSERT_ERROR_CONTAINS (error ,
571+ MONGOC_ERROR_CLIENT ,
572+ MONGOC_ERROR_CLIENT_AUTHENTICATE ,
573+ "Failed to send \"saslContinue\" command" );
574+ }
575+
576+ mongoc_cursor_destroy (cursor );
577+ mongoc_collection_destroy (collection );
578+
579+ if (pooled ) {
580+ mongoc_client_pool_push (pool , auth_client );
581+ mongoc_client_pool_destroy (pool );
582+ } else {
583+ mongoc_client_destroy (auth_client );
584+ }
585+
586+ /*
587+ * Remove all test users.
588+ */
589+ database = mongoc_client_get_database (admin_client , "test" );
590+ r = mongoc_database_remove_all_users (database , & error );
591+ BSON_ASSERT (r );
592+
593+ bson_destroy (& q );
594+ bson_free (uri_str_no_auth );
595+ bson_free (uri_str_auth );
596+ bson_destroy (& roles );
597+ bson_free (username );
598+ mongoc_database_destroy (database );
599+ mongoc_client_destroy (admin_client );
600+ }
601+
602+ static void
603+ test_mongoc_client_single_speculative_auth_failure (void * context )
604+ {
605+ test_mongoc_client_speculative_auth_failure (false);
606+ }
607+
608+ static void
609+ test_mongoc_client_pooled_speculative_auth_failure (void * context )
610+ {
611+ test_mongoc_client_speculative_auth_failure (true);
612+ }
613+
614+
487615static void
488616test_mongoc_client_authenticate_cached (bool pooled )
489617{
@@ -3857,6 +3985,20 @@ test_client_install (TestSuite *suite)
38573985 NULL ,
38583986 NULL ,
38593987 test_framework_skip_if_no_auth );
3988+ TestSuite_AddFull (suite ,
3989+ "/Client/speculative_auth_failure/single" ,
3990+ test_mongoc_client_single_speculative_auth_failure ,
3991+ NULL ,
3992+ NULL ,
3993+ test_framework_skip_if_no_auth ,
3994+ test_framework_skip_if_no_failpoint );
3995+ TestSuite_AddFull (suite ,
3996+ "/Client/speculative_auth_failure/pooled" ,
3997+ test_mongoc_client_pooled_speculative_auth_failure ,
3998+ NULL ,
3999+ NULL ,
4000+ test_framework_skip_if_no_auth ,
4001+ test_framework_skip_if_no_failpoint );
38604002 TestSuite_AddFull (suite ,
38614003 "/Client/authenticate_cached/pool" ,
38624004 test_mongoc_client_authenticate_cached_pooled ,
0 commit comments