Skip to content

Commit 2ea7749

Browse files
authored
CDRIVER-4489 revert aggressive validation of credential field requirements (#1952)
1 parent 6e2a3d8 commit 2ea7749

File tree

4 files changed

+50
-159
lines changed

4 files changed

+50
-159
lines changed

Diff for: NEWS

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ Unreleased (2.0.0)
1010
* `mongoc_server_description_host` changes the return type from `mongoc_host_list_t *` to `const mongoc_host_list_t *`.
1111
* URI authentication credentials validation (only applicable during creation of a new `mongoc_uri_t` object from a connection string):
1212
* The requirement that a username is non-empty when specified is now enforced regardless of authentication mechanism.
13+
* Username and password specification requirements are now validated and returns a client error for the specified authentication mechanism.
14+
* e.g. it is a client error to not specify a username or a password for SCRAM-SHA-1, SCRAM-SHA-256, and PLAIN.
15+
* e.g. it is a client error to specify a password for MONGODB-X509.
16+
* e.g. it is a client error to specify a username or a password without the other for MONGODB-AWS.
1317
* `authSource` is now correctly defaulted to `"$external"` for MONGODB-AWS (instead of the database name or `"admin"`).
1418
* `authMechanism` is now validated and returns a client error for invalid or unsupported values.
15-
* Requirements for the inclusion, exclusion, and supported values of authentication-related URI components (e.g. username and password), options (e.g. `authSource`), and mechanism properties (e.g. `authMechanismProperties` and its key-value pairs) are now validated and return a client error when able for invalid or unsupported configurations according to the specified authentication mechanism (`authMechanism`).
19+
* `authMechanismProperties` is now validated and returns a client error for invalid or unsupported properties for the specified authentication mechanism.
1620
* `authMechanismProperties` now correctly supports `':'` within property values.
1721
* Old behavior: `authMechanismProperties=A:B,C:D:E,F:G` is parsed as `{'A': 'B', 'C': 'D:E,F:G'}`.
1822
* New behavior: `authMechanismProperties=A:B,C:D:E,F:G` is parsed as `{'A': 'B': 'C': 'D:E', 'F': 'G'}`.

Diff for: src/libmongoc/src/mongoc/mongoc-uri.c

+27-56
Original file line numberDiff line numberDiff line change
@@ -1360,14 +1360,17 @@ _finalize_auth_username (const char *username,
13601360
}
13611361

13621362
static bool
1363-
_finalize_auth_source_external_required (const char *source, const char *mechanism, bson_error_t *error)
1363+
_finalize_auth_source_external (const char *source, const char *mechanism, bson_error_t *error)
13641364
{
13651365
BSON_OPTIONAL_PARAM (source);
13661366
BSON_ASSERT_PARAM (mechanism);
13671367
BSON_OPTIONAL_PARAM (error);
13681368

1369-
if (!source || strcasecmp (source, "$external") != 0) {
1370-
MONGOC_URI_ERROR (error, "'%s' authentication mechanism requires \"$external\" authSource", mechanism);
1369+
if (source && strcasecmp (source, "$external") != 0) {
1370+
MONGOC_URI_ERROR (error,
1371+
"'%s' authentication mechanism requires \"$external\" authSource, but \"%s\" was specified",
1372+
mechanism,
1373+
source);
13711374
return false;
13721375
}
13731376

@@ -1408,23 +1411,6 @@ _finalize_auth_password (const char *password,
14081411
return true;
14091412
}
14101413

1411-
static bool
1412-
_finalize_auth_mechanism_properties_prohibited (const bson_t *mechanism_properties,
1413-
const char *mechanism,
1414-
bson_error_t *error)
1415-
{
1416-
BSON_OPTIONAL_PARAM (mechanism_properties);
1417-
BSON_ASSERT_PARAM (mechanism);
1418-
BSON_OPTIONAL_PARAM (error);
1419-
1420-
if (mechanism_properties) {
1421-
MONGOC_URI_ERROR (error, "'%s' authentication mechanism does not accept mechanism properties", mechanism);
1422-
return false;
1423-
}
1424-
1425-
return true;
1426-
}
1427-
14281414
typedef struct __supported_mechanism_properties {
14291415
const char *name;
14301416
bson_type_t type;
@@ -1536,6 +1522,13 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
15361522
BSON_ASSERT_PARAM (uri);
15371523
BSON_OPTIONAL_PARAM (error);
15381524

1525+
// Most validation of MongoCredential fields below according to the Authentication spec must be deferred to the
1526+
// implementation of the Authentication Handshake algorithm (i.e. `_mongoc_cluster_auth_node`) due to support for
1527+
// partial and late setting of credential fields via `mongoc_uri_set_*` functions. Limit validation to requirements
1528+
// for individual field which are explicitly specified. Do not validate requirements on fields in relation to one
1529+
// another (e.g. "given field A, field B must..."). The username, password, and authSource credential fields are
1530+
// exceptions to this rule for both backward compatibility and spec test compliance.
1531+
15391532
bool ret = false;
15401533

15411534
bson_iter_t iter;
@@ -1591,9 +1584,7 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
15911584
goto fail;
15921585
}
15931586

1594-
// Defer validation of `MongoCredential` fields to `_mongoc_cluster_auth_node` during handshake according to
1595-
// `saslSupportedMechs`. Defaults for `MongoCredential.source` is handled by `mongoc_uri_get_auth_source` for
1596-
// backward compatibility.
1587+
// Defer remaining validation of `MongoCredential` fields to Authentication Handshake.
15971588
}
15981589

15991590
// SCRAM-SHA-1, SCRAM-SHA-256, and PLAIN (same validation requirements)
@@ -1604,21 +1595,12 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
16041595
goto fail;
16051596
}
16061597

1607-
// Authentication spec: source: MUST be specified. Defaults to the database name if
1608-
// supplied on the connection string or:
1609-
// - "admin" (for SCRAM-SHA-1 and SCRAM-SHA-256).
1610-
// - "$external" (for PLAIN).
1611-
// Handled by `mongoc_uri_get_auth_source` for backward compatibility.
1612-
16131598
// Authentication spec: password: MUST be specified.
16141599
if (!_finalize_auth_password (password, mechanism, _mongoc_uri_finalize_required, error)) {
16151600
goto fail;
16161601
}
16171602

1618-
// Authentication spec: mechanism_properties: MUST NOT be specified.
1619-
if (!_finalize_auth_mechanism_properties_prohibited (mechanism_properties, mechanism, error)) {
1620-
goto fail;
1621-
}
1603+
// Defer remaining validation of `MongoCredential` fields to Authentication Handshake.
16221604
}
16231605

