Skip to content
Permalink
Browse files
http://issues.apache.org/activemq/browse/AMQNET-239
Updates to better support client authentication when required by the server.
  • Loading branch information
Timothy A. Bish committed Mar 31, 2010
1 parent b0cf6c6 commit 40b009f0de69d408dd2216bbe456f165bdc3d58d
Showing 2 changed files with 96 additions and 27 deletions.
@@ -29,7 +29,9 @@ namespace Apache.NMS.Stomp.Transport.Tcp
{
public class SslTransport : TcpTransport
{
private string clientCertLocation;
private string serverName;
private string clientCertSubject;
private string clientCertFilename;
private string clientCertPassword;

private bool acceptInvalidBrokerCert = false;
@@ -46,15 +48,32 @@ public class SslTransport : TcpTransport
Dispose(false);
}

/// <summary>
/// Indicates the name of the Server's Certificate. By default the Host name
/// of the remote server is used, however if this doesn't match the name of the
/// Server's certificate then this option can be set to override the default.
/// </summary>
public string ServerName
{
get { return this.serverName; }
set { this.serverName = value; }
}

public string ClientCertSubject
{
get { return this.clientCertSubject; }
set { this.clientCertSubject = value; }
}

/// <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
public string ClientCertFilename
{
get { return this.clientCertLocation; }
set { this.clientCertLocation = value; }
get { return this.clientCertFilename; }
set { this.clientCertFilename = value; }
}

/// <summary>
@@ -83,24 +102,19 @@ protected override Stream CreateSocketStream()
{
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 );
new LocalCertificateSelectionCallback(SelectLocalCertificate) );

try
{
Tracer.Debug("Authorizing as Client for Server: " + this.RemoteAddress.Host);
sslStream.AuthenticateAsClient(this.RemoteAddress.Host);

string remoteCertName = this.serverName ?? this.RemoteAddress.Host;
Tracer.Debug("Authorizing as Client for Server: " + remoteCertName);
sslStream.AuthenticateAsClient(remoteCertName, LoadCertificates(), SslProtocols.Default, false);
Tracer.Debug("Server is Authenticated = " + sslStream.IsAuthenticated);
Tracer.Debug("Server is Encrypted = " + sslStream.IsEncrypted);
}
@@ -159,14 +173,53 @@ protected override Stream CreateSocketStream()
X509Certificate remoteCertificate,
string[] acceptableIssuers)
{
Tracer.Debug("Client is selecting a local certificate.");

X509Certificate2 certificate = new X509Certificate2( clientCertLocation, clientCertPassword );

return certificate;
Tracer.DebugFormat("Client is selecting a local certificate from {0} possibilities.", localCertificates.Count);

if(localCertificates.Count == 1)
{
Tracer.Debug("Client has selected certificate with Subject = " + localCertificates[0].Subject);
return localCertificates[0];
}
else if(localCertificates.Count > 1 && this.clientCertSubject != null)
{
foreach(X509Certificate2 certificate in localCertificates)
{
Tracer.Debug("Checking Client Certificate := " + certificate.ToString());
if(String.Compare(certificate.Subject, this.clientCertSubject, true) == 0)
{
Tracer.Debug("Client has selected certificate with Subject = " + certificate.Subject);
return certificate;
}
}
}

Tracer.Debug("Client did not select a Certificate, returning null.");
return null;
}

private X509Certificate2Collection LoadCertificates()
{
X509Certificate2Collection collection = new X509Certificate2Collection();

if(!String.IsNullOrEmpty(this.clientCertFilename))
{
Tracer.Debug("Attempting to load Client Certificate from file := " + this.clientCertFilename);
X509Certificate2 certificate = new X509Certificate2(this.clientCertFilename, this.clientCertPassword);
Tracer.Debug("Loaded Client Certificate := " + certificate.ToString());

collection.Add(certificate);
}
else
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

collection = store.Certificates;
}

return collection;
}

}
}

#endif
#endif
@@ -23,18 +23,32 @@ namespace Apache.NMS.Stomp.Transport.Tcp
{
public class SslTransportFactory : TcpTransportFactory
{
private string clientCertLocation;
private string serverName;
private string clientCertSubject;
private string clientCertFilename;
private string clientCertPassword;
private bool acceptInvalidBrokerCert = false;

public SslTransportFactory() : base()
{
}

public string ClientCertLocation
public string ServerName
{
get { return this.clientCertLocation; }
set { this.clientCertLocation = value; }
get { return this.serverName; }
set { this.serverName = value; }
}

public string ClientCertSubject
{
get { return this.clientCertSubject; }
set { this.clientCertSubject = value; }
}

public string ClientCertFilename
{
get { return this.clientCertFilename; }
set { this.clientCertFilename = value; }
}

public string ClientCertPassword
@@ -55,9 +69,11 @@ protected override ITransport DoCreateTransport(Uri location, Socket socket, IWi
#if !NETCF
SslTransport transport = new SslTransport(location, socket, wireFormat);

transport.ClientCertLocation = ClientCertLocation;
transport.ClientCertPassword = ClientCertPassword;
transport.AcceptInvalidBrokerCert = AcceptInvalidBrokerCert;
transport.ClientCertSubject = this.clientCertSubject;
transport.ClientCertFilename = this.clientCertFilename;
transport.ClientCertPassword = this.clientCertPassword;
transport.ServerName = this.serverName;
transport.AcceptInvalidBrokerCert = this.acceptInvalidBrokerCert;

return transport;
#else

0 comments on commit 40b009f

Please sign in to comment.