Skip to content

Commit cf82b59

Browse files
authored
JAVA-2434: Add support for custom cipher suites and host name validation to ProgrammaticSslEngineFactory (apache#1347)
1 parent 54a6785 commit cf82b59

4 files changed

Lines changed: 66 additions & 7 deletions

File tree

changelog/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### 4.3.0 (in progress)
66

7+
- [improvement] JAVA-2434: Add support for custom cipher suites and host name validation to ProgrammaticSslEngineFactory
78
- [improvement] JAVA-2480: Upgrade Jackson to 2.10.0
89
- [documentation] JAVA-2505: Annotate Node.getHostId() as nullable
910
- [improvement] JAVA-1708: Support DSE "everywhere" replication strategy

core/revapi.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4830,6 +4830,13 @@
48304830
"new": "method java.util.UUID com.datastax.oss.driver.api.core.metadata.Node::getHostId()",
48314831
"annotation": "@edu.umd.cs.findbugs.annotations.Nullable",
48324832
"justification": "JAVA-2505: Annotate Node.getHostId() as nullable"
4833+
},
4834+
{
4835+
"code": "java.annotation.added",
4836+
"old": "parameter void com.datastax.oss.driver.api.core.ssl.ProgrammaticSslEngineFactory::<init>(===javax.net.ssl.SSLContext===)",
4837+
"new": "parameter void com.datastax.oss.driver.api.core.ssl.ProgrammaticSslEngineFactory::<init>(===javax.net.ssl.SSLContext===)",
4838+
"annotation": "@edu.umd.cs.findbugs.annotations.NonNull",
4839+
"justification": "JAVA-2434: added @NonNull to ProgrammaticSslEngineFactory(SSLContext) constructor"
48334840
}
48344841
]
48354842
}

core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ public SelfT withAuthCredentials(@NonNull String username, @NonNull String passw
261261
*
262262
* <p>If the factory is provided programmatically with this method, it overrides the configuration
263263
* (that is, the {@code advanced.ssl-engine-factory} option will be ignored).
264+
*
265+
* @see ProgrammaticSslEngineFactory
264266
*/
265267
@NonNull
266268
public SelfT withSslEngineFactory(@Nullable SslEngineFactory sslEngineFactory) {
@@ -276,9 +278,12 @@ public SelfT withSslEngineFactory(@Nullable SslEngineFactory sslEngineFactory) {
276278
* #withSslEngineFactory(SslEngineFactory)}.
277279
*
278280
* <p>If you use this method, there is no way to customize cipher suites, or turn on host name
279-
* validation. Also, note that SSL engines will be created with advisory peer information ({@link
280-
* SSLContext#createSSLEngine(String, int)}) whenever possible. If you need finer control, write
281-
* your own factory.
281+
* validation. If you need finer control, use {@link #withSslEngineFactory(SslEngineFactory)}
282+
* directly and pass either your own implementation of {@link SslEngineFactory}, or a {@link
283+
* ProgrammaticSslEngineFactory} created with custom cipher suites and/or host name validation.
284+
*
285+
* <p>Also, note that SSL engines will be created with advisory peer information ({@link
286+
* SSLContext#createSSLEngine(String, int)}) whenever possible.
282287
*/
283288
@NonNull
284289
public SelfT withSslContext(@Nullable SSLContext sslContext) {

core/src/main/java/com/datastax/oss/driver/api/core/ssl/ProgrammaticSslEngineFactory.java

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,19 @@
1818
import com.datastax.oss.driver.api.core.metadata.EndPoint;
1919
import com.datastax.oss.driver.api.core.session.SessionBuilder;
2020
import edu.umd.cs.findbugs.annotations.NonNull;
21+
import edu.umd.cs.findbugs.annotations.Nullable;
2122
import java.net.InetSocketAddress;
2223
import java.net.SocketAddress;
2324
import javax.net.ssl.SSLContext;
2425
import javax.net.ssl.SSLEngine;
26+
import javax.net.ssl.SSLParameters;
2527

2628
/**
2729
* An SSL engine factory that allows you to configure the driver programmatically, by passing your
2830
* own {@link SSLContext}.
2931
*
30-
* <p>Unlike the configuration-based approach, this class does not allow you to customize cipher
31-
* suites, or turn on host name validation. Also, note that it will create SSL engines with advisory
32-
* peer information ({@link SSLContext#createSSLEngine(String, int)}) whenever possible.
32+
* <p>Note that this class will create SSL engines with advisory peer information ({@link
33+
* SSLContext#createSSLEngine(String, int)}) whenever possible.
3334
*
3435
* <p>If those defaults do not work for you, it should be pretty straightforward to write your own
3536
* implementation by extending or duplicating this class.
@@ -40,9 +41,46 @@
4041
public class ProgrammaticSslEngineFactory implements SslEngineFactory {
4142

4243
protected final SSLContext sslContext;
44+
protected final String[] cipherSuites;
45+
protected final boolean requireHostnameValidation;
4346

44-
public ProgrammaticSslEngineFactory(SSLContext sslContext) {
47+
/**
48+
* Creates an instance with the given {@link SSLContext}, default cipher suites and no host name
49+
* validation.
50+
*
51+
* @param sslContext the {@link SSLContext} to use.
52+
*/
53+
public ProgrammaticSslEngineFactory(@NonNull SSLContext sslContext) {
54+
this(sslContext, null);
55+
}
56+
57+
/**
58+
* Creates an instance with the given {@link SSLContext} and cipher suites, and no host name
59+
* validation.
60+
*
61+
* @param sslContext the {@link SSLContext} to use.
62+
* @param cipherSuites the cipher suites to use, or null to use the default ones.
63+
*/
64+
public ProgrammaticSslEngineFactory(
65+
@NonNull SSLContext sslContext, @Nullable String[] cipherSuites) {
66+
this(sslContext, cipherSuites, false);
67+
}
68+
69+
/**
70+
* Creates an instance with the given {@link SSLContext}, cipher suites and host name validation.
71+
*
72+
* @param sslContext the {@link SSLContext} to use.
73+
* @param cipherSuites the cipher suites to use, or null to use the default ones.
74+
* @param requireHostnameValidation whether to enable host name validation. If enabled, host name
75+
* validation will be done using HTTPS algorithm.
76+
*/
77+
public ProgrammaticSslEngineFactory(
78+
@NonNull SSLContext sslContext,
79+
@Nullable String[] cipherSuites,
80+
boolean requireHostnameValidation) {
4581
this.sslContext = sslContext;
82+
this.cipherSuites = cipherSuites;
83+
this.requireHostnameValidation = requireHostnameValidation;
4684
}
4785

4886
@NonNull
@@ -57,6 +95,14 @@ public SSLEngine newSslEngine(@NonNull EndPoint remoteEndpoint) {
5795
engine = sslContext.createSSLEngine();
5896
}
5997
engine.setUseClientMode(true);
98+
if (cipherSuites != null) {
99+
engine.setEnabledCipherSuites(cipherSuites);
100+
}
101+
if (requireHostnameValidation) {
102+
SSLParameters parameters = engine.getSSLParameters();
103+
parameters.setEndpointIdentificationAlgorithm("HTTPS");
104+
engine.setSSLParameters(parameters);
105+
}
60106
return engine;
61107
}
62108

0 commit comments

Comments
 (0)