blob: 4cea01cfac53a382b182f8ea71c26afc834d4ab7 [file] [log] [blame]
/*
* 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 Apache.Qpid.Proton.Engine.Exceptions;
using Apache.Qpid.Proton.Engine.Sasl;
using Apache.Qpid.Proton.Engine.Sasl.Client;
using Apache.Qpid.Proton.Test.Driver;
using Apache.Qpid.Proton.Types.Security;
using NUnit.Framework;
namespace Apache.Qpid.Proton.Engine.Implementation
{
[TestFixture, Timeout(20000)]
public class ProtonSaslClientTest : ProtonEngineTestSupport
{
[Test]
public void TestSaslAnonymousConnection()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
peer.ExpectSASLAnonymousConnect();
peer.ExpectOpen().Respond();
peer.ExpectClose().Respond();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator(null, null);
IConnection connection = engine.Start().Open();
connection.Close();
peer.WaitForScriptToComplete();
Assert.IsNull(failure);
}
[Test]
public void TestDriverThrowsIfServerStateRequestedAfterClientStateActivated()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
peer.ExpectSASLAnonymousConnect();
peer.ExpectOpen().Respond();
peer.ExpectClose().Respond();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator(null, null);
Assert.Throws<InvalidOperationException>(() => engine.SaslDriver.Server());
IConnection connection = engine.Start().Open();
connection.Close();
peer.WaitForScriptToComplete();
Assert.IsNull(failure);
}
[Test]
public void TestSaslAnonymousConnectionWhenPlainAlsoOfferedButNoCredentialsGiven()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
peer.ExpectSASLHeader().RespondWithSASLHeader();
peer.RemoteSaslMechanisms().WithMechanisms("PLAIN", "ANONYMOUS").Queue();
peer.ExpectSaslInit().WithMechanism("ANONYMOUS");
peer.RemoteSaslOutcome().WithCode(Test.Driver.Codec.Security.SaslCode.Ok).Queue();
peer.ExpectAMQPHeader().RespondWithAMQPHeader();
peer.ExpectOpen().Respond();
peer.ExpectClose().Respond();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator(null, null);
IConnection connection = engine.Start().Open();
connection.Close();
peer.WaitForScriptToComplete();
Assert.IsNull(failure);
}
[Test]
public void TestSaslPlainConnection()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
// Expect a PLAIN connection
String user = "user";
String pass = "qwerty123456";
peer.ExpectSASLPlainConnect(user, pass);
peer.ExpectOpen().Respond();
peer.ExpectClose().Respond();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator(user, pass);
IConnection connection = engine.Start().Open();
connection.Close();
peer.WaitForScriptToComplete();
Assert.IsNull(failure);
}
[Test]
public void TestSaslPlainConnectionWhenUnknownMechanismsOfferedBeforeIt()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
// Expect a PLAIN connection
String user = "user";
String pass = "qwerty123456";
peer.ExpectSASLHeader().RespondWithSASLHeader();
peer.RemoteSaslMechanisms().WithMechanisms("UNKNOWN", "PLAIN", "ANONYMOUS").Queue();
peer.ExpectSaslInit().WithMechanism("PLAIN").WithInitialResponse(peer.SaslPlainInitialResponse(user, pass));
peer.RemoteSaslOutcome().WithCode(Test.Driver.Codec.Security.SaslCode.Ok).Queue();
peer.ExpectAMQPHeader().RespondWithAMQPHeader();
peer.ExpectOpen().Respond();
peer.ExpectClose().Respond();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator(user, pass);
IConnection connection = engine.Start().Open();
connection.Close();
peer.WaitForScriptToComplete();
Assert.IsNull(failure);
}
[Test]
public void TestDefaultClientSaslMismatchBetweenClientAndServer()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
peer.ExpectSASLHeader().RespondWithSASLHeader();
peer.RemoteSaslMechanisms().WithMechanisms("PLAIN").Queue();
// Default client only know about ANONYMOUS
engine.SaslDriver.Client();
IConnection connection = engine.Start().Open();
try
{
connection.Close();
Assert.Fail("Engine should have failed");
}
catch (EngineFailedException)
{
// Expected as engine failed but was not shutdown
}
peer.WaitForScriptToComplete();
Assert.IsTrue(engine.IsFailed);
Assert.IsNotNull(failure);
}
[Test]
public void TestSaslXOauth2Connection()
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
// Expect a XOAUTH2 connection
String user = "user";
String pass = "eyB1c2VyPSJ1c2VyIiB9";
peer.ExpectSaslXOauth2Connect(user, pass);
peer.ExpectOpen().Respond();
peer.ExpectClose().Respond();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator(user, pass);
IConnection connection = engine.Start().Open();
connection.Close();
peer.WaitForScriptToComplete();
Assert.IsNull(failure);
}
[Test]
public void TestSaslFailureCodesFailEngine()
{
DoSaslFailureCodesTestImpl(SaslCode.Auth);
DoSaslFailureCodesTestImpl(SaslCode.Sys);
DoSaslFailureCodesTestImpl(SaslCode.SysPerm);
DoSaslFailureCodesTestImpl(SaslCode.SysTemp);
}
private void DoSaslFailureCodesTestImpl(SaslCode saslFailureCode)
{
IEngine engine = IEngineFactory.Proton.CreateEngine();
engine.ErrorHandler((result) => failure = result.FailureCause);
ProtonTestConnector peer = CreateTestPeer(engine);
peer.ExpectSASLHeader().RespondWithSASLHeader();
peer.RemoteSaslMechanisms().WithMechanisms("PLAIN", "ANONYMOUS").Queue();
peer.ExpectSaslInit().WithMechanism("PLAIN");
peer.RemoteSaslOutcome().WithCode(((byte)saslFailureCode)).Queue();
engine.SaslDriver.Client().Authenticator = CreateSaslPlainAuthenticator("user", "pass");
engine.Start().Open();
peer.WaitForScriptToComplete();
Assert.IsNotNull(failure);
Assert.IsFalse(engine.IsShutdown);
Assert.IsTrue(engine.IsFailed);
Assert.AreEqual(failure, engine.FailureCause);
Assert.IsTrue(failure is SaslException);
}
private SaslAuthenticator CreateSaslPlainAuthenticator(string user, string password)
{
ISaslCredentialsProvider credentials =
new DelegatedSaslCredentialsProvider().UsernameSupplier(() => user)
.PasswordSupplier(() => password);
return new SaslAuthenticator(credentials);
}
}
}