Skip to content

Commit c4e332a

Browse files
HBASE-28336 Correctly cast array of Certificates to array of X509Certificates (#5658)
Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
1 parent f34e214 commit c4e332a

File tree

2 files changed

+92
-21
lines changed

2 files changed

+92
-21
lines changed

hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/NettyRpcServer.java

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -416,33 +416,41 @@ private void initSSL(ChannelPipeline p, NettyServerRpcConnection conn, boolean s
416416
sslHandler.setWrapDataSize(
417417
conf.getInt(HBASE_SERVER_NETTY_TLS_WRAP_SIZE, DEFAULT_HBASE_SERVER_NETTY_TLS_WRAP_SIZE));
418418

419-
sslHandler.handshakeFuture().addListener(future -> {
420-
try {
421-
Certificate[] certificates = sslHandler.engine().getSession().getPeerCertificates();
422-
if (certificates != null && certificates.length > 0) {
423-
conn.clientCertificateChain = (X509Certificate[]) certificates;
424-
} else if (sslHandler.engine().getNeedClientAuth()) {
425-
LOG.error(
426-
"Could not get peer certificate on TLS connection from {}, although one is required",
427-
remoteAddress);
428-
}
429-
} catch (SSLPeerUnverifiedException e) {
430-
if (sslHandler.engine().getNeedClientAuth()) {
431-
LOG.error(
432-
"Could not get peer certificate on TLS connection from {}, although one is required",
433-
remoteAddress, e);
434-
}
435-
} catch (Exception e) {
436-
LOG.error("Unexpected error getting peer certificate for TLS connection from {}",
437-
remoteAddress, e);
438-
}
439-
});
419+
sslHandler.handshakeFuture()
420+
.addListener(future -> sslHandshakeCompleteHandler(conn, sslHandler, remoteAddress));
440421

441422
p.addLast("ssl", sslHandler);
442423
LOG.debug("SSL handler added for channel: {}", p.channel());
443424
}
444425
}
445426

