summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dotnet/client-010/client/client/Client.cs63
-rw-r--r--dotnet/client-010/client/client/ClientConnectionDelegate.cs36
-rw-r--r--dotnet/client-010/client/client/IClient.cs5
-rw-r--r--dotnet/client-010/client/transport/network/io/IoSSLTransport.cs79
-rw-r--r--dotnet/client-010/client/transport/network/io/IoSender.cs7
5 files changed, 137 insertions, 53 deletions
diff --git a/dotnet/client-010/client/client/Client.cs b/dotnet/client-010/client/client/Client.cs
index 864cf65186..fc9ff22191 100644
--- a/dotnet/client-010/client/client/Client.cs
+++ b/dotnet/client-010/client/client/Client.cs
@@ -22,6 +22,7 @@ using System.Threading;
using org.apache.qpid.transport;
using org.apache.qpid.transport.network.io;
using org.apache.qpid.transport.util;
+using System.Security.Cryptography.X509Certificates;
namespace org.apache.qpid.client
{
@@ -35,6 +36,7 @@ namespace org.apache.qpid.client
private IClosedListener _closedListner;
public event EventHandler<ExceptionArgs> ExceptionRaised;
+ public event EventHandler ConnectionOpenOK;
public event EventHandler ConnectionLost;
public bool IsClosed
@@ -61,6 +63,11 @@ namespace org.apache.qpid.client
#region Interface IClient
+ public void Connect(String host, int port, String virtualHost, String username, String password)
+ {
+ Connect(host, port, virtualHost, username, password, "PLAIN");
+ }
+
/// <summary>
/// Establishes a connection with a broker using the provided user auths
///
@@ -70,11 +77,12 @@ namespace org.apache.qpid.client
/// <param name="virtualHost">virtual host name</param>
/// <param name="username">User Name</param>
/// <param name="password">Password</param>
- public void Connect(String host, int port, String virtualHost, String username, String password)
+ /// <param name="mechanism">SASL authentication mechanism, possible values: PLAIN, EXTERNAL, DIGEST-MD5, ANONYMOUS</param>
+ public void Connect(String host, int port, String virtualHost, String username, String password, String mechanism)
{
- _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}", host,
- port, virtualHost, username));
- ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password);
+ _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}; mechanism {4}",
+ host, port, virtualHost, username, mechanism));
+ ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password, mechanism);
ManualResetEvent negotiationComplete = new ManualResetEvent(false);
connectionDelegate.SetCondition(negotiationComplete);
connectionDelegate.VirtualHost = virtualHost;
@@ -99,27 +107,36 @@ namespace org.apache.qpid.client
/// <param name="virtualHost">virtual host name</param>
/// <param name="username">User Name</param>
/// <param name="password">Password</param>
+ /// <param name="mechanism">SASL authentication mechanism, possible values: PLAIN, EXTERNAL, DIGEST-MD5, ANONYMOUS</param>
/// <param name="serverName">Name of the SSL server</param>
/// <param name="certPath">Path to the X509 certificate to be used for client authentication</param>
+ /// <param name="certPass">Password to certificate file, pass null if no password is required</param>
/// <param name="rejectUntrusted">If true connection will not be established if the broker is not trusted</param>
- public void ConnectSSL(String host, int port, String virtualHost, String username, String password, string serverName, string certPath, bool rejectUntrusted)
+ public void ConnectSSL(String host, int port, String virtualHost, String username, String password, String mechanism, string serverName, string certPath, String certPass, bool rejectUntrusted)
{
- _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}", host,
- port, virtualHost, username));
- _log.Debug(String.Format("SSL paramters: serverName: {0}; certPath: {1}; rejectUntrusted: {2}", serverName, certPath, rejectUntrusted));
- ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password);
- ManualResetEvent negotiationComplete = new ManualResetEvent(false);
- connectionDelegate.SetCondition(negotiationComplete);
- connectionDelegate.VirtualHost = virtualHost;
- _conn = IoSSLTransport.Connect(host, port, serverName, certPath, rejectUntrusted, connectionDelegate);
-
- _conn.Send(new ProtocolHeader(1, 0, 10));
- negotiationComplete.WaitOne();
+ _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}; mechanism {4}",
+ host, port, virtualHost, username, mechanism));
+ _log.Debug(String.Format("SSL parameters: serverName: {0}; certPath: {1}; rejectUntrusted: {2}", serverName, certPath, rejectUntrusted));
+ _conn = IoSSLTransport.Connect(host, port, virtualHost, mechanism, serverName, certPath, certPass, rejectUntrusted, this);
+ }
- if (connectionDelegate.Exception != null)
- throw connectionDelegate.Exception;
+ /// <summary>
+ /// Establishes a connection with a broker using SSL
+ ///
+ /// </summary>
+ /// <param name="host">Host name on which a broker is deployed</param>
+ /// <param name="port">Broker port </param>
+ /// <param name="mechanism">SASL authentication mechanism, possible values: PLAIN, EXTERNAL, DIGEST-MD5, ANONYMOUS</param>
+ /// <param name="certificate">X509 certificate to be used for client authentication</param>
+ /// <param name="rejectUntrusted">If true connection will not be established if the broker is not trusted</param>
+ public void ConnectSSL(String host, int port, String mechanism, X509Certificate certificate, bool rejectUntrusted)
+ {
+ _log.Debug(String.Format("Client Connecting to host {0}; port {1}; mechanism {2}",
+ host, port, mechanism));
+ _log.Debug(String.Format("SSL parameters: certSubject: {0}; rejectUntrusted: {1}",
+ certificate.Subject, rejectUntrusted));
- connectionDelegate.SetCondition(null);
+ _conn = IoSSLTransport.Connect(host, port, mechanism, certificate, rejectUntrusted, this);
}
public void Close()
@@ -166,5 +183,13 @@ namespace org.apache.qpid.client
if (ExceptionRaised != null)
ExceptionRaised(this, new ExceptionArgs(exception));
}
+
+ internal void ConnectionOpenOk(Channel context, ConnectionOpenOk mstruct)
+ {
+ if (ConnectionOpenOK != null)
+ {
+ ConnectionOpenOK(this, new EventArgs());
+ }
+ }
}
}
diff --git a/dotnet/client-010/client/client/ClientConnectionDelegate.cs b/dotnet/client-010/client/client/ClientConnectionDelegate.cs
index 9999f5312d..83aac80e83 100644
--- a/dotnet/client-010/client/client/ClientConnectionDelegate.cs
+++ b/dotnet/client-010/client/client/ClientConnectionDelegate.cs
@@ -33,6 +33,9 @@ namespace org.apache.qpid.client
private readonly Client _client;
private string _username;
private string _password;
+
+ // PLAIN SASL mechanism by default
+ private string _mechanism = "PLAIN";
private Exception _exception;
public ClientConnectionDelegate(Client client, string username, string pasword)
@@ -42,6 +45,12 @@ namespace org.apache.qpid.client
_password = pasword;
}
+ public ClientConnectionDelegate(Client client, string username, string pasword, string mechanism)
+ : this(client, username, pasword)
+ {
+ _mechanism = mechanism;
+ }
+
public Exception Exception
{
get { return _exception; }
@@ -64,16 +73,27 @@ namespace org.apache.qpid.client
public override void ConnectionStart(Channel context, ConnectionStart mystruct)
{
- const string mechanism = "PLAIN";
MemoryStream stResponse = new MemoryStream();
- byte[] part = Encoding.UTF8.GetBytes(_username);
- stResponse.WriteByte(0);
- stResponse.Write(part, 0, part.Length);
- stResponse.WriteByte(0);
- part = Encoding.UTF8.GetBytes(_password);
- stResponse.Write(part, 0, part.Length);
+
+ // do not send username and password for EXTERNAL mechanism,
+ // because they are inside a certificate file
+ if (_mechanism != "EXTERNAL")
+ {
+ byte[] part = Encoding.UTF8.GetBytes(_username);
+ stResponse.WriteByte(0);
+ stResponse.Write(part, 0, part.Length);
+ stResponse.WriteByte(0);
+ part = Encoding.UTF8.GetBytes(_password);
+ stResponse.Write(part, 0, part.Length);
+ }
Dictionary<String, Object> props = new Dictionary<String, Object>();
- context.ConnectionStartOk(props, mechanism, stResponse.ToArray(), "utf8");
+ context.ConnectionStartOk(props, _mechanism, stResponse.ToArray(), "utf8");
+ }
+
+ public override void ConnectionOpenOk(Channel context, ConnectionOpenOk mstruct)
+ {
+ base.ConnectionOpenOk(context, mstruct);
+ _client.ConnectionOpenOk(context, mstruct);
}
public override void Closed()
diff --git a/dotnet/client-010/client/client/IClient.cs b/dotnet/client-010/client/client/IClient.cs
index 6fe4a4d4b8..b7b6c26957 100644
--- a/dotnet/client-010/client/client/IClient.cs
+++ b/dotnet/client-010/client/client/IClient.cs
@@ -33,7 +33,8 @@ namespace org.apache.qpid.client
/// <param name="virtualHost">virtualHost the virtual host name</param>
/// <param name="username"> username user name</param>
/// <param name="passwor">password password</param>
- void Connect(String host, int port, String virtualHost, String username, String passwor);
+ void Connect(String host, int port, String virtualHost, String username, String password, String mechanism);
+ void Connect(String host, int port, String virtualHost, String username, String password);
/// <summary>
/// Close this client
@@ -76,6 +77,6 @@ namespace org.apache.qpid.client
/// <param name="serverName">Name of the SSL server</param>
/// <param name="certPath">Path to the X509 certificate to be used for client authentication</param>
/// <param name="rejectUntrusted">If true connection will not be established if the broker is not trusted</param>
- void ConnectSSL(String host, int port, String virtualHost, String username, String password, string serverName, string certPath, bool rejectUntrusted);
+ void ConnectSSL(String host, int port, String virtualHost, String username, String password, String mechanism, string serverName, string certPath, String certPass, bool rejectUntrusted);
}
}
diff --git a/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs b/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs
index 8b36693bc2..b6c7940a1d 100644
--- a/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs
+++ b/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs
@@ -22,7 +22,10 @@ using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+
using org.apache.qpid.transport.util;
+using org.apache.qpid.client;
namespace org.apache.qpid.transport.network.io
{
@@ -41,16 +44,48 @@ namespace org.apache.qpid.transport.network.io
private Connection m_con;
private readonly bool _rejectUntrusted;
- public static Connection Connect(String host, int port, string serverName, string certPath, bool rejectUntrusted, ConnectionDelegate conndel)
- {
- IIoTransport transport = new IoSSLTransport(host, port, serverName, certPath, rejectUntrusted, conndel);
- return transport.Connection;
+ public static Connection Connect(String host, int port, String mechanism, X509Certificate certificate, bool rejectUntrusted, Client client)
+ {
+ ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(client, string.Empty, string.Empty, mechanism);
+ ManualResetEvent negotiationComplete = new ManualResetEvent(true);
+ connectionDelegate.SetCondition(negotiationComplete);
+ connectionDelegate.VirtualHost = string.Empty;
+
+ IIoTransport transport = new IoSSLTransport(host, port, certificate, rejectUntrusted, connectionDelegate);
+
+ Connection _conn = transport.Connection;
+ _conn.Send(new ProtocolHeader(1, 0, 10));
+ negotiationComplete.WaitOne();
+
+ if (connectionDelegate.Exception != null)
+ throw connectionDelegate.Exception;
+
+ connectionDelegate.SetCondition(null);
+
+ return _conn;
+ }
+
+ public static Connection Connect(String host, int port, String virtualHost, String mechanism, string serverName, string certPath, String certPass, bool rejectUntrusted, Client client)
+ {
+ // create certificate object based on whether or not password is null
+ X509Certificate cert;
+ if (certPass != null)
+ {
+ cert = new X509Certificate2(certPath, certPass);
+ }
+ else
+ {
+ cert = X509Certificate.CreateFromCertFile(certPath);
+ }
+
+ return Connect(host, port, mechanism, cert, rejectUntrusted, client);
}
- public IoSSLTransport(String host, int port, string serverName, string certPath, bool rejectUntrusted, ConnectionDelegate conndel)
+ public IoSSLTransport(String host, int port, X509Certificate certificate, bool rejectUntrusted, ConnectionDelegate conndel)
{
_rejectUntrusted = rejectUntrusted;
- CreateSocket(host, port, serverName, certPath);
+ CreateSocket(host, port);
+ CreateSSLStream(host, Socket, certificate);
Sender = new IoSender(this, QUEUE_SIZE, TIMEOUT);
Receiver = new IoReceiver(Stream, Socket.ReceiveBufferSize*2, TIMEOUT);
Assembler assembler = new Assembler();
@@ -101,7 +136,7 @@ namespace org.apache.qpid.transport.network.io
#region Private Support Functions
- private void CreateSocket(String host, int port, string serverName, string certPath)
+ private void CreateSocket(String host, int port)
{
TcpClient socket;
try
@@ -128,23 +163,21 @@ namespace org.apache.qpid.transport.network.io
}
catch (Exception e)
{
- throw new TransportException("Error connecting to broker", e);
+ throw new TransportException(string.Format("Error connecting to broker: {0}", e.Message));
}
+ }
+
+ private void CreateSSLStream(String host, TcpClient socket, X509Certificate certificate)
+ {
try
{
//Initializes a new instance of the SslStream class using the specified Stream, stream closure behavior, certificate validation delegate and certificate selection delegate
- SslStream sslStream = new SslStream(socket.GetStream(), false, ValidateServerCertificate, LocalCertificateSelection);
- if (certPath != null)
- {
- X509CertificateCollection col = new X509CertificateCollection();
- X509Certificate cert = X509Certificate.CreateFromCertFile(certPath);
- col.Add(cert);
- sslStream.AuthenticateAsClient(serverName, col, SslProtocols.Default, true);
- }
- else
- {
- sslStream.AuthenticateAsClient(serverName);
- }
+ SslStream sslStream = new SslStream(socket.GetStream(), false, ValidateServerCertificate, LocalCertificateSelection);
+
+ X509CertificateCollection certCol = new X509CertificateCollection();
+ certCol.Add(certificate);
+
+ sslStream.AuthenticateAsClient(host, certCol, SslProtocols.Default, true);
Stream = sslStream;
}
catch (AuthenticationException e)
@@ -153,9 +186,10 @@ namespace org.apache.qpid.transport.network.io
if (e.InnerException != null)
{
log.Warn("Inner exception: {0}", e.InnerException.Message);
+ e = new AuthenticationException(e.InnerException.Message, e.InnerException);
}
socket.Close();
- throw new TransportException("Authentication failed - closing the connection.");
+ throw new TransportException(string.Format("Authentication failed, closing connection to broker: {0}", e.Message));
}
}
@@ -184,7 +218,8 @@ namespace org.apache.qpid.transport.network.io
string[] acceptableIssuers
)
{
- return remoteCertificate;
+ // used to be return null; in the original version
+ return localCertificates[0];
}
#endregion
diff --git a/dotnet/client-010/client/transport/network/io/IoSender.cs b/dotnet/client-010/client/transport/network/io/IoSender.cs
index 4491d2e98b..025b782a12 100644
--- a/dotnet/client-010/client/transport/network/io/IoSender.cs
+++ b/dotnet/client-010/client/transport/network/io/IoSender.cs
@@ -27,6 +27,7 @@ namespace org.apache.qpid.transport.network.io
public sealed class IoSender : IIoSender<MemoryStream>
{
private static readonly Logger log = Logger.Get(typeof (IoReceiver));
+ private readonly IIoTransport ioTransport;
private readonly Stream bufStream;
private bool closed;
private readonly Mutex mutClosed = new Mutex();
@@ -37,6 +38,7 @@ namespace org.apache.qpid.transport.network.io
public IoSender(IIoTransport transport, int queueSize, int timeout)
{
this.timeout = timeout;
+ ioTransport = transport;
bufStream = transport.Stream;
queue = new CircularBuffer<byte[]>(queueSize);
thread = new Thread(Go);
@@ -71,7 +73,7 @@ namespace org.apache.qpid.transport.network.io
int length = (int)_tobeSent.Position;
byte[] buf = new byte[length];
_tobeSent.Seek(0, SeekOrigin.Begin);
- _tobeSent.Read(buf, 0, length);
+ _tobeSent.Read(buf, 0, length);
queue.Enqueue(buf);
// bufStream.Write(buf, 0, length);
// _tobeSent = new MemoryStream();
@@ -125,7 +127,8 @@ namespace org.apache.qpid.transport.network.io
}
catch (Exception e)
{
- Console.WriteLine(e);
+ closed = true;
+ ioTransport.Connection.On_ReceivedException(this, new ExceptionArgs(e));
}
}
}