16241606
// MONGODB-X509
@@ -1630,6 +1612,11 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
16301612
goto fail;
16311613
}
16321614

1615+
// Authentication spec: password: MUST NOT be specified.
1616+
if (!_finalize_auth_password (password, mechanism, _mongoc_uri_finalize_prohibited, error)) {
1617+
goto fail;
1618+
}
1619+
16331620
// Authentication spec: source: MUST be "$external" and defaults to "$external".
16341621
if (!source) {
16351622
bsonBuildAppend (uri->credentials, kv (MONGOC_URI_AUTHSOURCE, cstr ("$external")));
@@ -1640,19 +1627,11 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
16401627
bsonBuildError);
16411628
goto fail;
16421629
}
1643-
} else if (!_finalize_auth_source_external_required (source, mechanism, error)) {
1630+
} else if (!_finalize_auth_source_external (source, mechanism, error)) {
16441631
goto fail;
16451632
}
16461633

1647-
// Authentication spec: password: MUST NOT be specified.
1648-
if (!_finalize_auth_password (password, mechanism, _mongoc_uri_finalize_prohibited, error)) {
1649-
goto fail;
1650-
}
1651-
1652-
// Authentication spec: mechanism_properties: MUST NOT be specified.
1653-
if (!_finalize_auth_mechanism_properties_prohibited (mechanism_properties, mechanism, error)) {
1654-
goto fail;
1655-
}
1634+
// Defer remaining validation of `MongoCredential` fields to Authentication Handshake.
16561635
}
16571636

16581637
// GSSAPI
@@ -1672,7 +1651,7 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
16721651
bsonBuildError);
16731652
goto fail;
16741653
}
1675-
} else if (!_finalize_auth_source_external_required (source, mechanism, error)) {
1654+
} else if (!_finalize_auth_source_external (source, mechanism, error)) {
16761655
goto fail;
16771656
}
16781657

@@ -1721,6 +1700,8 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
17211700
goto fail;
17221701
}
17231702
}
1703+
1704+
// Defer remaining validation of `MongoCredential` fields to Authentication Handshake.
17241705
}
17251706

17261707
// MONGODB-AWS
@@ -1740,7 +1721,7 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
17401721
bsonBuildError);
17411722
goto fail;
17421723
}
1743-
} else if (!_finalize_auth_source_external_required (source, mechanism, error)) {
1724+
} else if (!_finalize_auth_source_external (source, mechanism, error)) {
17441725
goto fail;
17451726
}
17461727

@@ -1762,17 +1743,7 @@ mongoc_uri_finalize_auth (mongoc_uri_t *uri, bson_error_t *error)
17621743
goto fail;
17631744
}
17641745

