#109 expose IPrincipal on connection when identify is established through SASL or transport
This commit is contained in:
Родитель
96d009ee96
Коммит
79af04dccc
1
amqp.sln
1
amqp.sln
|
@ -15,6 +15,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
Amqp.Micro.nuspec = Amqp.Micro.nuspec
|
||||
Amqp.Net.nuspec = Amqp.Net.nuspec
|
||||
build.cmd = build.cmd
|
||||
dnx\Amqp.DotNet\project.json = dnx\Amqp.DotNet\project.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amqp.Net", "src\Amqp.Net.csproj", "{92153715-1D99-43B1-B291-470CF91A156D}"
|
||||
|
|
|
@ -64,7 +64,9 @@
|
|||
"System.Reflection.Emit.Lightweight": "4.0.1-beta-23409",
|
||||
"System.Reflection.Extensions": "4.0.1-beta-23409",
|
||||
"System.Reflection.TypeExtensions": "4.0.1-beta-23409",
|
||||
"System.Runtime.Serialization.Primitives": "4.0.11-beta-23409"
|
||||
"System.Runtime.Serialization.Primitives": "4.0.11-beta-23409",
|
||||
"System.Security.Claims": "4.0.1-beta-23509",
|
||||
"System.Security.Principal": "4.0.1-beta-23509"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
<Compile Include="Listener\AttachContext.cs" />
|
||||
<Compile Include="Listener\ContextState.cs" />
|
||||
<Compile Include="Listener\FlowContext.cs" />
|
||||
<Compile Include="Listener\IAuthenticated.cs" />
|
||||
<Compile Include="Listener\X509Identity.cs" />
|
||||
<Compile Include="Listener\LinkCollection.cs" />
|
||||
<Compile Include="Listener\ILinkProcessor.cs" />
|
||||
<Compile Include="Listener\LinkEndpoint.cs" />
|
||||
|
@ -71,8 +73,8 @@
|
|||
<Compile Include="Net\ConnectionFactoryBase.cs" />
|
||||
<Compile Include="Properties\Version.cs" />
|
||||
<Compile Include="Sasl\SaslExternalProfile.cs" />
|
||||
<Compile Include="Sasl\SaslPlainMechanism.cs" />
|
||||
<Compile Include="Sasl\SaslMechanism.cs" />
|
||||
<Compile Include="Listener\SaslPlainMechanism.cs" />
|
||||
<Compile Include="Listener\SaslMechanism.cs" />
|
||||
<Compile Include="Listener\IContainer.cs" />
|
||||
<Compile Include="Listener\ListenerSession.cs" />
|
||||
<Compile Include="Listener\ListenerConnection.cs" />
|
||||
|
|
|
@ -51,8 +51,6 @@
|
|||
<Compile Include="Net\TypeExtensions.cs" />
|
||||
<Compile Include="Properties\Version.cs" />
|
||||
<Compile Include="Sasl\SaslExternalProfile.cs" />
|
||||
<Compile Include="Sasl\SaslPlainMechanism.cs" />
|
||||
<Compile Include="Sasl\SaslMechanism.cs" />
|
||||
<Compile Include="Delivery.cs" />
|
||||
<Compile Include="Framing\Accepted.cs" />
|
||||
<Compile Include="Framing\ApplicationProperties.cs" />
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
<Compile Include="Listener\AttachContext.cs" />
|
||||
<Compile Include="Listener\ContextState.cs" />
|
||||
<Compile Include="Listener\FlowContext.cs" />
|
||||
<Compile Include="Listener\IAuthenticated.cs" />
|
||||
<Compile Include="Listener\LinkCollection.cs" />
|
||||
<Compile Include="Listener\ILinkProcessor.cs" />
|
||||
<Compile Include="Listener\LinkEndpoint.cs" />
|
||||
|
@ -58,6 +59,9 @@
|
|||
<Compile Include="Listener\IMessageProcessor.cs" />
|
||||
<Compile Include="Listener\Context.cs" />
|
||||
<Compile Include="Listener\ListenerLink.cs" />
|
||||
<Compile Include="Listener\SaslMechanism.cs" />
|
||||
<Compile Include="Listener\SaslPlainMechanism.cs" />
|
||||
<Compile Include="Listener\X509Identity.cs" />
|
||||
<Compile Include="Net\ResourceManager.cs" />
|
||||
<Compile Include="Net\BufferManager.cs" />
|
||||
<Compile Include="Net\SocketExtensions.cs" />
|
||||
|
@ -70,8 +74,6 @@
|
|||
<Compile Include="Net\ConnectionFactoryBase.cs" />
|
||||
<Compile Include="Properties\Version.cs" />
|
||||
<Compile Include="Sasl\SaslExternalProfile.cs" />
|
||||
<Compile Include="Sasl\SaslPlainMechanism.cs" />
|
||||
<Compile Include="Sasl\SaslMechanism.cs" />
|
||||
<Compile Include="Listener\IContainer.cs" />
|
||||
<Compile Include="Listener\ListenerSession.cs" />
|
||||
<Compile Include="Listener\ListenerConnection.cs" />
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace Amqp.Listener
|
|||
#endif
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Sasl;
|
||||
|
@ -190,13 +191,27 @@ namespace Amqp.Listener
|
|||
|
||||
async Task HandleTransportAsync(IAsyncTransport transport)
|
||||
{
|
||||
IPrincipal principal = null;
|
||||
if (this.saslSettings != null)
|
||||
{
|
||||
ListenerSaslProfile profile = new ListenerSaslProfile(this);
|
||||
transport = await profile.OpenAsync(null, this.BufferManager, transport);
|
||||
principal = profile.GetPrincipal();
|
||||
}
|
||||
|
||||
Connection connection = new ListenerConnection(this, this.address, transport);
|
||||
var connection = new ListenerConnection(this, this.address, transport);
|
||||
if (principal == null)
|
||||
{
|
||||
// SASL principal preferred. If not present, check transport.
|
||||
IAuthenticated authenticated = transport as IAuthenticated;
|
||||
if (authenticated != null)
|
||||
{
|
||||
principal = authenticated.Principal;
|
||||
}
|
||||
}
|
||||
|
||||
connection.Principal = principal;
|
||||
|
||||
bool shouldClose = false;
|
||||
lock (this.connections)
|
||||
{
|
||||
|
@ -355,9 +370,15 @@ namespace Amqp.Listener
|
|||
this.listener = listener;
|
||||
}
|
||||
|
||||
public SaslProfile InnerProfile
|
||||
public IPrincipal GetPrincipal()
|
||||
{
|
||||
get { return this.innerProfile; }
|
||||
IAuthenticated authenticated = this.innerProfile as IAuthenticated;
|
||||
if (authenticated != null)
|
||||
{
|
||||
return authenticated.Principal;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
|
@ -499,7 +520,7 @@ namespace Amqp.Listener
|
|||
protected virtual Task<IAsyncTransport> CreateTransportAsync(Socket socket)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<IAsyncTransport>();
|
||||
tcs.SetResult(new TcpTransport(socket, this.Listener.BufferManager));
|
||||
tcs.SetResult(new ListenerTcpTransport(socket, this.Listener.BufferManager));
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
|
@ -558,7 +579,36 @@ namespace Amqp.Listener
|
|||
this.Listener.sslSettings.Protocols, this.Listener.sslSettings.CheckCertificateRevocation);
|
||||
}
|
||||
|
||||
return new TcpTransport(sslStream, this.Listener.BufferManager);
|
||||
return new ListenerTcpTransport(sslStream, this.Listener.BufferManager);
|
||||
}
|
||||
}
|
||||
|
||||
class ListenerTcpTransport : TcpTransport, IAuthenticated
|
||||
{
|
||||
public ListenerTcpTransport(Socket socket, IBufferManager bufferManager)
|
||||
: base(bufferManager)
|
||||
{
|
||||
this.socketTransport = new TcpSocket(this, socket);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
public ListenerTcpTransport(SslStream sslStream, IBufferManager bufferManager)
|
||||
: base(bufferManager)
|
||||
{
|
||||
this.socketTransport = new SslSocket(this, sslStream);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
if (sslStream.RemoteCertificate != null)
|
||||
{
|
||||
this.Principal = new GenericPrincipal(
|
||||
new X509Identity(sslStream.RemoteCertificate),
|
||||
new string[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public IPrincipal Principal
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,7 +647,7 @@ namespace Amqp.Listener
|
|||
try
|
||||
{
|
||||
var wsContext = await context.AcceptWebSocketAsync(WebSocketTransport.WebSocketSubProtocol);
|
||||
var wsTransport = new WebSocketTransport(wsContext.WebSocket);
|
||||
var wsTransport = new ListenerWebSocketTransport(wsContext);
|
||||
await this.listener.HandleTransportAsync(wsTransport);
|
||||
}
|
||||
catch(Exception exception)
|
||||
|
@ -627,6 +677,21 @@ namespace Amqp.Listener
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ListenerWebSocketTransport : WebSocketTransport, IAuthenticated
|
||||
{
|
||||
public ListenerWebSocketTransport(HttpListenerWebSocketContext context)
|
||||
: base(context.WebSocket)
|
||||
{
|
||||
this.Principal = context.User;
|
||||
}
|
||||
|
||||
public IPrincipal Principal
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System.Security.Principal;
|
||||
|
||||
interface IAuthenticated
|
||||
{
|
||||
IPrincipal Principal { get; }
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using Amqp.Framing;
|
||||
|
||||
|
@ -35,6 +36,16 @@ namespace Amqp.Listener
|
|||
this.listener = listener;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a IPrincipal object for the connection. If the value is null,
|
||||
/// the connection is not authenticated.
|
||||
/// </summary>
|
||||
public IPrincipal Principal
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
internal ConnectionListener Listener
|
||||
{
|
||||
get { return this.listener; }
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using Amqp.Sasl;
|
||||
|
||||
abstract class SaslMechanism
|
||||
{
|
||||
public abstract string Name { get; }
|
|
@ -15,12 +15,14 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Sasl
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Types;
|
||||
using Amqp.Sasl;
|
||||
using System.Security.Principal;
|
||||
|
||||
class SaslPlainMechanism : SaslMechanism
|
||||
{
|
||||
|
@ -43,7 +45,7 @@ namespace Amqp.Sasl
|
|||
return new SaslPlainProfile(this);
|
||||
}
|
||||
|
||||
class SaslPlainProfile : SaslProfile
|
||||
class SaslPlainProfile : SaslProfile, IAuthenticated
|
||||
{
|
||||
readonly SaslPlainMechanism mechanism;
|
||||
|
||||
|
@ -52,6 +54,12 @@ namespace Amqp.Sasl
|
|||
this.mechanism = mechanism;
|
||||
}
|
||||
|
||||
public IPrincipal Principal
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
protected override ITransport UpgradeTransport(ITransport transport)
|
||||
{
|
||||
return transport;
|
||||
|
@ -85,6 +93,10 @@ namespace Amqp.Sasl
|
|||
string.Equals(this.mechanism.user, items[1], StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(this.mechanism.password, items[2], StringComparison.Ordinal))
|
||||
{
|
||||
this.Principal = new GenericPrincipal(
|
||||
new GenericIdentity(string.IsNullOrEmpty(items[2]) ? items[0] : items[2], this.mechanism.Name),
|
||||
new string[0]);
|
||||
|
||||
return SaslCode.Ok;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// ------------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
|
||||
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
namespace Amqp.Listener
|
||||
{
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an client identity established by SSL client certificate authentication.
|
||||
/// </summary>
|
||||
public class X509Identity : IIdentity
|
||||
{
|
||||
internal X509Identity(X509Certificate certificate)
|
||||
{
|
||||
this.Certificate = certificate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the client certificate.
|
||||
/// </summary>
|
||||
public X509Certificate Certificate
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of authentication used. ("X509").
|
||||
/// </summary>
|
||||
public string AuthenticationType
|
||||
{
|
||||
get { return "X509"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the user has been authenticated.
|
||||
/// </summary>
|
||||
public bool IsAuthenticated
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the identity.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return this.Certificate.Subject; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,13 +24,13 @@ namespace Amqp
|
|||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
sealed class TcpTransport : IAsyncTransport
|
||||
class TcpTransport : IAsyncTransport
|
||||
{
|
||||
static readonly RemoteCertificateValidationCallback noneCertValidator = (a, b, c, d) => true;
|
||||
readonly IBufferManager bufferManager;
|
||||
Connection connection;
|
||||
Writer writer;
|
||||
IAsyncTransport socketTransport;
|
||||
protected Writer writer;
|
||||
protected IAsyncTransport socketTransport;
|
||||
|
||||
public TcpTransport()
|
||||
: this(null)
|
||||
|
@ -42,22 +42,6 @@ namespace Amqp
|
|||
this.bufferManager = bufferManager;
|
||||
}
|
||||
|
||||
// called by listener
|
||||
public TcpTransport(Socket socket, IBufferManager bufferManager)
|
||||
: this(bufferManager)
|
||||
{
|
||||
this.socketTransport = new TcpSocket(this, socket);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
// called by listener
|
||||
public TcpTransport(SslStream sslStream, IBufferManager bufferManager)
|
||||
: this(bufferManager)
|
||||
{
|
||||
this.socketTransport = new SslSocket(this, sslStream);
|
||||
this.writer = new Writer(this, this.socketTransport);
|
||||
}
|
||||
|
||||
public void Connect(Connection connection, Address address, bool noVerification)
|
||||
{
|
||||
this.connection = connection;
|
||||
|
@ -203,7 +187,7 @@ namespace Amqp
|
|||
this.writer.DisposeQueuedBuffers();
|
||||
}
|
||||
|
||||
class TcpSocket : IAsyncTransport
|
||||
protected class TcpSocket : IAsyncTransport
|
||||
{
|
||||
readonly static EventHandler<SocketAsyncEventArgs> onWriteComplete = OnWriteComplete;
|
||||
readonly TcpTransport transport;
|
||||
|
@ -353,7 +337,7 @@ namespace Amqp
|
|||
}
|
||||
}
|
||||
|
||||
class SslSocket : IAsyncTransport
|
||||
protected class SslSocket : IAsyncTransport
|
||||
{
|
||||
readonly TcpTransport transport;
|
||||
readonly SslStream sslStream;
|
||||
|
@ -439,7 +423,7 @@ namespace Amqp
|
|||
}
|
||||
}
|
||||
|
||||
sealed class Writer
|
||||
protected class Writer
|
||||
{
|
||||
readonly TcpTransport owner;
|
||||
readonly IAsyncTransport transport;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Amqp
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
sealed class WebSocketTransport : IAsyncTransport
|
||||
class WebSocketTransport : IAsyncTransport
|
||||
{
|
||||
public const string WebSocketSubProtocol = "AMQPWSB10";
|
||||
public const string WebSockets = "WS";
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using Amqp;
|
||||
using Amqp.Framing;
|
||||
using Amqp.Listener;
|
||||
using Amqp.Sasl;
|
||||
using Amqp.Types;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
|
@ -58,6 +60,7 @@ namespace Test.Amqp
|
|||
this.Uri = new Uri("amqp://guest:guest@localhost:5765");
|
||||
|
||||
this.host = new ContainerHost(new List<Uri>() { this.Uri }, null, this.Uri.UserInfo);
|
||||
this.host.Listeners[0].SASL.EnableExternalMechanism = true;
|
||||
this.host.Open();
|
||||
}
|
||||
|
||||
|
@ -476,6 +479,70 @@ namespace Test.Amqp
|
|||
connection.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ContainerHostPlainPrincipalTest()
|
||||
{
|
||||
string name = MethodInfo.GetCurrentMethod().Name;
|
||||
ListenerLink link = null;
|
||||
var linkProcessor = new TestLinkProcessor();
|
||||
linkProcessor.OnLinkAttached += a => link = a;
|
||||
this.host.RegisterLinkProcessor(linkProcessor);
|
||||
|
||||
var connection = new Connection(Address);
|
||||
var session = new Session(connection);
|
||||
var sender = new SenderLink(session, name, name);
|
||||
sender.Send(new Message("msg1"), SendTimeout);
|
||||
connection.Close();
|
||||
|
||||
Assert.IsTrue(link != null, "link is null");
|
||||
var listenerConnection = (ListenerConnection)link.Session.Connection;
|
||||
Assert.IsTrue(listenerConnection.Principal != null, "principal is null");
|
||||
Assert.IsTrue(listenerConnection.Principal.Identity.AuthenticationType == "PLAIN", "wrong auth type");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ContainerHostX509PrincipalTest()
|
||||
{
|
||||
string name = MethodInfo.GetCurrentMethod().Name;
|
||||
string address = "amqps://localhost:5676";
|
||||
X509Certificate2 cert = GetCertificate(StoreLocation.LocalMachine, StoreName.My, "localhost");
|
||||
ContainerHost sslHost = new ContainerHost(new Uri(address));
|
||||
sslHost.Listeners[0].SSL.Certificate = cert;
|
||||
sslHost.Listeners[0].SSL.ClientCertificateRequired = true;
|
||||
sslHost.Listeners[0].SSL.RemoteCertificateValidationCallback = (a, b, c, d) => true;
|
||||
sslHost.Listeners[0].SASL.EnableExternalMechanism = true;
|
||||
ListenerLink link = null;
|
||||
var linkProcessor = new TestLinkProcessor();
|
||||
linkProcessor.OnLinkAttached += a => link = a;
|
||||
sslHost.RegisterLinkProcessor(linkProcessor);
|
||||
sslHost.Open();
|
||||
|
||||
try
|
||||
{
|
||||
var factory = new ConnectionFactory();
|
||||
factory.SSL.RemoteCertificateValidationCallback = (a, b, c, d) => true;
|
||||
factory.SSL.ClientCertificates.Add(cert);
|
||||
factory.SASL.Profile = SaslProfile.External;
|
||||
var connection = factory.CreateAsync(new Address(address)).Result;
|
||||
var session = new Session(connection);
|
||||
var sender = new SenderLink(session, name, name);
|
||||
sender.Send(new Message("msg1"), SendTimeout);
|
||||
connection.Close();
|
||||
|
||||
Assert.IsTrue(link != null, "link is null");
|
||||
var listenerConnection = (ListenerConnection)link.Session.Connection;
|
||||
Assert.IsTrue(listenerConnection.Principal != null, "principal is null");
|
||||
Assert.IsTrue(listenerConnection.Principal.Identity.AuthenticationType == "X509", "wrong auth type");
|
||||
|
||||
X509Identity identity = (X509Identity)listenerConnection.Principal.Identity;
|
||||
Assert.IsTrue(identity.Certificate != null, "certificate is null");
|
||||
}
|
||||
finally
|
||||
{
|
||||
sslHost.Close();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InvalidAddresses()
|
||||
{
|
||||
|
@ -509,6 +576,23 @@ namespace Test.Amqp
|
|||
connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
static X509Certificate2 GetCertificate(StoreLocation storeLocation, StoreName storeName, string certFindValue)
|
||||
{
|
||||
X509Store store = new X509Store(storeName, storeLocation);
|
||||
store.Open(OpenFlags.OpenExistingOnly);
|
||||
X509Certificate2Collection collection = store.Certificates.Find(
|
||||
X509FindType.FindBySubjectName,
|
||||
certFindValue,
|
||||
false);
|
||||
if (collection.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("No certificate can be found using the find value " + certFindValue);
|
||||
}
|
||||
|
||||
store.Close();
|
||||
return collection[0];
|
||||
}
|
||||
}
|
||||
|
||||
class TestMessageProcessor : IMessageProcessor
|
||||
|
@ -569,8 +653,15 @@ namespace Test.Amqp
|
|||
|
||||
class TestLinkProcessor : ILinkProcessor
|
||||
{
|
||||
public Action<ListenerLink> OnLinkAttached;
|
||||
|
||||
public void Process(AttachContext attachContext)
|
||||
{
|
||||
if (this.OnLinkAttached != null)
|
||||
{
|
||||
this.OnLinkAttached(attachContext.Link);
|
||||
}
|
||||
|
||||
attachContext.Complete(new TestLinkEndpoint(), attachContext.Attach.Role ? 0 : 30);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче