Skip to content

Commit f07892e

Browse files
committed
oncrpc: accept SSLParameters to configure SSLEngine
Motivation: SSLParameters is used to configure supported ciphers, client auth mode or protocols to use. Modification: add OncRpcSvcBuilder#withSSLParameters method to make use of SSLParameters baed SSLEngine configuration. Result: configurable behavior SSLEngine Acked-by: Paul Millar Target: master
1 parent 052e329 commit f07892e

File tree

3 files changed

+120
-18
lines changed

3 files changed

+120
-18
lines changed

oncrpc4j-core/src/main/java/org/dcache/oncrpc4j/rpc/OncRpcSvc.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import static com.google.common.base.Throwables.propagateIfPossible;
7373
import java.net.SocketAddress;
7474
import java.util.stream.Collectors;
75+
import javax.net.ssl.SSLParameters;
7576
import org.dcache.oncrpc4j.grizzly.GrizzlyRpcTransport;
7677
import static org.dcache.oncrpc4j.grizzly.GrizzlyUtils.getSelectorPoolCfg;
7778
import static org.dcache.oncrpc4j.grizzly.GrizzlyUtils.rpcMessageReceiverFor;
@@ -105,6 +106,11 @@ public class OncRpcSvc {
105106
*/
106107
private final SSLContext _sslContext;
107108

109+
/**
110+
* SSL parameters that should be applied to SSL engine.
111+
*/
112+
private final SSLParameters _sslParams;
113+
108114
/**
109115
* Start TLS only when requested.
110116
*/
@@ -180,6 +186,7 @@ public class OncRpcSvc {
180186
_svcName = builder.getServiceName();
181187
_sslContext = builder.getSSLContext();
182188
_startTLS = builder.isStartTLS();
189+
_sslParams = builder.getSSLParameters();
183190
}
184191

185192
/**
@@ -319,6 +326,18 @@ public void start() throws IOException {
319326
SSLEngineConfigurator clientSSLEngineConfigurator =
320327
new SSLEngineConfigurator(_sslContext, true, false, false);
321328

329+
if (_sslParams != null) {
330+
String[] cipherSuites = _sslParams.getCipherSuites();
331+
serverSSLEngineConfigurator.setEnabledCipherSuites(cipherSuites);
332+
clientSSLEngineConfigurator.setEnabledCipherSuites(cipherSuites);
333+
334+
String[] protocols = _sslParams.getProtocols();
335+
serverSSLEngineConfigurator.setEnabledProtocols(protocols);
336+
clientSSLEngineConfigurator.setEnabledProtocols(protocols);
337+
338+
serverSSLEngineConfigurator.setNeedClientAuth(_sslParams.getNeedClientAuth());
339+
serverSSLEngineConfigurator.setWantClientAuth(_sslParams.getWantClientAuth());
340+
}
322341
SSLFilter sslFilter = new SSLFilter(serverSSLEngineConfigurator,
323342
clientSSLEngineConfigurator);
324343
filterChain.add(_startTLS ? new StartTlsFilter(sslFilter, _isClient) : sslFilter);

oncrpc4j-core/src/main/java/org/dcache/oncrpc4j/rpc/OncRpcSvcBuilder.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.concurrent.Executors;
3131
import java.util.concurrent.ThreadFactory;
3232
import javax.net.ssl.SSLContext;
33+
import javax.net.ssl.SSLParameters;
3334

3435
import static com.google.common.base.Preconditions.checkArgument;
3536
import static org.dcache.oncrpc4j.grizzly.GrizzlyUtils.getDefaultWorkerPoolSize;
@@ -80,6 +81,7 @@ public class OncRpcSvcBuilder {
8081
private boolean _subjectPropagation = false;
8182
private SSLContext _sslContext = null;
8283
private boolean _startTLS = false;
84+
private SSLParameters _sslParams;
8385

8486
public OncRpcSvcBuilder withAutoPublish() {
8587
_autoPublish = true;
@@ -214,6 +216,11 @@ public OncRpcSvcBuilder withSSLContext(SSLContext sslContext) {
214216
return this;
215217
}
216218

219+
public OncRpcSvcBuilder withSSLParameters(SSLParameters sslParams) {
220+
_sslParams = sslParams;
221+
return this;
222+
}
223+
217224
public boolean getSubjectPropagation() {
218225
return _subjectPropagation;
219226
}
@@ -302,6 +309,10 @@ public SSLContext getSSLContext() {
302309
return _sslContext;
303310
}
304311

312+
public SSLParameters getSSLParameters() {
313+
return _sslParams;
314+
}
315+
305316
public OncRpcSvc build() {
306317

307318
if (_protocol == 0 || (((_protocol & TCP) != TCP) && ((_protocol & UDP) != UDP))) {

oncrpc4j-core/src/test/java/org/dcache/oncrpc4j/rpc/ClientServerTLSTest.java

Lines changed: 90 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
import org.dcache.oncrpc4j.rpc.net.IpProtocolType;
44
import org.dcache.oncrpc4j.xdr.XdrString;
55

6+
import java.io.EOFException;
67
import java.io.IOException;
78
import java.math.BigInteger;
89
import java.security.GeneralSecurityException;
910
import java.security.KeyPair;
1011
import java.security.KeyPairGenerator;
1112
import java.security.KeyStore;
13+
import java.security.PrivateKey;
1214
import java.security.SecureRandom;
1315
import java.security.Security;
1416
import java.security.cert.Certificate;
1517
import java.util.Date;
1618
import java.util.concurrent.TimeUnit;
1719
import javax.net.ssl.KeyManagerFactory;
1820
import javax.net.ssl.SSLContext;
21+
import javax.net.ssl.SSLParameters;
1922
import javax.net.ssl.TrustManagerFactory;
2023

2124
import org.bouncycastle.asn1.x500.X500Name;
@@ -49,7 +52,8 @@ public class ClientServerTLSTest {
4952
private OncRpcSvc svc;
5053
private OncRpcSvc clnt;
5154
private RpcCall clntCall;
52-
private SSLContext sslContext;
55+
private SSLContext sslServerContext;
56+
private SSLContext sslClientContext;
5357

5458
private RpcDispatchable echo = (RpcCall call) -> {
5559
switch (call.getProcedure()) {
@@ -88,7 +92,15 @@ public static void setupClass() {
8892

8993
@Before
9094
public void setUp() throws Exception {
91-
sslContext = createSslContext();
95+
96+
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
97+
keyPairGenerator.initialize(2048, new SecureRandom());
98+
KeyPair keyPair = keyPairGenerator.generateKeyPair();
99+
100+
Certificate certificate = generateSelfSignedCert(keyPair);
101+
102+
sslServerContext = createServerSslContext(certificate, keyPair.getPrivate());
103+
sslClientContext = createClientSslContext(certificate);
92104
}
93105

94106
@After
@@ -112,7 +124,7 @@ public void shouldCallCorrectProcedure() throws IOException {
112124
.withSelectorThreadPoolSize(1)
113125
.withWorkerThreadPoolSize(1)
114126
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), echo)
115-
.withSSLContext(sslContext)
127+
.withSSLContext(sslServerContext)
116128
.withServiceName("svc")
117129
.build();
118130
svc.start();
@@ -125,7 +137,7 @@ public void shouldCallCorrectProcedure() throws IOException {
125137
.withSelectorThreadPoolSize(1)
126138
.withWorkerThreadPoolSize(1)
127139
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), upper)
128-
.withSSLContext(sslContext)
140+
.withSSLContext(sslClientContext)
129141
.withServiceName("clnt")
130142
.build();
131143
clnt.start();
@@ -153,7 +165,7 @@ public void shouldTriggerClientCallback() throws IOException {
153165
.withSelectorThreadPoolSize(1)
154166
.withWorkerThreadPoolSize(1)
155167
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), echo)
156-
.withSSLContext(sslContext)
168+
.withSSLContext(sslServerContext)
157169
.withServiceName("svc")
158170
.build();
159171
svc.start();
@@ -166,7 +178,7 @@ public void shouldTriggerClientCallback() throws IOException {
166178
.withSelectorThreadPoolSize(1)
167179
.withWorkerThreadPoolSize(1)
168180
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), upper)
169-
.withSSLContext(sslContext)
181+
.withSSLContext(sslClientContext)
170182
.withServiceName("clnt")
171183
.build();
172184
clnt.start();
@@ -194,7 +206,7 @@ public void shouldStartTLSHandshake() throws IOException {
194206
.withSelectorThreadPoolSize(1)
195207
.withWorkerThreadPoolSize(1)
196208
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), echo)
197-
.withSSLContext(sslContext)
209+
.withSSLContext(sslServerContext)
198210
.withStartTLS()
199211
.withServiceName("svc")
200212
.build();
@@ -207,7 +219,7 @@ public void shouldStartTLSHandshake() throws IOException {
207219
.withWorkerThreadIoStrategy()
208220
.withSelectorThreadPoolSize(1)
209221
.withWorkerThreadPoolSize(1)
210-
.withSSLContext(sslContext)
222+
.withSSLContext(sslClientContext)
211223
.withStartTLS()
212224
.withServiceName("clnt")
213225
.build();
@@ -239,7 +251,7 @@ public void shouldFailWhenNoTLSOnClient() throws IOException {
239251
.withSelectorThreadPoolSize(1)
240252
.withWorkerThreadPoolSize(1)
241253
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), echo)
242-
.withSSLContext(sslContext)
254+
.withSSLContext(sslServerContext)
243255
.withStartTLS()
244256
.withServiceName("svc")
245257
.build();
@@ -275,7 +287,7 @@ public void shouldFailSecondStartTLS() throws IOException {
275287
.withSelectorThreadPoolSize(1)
276288
.withWorkerThreadPoolSize(1)
277289
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), echo)
278-
.withSSLContext(sslContext)
290+
.withSSLContext(sslServerContext)
279291
.withStartTLS()
280292
.withServiceName("svc")
281293
.build();
@@ -288,7 +300,7 @@ public void shouldFailSecondStartTLS() throws IOException {
288300
.withWorkerThreadIoStrategy()
289301
.withSelectorThreadPoolSize(1)
290302
.withWorkerThreadPoolSize(1)
291-
.withSSLContext(sslContext)
303+
.withSSLContext(sslClientContext)
292304
.withStartTLS()
293305
.withServiceName("clnt")
294306
.build();
@@ -324,7 +336,7 @@ public void shouldRejectStartTlsWhenNotConfigured() throws IOException {
324336
.withWorkerThreadIoStrategy()
325337
.withSelectorThreadPoolSize(1)
326338
.withWorkerThreadPoolSize(1)
327-
.withSSLContext(sslContext)
339+
.withSSLContext(sslClientContext)
328340
.withStartTLS()
329341
.withServiceName("clnt")
330342
.build();
@@ -336,21 +348,81 @@ public void shouldRejectStartTlsWhenNotConfigured() throws IOException {
336348
clntCall.call(0, XdrVoid.XDR_VOID, XdrVoid.XDR_VOID, new RpcAuthTypeTls());
337349
}
338350

339-
public static SSLContext createSslContext() throws Exception {
351+
352+
@Test(expected = EOFException.class) // rfc8446#section-6.2
353+
public void shouldRejectTlsWhenClientCertRequired() throws IOException, Exception {
354+
355+
SSLParameters parameters = new SSLParameters();
356+
parameters.setNeedClientAuth(true);
357+
358+
svc = new OncRpcSvcBuilder()
359+
.withoutAutoPublish()
360+
.withTCP()
361+
.withWorkerThreadIoStrategy()
362+
.withBindAddress("127.0.0.1")
363+
.withSelectorThreadPoolSize(1)
364+
.withWorkerThreadPoolSize(1)
365+
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), echo)
366+
.withSSLContext(sslServerContext)
367+
.withSSLParameters(parameters)
368+
.withServiceName("svc")
369+
.build();
370+
svc.start();
371+
372+
clnt = new OncRpcSvcBuilder()
373+
.withoutAutoPublish()
374+
.withTCP()
375+
.withClientMode()
376+
.withWorkerThreadIoStrategy()
377+
.withSelectorThreadPoolSize(1)
378+
.withWorkerThreadPoolSize(1)
379+
.withRpcService(new OncRpcProgram(PROGNUM, PROGVER), upper)
380+
.withSSLContext(sslClientContext)
381+
.withServiceName("clnt")
382+
.build();
383+
clnt.start();
384+
385+
RpcTransport t = clnt.connect(svc.getInetSocketAddress(IpProtocolType.TCP));
386+
clntCall = new RpcCall(PROGNUM, PROGVER, new RpcAuthTypeNone(), t);
387+
388+
XdrString s = new XdrString("hello");
389+
XdrString reply = new XdrString();
390+
clntCall.call(ECHO, s, reply);
391+
}
392+
393+
public static SSLContext createClientSslContext(Certificate certificate) throws Exception {
340394

341395
char[] password = "password".toCharArray();
342396

397+
// create emtpy keystore and put certificates into it
398+
KeyStore keyStore = createEmptyKeystore();
399+
keyStore.setEntry("chain", new KeyStore.TrustedCertificateEntry(certificate),null);
343400

344-
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
345-
keyPairGenerator.initialize(2048, new SecureRandom());
346-
KeyPair keyPair = keyPairGenerator.generateKeyPair();
401+
KeyManagerFactory keyManagerFactory
402+
= KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
403+
keyManagerFactory.init(keyStore, password);
404+
405+
TrustManagerFactory trustManagerFactory
406+
= TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
407+
trustManagerFactory.init(keyStore);
408+
409+
SSLContext sslContext = SSLContext.getInstance("TLS");
410+
sslContext.init(keyManagerFactory.getKeyManagers(),
411+
trustManagerFactory.getTrustManagers(),
412+
new SecureRandom());
413+
414+
return sslContext;
415+
}
416+
417+
public static SSLContext createServerSslContext(Certificate certificate, PrivateKey privateKey) throws Exception {
418+
419+
char[] password = "password".toCharArray();
347420

348-
Certificate certificate = generateSelfSignedCert(keyPair);
349421
Certificate[] certificateChain = {certificate};
350422

351423
// create emtpy keystore and put certificates into it
352424
KeyStore keyStore = createEmptyKeystore();
353-
keyStore.setKeyEntry("private", keyPair.getPrivate(), password, certificateChain);
425+
keyStore.setKeyEntry("private", privateKey, password, certificateChain);
354426
keyStore.setCertificateEntry("cert", certificate);
355427

356428
KeyManagerFactory keyManagerFactory

0 commit comments

Comments
 (0)