Author: tabish
Date: Tue Mar  9 19:16:00 2010
New Revision: 921061

URL: http://svn.apache.org/viewvc?rev=921061&view=rev
Log:
https://issues.apache.org/activemq/browse/AMQNET-239

Add an SslTransport to the Stomp Client and throw an exception when Ssl is 
specified on NETCF platforms.

Added:
    
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransport.cs
   (with props)
    
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransportFactory.cs
   (with props)
Modified:
    
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransport.cs
    
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransportFactory.cs
    
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/TransportFactory.cs
    activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/vs2008-stomp.csproj

Added: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransport.cs
URL: 
http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransport.cs?rev=921061&view=auto
==============================================================================
--- 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransport.cs
 (added)
+++ 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransport.cs
 Tue Mar  9 19:16:00 2010
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !NETCF
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Net.Security;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Apache.NMS.Stomp.Transport.Tcp
+{
+    public class SslTransport : TcpTransport
+    {
+        private string clientCertLocation;
+        private string clientCertPassword;
+        
+        private bool acceptInvalidBrokerCert = false;
+        
+        private SslStream sslStream;
+
+        public SslTransport(Uri location, Socket socket, IWireFormat 
wireFormat) :
+            base(location, socket, wireFormat)
+        {
+        }
+
+        ~SslTransport()
+        {
+            Dispose(false);
+        }
+
+        /// <summary>
+        /// Indicates the location of the Client Certificate to use when the 
Broker
+        /// is configured for Client Auth (not common).  The SslTransport will 
supply
+        /// this certificate to the SslStream via the SelectLocalCertificate 
method.
+        /// </summary>
+        public string ClientCertLocation
+        {
+            get { return this.clientCertLocation; }
+            set { this.clientCertLocation = value; }
+        }
+
+        /// <summary>
+        /// Password for the Client Certificate specified via configuration.
+        /// </summary>
+        public string ClientCertPassword
+        {
+            get { return this.clientCertPassword; }
+            set { this.clientCertPassword = value; }
+        }
+       
+        /// <summary>
+        /// Indicates if the SslTransport should ignore any errors in the 
supplied Broker
+        /// certificate and connect anyway, this is useful in testing with a 
default AMQ
+        /// broker certificate that is self signed.
+        /// </summary>
+        public bool AcceptInvalidBrokerCert
+        {
+            get { return this.acceptInvalidBrokerCert; }
+            set { this.acceptInvalidBrokerCert = value; }
+        }
+        
+        protected override Stream CreateSocketStream()
+        {
+            if(this.sslStream != null)
+            {
+                return this.sslStream;
+            }
+            
+            LocalCertificateSelectionCallback clientCertSelect = null;
+            
+            if(this.clientCertLocation != null )
+            {
+                clientCertSelect = new 
LocalCertificateSelectionCallback(SelectLocalCertificate);
+            }
+
+            this.sslStream = new SslStream(
+                new NetworkStream(this.socket), 
+                false,
+                new 
RemoteCertificateValidationCallback(ValidateServerCertificate),
+                clientCertSelect );
+
+            try
+            {
+                Tracer.Debug("Authorizing as Client for Server: " + 
this.RemoteAddress.Host);
+                sslStream.AuthenticateAsClient(this.RemoteAddress.Host);
+                Tracer.Debug("Server is Authenticated = " + 
sslStream.IsAuthenticated);
+                Tracer.Debug("Server is Encrypted = " + 
sslStream.IsEncrypted);                
+            }
+            catch(Exception e)
+            {
+                Tracer.ErrorFormat("Exception: {0}", e.Message);
+                if(e.InnerException != null)
+                {
+                    Tracer.ErrorFormat("Inner exception: {0}", 
e.InnerException.Message);
+                }
+                Tracer.Error("Authentication failed - closing the 
connection.");
+
+                throw e;
+            }
+
+            return sslStream;
+        }
+
+        private bool ValidateServerCertificate(object sender,
+                                               X509Certificate certificate,
+                                               X509Chain chain,
+                                               SslPolicyErrors sslPolicyErrors)
+        {
+            Tracer.DebugFormat("ValidateServerCertificate: Issued By {0}", 
certificate.Issuer);
+            if(sslPolicyErrors == SslPolicyErrors.None)
+            {
+                return true;
+            }
+
+            Tracer.WarnFormat("Certificate error: {0}", 
sslPolicyErrors.ToString());
+            if(sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
+            {
+                Tracer.Error("Chain Status errors: ");
+                foreach( X509ChainStatus status in chain.ChainStatus )
+                {
+                    Tracer.Error("*** Chain Status error: " + status.Status);
+                    Tracer.Error("*** Chain Status information: " + 
status.StatusInformation);
+                }
+            }
+            else if(sslPolicyErrors == 
SslPolicyErrors.RemoteCertificateNameMismatch)
+            {
+                Tracer.Error("Mismatch between Remote Cert Name.");
+            }
+            else if(sslPolicyErrors == 
SslPolicyErrors.RemoteCertificateNotAvailable)
+            {
+                Tracer.Error("The Remote Certificate was not Available.");
+            }
+
+            // Configuration may or may not allow us to connect with an 
invliad broker cert.
+            return AcceptInvalidBrokerCert;
+        }
+        
+        private X509Certificate SelectLocalCertificate(object sender,
+                                                       string targetHost, 
+                                                       
X509CertificateCollection localCertificates, 
+                                                       X509Certificate 
remoteCertificate, 
+                                                       string[] 
acceptableIssuers)
+        {    
+            Tracer.Debug("Client is selecting a local certificate.");
+        
+            X509Certificate2 certificate = new X509Certificate2( 
clientCertLocation, clientCertPassword );
+                        
+            return certificate;
+        }
+        
+    }
+}
+
+#endif

Propchange: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransport.cs
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransportFactory.cs
URL: 
http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransportFactory.cs?rev=921061&view=auto
==============================================================================
--- 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransportFactory.cs
 (added)
+++ 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransportFactory.cs
 Tue Mar  9 19:16:00 2010
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Apache.NMS.Stomp.Transport.Tcp
+{
+       public class SslTransportFactory : TcpTransportFactory
+       {
+        private string clientCertLocation;
+        private string clientCertPassword;
+        private bool acceptInvalidBrokerCert = false;
+        
+        public SslTransportFactory() : base()
+        {
+        }
+
+        public string ClientCertLocation
+        {
+            get { return this.clientCertLocation; }
+            set { this.clientCertLocation = value; }
+        }
+
+        public string ClientCertPassword
+        {
+            get { return this.clientCertPassword; }
+            set { this.clientCertPassword = value; }
+        }        
+
+        public bool AcceptInvalidBrokerCert
+        {
+            get { return this.acceptInvalidBrokerCert; }
+            set { this.acceptInvalidBrokerCert = value; }
+        }
+        
+               protected override ITransport DoCreateTransport(Uri location, 
Socket socket, IWireFormat wireFormat )
+               {
+            Tracer.Debug("Creating new instance of the SSL Transport.");
+#if !NETCF
+            SslTransport transport = new SslTransport(location, socket, 
wireFormat);
+            
+            transport.ClientCertLocation = ClientCertLocation;
+            transport.ClientCertPassword = ClientCertPassword;
+            transport.AcceptInvalidBrokerCert = AcceptInvalidBrokerCert;
+            
+            return transport;
+#else
+            throw new NotSupportedException("SslTransport not implemented on 
the .NET Compact Framework.");
+#endif
+               }               
+       }
+}

Propchange: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/SslTransportFactory.cs
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransport.cs
URL: 
http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransport.cs?rev=921061&r1=921060&r2=921061&view=diff
==============================================================================
--- 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransport.cs
 (original)
+++ 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransport.cs
 Tue Mar  9 19:16:00 2010
@@ -29,8 +29,8 @@ namespace Apache.NMS.Stomp.Transport.Tcp
     /// </summary>
     public class TcpTransport : ITransport
     {
-        private readonly object myLock = new object();
-        private readonly Socket socket;
+        protected readonly object myLock = new object();
+        protected readonly Socket socket;
         private IWireFormat wireformat;
         private BinaryReader socketReader;
         private BinaryWriter socketWriter;
@@ -60,6 +60,11 @@ namespace Apache.NMS.Stomp.Transport.Tcp
             Dispose(false);
         }
 
+        protected virtual Stream CreateSocketStream()
+        {
+            return new NetworkStream(socket);
+        }
+
         /// <summary>
         /// Method Start
         /// </summary>
@@ -83,10 +88,11 @@ namespace Apache.NMS.Stomp.Transport.Tcp
 
                     started = true;
 
-                    // As reported in AMQ-988 it appears that NetworkStream is 
not thread safe
-                    // so lets use an instance for each of the 2 streams
-                    socketWriter = new BinaryWriter(new NetworkStream(socket));
-                    socketReader = new BinaryReader(new NetworkStream(socket));
+                    // Initialize our Read and Writer instances.  Its not 
actually necessary
+                    // to have two distinct NetworkStream instances but for 
now the TcpTransport
+                    // will continue to do so for legacy reasons.
+                    socketWriter = new BinaryWriter(CreateSocketStream());
+                    socketReader = new BinaryReader(CreateSocketStream());
 
                     // now lets create the background read thread
                     readThread = new Thread(new ThreadStart(ReadLoop));

Modified: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransportFactory.cs
URL: 
http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransportFactory.cs?rev=921061&r1=921060&r2=921061&view=diff
==============================================================================
--- 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransportFactory.cs
 (original)
+++ 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/Tcp/TcpTransportFactory.cs
 Tue Mar  9 19:16:00 2010
@@ -119,7 +119,7 @@ namespace Apache.NMS.Stomp.Transport.Tcp
                        IWireFormat wireformat = new StompWireFormat();
                        // Set wireformat. properties on the wireformat owned 
by the tcpTransport
                        URISupport.SetProperties(wireformat, map, 
"wireFormat.");
-                       ITransport transport = new TcpTransport(location, 
socket, wireformat);
+            ITransport transport = DoCreateTransport(location, socket, 
wireformat);
 
                        wireformat.Transport = transport;
 
@@ -151,6 +151,15 @@ namespace Apache.NMS.Stomp.Transport.Tcp
 
                #endregion
 
+        /// <summary>
+        /// Override in a subclass to create the specific type of transport 
that is
+        /// being implemented.
+        /// </summary>
+        protected virtual ITransport DoCreateTransport(Uri location, Socket 
socket, IWireFormat wireFormat )
+        {
+            return new TcpTransport(location, socket, wireFormat);
+        }
+
                // DISCUSSION: Caching host entries may not be the best 
strategy when using the
                // failover protocol.  The failover protocol needs to be very 
dynamic when looking
                // up hostnames at runtime.  If old hostname->IP mappings are 
kept around, this may

Modified: 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/TransportFactory.cs
URL: 
http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/TransportFactory.cs?rev=921061&r1=921060&r2=921061&view=diff
==============================================================================
--- 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/TransportFactory.cs
 (original)
+++ 
activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/src/main/csharp/Transport/TransportFactory.cs
 Tue Mar  9 19:16:00 2010
@@ -80,6 +80,9 @@ namespace Apache.NMS.Stomp.Transport
                 case "tcp":
                     factory = new TcpTransportFactory();
                     break;
+                case "ssl":
+                    factory = new SslTransportFactory();
+                    break;
                 default:
                     throw new NMSConnectionException(String.Format("The 
transport {0} is not supported.", scheme));
                 }

Modified: activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/vs2008-stomp.csproj
URL: 
http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/vs2008-stomp.csproj?rev=921061&r1=921060&r2=921061&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/vs2008-stomp.csproj 
(original)
+++ activemq/activemq-dotnet/Apache.NMS.Stomp/trunk/vs2008-stomp.csproj Tue Mar 
 9 19:16:00 2010
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"; ToolsVersion="3.5">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -31,6 +31,7 @@
     <BootstrapperEnabled>true</BootstrapperEnabled>
     <SignAssembly>true</SignAssembly>
     <AssemblyOriginatorKeyFile>keyfile\NMSKey.snk</AssemblyOriginatorKeyFile>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' 
">
     <DebugSymbols>true</DebugSymbols>
@@ -143,6 +144,8 @@
     <Compile Include="src\main\csharp\Protocol\StompFrame.cs" />
     <Compile Include="src\main\csharp\Protocol\IPrimitiveMapMarshaler.cs" />
     <Compile Include="src\main\csharp\Protocol\XmlPrimitiveMapMarshaler.cs" />
+    <Compile Include="src\main\csharp\Transport\Tcp\SslTransport.cs" />
+    <Compile Include="src\main\csharp\Transport\Tcp\SslTransportFactory.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="keyfile\NMSKey.snk" />


Reply via email to