From d0b18db383dc7f48a8e1bfd327c269497e584695 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Tue, 21 Oct 2014 10:14:15 +0200 Subject: [PATCH] Allow to enable client authentication on the OpenSslEngine Motivation: At the moment there is no way to enable client authentication when using OpenSslEngine. This limits the uses of OpenSslEngine. Modifications: Add support for different authentication modes. Result: OpenSslEngine can now also be used when client authenticiation is needed. --- .../io/netty/handler/ssl/OpenSslEngine.java | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) 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 3f1a040865..b0075c46f6 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java @@ -91,6 +91,12 @@ public final class OpenSslEngine extends SSLEngine { static final int MAX_ENCRYPTION_OVERHEAD_LENGTH = MAX_ENCRYPTED_PACKET_LENGTH - MAX_PLAINTEXT_LENGTH; + enum ClientAuthMode { + NONE, + OPTIONAL, + REQUIRE, + } + private static final AtomicIntegerFieldUpdater DESTROYED_UPDATER; private static final AtomicReferenceFieldUpdater SESSION_UPDATER; @@ -115,6 +121,7 @@ public final class OpenSslEngine extends SSLEngine { // We store this outside of the SslSession so we not need to create an instance during verifyCertificates(...) private volatile Certificate[] peerCerts; + private volatile ClientAuthMode clientAuth = ClientAuthMode.NONE; // SSL Engine status variables private boolean isInboundDone; @@ -1070,26 +1077,46 @@ public final class OpenSslEngine extends SSLEngine { @Override public void setNeedClientAuth(boolean b) { - if (b) { - throw new UnsupportedOperationException(); - } + setClientAuth(b ? ClientAuthMode.REQUIRE : ClientAuthMode.NONE); } @Override public boolean getNeedClientAuth() { - return false; + return clientAuth == ClientAuthMode.REQUIRE; } @Override public void setWantClientAuth(boolean b) { - if (b) { - throw new UnsupportedOperationException(); - } + setClientAuth(b ? ClientAuthMode.OPTIONAL : ClientAuthMode.NONE); } @Override public boolean getWantClientAuth() { - return false; + return clientAuth == ClientAuthMode.OPTIONAL; + } + + private void setClientAuth(ClientAuthMode mode) { + if (clientMode) { + return; + } + synchronized (this) { + if (clientAuth == mode) { + // No need to issue any JNI calls if the mode is the same + return; + } + switch (mode) { + case NONE: + SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, OpenSslContext.VERIFY_DEPTH); + break; + case REQUIRE: + SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRE, OpenSslContext.VERIFY_DEPTH); + break; + case OPTIONAL: + SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, OpenSslContext.VERIFY_DEPTH); + break; + } + clientAuth = mode; + } } @Override