alshabib
Committed by Gerrit Code Review

securing the openflow channel

Change-Id: Ifae379e7e372baeb14a4ad919f014c64752c3a7f
...@@ -39,9 +39,15 @@ import org.projectfloodlight.openflow.protocol.OFVersion; ...@@ -39,9 +39,15 @@ import org.projectfloodlight.openflow.protocol.OFVersion;
39 import org.slf4j.Logger; 39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory; 40 import org.slf4j.LoggerFactory;
41 41
42 +import javax.net.ssl.KeyManagerFactory;
43 +import javax.net.ssl.SSLContext;
44 +import javax.net.ssl.SSLEngine;
45 +import javax.net.ssl.TrustManagerFactory;
46 +import java.io.FileInputStream;
42 import java.lang.management.ManagementFactory; 47 import java.lang.management.ManagementFactory;
43 import java.lang.management.RuntimeMXBean; 48 import java.lang.management.RuntimeMXBean;
44 import java.net.InetSocketAddress; 49 import java.net.InetSocketAddress;
50 +import java.security.KeyStore;
45 import java.util.Dictionary; 51 import java.util.Dictionary;
46 import java.util.HashMap; 52 import java.util.HashMap;
47 import java.util.List; 53 import java.util.List;
...@@ -66,6 +72,8 @@ public class Controller { ...@@ -66,6 +72,8 @@ public class Controller {
66 72
67 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13); 73 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
68 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10); 74 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
75 + private static final boolean TLS_DISABLED = false;
76 + private static final short MIN_KS_LENGTH = 6;
69 77
70 protected HashMap<String, String> controllerNodeIPsCache; 78 protected HashMap<String, String> controllerNodeIPsCache;
71 79
...@@ -82,9 +90,16 @@ public class Controller { ...@@ -82,9 +90,16 @@ public class Controller {
82 90
83 private NioServerSocketChannelFactory execFactory; 91 private NioServerSocketChannelFactory execFactory;
84 92
93 + protected String ksLocation;
94 + protected String tsLocation;
95 + protected char[] ksPwd;
96 + protected char[] tsPwd;
97 + private SSLEngine serverSSLEngine;
98 +
85 // Perf. related configuration 99 // Perf. related configuration
86 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; 100 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
87 private DriverService driverService; 101 private DriverService driverService;
102 + private boolean enableOFTLS = TLS_DISABLED;
88 103
89 // *************** 104 // ***************
90 // Getters/Setters 105 // Getters/Setters
...@@ -134,7 +149,7 @@ public class Controller { ...@@ -134,7 +149,7 @@ public class Controller {
134 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); 149 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
135 150
136 ChannelPipelineFactory pfact = 151 ChannelPipelineFactory pfact =
137 - new OpenflowPipelineFactory(this, null); 152 + new OpenflowPipelineFactory(this, null, serverSSLEngine);
138 bootstrap.setPipelineFactory(pfact); 153 bootstrap.setPipelineFactory(pfact);
139 cg = new DefaultChannelGroup(); 154 cg = new DefaultChannelGroup();
140 openFlowPorts.forEach(port -> { 155 openFlowPorts.forEach(port -> {
...@@ -189,6 +204,68 @@ public class Controller { ...@@ -189,6 +204,68 @@ public class Controller {
189 this.controllerNodeIPsCache = new HashMap<>(); 204 this.controllerNodeIPsCache = new HashMap<>();
190 205
191 this.systemStartTime = System.currentTimeMillis(); 206 this.systemStartTime = System.currentTimeMillis();
207 +
208 + try {
209 + getTLSParameters();
210 + if (enableOFTLS) {
211 + initSSL();
212 + }
213 + } catch (Exception ex) {
214 + log.error("SSL init failed: {}", ex.getMessage());
215 + }
216 +
217 + }
218 +
219 + private void getTLSParameters() {
220 + String tempString = System.getProperty("enableOFTLS");
221 + enableOFTLS = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString);
222 + log.info("OpenFlow Security is {}", enableOFTLS ? "enabled" : "disabled");
223 + if (enableOFTLS) {
224 + ksLocation = System.getProperty("javax.net.ssl.keyStore");
225 + if (Strings.isNullOrEmpty(ksLocation)) {
226 + enableOFTLS = TLS_DISABLED;
227 + return;
228 + }
229 + tsLocation = System.getProperty("javax.net.ssl.trustStore");
230 + if (Strings.isNullOrEmpty(tsLocation)) {
231 + enableOFTLS = TLS_DISABLED;
232 + return;
233 + }
234 + ksPwd = System.getProperty("javax.net.ssl.keyStorePassword").toCharArray();
235 + if (MIN_KS_LENGTH > ksPwd.length) {
236 + enableOFTLS = TLS_DISABLED;
237 + return;
238 + }
239 + tsPwd = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray();
240 + if (MIN_KS_LENGTH > tsPwd.length) {
241 + enableOFTLS = TLS_DISABLED;
242 + return;
243 + }
244 + }
245 + }
246 +
247 + private void initSSL() throws Exception {
248 +
249 + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
250 + KeyStore ts = KeyStore.getInstance("JKS");
251 + ts.load(new FileInputStream(tsLocation), tsPwd);
252 + tmFactory.init(ts);
253 +
254 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
255 + KeyStore ks = KeyStore.getInstance("JKS");
256 + ks.load(new FileInputStream(ksLocation), ksPwd);
257 + kmf.init(ks, ksPwd);
258 +
259 + SSLContext serverContext = SSLContext.getInstance("TLS");
260 + serverContext.init(kmf.getKeyManagers(), tmFactory.getTrustManagers(), null);
261 +
262 + serverSSLEngine = serverContext.createSSLEngine();
263 +
264 + serverSSLEngine.setNeedClientAuth(true);
265 + serverSSLEngine.setUseClientMode(false);
266 + serverSSLEngine.setEnabledProtocols(serverSSLEngine.getSupportedProtocols());
267 + serverSSLEngine.setEnabledCipherSuites(serverSSLEngine.getSupportedCipherSuites());
268 + serverSSLEngine.setEnableSessionCreation(true);
192 } 269 }
193 270
194 // ************** 271 // **************
......
...@@ -27,6 +27,10 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler; ...@@ -27,6 +27,10 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
27 import org.jboss.netty.util.ExternalResourceReleasable; 27 import org.jboss.netty.util.ExternalResourceReleasable;
28 import org.jboss.netty.util.HashedWheelTimer; 28 import org.jboss.netty.util.HashedWheelTimer;
29 import org.jboss.netty.util.Timer; 29 import org.jboss.netty.util.Timer;
30 +import org.slf4j.Logger;
31 +import org.slf4j.LoggerFactory;
32 +
33 +import javax.net.ssl.SSLEngine;
30 34
31 /** 35 /**
32 * Creates a ChannelPipeline for a server-side openflow channel. 36 * Creates a ChannelPipeline for a server-side openflow channel.
...@@ -34,6 +38,9 @@ import org.jboss.netty.util.Timer; ...@@ -34,6 +38,9 @@ import org.jboss.netty.util.Timer;
34 public class OpenflowPipelineFactory 38 public class OpenflowPipelineFactory
35 implements ChannelPipelineFactory, ExternalResourceReleasable { 39 implements ChannelPipelineFactory, ExternalResourceReleasable {
36 40
41 + private final Logger log = LoggerFactory.getLogger(getClass());
42 +
43 + private final SSLEngine sslEngine;
37 protected Controller controller; 44 protected Controller controller;
38 protected ThreadPoolExecutor pipelineExecutor; 45 protected ThreadPoolExecutor pipelineExecutor;
39 protected Timer timer; 46 protected Timer timer;
...@@ -41,13 +48,15 @@ public class OpenflowPipelineFactory ...@@ -41,13 +48,15 @@ public class OpenflowPipelineFactory
41 protected ReadTimeoutHandler readTimeoutHandler; 48 protected ReadTimeoutHandler readTimeoutHandler;
42 49
43 public OpenflowPipelineFactory(Controller controller, 50 public OpenflowPipelineFactory(Controller controller,
44 - ThreadPoolExecutor pipelineExecutor) { 51 + ThreadPoolExecutor pipelineExecutor,
52 + SSLEngine sslEngine) {
45 super(); 53 super();
46 this.controller = controller; 54 this.controller = controller;
47 this.pipelineExecutor = pipelineExecutor; 55 this.pipelineExecutor = pipelineExecutor;
48 this.timer = new HashedWheelTimer(); 56 this.timer = new HashedWheelTimer();
49 this.idleHandler = new IdleStateHandler(timer, 20, 25, 0); 57 this.idleHandler = new IdleStateHandler(timer, 20, 25, 0);
50 this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30); 58 this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30);
59 + this.sslEngine = sslEngine;
51 } 60 }
52 61
53 @Override 62 @Override
...@@ -55,6 +64,13 @@ public class OpenflowPipelineFactory ...@@ -55,6 +64,13 @@ public class OpenflowPipelineFactory
55 OFChannelHandler handler = new OFChannelHandler(controller); 64 OFChannelHandler handler = new OFChannelHandler(controller);
56 65
57 ChannelPipeline pipeline = Channels.pipeline(); 66 ChannelPipeline pipeline = Channels.pipeline();
67 + if (sslEngine != null) {
68 + log.info("OpenFlow SSL enabled.");
69 + pipeline.addLast("ssl",
70 + new org.jboss.netty.handler.ssl.SslHandler(sslEngine));
71 + } else {
72 + log.info("OpenFlow SSL disabled");
73 + }
58 pipeline.addLast("ofmessagedecoder", new OFMessageDecoder()); 74 pipeline.addLast("ofmessagedecoder", new OFMessageDecoder());
59 pipeline.addLast("ofmessageencoder", new OFMessageEncoder()); 75 pipeline.addLast("ofmessageencoder", new OFMessageEncoder());
60 pipeline.addLast("idle", idleHandler); 76 pipeline.addLast("idle", idleHandler);
......