From 0915b1b215ffe8dda34575f874761ca57a30f286 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 9 Sep 2015 21:12:04 +0200 Subject: [PATCH] Support SSLSession.getLocalCertificates() and getLocalPrincipal() when using OpenSSL Motivation: SSLSession.getLocalCertificates() and getLocalPrincipal() was not supported when using OpenSSL, which can produce problems when switch from JDK to OpenSSL impl. Modifications: Implement SSLSession.getLocalCertificates() and getLocalPrincipal() for OpenSslEngine. Result: More consistent behaving between JDK and OpenSSL based SSLEngine. --- .../netty/handler/ssl/OpenSslClientContext.java | 4 ++-- .../io/netty/handler/ssl/OpenSslContext.java | 12 ++++++++---- .../java/io/netty/handler/ssl/OpenSslEngine.java | 16 +++++++++++----- .../netty/handler/ssl/OpenSslServerContext.java | 4 ++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java index 5e962323bd..52bb9fea5f 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java @@ -171,7 +171,7 @@ public final class OpenSslClientContext extends OpenSslContext { CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { - super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT); + super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, null); boolean success = false; try { if (trustCertChainFile != null && !trustCertChainFile.isFile()) { @@ -271,7 +271,7 @@ public final class OpenSslClientContext extends OpenSslContext { CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { - super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT); + super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain); boolean success = false; try { if (key == null && keyCertChain != null || key != null && keyCertChain == null) { diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java index e5680180ce..4f16f42e72 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java @@ -36,6 +36,7 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.X509ExtendedTrustManager; import javax.net.ssl.X509TrustManager; import java.security.PrivateKey; +import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; @@ -81,6 +82,7 @@ public abstract class OpenSslContext extends SslContext { private final OpenSslEngineMap engineMap = new DefaultOpenSslEngineMap(); private final OpenSslApplicationProtocolNegotiator apn; private final int mode; + private final Certificate[] keyCertChain; static final OpenSslApplicationProtocolNegotiator NONE_PROTOCOL_NEGOTIATOR = new OpenSslApplicationProtocolNegotiator() { @@ -125,13 +127,14 @@ public abstract class OpenSslContext extends SslContext { } OpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apnCfg, - long sessionCacheSize, long sessionTimeout, int mode) throws SSLException { - this(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode); + long sessionCacheSize, long sessionTimeout, int mode, Certificate[] keyCertChain) + throws SSLException { + this(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode, keyCertChain); } OpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize, - long sessionTimeout, int mode) throws SSLException { + long sessionTimeout, int mode, Certificate[] keyCertChain) throws SSLException { OpenSsl.ensureAvailability(); if (mode != SSL.SSL_MODE_SERVER && mode != SSL.SSL_MODE_CLIENT) { @@ -143,6 +146,7 @@ public abstract class OpenSslContext extends SslContext { rejectRemoteInitiatedRenegotiation = JDK_REJECT_CLIENT_INITIATED_RENEGOTIATION; } + this.keyCertChain = keyCertChain == null ? null : keyCertChain.clone(); final List convertedCiphers; if (ciphers == null) { convertedCiphers = null; @@ -287,7 +291,7 @@ public abstract class OpenSslContext extends SslContext { @Override public final SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) { final OpenSslEngine engine = new OpenSslEngine(ctx, alloc, isClient(), sessionContext(), apn, engineMap, - rejectRemoteInitiatedRenegotiation, peerHost, peerPort); + rejectRemoteInitiatedRenegotiation, peerHost, peerPort, keyCertChain); engineMap.add(engine); return engine; } diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java index 9ff8039747..1a24a3e505 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java @@ -174,6 +174,7 @@ public final class OpenSslEngine extends SSLEngine { private final OpenSslApplicationProtocolNegotiator apn; private final boolean rejectRemoteInitiatedRenegation; private final OpenSslSession session; + private final java.security.cert.Certificate[] localCerts; // This is package-private as we set it from OpenSslContext if an exception is thrown during // the verification step. @@ -203,13 +204,15 @@ public final class OpenSslEngine extends SSLEngine { boolean clientMode, OpenSslSessionContext sessionContext, OpenSslApplicationProtocolNegotiator apn, OpenSslEngineMap engineMap, boolean rejectRemoteInitiatedRenegation) { - this(sslCtx, alloc, clientMode, sessionContext, apn, engineMap, rejectRemoteInitiatedRenegation, null, -1); + this(sslCtx, alloc, clientMode, sessionContext, apn, engineMap, rejectRemoteInitiatedRenegation, null, -1, + null); } OpenSslEngine(long sslCtx, ByteBufAllocator alloc, boolean clientMode, OpenSslSessionContext sessionContext, OpenSslApplicationProtocolNegotiator apn, OpenSslEngineMap engineMap, - boolean rejectRemoteInitiatedRenegation, String peerHost, int peerPort) { + boolean rejectRemoteInitiatedRenegation, String peerHost, int peerPort, + java.security.cert.Certificate[] localCerts) { super(peerHost, peerPort); OpenSsl.ensureAvailability(); if (sslCtx == 0) { @@ -224,6 +227,7 @@ public final class OpenSslEngine extends SSLEngine { this.clientMode = clientMode; this.engineMap = engineMap; this.rejectRemoteInitiatedRenegation = rejectRemoteInitiatedRenegation; + this.localCerts = localCerts; } @Override @@ -1537,8 +1541,10 @@ public final class OpenSslEngine extends SSLEngine { @Override public Certificate[] getLocalCertificates() { - // TODO: Find out how to get these - return EMPTY_CERTIFICATES; + if (localCerts == null) { + return null; + } + return localCerts.clone(); } @Override @@ -1561,7 +1567,7 @@ public final class OpenSslEngine extends SSLEngine { @Override public Principal getLocalPrincipal() { - Certificate[] local = getLocalCertificates(); + Certificate[] local = localCerts; if (local == null || local.length == 0) { return null; } diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java index b378bc6e48..58dad953ab 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java @@ -317,7 +317,7 @@ public final class OpenSslServerContext extends OpenSslContext { File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize, long sessionTimeout) throws SSLException { - super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER); + super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, null); OpenSsl.ensureAvailability(); checkNotNull(keyCertChainFile, "keyCertChainFile"); @@ -418,7 +418,7 @@ public final class OpenSslServerContext extends OpenSslContext { X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { - super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER); + super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain); OpenSsl.ensureAvailability(); checkNotNull(keyCertChain, "keyCertChainFile");