From ea236d3adc73f6241430b33753cd0da3e2872360 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Shen Date: Sun, 21 Dec 2014 17:49:07 -0800 Subject: [PATCH] Enable SSL two way authentication With this fix the ovsdb server will provide ssl connection with two way authentication. Both server and client will authenticate peer certificate. The method of getting peer certificate is also provided in ovsdb connection info. Signed-off-by: Hsin-Yi Shen --- .../ovsdb/lib/OvsdbConnection.java | 6 ++--- .../ovsdb/lib/OvsdbConnectionInfo.java | 11 +++++++++ .../lib/impl/OvsdbConnectionService.java | 23 ++++++++++++------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnection.java b/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnection.java index 05e94ccb2..8852f41b3 100644 --- a/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnection.java +++ b/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnection.java @@ -12,7 +12,7 @@ package org.opendaylight.ovsdb.lib; import java.net.InetAddress; import java.util.Collection; -import io.netty.handler.ssl.SslContext; +import javax.net.ssl.SSLContext; /** * OvsDBConnection Interface provides OVSDB connection management APIs which includes @@ -46,7 +46,7 @@ public interface OvsdbConnection { * @return OvsDBClient The primary Client interface for the ovsdb connection. */ public OvsdbClient connectWithSsl(final InetAddress address, final int port, - final SslContext sslContext); + final SSLContext sslContext); /** * Method to disconnect an existing connection. @@ -63,7 +63,7 @@ public interface OvsdbConnection { * Method to start ovsdb server for passive connection with SSL */ public boolean startOvsdbManagerWithSsl(final int ovsdbListenPort, - final SslContext sslContext); + final SSLContext sslContext); /** * Method to register a Passive Connection Listener with the ConnectionService. diff --git a/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnectionInfo.java b/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnectionInfo.java index 232dbc507..77cca967f 100644 --- a/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnectionInfo.java +++ b/library/src/main/java/org/opendaylight/ovsdb/lib/OvsdbConnectionInfo.java @@ -11,10 +11,13 @@ package org.opendaylight.ovsdb.lib; import io.netty.channel.Channel; +import io.netty.handler.ssl.SslHandler; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.security.cert.Certificate; +import javax.net.ssl.SSLPeerUnverifiedException; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; @@ -55,6 +58,14 @@ public class OvsdbConnectionInfo { public ConnectionType getType() { return type; } + @XmlElement(name="clientCertificate") + public Certificate getCertificate() throws SSLPeerUnverifiedException { + SslHandler sslHandler = (SslHandler) channel.pipeline().get("ssl"); + if (sslHandler != null) { + return sslHandler.engine().getSession().getPeerCertificates()[0]; + } + return null; + } @Override public int hashCode() { diff --git a/library/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java b/library/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java index fd88677d4..fe279abba 100644 --- a/library/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java +++ b/library/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java @@ -26,7 +26,10 @@ import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.util.CharsetUtil; -import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslHandler; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; import java.net.InetAddress; import java.util.Collection; @@ -44,7 +47,6 @@ import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcDecoder; import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcEndpoint; import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcServiceBinderHandler; import org.opendaylight.ovsdb.lib.message.OvsdbRPC; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,7 +94,7 @@ public class OvsdbConnectionService implements OvsdbConnection { } @Override public OvsdbClient connectWithSsl(final InetAddress address, final int port, - final SslContext sslContext) { + final SSLContext sslContext) { try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(new NioEventLoopGroup()); @@ -105,8 +107,10 @@ public class OvsdbConnectionService implements OvsdbConnection { public void initChannel(SocketChannel channel) throws Exception { if (sslContext != null) { /* First add ssl handler if ssl context is given */ - channel.pipeline().addLast(sslContext.newHandler(channel.alloc(), - address.toString(), port)); + SSLEngine engine = + sslContext.createSSLEngine(address.toString(), port); + engine.setUseClientMode(true); + channel.pipeline().addLast("ssl", new SslHandler(engine)); } channel.pipeline().addLast( //new LoggingHandler(LogLevel.INFO), @@ -195,7 +199,7 @@ public class OvsdbConnectionService implements OvsdbConnection { @Override synchronized public boolean startOvsdbManagerWithSsl(final int ovsdbListenPort, - final SslContext sslContext) { + final SSLContext sslContext) { if (!singletonCreated) { new Thread() { @Override @@ -222,7 +226,7 @@ public class OvsdbConnectionService implements OvsdbConnection { * OVSDB Passive listening thread that uses Netty ServerBootstrap to open * passive connection with Ssl and handle channel callbacks. */ - private static void ovsdbManagerWithSsl(int port, final SslContext sslContext) { + private static void ovsdbManagerWithSsl(int port, final SSLContext sslContext) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { @@ -237,7 +241,10 @@ public class OvsdbConnectionService implements OvsdbConnection { logger.debug("New Passive channel created : "+ channel.toString()); if (sslContext != null) { /* Add SSL handler first if SSL context is provided */ - channel.pipeline().addLast(sslContext.newHandler(channel.alloc())); + SSLEngine engine = sslContext.createSSLEngine(); + engine.setUseClientMode(false); // work in a server mode + engine.setNeedClientAuth(true); // need client authentication + channel.pipeline().addLast("ssl", new SslHandler(engine)); } channel.pipeline().addLast( -- 2.36.6