Skip to content

Commit e657c13

Browse files
committed
CDRIVER-3934 Correctly handle network errors during speculative authentication (#791)
* CDRIVER-3934 Correctly handle network errors during speculative authentication * Assert request before getting memory failure * Fix code review feedback
1 parent e87cc77 commit e657c13

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed

src/libmongoc/src/mongoc/mongoc-cluster.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2426,6 +2426,12 @@ mongoc_cluster_fetch_stream_single (mongoc_cluster_t *cluster,
24262426
_mongoc_scram_destroy (&scanner_node->scram);
24272427
#endif
24282428

2429+
if (!scanner_node->stream) {
2430+
memcpy (error, &sd->error, sizeof *error);
2431+
mongoc_server_description_destroy (sd);
2432+
return NULL;
2433+
}
2434+
24292435
if (!has_speculative_auth &&
24302436
!_mongoc_cluster_auth_node (cluster,
24312437
scanner_node->stream,

src/libmongoc/tests/test-mongoc-change-stream.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,12 +776,14 @@ test_change_stream_resumable_error (void)
776776
"db",
777777
MONGOC_QUERY_SLAVE_OK,
778778
"{ 'getMore': 123, 'collection': 'coll' }");
779+
BSON_ASSERT (request);
779780
mock_server_hangs_up (request);
780781
request_destroy (request);
781782

782783
/* Retry command */
783784
request = mock_server_receives_command (
784785
server, "db", MONGOC_QUERY_SLAVE_OK, watch_cmd);
786+
BSON_ASSERT (request);
785787
mock_server_replies_simple (
786788
request,
787789
"{'cursor': {'id': 124,'ns': 'db.coll','firstBatch': []},'ok': 1 }");

src/libmongoc/tests/test-mongoc-client.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
487615
static void
488616
test_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

Comments
 (0)