From f15be2e58d2d66e545759c9ba1857f603e0edcef Mon Sep 17 00:00:00 2001 From: StevenBonePgh Date: Wed, 11 Jan 2017 14:51:24 -0500 Subject: [PATCH 1/2] Resolve Issue #158 "TLS 1.2 Support in Fleck and WebSocket4Net" by adding overloads to Fleck and WebSocket4Net. Also added convienence overloads for WAMP2 DefaultRouter (Fleck) and for WAMP1 Channel Factory extensions (WebSocket4Net). Added overloads where defaults would also be acceptable for backwards binary compatibility - these can be removed if this is undesired. I was unable to validate the Mono build. --- .../FleckAuthenticatedWebSocketTransport.cs | 15 +++++- .../Fleck/FleckWampConnectionListener.cs | 16 +++++++ .../Fleck/FleckWebSocketTransport.cs | 42 +++++++++++++++-- .../WebSocket4NetBinaryConnection.cs | 19 +++++++- .../WebSocket4Net/WebSocket4NetConnection.cs | 11 +++++ .../WebSocket4NetTextConnection.cs | 19 +++++++- .../WAMP2/V2/DefaultWampAuthenticationHost.cs | 47 +++++++++++++++++-- .../WAMP2/V2/DefaultWampHost.cs | 33 +++++++++++-- .../WAMP1/V1/WampChannelFactoryExtensions.cs | 22 +++++++-- 9 files changed, 200 insertions(+), 24 deletions(-) diff --git a/src/net45/Default/WampSharp.Fleck/Fleck/FleckAuthenticatedWebSocketTransport.cs b/src/net45/Default/WampSharp.Fleck/Fleck/FleckAuthenticatedWebSocketTransport.cs index b41aad617..b6cb5d4d9 100644 --- a/src/net45/Default/WampSharp.Fleck/Fleck/FleckAuthenticatedWebSocketTransport.cs +++ b/src/net45/Default/WampSharp.Fleck/Fleck/FleckAuthenticatedWebSocketTransport.cs @@ -1,4 +1,6 @@ -using System.Security.Cryptography.X509Certificates; +using System; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; using WampSharp.V2.Authentication; namespace WampSharp.Fleck @@ -9,7 +11,16 @@ public FleckAuthenticatedWebSocketTransport (string location, ICookieAuthenticatorFactory cookieAuthenticatorFactory = null, X509Certificate2 certificate = null) - : base(location, cookieAuthenticatorFactory, certificate) + : this(location: location, cookieAuthenticatorFactory: cookieAuthenticatorFactory, certificate: certificate, getEnabledSslProtocols: null) + { + } + + public FleckAuthenticatedWebSocketTransport + (string location, + ICookieAuthenticatorFactory cookieAuthenticatorFactory = null, + X509Certificate2 certificate = null, + Func getEnabledSslProtocols = null) + : base(location, cookieAuthenticatorFactory, certificate, getEnabledSslProtocols) { } } diff --git a/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs b/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs index c068362ee..92deac600 100644 --- a/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs +++ b/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs @@ -1,6 +1,7 @@ using System; using System.Reactive.Disposables; using System.Reactive.Subjects; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Fleck; using WampSharp.Core.Listener; @@ -17,15 +18,25 @@ public class FleckWampConnectionListener : IWampConnectionListener mBinding; private readonly X509Certificate2 mCertificate; + private readonly Func mGetEnabledSslProtocols; private readonly object mLock = new object(); public FleckWampConnectionListener(string location, IWampTextBinding binding, X509Certificate2 certificate = null) + :this(location: location, binding: binding, certificate: certificate, getEnabledSslProtocols: null) + { + } + + public FleckWampConnectionListener(string location, + IWampTextBinding binding, + X509Certificate2 certificate, + Func getEnabledSslProtocols) { mLocation = location; mBinding = binding; mCertificate = certificate; + mGetEnabledSslProtocols = getEnabledSslProtocols; } public IDisposable Subscribe(IObserver> observer) @@ -65,6 +76,11 @@ private void StartServer() server.Certificate = mCertificate; } + if(mGetEnabledSslProtocols != null) + { + server.EnabledSslProtocols = mGetEnabledSslProtocols(); + } + mServer.Start(connection => { FleckWampTextConnection wampConnection = diff --git a/src/net45/Default/WampSharp.Fleck/Fleck/FleckWebSocketTransport.cs b/src/net45/Default/WampSharp.Fleck/Fleck/FleckWebSocketTransport.cs index 07a5b766a..abcc35fd6 100644 --- a/src/net45/Default/WampSharp.Fleck/Fleck/FleckWebSocketTransport.cs +++ b/src/net45/Default/WampSharp.Fleck/Fleck/FleckWebSocketTransport.cs @@ -1,4 +1,5 @@ using System; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Fleck; using WampSharp.Core.Listener; @@ -22,9 +23,21 @@ public class FleckWebSocketTransport : WebSocketTransport /// given the server address to run at. /// /// The given server address. - /// + /// The certificate to use for secured websockets. public FleckWebSocketTransport(string location, X509Certificate2 certificate = null) - : this(location, null, certificate) + : this(location: location, cookieAuthenticatorFactory: null, certificate: certificate, getEnabledSslProtocols: null) + { + } + + /// + /// Creates a new instance of + /// given the server address to run at. + /// + /// The given server address. + /// The certificate to use for secured websockets. + /// If non-null, used to set Fleck's EnabledSslProtocols. + public FleckWebSocketTransport(string location, X509Certificate2 certificate, Func getEnabledSslProtocols) + : this(location: location, cookieAuthenticatorFactory: null, certificate: certificate, getEnabledSslProtocols: getEnabledSslProtocols) { } @@ -34,15 +47,36 @@ public FleckWebSocketTransport(string location, X509Certificate2 certificate = n /// /// The given server address. /// - /// + /// The certificate to use for secured websockets. protected FleckWebSocketTransport(string location, ICookieAuthenticatorFactory cookieAuthenticatorFactory = null, X509Certificate2 certificate = null) + : this(location: location, cookieAuthenticatorFactory: null, certificate: certificate, getEnabledSslProtocols: null) + { + } + + /// + /// Creates a new instance of + /// given the server address to run at. + /// + /// The given server address. + /// + /// The certificate to use for secured websockets. + /// If non-null, used to set Fleck's EnabledSslProtocols. + protected FleckWebSocketTransport(string location, + ICookieAuthenticatorFactory cookieAuthenticatorFactory = null, + X509Certificate2 certificate = null, + Func getEnabledSslProtocols = null) : base(cookieAuthenticatorFactory) { mServer = new WebSocketServer(location); mServer.Certificate = certificate; - + + if (getEnabledSslProtocols != null) + { + mServer.EnabledSslProtocols = getEnabledSslProtocols(); + } + RouteLogs(); } diff --git a/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetBinaryConnection.cs b/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetBinaryConnection.cs index 39a8c9629..80e9b256d 100644 --- a/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetBinaryConnection.cs +++ b/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetBinaryConnection.cs @@ -1,4 +1,6 @@ -using WampSharp.Core.Message; +using System; +using SuperSocket.ClientEngine; +using WampSharp.Core.Message; using WampSharp.V2.Binding; using WebSocket4Net; @@ -32,7 +34,20 @@ public WebSocket4NetBinaryConnection(WebSocket webSocket, IWampBinaryBindingThe server address to connect to. /// The to use. public WebSocket4NetBinaryConnection(string serverAddress, IWampBinaryBinding binding) - : base(serverAddress, binding) + : this(serverAddress: serverAddress, binding: binding, configureSecurityOptions: null) + { + } + + /// + /// Creates a new instance of + /// given the server address to connect to, the binary binding to use, and an Action + /// to configure WebSocket Security Options. + /// + /// The server address to connect to. + /// The to use. + /// If non-null, called to allow custom setup of the WebSocket security options. + public WebSocket4NetBinaryConnection(string serverAddress, IWampBinaryBinding binding, Action configureSecurityOptions) + : base(serverAddress, binding, configureSecurityOptions) { mBinding = binding; WebSocket.DataReceived += OnDataReceived; diff --git a/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetConnection.cs b/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetConnection.cs index b54ab749a..8e31168ba 100644 --- a/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetConnection.cs +++ b/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetConnection.cs @@ -29,8 +29,19 @@ public WebSocket4NetConnection(WebSocket webSocket, public WebSocket4NetConnection(string serverAddress, IWampBinding binding) + : this(serverAddress: serverAddress, binding: binding, configureSecurityOptions: null) + { + } + + public WebSocket4NetConnection(string serverAddress, + IWampBinding binding, + Action configureSecurityOptions) : this(new WebSocket(serverAddress, binding.Name, WebSocketVersion.None), binding) { + if (configureSecurityOptions != null) + { + configureSecurityOptions(WebSocket.Security); + } } public IWampBinding Binding diff --git a/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetTextConnection.cs b/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetTextConnection.cs index e6397b3a9..4d5b26a3e 100644 --- a/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetTextConnection.cs +++ b/src/net45/Default/WampSharp.WebSocket4Net/WebSocket4Net/WebSocket4NetTextConnection.cs @@ -1,4 +1,6 @@ -using WampSharp.Core.Message; +using System; +using SuperSocket.ClientEngine; +using WampSharp.Core.Message; using WampSharp.V2.Binding; using WebSocket4Net; @@ -32,7 +34,20 @@ public WebSocket4NetTextConnection(WebSocket webSocket, IWampTextBindingThe server address to connect to. /// The to use. public WebSocket4NetTextConnection(string serverAddress, IWampTextBinding binding) - : base(serverAddress, binding) + : this(serverAddress: serverAddress, binding: binding, configureSecurityOptions: null) + { + } + + /// + /// Creates a new instance of + /// given the server address to connect to, the text binding to use, and an Action + /// to configure WebSocket Security Options. + /// + /// The server address to connect to. + /// The to use. + /// If non-null, called to allow custom setup of the WebSocket security options. + public WebSocket4NetTextConnection(string serverAddress, IWampTextBinding binding, Action configureSecurityOptions) + : base(serverAddress, binding, configureSecurityOptions) { mBinding = binding; WebSocket.MessageReceived += OnMessageReceived; diff --git a/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampAuthenticationHost.cs b/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampAuthenticationHost.cs index a1b78488d..780f75147 100644 --- a/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampAuthenticationHost.cs +++ b/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampAuthenticationHost.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using WampSharp.Binding; using WampSharp.Fleck; @@ -68,7 +70,7 @@ public DefaultWampAuthenticationHost /// /// The given bindings. /// - /// + /// The certificate to use for secured websockets. public DefaultWampAuthenticationHost (string location, IWampSessionAuthenticatorFactory sessionAuthenticationFactory, @@ -99,19 +101,54 @@ public DefaultWampAuthenticationHost /// The given used to authenticate /// users given their cookies. /// The certificate to use for secured websockets. + public DefaultWampAuthenticationHost(string location, + IWampSessionAuthenticatorFactory sessionAuthenticationFactory, + IWampRealmContainer realmContainer = null, + IWampUriValidator uriValidator = null, + IEnumerable bindings = null, + ICookieAuthenticatorFactory cookieAuthenticatorFactory = null, + X509Certificate2 certificate = null) + : this(location: location, + sessionAuthenticationFactory: sessionAuthenticationFactory, + realmContainer: null, + uriValidator: null, + bindings: bindings, + cookieAuthenticatorFactory: cookieAuthenticatorFactory, + certificate: certificate, + getEnabledSslProtocols: null) + { + } + + /// + /// Initializes a new instance of listening at + /// the given location with the given bindings and the given + /// . + /// + /// The given location. + /// The + /// used to accept pending clients. + /// The associated with this + /// host. + /// The used to validate uris. + /// The given bindings. + /// The given used to authenticate + /// users given their cookies. + /// The certificate to use for secured websockets. + /// If non-null, used to set Fleck's EnabledSslProtocols. public DefaultWampAuthenticationHost(string location, IWampSessionAuthenticatorFactory sessionAuthenticationFactory, IWampRealmContainer realmContainer = null, IWampUriValidator uriValidator = null, IEnumerable bindings = null, ICookieAuthenticatorFactory cookieAuthenticatorFactory = null, - X509Certificate2 certificate = null) + X509Certificate2 certificate = null, + Func getEnabledSslProtocols = null) : base(sessionAuthenticationFactory, realmContainer, uriValidator) { - bindings = bindings ?? new IWampBinding[] {new JTokenJsonBinding(), new JTokenMsgpackBinding()}; + bindings = bindings ?? new IWampBinding[] { new JTokenJsonBinding(), new JTokenMsgpackBinding() }; this.RegisterTransport( - new FleckAuthenticatedWebSocketTransport(location, cookieAuthenticatorFactory, certificate), + new FleckAuthenticatedWebSocketTransport(location, cookieAuthenticatorFactory, certificate, getEnabledSslProtocols), bindings.ToArray()); } diff --git a/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampHost.cs b/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampHost.cs index 4beaf2581..0a523f85b 100644 --- a/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampHost.cs +++ b/src/net45/WampSharp.Default.Router/WAMP2/V2/DefaultWampHost.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using WampSharp.Binding; using WampSharp.Fleck; @@ -33,7 +35,7 @@ public DefaultWampHost(string location) /// . /// /// The given location. - /// + /// The certificate to use for secured websockets. public DefaultWampHost(string location, X509Certificate2 certificate = null) : this(location: location, bindings: null, certificate: certificate) { @@ -46,7 +48,7 @@ public DefaultWampHost(string location, X509Certificate2 certificate = null) /// /// The given location. /// The given bindings. - /// + /// The certificate to use for secured websockets. public DefaultWampHost(string location, IEnumerable bindings, X509Certificate2 certificate = null) : this(location: location, realmContainer: null, uriValidator: null, bindings: bindings, certificate: certificate) { @@ -61,17 +63,38 @@ public DefaultWampHost(string location, IEnumerable bindings, X509 /// The given . /// The to use to validate uris. /// The given bindings. - /// + /// The certificate to use for secured websockets. public DefaultWampHost(string location, IWampRealmContainer realmContainer = null, IWampUriValidator uriValidator = null, IEnumerable bindings = null, X509Certificate2 certificate = null) + : this(location: location, realmContainer: null, uriValidator: null, bindings: bindings, certificate: certificate, getEnabledSslProtocols: null) + { + } + + /// + /// Initializes a new instance of listening at + /// the given location with the given bindings and the given + /// . + /// + /// The given location. + /// The given . + /// The to use to validate uris. + /// The given bindings. + /// The certificate to use for secured websockets. + /// If non-null, used to set Fleck's EnabledSslProtocols. + public DefaultWampHost(string location, + IWampRealmContainer realmContainer = null, + IWampUriValidator uriValidator = null, + IEnumerable bindings = null, + X509Certificate2 certificate = null, + Func getEnabledSslProtocols = null) : base(realmContainer, uriValidator) { bindings = bindings ?? new IWampBinding[] {new JTokenJsonBinding(), new JTokenMsgpackBinding()}; - this.RegisterTransport(new FleckWebSocketTransport(location, certificate), + this.RegisterTransport(new FleckWebSocketTransport(location, certificate, getEnabledSslProtocols), bindings.ToArray()); } diff --git a/src/net45/WampSharp.WAMP1.Default/WAMP1/V1/WampChannelFactoryExtensions.cs b/src/net45/WampSharp.WAMP1.Default/WAMP1/V1/WampChannelFactoryExtensions.cs index a4f86433c..6da419a68 100644 --- a/src/net45/WampSharp.WAMP1.Default/WAMP1/V1/WampChannelFactoryExtensions.cs +++ b/src/net45/WampSharp.WAMP1.Default/WAMP1/V1/WampChannelFactoryExtensions.cs @@ -1,5 +1,7 @@ -using Newtonsoft.Json; +using System; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using SuperSocket.ClientEngine; using WampSharp.Core.Serialization; using WampSharp.Newtonsoft; using WampSharp.V2.Binding.Parsers; @@ -12,13 +14,25 @@ public static class WampChannelFactoryExtensions { public static IWampChannel CreateChannel(this DefaultWampChannelFactory factory, string address) { - return factory.CreateChannel(address, new JTokenMessageParser(factory.Serializer)); + return factory.CreateChannel(address, (Action)null); + } + + public static IWampChannel CreateChannel(this DefaultWampChannelFactory factory, string address, + Action configureSecurityOptions) + { + return factory.CreateChannel(address, new JTokenMessageParser(factory.Serializer), configureSecurityOptions); } public static IWampChannel CreateChannel(this IWampChannelFactory factory, string address, IWampTextMessageParser parser) { - return factory.CreateChannel(new WebSocket4NetTextConnection(address, - new Wamp1Binding(parser, factory.Formatter))); + return factory.CreateChannel(address, parser, (Action)null); + } + + public static IWampChannel CreateChannel(this IWampChannelFactory factory, string address, + IWampTextMessageParser parser, Action configureSecurityOptions) + { + return factory.CreateChannel(new WebSocket4NetTextConnection(address, + new Wamp1Binding(parser, factory.Formatter), configureSecurityOptions)); } public static IWampChannel CreateChannel(this IWampChannelFactory factory, From 6ac666161bf4ca205e28ffe4a6333c79e1a85577 Mon Sep 17 00:00:00 2001 From: StevenBonePgh Date: Wed, 11 Jan 2017 15:58:01 -0500 Subject: [PATCH 2/2] Add missing space. --- .../WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs b/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs index 92deac600..ad2ff3b7a 100644 --- a/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs +++ b/src/net45/Default/WampSharp.Fleck/Fleck/FleckWampConnectionListener.cs @@ -76,7 +76,7 @@ private void StartServer() server.Certificate = mCertificate; } - if(mGetEnabledSslProtocols != null) + if (mGetEnabledSslProtocols != null) { server.EnabledSslProtocols = mGetEnabledSslProtocols(); }