427+
static void sslHandshakeCompleteHandler(NettyServerRpcConnection conn, SslHandler sslHandler,
428+
SocketAddress remoteAddress) {
429+
try {
430+
Certificate[] certificates = sslHandler.engine().getSession().getPeerCertificates();
431+
if (certificates != null && certificates.length > 0) {
432+
X509Certificate[] x509Certificates = new X509Certificate[certificates.length];
433+
for (int i = 0; i < x509Certificates.length; i++) {
434+
x509Certificates[i] = (X509Certificate) certificates[i];
435+
}
436+
conn.clientCertificateChain = x509Certificates;
437+
} else if (sslHandler.engine().getNeedClientAuth()) {
438+
LOG.debug(
439+
"Could not get peer certificate on TLS connection from {}, although one is required",
440+
remoteAddress);
441+
}
442+
} catch (SSLPeerUnverifiedException e) {
443+
if (sslHandler.engine().getNeedClientAuth()) {
444+
LOG.debug(
445+
"Could not get peer certificate on TLS connection from {}, although one is required",
446+
remoteAddress, e);
447+
}
448+
} catch (Exception e) {
449+
LOG.debug("Unexpected error getting peer certificate for TLS connection from {}",
450+
remoteAddress, e);
451+
}
452+
}
453+
446454
SslContext getSslContext() throws X509Exception, IOException {
447455
SslContext result = sslContextForServer.get();
448456
if (result == null) {

hbase-server/src/test/java/org/apache/hadoop/hbase/ipc/TestNettyRpcServer.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,25 @@
1717
*/
1818
package org.apache.hadoop.hbase.ipc;
1919

20+
import static org.junit.Assert.assertArrayEquals;
2021
import static org.junit.Assert.assertNotNull;
2122
import static org.junit.Assert.assertTrue;
23+
import static org.mockito.Mockito.mock;
24+
import static org.mockito.Mockito.when;
2225

26+
import java.io.ByteArrayInputStream;
27+
import java.net.InetSocketAddress;
28+
import java.net.SocketAddress;
29+
import java.nio.charset.StandardCharsets;
30+
import java.security.cert.Certificate;
31+
import java.security.cert.CertificateException;
32+
import java.security.cert.CertificateFactory;
33+
import java.security.cert.X509Certificate;
2334
import java.util.Arrays;
2435
import java.util.Collection;
36+
import javax.net.ssl.SSLEngine;
37+
import javax.net.ssl.SSLPeerUnverifiedException;
38+
import javax.net.ssl.SSLSession;
2539
import org.apache.hadoop.hbase.HBaseClassTestRule;
2640
import org.apache.hadoop.hbase.HBaseTestingUtil;
2741
import org.apache.hadoop.hbase.TableName;
@@ -47,6 +61,8 @@
4761
import org.junit.runners.Parameterized;
4862
import org.junit.runners.Parameterized.Parameters;
4963

64+
import org.apache.hbase.thirdparty.io.netty.handler.ssl.SslHandler;
65+
5066
@Category({ RPCTests.class, MediumTests.class })
5167
@RunWith(Parameterized.class)
5268
public class TestNettyRpcServer {
@@ -122,4 +138,51 @@ protected void doTest(TableName tableName) throws Exception {
122138
}
123139
}
124140

141+
private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
142+
+ "MIIEITCCAwmgAwIBAgIUaLL8vLOhWLCLXVHEJqXJhfmsTB8wDQYJKoZIhvcNAQEL\n"
143+
+ "BQAwgawxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYD\n"
144+
+ "VQQHDAlDYW1icmlkZ2UxGDAWBgNVBAoMD25ldHR5IHRlc3QgY2FzZTEYMBYGA1UE\n"
145+
+ "CwwPbmV0dHkgdGVzdCBjYXNlMRgwFgYDVQQDDA9uZXR0eSB0ZXN0IGNhc2UxIzAh\n"
146+
+ "BgkqhkiG9w0BCQEWFGNjb25uZWxsQGh1YnNwb3QuY29tMB4XDTI0MDEyMTE5MzMy\n"
147+
+ "MFoXDTI1MDEyMDE5MzMyMFowgawxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNz\n"
148+
+ "YWNodXNldHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxGDAWBgNVBAoMD25ldHR5IHRl\n"
149+
+ "c3QgY2FzZTEYMBYGA1UECwwPbmV0dHkgdGVzdCBjYXNlMRgwFgYDVQQDDA9uZXR0\n"
150+
+ "eSB0ZXN0IGNhc2UxIzAhBgkqhkiG9w0BCQEWFGNjb25uZWxsQGh1YnNwb3QuY29t\n"
151+
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+qzEZpQMjVdLj0siUcG\n"
152+
+ "y8LIHOW4S+tgHIKFkF865qWq6FVGbROe2Z0f5W6yIamZkdxzptT0iv+8S5okNNeW\n"
153+
+ "2NbsN/HNJIRtWfxku1Jh1gBqSkAYIjXyq7+20hIaJTzzxqike9M/Lc14EGb33Ja/\n"
154+
+ "kDPRV3UtiM3Ntf3eALXKbrWptkbgQngCaTgtfg8IkMAEpP270wZ9fW0lDHv3NPPt\n"
155+
+ "Zt0QSJzWSqWfu+l4ayvcUQYyNJesx9YmTHSJu69lvT4QApoX8FEiHfNCJ28R50CS\n"
156+
+ "aIgOpCWUvkH7rqx0p9q393uJRS/S6RlLbU30xUN1fNrVmP/XAapfy+R0PSgiUi8o\n"
157+
+ "EQIDAQABozkwNzAWBgNVHRIEDzANggt3d3cuZm9vLmNvbTAdBgNVHQ4EFgQUl4FD\n"
158+
+ "Y8jJ/JHJR68YqPsGUjUJuwgwDQYJKoZIhvcNAQELBQADggEBADVzivYz2M0qsWUc\n"
159+
+ "jXjCHymwTIr+7ud10um53FbYEAfKWsIY8Pp35fKpFzUwc5wVdCnLU86K/YMKRzNB\n"
160+
+ "zL2Auow3PJFRvXecOv7dWxNlNneLDcwbVrdNRu6nQXmZUgyz0oUKuJbF+JGtI+7W\n"
161+
+ "kRw7yhBfki+UCSQWeDqvaWzgmA4Us0N8NFq3euAs4xFbMMPMQWrT9Z7DGchCeRiB\n"
162+
+ "dkQBvh88vbR3v2Saq14W4Wt5rj2++vXWGQSeAQL6nGbOwc3ohW6isNNV0eGQQTmS\n"
163+
+ "khS2d/JDZq2XL5RGexf3CA6YYzWiTr9YZHNjuobvLH7mVnA2c8n6Zty/UhfnuK1x\n" + "JbkleFk=\n"
164+
+ "-----END CERTIFICATE-----";
165+
166+
@Test
167+
public void testHandshakeCompleteHandler()
168+
throws SSLPeerUnverifiedException, CertificateException {
169+
NettyServerRpcConnection conn = mock(NettyServerRpcConnection.class);
170+
SslHandler sslHandler = mock(SslHandler.class);
171+
SocketAddress remoteAddress = new InetSocketAddress("localhost", 5555);
172+
SSLEngine engine = mock(SSLEngine.class);
173+
SSLSession session = mock(SSLSession.class);
174+
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
175+
X509Certificate x509Certificate = (X509Certificate) certificateFactory
176+
.generateCertificate(new ByteArrayInputStream(CERTIFICATE.getBytes(StandardCharsets.UTF_8)));
177+
Certificate[] certificates = new Certificate[] { x509Certificate };
178+
179+
when(sslHandler.engine()).thenReturn(engine);
180+
when(engine.getSession()).thenReturn(session);
181+
when(session.getPeerCertificates()).thenReturn(certificates);
182+
183+
NettyRpcServer.sslHandshakeCompleteHandler(conn, sslHandler, remoteAddress);
184+
185+
assertArrayEquals(certificates, conn.clientCertificateChain);
186+
}
187+
125188
}

0 commit comments

Comments
 (0)