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" />