diff --git a/driver-core/src/main/com/mongodb/ConnectionString.java b/driver-core/src/main/com/mongodb/ConnectionString.java index 1cd7714092..5b80d711cd 100644 --- a/driver-core/src/main/com/mongodb/ConnectionString.java +++ b/driver-core/src/main/com/mongodb/ConnectionString.java @@ -269,8 +269,9 @@ *
If present, its value is used as the domain for SRV host name validation, replacing the domain inferred from + * the SRV host name. The value is normalized to always begin with {@code "."}.
+ * + *WARNING: Modifying the default SRV domain name validation can create vulnerabilities.
+ * + * @return the normalized SRV allowed hosts suffix, always beginning with {@code "."}. Defaults to null. + * @since 5.13 + * @see Builder#srvAllowedHostsSuffix(String) + */ + @Nullable + public String getSrvAllowedHostsSuffix() { + return wrapped.getClusterSettings().getSrvAllowedHostsSuffix(); + } + /** * Gets the server API to use when sending commands to the server. * @@ -1429,6 +1446,25 @@ public Builder srvServiceName(final String srvServiceName) { return this; } + /** + * Sets the SRV allowed hosts suffix used to validate hosts returned via SRV lookup. + * + *If set, its value is used as the domain for SRV host name validation, replacing the domain inferred from + * the SRV host name. The value is normalized: a leading {@code "."} is prepended if absent, so + * {@link #getSrvAllowedHostsSuffix()} always returns a value beginning with {@code "."}. This setting is only + * used with SRV. Specifying an overly broad suffix (for example a bare TLD) weakens SRV host name validation and + * is the responsibility of the caller.
+ * + * @param srvAllowedHostsSuffix the SRV allowed hosts suffix; may not be null or empty + * @return this + * @since 5.13 + * @see #getSrvAllowedHostsSuffix() + */ + public Builder srvAllowedHostsSuffix(final String srvAllowedHostsSuffix) { + wrapped.applyToClusterSettings(builder -> builder.srvAllowedHostsSuffix(srvAllowedHostsSuffix)); + return this; + } + /** * Sets the time limit, in milliseconds for the full execution of an operation. * diff --git a/driver-legacy/src/main/com/mongodb/MongoClientURI.java b/driver-legacy/src/main/com/mongodb/MongoClientURI.java index e7ce89566d..7e8289648a 100644 --- a/driver-legacy/src/main/com/mongodb/MongoClientURI.java +++ b/driver-legacy/src/main/com/mongodb/MongoClientURI.java @@ -110,6 +110,14 @@ *Connection pool configuration:
@@ -472,6 +480,10 @@ public MongoClientOptions getOptions() { if (srvServiceName != null) { builder.srvServiceName(srvServiceName); } + String srvAllowedHostsSuffix = proxied.getSrvAllowedHostsSuffix(); + if (srvAllowedHostsSuffix != null) { + builder.srvAllowedHostsSuffix(srvAllowedHostsSuffix); + } Long timeout = proxied.getTimeout(); if (timeout != null) { builder.timeout(timeout); diff --git a/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy b/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy index a386cd7f68..16f1604838 100644 --- a/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy +++ b/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy @@ -80,6 +80,7 @@ class MongoClientOptionsSpecification extends Specification { options.getSrvMaxHosts() == null options.getSrvServiceName() == 'mongodb' + options.getSrvAllowedHostsSuffix() == null } def 'should handle illegal arguments'() { @@ -100,6 +101,16 @@ class MongoClientOptionsSpecification extends Specification { builder.dbEncoderFactory(null) then: thrown(IllegalArgumentException) + + when: + builder.srvAllowedHostsSuffix(null) + then: + thrown(IllegalArgumentException) + + when: + builder.srvAllowedHostsSuffix("") + then: + thrown(IllegalArgumentException) } def 'should build with set options'() { @@ -312,6 +323,7 @@ class MongoClientOptionsSpecification extends Specification { def options = MongoClientOptions.builder() .srvServiceName('test') .srvMaxHosts(4) + .srvAllowedHostsSuffix(".build.10gen.cc") .build() settings = options.asMongoClientSettings(null, 'test3.test.build.10gen.cc', MULTIPLE, null) @@ -320,9 +332,11 @@ class MongoClientOptionsSpecification extends Specification { settings.clusterSettings == ClusterSettings.builder().srvHost('test3.test.build.10gen.cc') .srvServiceName('test') .srvMaxHosts(4) + .srvAllowedHostsSuffix(".build.10gen.cc") .build() options.getSrvServiceName() == 'test' options.getSrvMaxHosts() == 4 + options.getSrvAllowedHostsSuffix() == ".build.10gen.cc" } def 'should be easy to create new options from existing'() { diff --git a/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy b/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy index 3de1f77b6d..7e8fc5e31c 100644 --- a/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy +++ b/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy @@ -308,7 +308,8 @@ class MongoClientURISpecification extends Specification { def 'should apply SRV parameters'() { when: - def uri = new MongoClientURI('mongodb+srv://test3.test.build.10gen.cc/?srvMaxHosts=4&srvServiceName=test') + def uri = new MongoClientURI( + 'mongodb+srv://test3.test.build.10gen.cc/?srvMaxHosts=4&srvServiceName=test&srvAllowedHostsSuffix=.build.10gen.cc') then: uri.getSrvMaxHosts() == 4 @@ -320,6 +321,7 @@ class MongoClientURISpecification extends Specification { then: options.getSrvMaxHosts() == 4 options.getSrvServiceName() == 'test' + options.getSrvAllowedHostsSuffix() == '.build.10gen.cc' } def 'should respect MongoClientOptions builder'() {