Skip to content

Commit 0cb8ca0

Browse files
committed
PROTON-1962: update some defaults and related handling
1 parent 31f5fc9 commit 0cb8ca0

File tree

11 files changed

+328
-22
lines changed

11 files changed

+328
-22
lines changed

proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,24 @@ public enum Mode
4949
/**
5050
* Determines the level of peer validation.
5151
*
52-
* {@link #ANONYMOUS_PEER} is configured by default.
52+
* {@link #VERIFY_PEER_NAME} is used by default in {@link Mode#CLIENT client}
53+
* mode if not configured otherwise, with {@link #ANONYMOUS_PEER} used for
54+
* {@link Mode#SERVER server} mode if not configured otherwise.
5355
*/
5456
public enum VerifyMode
5557
{
5658
/**
57-
* will only connect to those peers that provide a valid identifying certificate signed
58-
* by a trusted CA and are using an authenticated cipher
59+
* Requires peers provide a valid identifying certificate signed by
60+
* a trusted certificate. Does not verify hostname details of the
61+
* peer certificate, use {@link #VERIFY_PEER_NAME} for this instead.
5962
*/
6063
VERIFY_PEER,
64+
/**
65+
* Requires peers provide a valid identifying certificate signed
66+
* by a trusted certificate, including verifying hostname details
67+
* of the certificate using peer details provided when configuring
68+
* TLS via {@link Transport#ssl(SslDomain, SslPeerDetails)}.
69+
*/
6170
VERIFY_PEER_NAME,
6271
/**
6372
* does not require a valid certificate, and permits use of ciphers that

proton-j/src/main/java/org/apache/qpid/proton/engine/Transport.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,21 @@ public static Transport create() {
194194
* {@link Ssl} object, regardless of the parameters supplied.
195195
*
196196
* @param sslDomain the SSL settings to use
197-
* @param sslPeerDetails may be null, in which case SSL session resume will not be attempted
197+
* @param sslPeerDetails peer details, used for SNI, hostname verification, etc when connecting. May be null.
198198
* @return an {@link Ssl} object representing the SSL session.
199+
* @throws IllegalArgumentException if the sslDomain requests hostname verification but sslPeerDetails are null.
200+
* @throws IllegalStateException if the sslDomain has not been initialised.
199201
*/
200-
Ssl ssl(SslDomain sslDomain, SslPeerDetails sslPeerDetails);
202+
Ssl ssl(SslDomain sslDomain, SslPeerDetails sslPeerDetails) throws IllegalArgumentException;
201203

202204
/**
203-
* As per {@link #ssl(SslDomain, SslPeerDetails)} but no attempt is made to resume a previous SSL session.
205+
* Equivalent to {@link #ssl(SslDomain, SslPeerDetails)} but passing null for SslPeerDetails, meaning no SNI detail
206+
* is sent, hostname verification isn't supported etc when connecting.
207+
*
208+
* @throws IllegalArgumentException if the sslDomain requests hostname verification.
209+
* @throws IllegalStateException if the sslDomain has not been initialised.
204210
*/
205-
Ssl ssl(SslDomain sslDomain);
211+
Ssl ssl(SslDomain sslDomain) throws IllegalArgumentException;
206212

207213

208214
/**

proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,15 @@ public void process() throws TransportException
360360
try {
361361
unwrapInput();
362362
} catch (SSLException e) {
363-
_logger.log(Level.WARNING, e.getMessage());
363+
if(_logger.isLoggable(Level.FINEST)){
364+
_logger.log(Level.FINEST, e.getMessage(), e);
365+
} else {
366+
_logger.log(Level.WARNING, e.getMessage());
367+
}
364368
_inputBuffer.position(_inputBuffer.limit());
365369
_tail_closed = true;
370+
371+
throw new TransportException(e);
366372
} finally {
367373
_inputBuffer.compact();
368374
}

proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@
1919
package org.apache.qpid.proton.engine.impl.ssl;
2020

2121
import javax.net.ssl.SSLContext;
22-
import org.apache.qpid.proton.ProtonUnsupportedOperationException;
2322
import org.apache.qpid.proton.engine.ProtonJSslDomain;
2423
import org.apache.qpid.proton.engine.SslDomain;
2524
import org.apache.qpid.proton.engine.SslPeerDetails;
2625

2726
public class SslDomainImpl implements SslDomain, ProtonSslEngineProvider, ProtonJSslDomain
2827
{
2928
private Mode _mode;
30-
private VerifyMode _verifyMode = VerifyMode.ANONYMOUS_PEER;
29+
private VerifyMode _verifyMode;
3130
private String _certificateFile;
3231
private String _privateKeyFile;
3332
private String _privateKeyPassword;
@@ -94,17 +93,18 @@ public SSLContext getSslContext()
9493
@Override
9594
public void setPeerAuthentication(VerifyMode verifyMode)
9695
{
97-
if(verifyMode == VerifyMode.VERIFY_PEER_NAME)
98-
{
99-
throw new ProtonUnsupportedOperationException();
100-
}
10196
_verifyMode = verifyMode;
10297
_sslEngineFacadeFactory.resetCache();
10398
}
10499

105100
@Override
106101
public VerifyMode getPeerAuthentication()
107102
{
103+
if(_verifyMode == null)
104+
{
105+
return _mode == Mode.SERVER ? VerifyMode.ANONYMOUS_PEER : VerifyMode.VERIFY_PEER_NAME;
106+
}
107+
108108
return _verifyMode;
109109
}
110110

proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import javax.net.ssl.KeyManagerFactory;
5454
import javax.net.ssl.SSLContext;
5555
import javax.net.ssl.SSLEngine;
56+
import javax.net.ssl.SSLParameters;
5657
import javax.net.ssl.TrustManager;
5758
import javax.net.ssl.TrustManagerFactory;
5859
import javax.net.ssl.X509TrustManager;
@@ -232,6 +233,13 @@ private SSLEngine createAndInitialiseSslEngine(SslDomain domain, SslPeerDetails
232233
{
233234
sslEngine.setNeedClientAuth(true);
234235
}
236+
237+
if(domain.getPeerAuthentication() == SslDomain.VerifyMode.VERIFY_PEER_NAME)
238+
{
239+
SSLParameters sslParameters = sslEngine.getSSLParameters();
240+
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
241+
sslEngine.setSSLParameters(sslParameters);
242+
}
235243
}
236244

237245
if(_logger.isLoggable(Level.FINE))

proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.qpid.proton.ProtonUnsupportedOperationException;
2626
import org.apache.qpid.proton.engine.Ssl;
2727
import org.apache.qpid.proton.engine.SslDomain;
28+
import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
2829
import org.apache.qpid.proton.engine.SslPeerDetails;
2930
import org.apache.qpid.proton.engine.Transport;
3031
import org.apache.qpid.proton.engine.TransportException;
@@ -54,6 +55,14 @@ public SslImpl(SslDomain domain, SslPeerDetails peerDetails)
5455
_domain = domain;
5556
_protonSslEngineProvider = (ProtonSslEngineProvider)domain;
5657
_peerDetails = peerDetails;
58+
59+
if(_domain.getMode() == null) {
60+
throw new IllegalStateException("Client/server mode must be configured, SslDomain must have init called.");
61+
}
62+
63+
if(_peerDetails == null && _domain.getPeerAuthentication() == VerifyMode.VERIFY_PEER_NAME) {
64+
throw new IllegalArgumentException("Peer hostname verification is enabled, but no peer details were provided");
65+
}
5766
}
5867

5968
public TransportWrapper wrap(TransportInput inputProcessor, TransportOutput outputProcessor)

proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.qpid.proton.engine.Event;
3838
import org.apache.qpid.proton.engine.Sasl;
3939
import org.apache.qpid.proton.engine.Transport;
40+
import org.apache.qpid.proton.engine.TransportException;
4041
import org.apache.qpid.proton.engine.impl.TransportImpl;
4142
import org.apache.qpid.proton.engine.Record;
4243
import org.apache.qpid.proton.reactor.Reactor;
@@ -232,7 +233,7 @@ public void run(Selectable selectable) {
232233
} else {
233234
transport.process();
234235
}
235-
} catch (IOException e) {
236+
} catch (IOException | TransportException e) {
236237
ErrorCondition condition = new ErrorCondition();
237238
condition.setCondition(Symbol.getSymbol("proton:io"));
238239
condition.setDescription(e.getMessage());

proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapperTest.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,19 @@ public void testUnderlyingInputHasZeroCapacityMidProcessing()
347347
@Test
348348
public void testSslUnwrapThrowsException_returnsErrorResultAndRefusesFurtherInput() throws Exception
349349
{
350-
SSLException sslException = new SSLException("unwrap exception");
350+
String unwrapExceptionMessage = "unwrap exception message";
351+
SSLException sslException = new SSLException(unwrapExceptionMessage);
351352
_dummySslEngine.rejectNextEncodedPacket(sslException);
352353

353354
_sslWrapper.tail().put("<-A->".getBytes(StandardCharsets.UTF_8));
354-
_sslWrapper.process();
355-
assertEquals(_sslWrapper.capacity(), Transport.END_OF_STREAM);
355+
try {
356+
_sslWrapper.process();
357+
fail("no exception");
358+
} catch(TransportException e) {
359+
assertEquals("javax.net.ssl.SSLException: " + unwrapExceptionMessage, e.getMessage());
360+
}
361+
362+
assertEquals(Transport.END_OF_STREAM, _sslWrapper.capacity());
356363
}
357364

358365
@Test
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.qpid.proton.engine.impl.ssl;
20+
21+
import static org.junit.Assert.assertEquals;
22+
import static org.junit.Assert.assertNotEquals;
23+
import static org.junit.Assert.assertNull;
24+
25+
import org.apache.qpid.proton.engine.SslDomain;
26+
import org.apache.qpid.proton.engine.SslDomain.Mode;
27+
import org.apache.qpid.proton.engine.SslDomain.VerifyMode;
28+
import org.junit.Test;
29+
30+
public class SslDomainImplTest {
31+
32+
@Test
33+
public void testInitGetMode() throws Exception
34+
{
35+
SslDomain sslDomain = SslDomain.Factory.create();
36+
assertNull("Unexpected mode, none was set", sslDomain.getMode());
37+
38+
sslDomain.init(Mode.CLIENT);
39+
assertEquals("Unexpected mode", Mode.CLIENT, sslDomain.getMode());
40+
41+
sslDomain.init(Mode.SERVER);
42+
assertEquals("Unexpected mode", Mode.SERVER, sslDomain.getMode());
43+
}
44+
45+
@Test
46+
public void testVerifyModeDefault() throws Exception
47+
{
48+
SslDomain clientSslDomain = SslDomain.Factory.create();
49+
assertEquals("Unexpected default verification mode", VerifyMode.VERIFY_PEER_NAME, clientSslDomain.getPeerAuthentication());
50+
clientSslDomain.init(Mode.CLIENT);
51+
assertEquals("Unexpected default verification mode", VerifyMode.VERIFY_PEER_NAME, clientSslDomain.getPeerAuthentication());
52+
53+
SslDomain serverSslDomain = SslDomain.Factory.create();
54+
serverSslDomain.init(Mode.SERVER);
55+
assertEquals("Unexpected default verification mode", VerifyMode.ANONYMOUS_PEER, serverSslDomain.getPeerAuthentication());
56+
}
57+
58+
@Test
59+
public void testVerifyModeSetGet() throws Exception
60+
{
61+
SslDomain clientSslDomain = SslDomain.Factory.create();
62+
clientSslDomain.init(Mode.CLIENT);
63+
assertNotEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, clientSslDomain.getPeerAuthentication());
64+
clientSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER);
65+
assertEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, clientSslDomain.getPeerAuthentication());
66+
67+
SslDomain serverSslDomain = SslDomain.Factory.create();
68+
serverSslDomain.init(Mode.SERVER);
69+
assertNotEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, serverSslDomain.getPeerAuthentication());
70+
serverSslDomain.setPeerAuthentication(VerifyMode.VERIFY_PEER);
71+
assertEquals("Unexpected verification mode", VerifyMode.VERIFY_PEER, serverSslDomain.getPeerAuthentication());
72+
}
73+
}

0 commit comments

Comments
 (0)