1765-
// Authentication spec: if *only* a session token is provided, Drivers MUST raise an error.
1766-
if (!username && mechanism_properties) {
1767-
bson_iter_t iter;
1768-
if (bson_iter_init_find_case (&iter, mechanism_properties, "AWS_SESSION_TOKEN")) {
1769-
MONGOC_URI_ERROR (error,
1770-
"%s",
1771-
"'MONGODB-AWS' authentication mechanism requires AWS_SESSION_TOKEN to be accompanied by "
1772-
"a username and a password");
1773-
goto fail;
1774-
}
1775-
}
1746+
// Defer remaining validation of `MongoCredential` fields to Authentication Handshake.
17761747
}
17771748

17781749
// Invalid or unsupported authentication mechanism.

Diff for: src/libmongoc/tests/test-mongoc-aws.c

+10-11
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ test_obtain_credentials (void *unused)
2828
BSON_UNUSED (unused);
2929

3030
/* A username specified with a password is parsed correctly. */
31-
uri = mongoc_uri_new_with_error ("mongodb://access_key_id:secret_access_key@localhost/", &error);
31+
uri = mongoc_uri_new_with_error ("mongodb://access_key_id:secret_access_key@localhost/?authMechanism=MONGODB-AWS",
32+
&error);
3233
ASSERT_OR_PRINT (uri, error);
33-
ASSERT (mongoc_uri_set_auth_mechanism (uri, "MONGODB-AWS"));
3434
ret = _mongoc_aws_credentials_obtain (uri, &creds, &error);
3535
ASSERT_OR_PRINT (ret, error);
3636
ASSERT_CMPSTR (creds.access_key_id, "access_key_id");
@@ -40,9 +40,8 @@ test_obtain_credentials (void *unused)
4040
mongoc_uri_destroy (uri);
4141

4242
/* A username specified with no password is an error. */
43-
uri = mongoc_uri_new_with_error ("mongodb://access_key_id:@localhost/", &error);
43+
uri = mongoc_uri_new_with_error ("mongodb://access_key_id:@localhost/?authMechanism=MONGODB-AWS", &error);
4444
ASSERT_OR_PRINT (uri, error);
45-
ASSERT (mongoc_uri_set_auth_mechanism (uri, "MONGODB-AWS"));
4645
ret = _mongoc_aws_credentials_obtain (uri, &creds, &error);
4746
ASSERT (!ret);
4847
ASSERT_ERROR_CONTAINS (error,
@@ -53,9 +52,9 @@ test_obtain_credentials (void *unused)
5352
mongoc_uri_destroy (uri);
5453

5554
/* Password not set at all (not empty string) */
56-
uri = mongoc_uri_new_with_error ("mongodb://access_key_id@localhost/", &error);
55+
uri = mongoc_uri_new_with_error ("mongodb://localhost/?authMechanism=MONGODB-AWS", &error);
56+
ASSERT (mongoc_uri_set_username (uri, "access_key_id"));
5757
ASSERT_OR_PRINT (uri, error);
58-
ASSERT (mongoc_uri_set_auth_mechanism (uri, "MONGODB-AWS"));
5958
ret = _mongoc_aws_credentials_obtain (uri, &creds, &error);
6059
ASSERT (!ret);
6160
ASSERT_ERROR_CONTAINS (error,
@@ -67,10 +66,10 @@ test_obtain_credentials (void *unused)
6766

6867
/* A session token may be set through the AWS_SESSION_TOKEN auth mechanism
6968
* property */
70-
uri = mongoc_uri_new_with_error (
71-
"mongodb://access_key_id:secret_access_key@localhost/?authMechanismProperties=AWS_SESSION_TOKEN:token", &error);
69+
uri = mongoc_uri_new_with_error ("mongodb://access_key_id:secret_access_key@localhost/"
70+
"?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:token",
71+
&error);
7272
ASSERT_OR_PRINT (uri, error);
73-
ASSERT (mongoc_uri_set_auth_mechanism (uri, "MONGODB-AWS"));
7473
ret = _mongoc_aws_credentials_obtain (uri, &creds, &error);
7574
ASSERT_OR_PRINT (ret, error);
7675
ASSERT_CMPSTR (creds.access_key_id, "access_key_id");
@@ -80,9 +79,9 @@ test_obtain_credentials (void *unused)
8079
mongoc_uri_destroy (uri);
8180

8281
/* A session token in the URI with no username/password is an error. */
83-
uri = mongoc_uri_new_with_error ("mongodb://localhost/?authMechanismProperties=AWS_SESSION_TOKEN:token", &error);
82+
uri = mongoc_uri_new_with_error (
83+
"mongodb://localhost/?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:token", &error);
8484
ASSERT_OR_PRINT (uri, error);
85-
ASSERT (mongoc_uri_set_auth_mechanism (uri, "MONGODB-AWS"));
8685
ret = _mongoc_aws_credentials_obtain (uri, &creds, &error);
8786
ASSERT (!ret);
8887
ASSERT_ERROR_CONTAINS (error,

0 commit comments

Comments
 (0)