Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Multifactor.Core.Ldap.Name;
using Multifactor.Core.Ldap.Schema;
using Multifactor.Radius.Adapter.v2.Core;
using Multifactor.Radius.Adapter.v2.Core.Auth;
using Multifactor.Radius.Adapter.v2.Core.Auth.PreAuthMode;
using Multifactor.Radius.Adapter.v2.Core.Configuration.Client;
using Multifactor.Radius.Adapter.v2.Core.FirstFactor;
using Multifactor.Radius.Adapter.v2.Core.FirstFactor.BindNameFormat;
using Multifactor.Radius.Adapter.v2.Core.FirstFactor.LdapAuth;
using Multifactor.Radius.Adapter.v2.Core.Ldap;
using Multifactor.Radius.Adapter.v2.Core.Radius.Packet;
using Multifactor.Radius.Adapter.v2.Infrastructure.Pipeline.Context;
using Multifactor.Radius.Adapter.v2.Tests.Fixture;


namespace Multifactor.Radius.Adapter.v2.Tests.FirstFactorAuthTests;

[Collection("LDAP")]
public class LdapFirstFactorProcessorTests
public class PapAuthProcessorTests
{
[Theory]
[InlineData("ActiveDirectoryCredentials.txt", "|", LdapImplementation.ActiveDirectory)]
//[InlineData("FreeIpaCredentials.txt", "|", LdapImplementation.FreeIPA)]
public async Task LdapFirstFactorProcessor_CorrectCredentials_ShouldAccept(string config, string separator, LdapImplementation ldapImplementation)
[Fact]
public async Task LdapFirstFactorProcessor_CorrectCredentials_ShouldAccept()
{
//Arrange
var sensitiveData = GetConfig(config, separator);
var formatterProviderMock = new LdapBindNameFormatterProvider([new ActiveDirectoryFormatter(), new FreeIpaFormatter()]);

var processor = new LdapFirstFactorProcessor(new CustomLdapConnectionFactory(), formatterProviderMock, NullLogger<LdapFirstFactorProcessor>.Instance);
var sensitiveData = GetConfig();
var processor = new PapAuthProcessor(new CustomLdapConnectionFactory(), new Mock<ILdapBindNameFormatterProvider>().Object, NullLogger<PapAuthProcessor>.Instance);

var contextMock = new Mock<IRadiusPipelineExecutionContext>();
var packetMock = new Mock<IRadiusPacket>();
Expand All @@ -40,6 +33,7 @@ public async Task LdapFirstFactorProcessor_CorrectCredentials_ShouldAccept(strin
serverSettings.Setup(x => x.ConnectionString).Returns(sensitiveData["ConnectionString"]);
serverSettings.Setup(x => x.BindTimeoutInSeconds).Returns(30);
contextMock.Setup(x => x.LdapServerConfiguration).Returns(serverSettings.Object);
contextMock.Setup(x => x.LdapSchema).Returns(new Mock<ILdapSchema>().Object);

var authState = new AuthenticationState();
contextMock.Setup(x => x.AuthenticationState).Returns(authState);
Expand All @@ -48,27 +42,15 @@ public async Task LdapFirstFactorProcessor_CorrectCredentials_ShouldAccept(strin
contextMock.Setup(x => x.UserNameTransformRules).Returns(transformRules);
contextMock.Setup(x => x.PreAuthnMode).Returns(PreAuthModeDescriptor.Default);
contextMock.Setup(x => x.Passphrase).Returns(UserPassphrase.Parse(sensitiveData["Password"], PreAuthModeDescriptor.Default));
contextMock.Setup(x => x.LdapSchema.LdapServerImplementation).Returns(ldapImplementation);
var profile = new Mock<ILdapProfile>();
profile.Setup(x => x.Dn).Returns(new DistinguishedName(sensitiveData["UserDn"]));
contextMock.Setup(x => x.UserLdapProfile).Returns(profile.Object);

//Act
await processor.ProcessFirstFactor(contextMock.Object);

//Assert
Assert.Equal(AuthenticationStatus.Accept, authState.FirstFactorStatus);
var result = await processor.Auth(contextMock.Object);
Assert.True(result.IsSuccess);
}

[Theory]
[InlineData("ActiveDirectoryCredentials.txt", "|")]
[InlineData("FreeIpaCredentials.txt", "|")]
public async Task LdapFirstFactorProcessor_IncorrectPassword_ShouldReject(string config, string separator)

[Fact]
public async Task LdapFirstFactorProcessor_IncorrectPassword_ShouldReject()
{
//Arrange
var sensitiveData = GetConfig(config, separator);
var formatterProviderMock = new LdapBindNameFormatterProvider([]);
var processor = new LdapFirstFactorProcessor(new CustomLdapConnectionFactory(), formatterProviderMock, NullLogger<LdapFirstFactorProcessor>.Instance);
var sensitiveData = GetConfig();
var processor = new PapAuthProcessor(new CustomLdapConnectionFactory(), new Mock<ILdapBindNameFormatterProvider>().Object, NullLogger<PapAuthProcessor>.Instance);
var contextMock = new Mock<IRadiusPipelineExecutionContext>();
var packetMock = new Mock<IRadiusPacket>();
var serverSettings = new Mock<ILdapServerConfiguration>();
Expand All @@ -84,23 +66,17 @@ public async Task LdapFirstFactorProcessor_IncorrectPassword_ShouldReject(string
contextMock.Setup(x => x.UserNameTransformRules).Returns(transformRules);
contextMock.Setup(x => x.PreAuthnMode).Returns(PreAuthModeDescriptor.Default);
contextMock.Setup(x => x.Passphrase).Returns(UserPassphrase.Parse("123456", PreAuthModeDescriptor.Default));
contextMock.Setup(x => x.LdapSchema).Returns(new Mock<ILdapSchema>().Object);

//Act
await processor.ProcessFirstFactor(contextMock.Object);

//Assert
Assert.Equal(AuthenticationStatus.Reject, authState.FirstFactorStatus);
var result = await processor.Auth(contextMock.Object);
Assert.False(result.IsSuccess);
}

[Theory]
[InlineData("ActiveDirectoryCredentials.txt", "|")]
[InlineData("FreeIpaCredentials.txt", "|")]
public async Task LdapFirstFactorProcessor_IncorrectLogin_ShouldReject(string config, string separator)

[Fact]
public async Task LdapFirstFactorProcessor_IncorrectLogin_ShouldReject()
{
//Arrange
var sensitiveData = GetConfig(config, separator);
var formatterProviderMock = new LdapBindNameFormatterProvider([]);
var processor = new LdapFirstFactorProcessor(new CustomLdapConnectionFactory(), formatterProviderMock, NullLogger<LdapFirstFactorProcessor>.Instance);
var sensitiveData = GetConfig();
var processor = new PapAuthProcessor(new CustomLdapConnectionFactory(), new Mock<ILdapBindNameFormatterProvider>().Object, NullLogger<PapAuthProcessor>.Instance);
var contextMock = new Mock<IRadiusPipelineExecutionContext>();
var packetMock = new Mock<IRadiusPacket>();
var serverSettings = new Mock<ILdapServerConfiguration>();
Expand All @@ -116,16 +92,14 @@ public async Task LdapFirstFactorProcessor_IncorrectLogin_ShouldReject(string co
contextMock.Setup(x => x.UserNameTransformRules).Returns(transformRules);
contextMock.Setup(x => x.PreAuthnMode).Returns(PreAuthModeDescriptor.Default);
contextMock.Setup(x => x.Passphrase).Returns(UserPassphrase.Parse("123456", PreAuthModeDescriptor.Default));
contextMock.Setup(x => x.LdapSchema).Returns(new Mock<ILdapSchema>().Object);

//Act
await processor.ProcessFirstFactor(contextMock.Object);

//Assert
Assert.Equal(AuthenticationStatus.Reject, authState.FirstFactorStatus);
var result = await processor.Auth(contextMock.Object);
Assert.False(result.IsSuccess);
}

private Dictionary<string, string> GetConfig(string config, string separator)
private Dictionary<string, string> GetConfig()
{
return ConfigUtils.GetConfigSensitiveData(config, separator);
return ConfigUtils.GetConfigSensitiveData("LdapFirstFactorProcessorTests.txt", "|");
}
}
Original file line number Diff line number Diff line change
@@ -1,123 +1,99 @@
using System.DirectoryServices.Protocols;
using System.Net;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Multifactor.Core.Ldap.Connection;
using Multifactor.Core.Ldap.Schema;
using Multifactor.Radius.Adapter.v2.Core;
using Multifactor.Radius.Adapter.v2.Core.Auth;
using Multifactor.Radius.Adapter.v2.Core.Auth.PreAuthMode;
using Multifactor.Radius.Adapter.v2.Core.Configuration.Client;
using Multifactor.Radius.Adapter.v2.Core.FirstFactor;
using Multifactor.Radius.Adapter.v2.Core.FirstFactor.BindNameFormat;
using Multifactor.Radius.Adapter.v2.Core.Ldap;
using Multifactor.Radius.Adapter.v2.Core.FirstFactor.LdapAuth;
using Multifactor.Radius.Adapter.v2.Core.Radius;
using Multifactor.Radius.Adapter.v2.Core.Radius.Packet;
using Multifactor.Radius.Adapter.v2.Infrastructure.Pipeline.Context;
using Multifactor.Radius.Adapter.v2.Tests.Fixture;
using ILdapConnectionFactory = Multifactor.Core.Ldap.Connection.LdapConnectionFactory.ILdapConnectionFactory;

namespace Multifactor.Radius.Adapter.v2.Tests.Unit.FirstFactorAuth;

public class LdapFirstFactorProcessorTests
{
[Theory]
[ClassData(typeof(EmptyStringsListInput))]
public async Task LdapFirstFactorProcessor_EmptyLogin_ShouldReject(string login)
[Fact]
public async Task LdapFirstFactorProcessor_NoRequestPacket_ShouldThrow()
{
//Arrange
var formatterProviderMock = new LdapBindNameFormatterProvider([]);
var processor = new LdapFirstFactorProcessor(new CustomLdapConnectionFactory(), formatterProviderMock, NullLogger<LdapFirstFactorProcessor>.Instance);
var authProviderMock = new Mock<ILdapAuthProvider>();
var processor = new LdapFirstFactorProcessor(authProviderMock.Object, NullLogger<LdapFirstFactorProcessor>.Instance);

var contextMock = new Mock<IRadiusPipelineExecutionContext>();
var packetMock = new Mock<IRadiusPacket>();
var authState = new AuthenticationState();
var transformRules = new UserNameTransformRules();
packetMock.Setup(x => x.UserName).Returns(login);
packetMock.Setup(x => x.TryGetUserPassword()).Returns("correctLogin");
packetMock.Setup(x => x.Identifier).Returns(0);
contextMock.Setup(x => x.RequestPacket).Returns(packetMock.Object);
contextMock.Setup(x => x.RemoteEndpoint).Returns(IPEndPoint.Parse("127.0.0.1:8080"));
contextMock.Setup(x => x.LdapServerConfiguration).Returns(new Mock<ILdapServerConfiguration>().Object);
contextMock.Setup(x => x.AuthenticationState).Returns(authState);
contextMock.Setup(x => x.UserNameTransformRules).Returns(transformRules);
contextMock.Setup(x => x.PreAuthnMode).Returns(PreAuthModeDescriptor.Default);

contextMock.Setup(x => x.RequestPacket).Returns(() => null);

await Assert.ThrowsAsync<ArgumentNullException>(() => processor.ProcessFirstFactor(contextMock.Object));
}

[Fact]
public async Task LdapFirstFactorProcessor_NoLdapServerConfiguration_ShouldThrow()
{
var authProviderMock = new Mock<ILdapAuthProvider>();
var processor = new LdapFirstFactorProcessor(authProviderMock.Object, NullLogger<LdapFirstFactorProcessor>.Instance);

//Act
await processor.ProcessFirstFactor(contextMock.Object);
var contextMock = new Mock<IRadiusPipelineExecutionContext>();

//Assert
Assert.Equal(AuthenticationStatus.Reject, authState.FirstFactorStatus);
contextMock.Setup(x => x.LdapServerConfiguration).Returns(() => null);
contextMock.Setup(x => x.RequestPacket).Returns(new Mock<IRadiusPacket>().Object);

await Assert.ThrowsAsync<InvalidOperationException>(() => processor.ProcessFirstFactor(contextMock.Object));
}

[Fact]
public async Task LdapFirstFactorProcessor_NoAuthProcessors_ShouldThrow()
{
var authProviderMock = new Mock<ILdapAuthProvider>();
authProviderMock.Setup(x => x.GetLdapAuthProcessor(It.IsAny<AuthenticationType>())).Returns(() => null);

var processor = new LdapFirstFactorProcessor(authProviderMock.Object, NullLogger<LdapFirstFactorProcessor>.Instance);

[Theory]
[ClassData(typeof(EmptyStringsListInput))]
public async Task LdapFirstFactorProcessor_EmptyPassword_ShouldReject(string pwd)
var contextMock = new Mock<IRadiusPipelineExecutionContext>();

contextMock.Setup(x => x.LdapServerConfiguration).Returns(new Mock<ILdapServerConfiguration>().Object);
contextMock.Setup(x => x.RequestPacket).Returns(new Mock<IRadiusPacket>().Object);

await Assert.ThrowsAsync<InvalidOperationException>(() => processor.ProcessFirstFactor(contextMock.Object));
}

[Fact]
public async Task LdapFirstFactorProcessor_AuthFailed_ShouldReject()
{
//Arrange
var formatterProviderMock = new LdapBindNameFormatterProvider([]);
var processor = new LdapFirstFactorProcessor(new CustomLdapConnectionFactory(), formatterProviderMock, NullLogger<LdapFirstFactorProcessor>.Instance);
var authProviderMock = new Mock<ILdapAuthProvider>();
var authProcessorMock = new Mock<ILdapAuthProcessor>();
authProcessorMock.Setup(x=> x.Auth(It.IsAny<IRadiusPipelineExecutionContext>())).ReturnsAsync(new AuthResult() { IsSuccess = false });
authProviderMock.Setup(x => x.GetLdapAuthProcessor(It.IsAny<AuthenticationType>())).Returns(authProcessorMock.Object);

var processor = new LdapFirstFactorProcessor(authProviderMock.Object, NullLogger<LdapFirstFactorProcessor>.Instance);

var contextMock = new Mock<IRadiusPipelineExecutionContext>();
var packetMock = new Mock<IRadiusPacket>();

var authState = new AuthenticationState();
var transformRules = new UserNameTransformRules();
packetMock.Setup(x => x.UserName).Returns("correctLogin");
packetMock.Setup(x => x.TryGetUserPassword()).Returns(pwd);
packetMock.Setup(x => x.Identifier).Returns(0);
contextMock.Setup(x => x.RequestPacket).Returns(packetMock.Object);
contextMock.Setup(x => x.RemoteEndpoint).Returns(IPEndPoint.Parse("127.0.0.1:8080"));
contextMock.Setup(x => x.LdapServerConfiguration).Returns(new Mock<ILdapServerConfiguration>().Object);
contextMock.Setup(x => x.RequestPacket).Returns(new Mock<IRadiusPacket>().Object);
contextMock.Setup(x => x.AuthenticationState).Returns(authState);
contextMock.Setup(x => x.UserNameTransformRules).Returns(transformRules);
contextMock.Setup(x => x.PreAuthnMode).Returns(PreAuthModeDescriptor.Default);
contextMock.Setup(x => x.Passphrase).Returns(UserPassphrase.Parse("123456", PreAuthModeDescriptor.Default));

//Act
await processor.ProcessFirstFactor(contextMock.Object);

//Assert
Assert.Equal(AuthenticationStatus.Reject, authState.FirstFactorStatus);
}

[Fact]
public async Task LdapFirstFactorProcessor_MustChangePasswordResponse_ShouldReject()
public async Task LdapFirstFactorProcessor_AuthSucceed_ShouldReject()
{
//Arrange
var factoryMock = new Mock<ILdapConnectionFactory>();
factoryMock.Setup(x => x.CreateConnection(It.IsAny<LdapConnectionOptions>())).Throws(GetLdapException);
factoryMock.Setup(x => x.TargetPlatform).Returns(OSPlatform.Windows);
var factory = new CustomLdapConnectionFactory([factoryMock.Object]);
var formatterProviderMock = new Mock<ILdapBindNameFormatterProvider>();
var processor = new LdapFirstFactorProcessor(factory, formatterProviderMock.Object, NullLogger<LdapFirstFactorProcessor>.Instance);
var authProviderMock = new Mock<ILdapAuthProvider>();
var authProcessorMock = new Mock<ILdapAuthProcessor>();
authProcessorMock.Setup(x=> x.Auth(It.IsAny<IRadiusPipelineExecutionContext>())).ReturnsAsync(new AuthResult() { IsSuccess = true });
authProviderMock.Setup(x => x.GetLdapAuthProcessor(It.IsAny<AuthenticationType>())).Returns(authProcessorMock.Object);

var processor = new LdapFirstFactorProcessor(authProviderMock.Object, NullLogger<LdapFirstFactorProcessor>.Instance);

var contextMock = new Mock<IRadiusPipelineExecutionContext>();
var packetMock = new Mock<IRadiusPacket>();
var serverSettings = new Mock<ILdapServerConfiguration>();

var authState = new AuthenticationState();
var transformRules = new UserNameTransformRules();
packetMock.Setup(x => x.UserName).Returns("user");
packetMock.Setup(x => x.TryGetUserPassword()).Returns("pwd");
contextMock.Setup(x => x.RequestPacket).Returns(packetMock.Object);
serverSettings.Setup(x => x.ConnectionString).Returns("your.domain");
serverSettings.Setup(x => x.BindTimeoutInSeconds).Returns(30);
contextMock.Setup(x => x.LdapServerConfiguration).Returns(serverSettings.Object);
contextMock.Setup(x => x.LdapServerConfiguration).Returns(new Mock<ILdapServerConfiguration>().Object);
contextMock.Setup(x => x.RequestPacket).Returns(new Mock<IRadiusPacket>().Object);
contextMock.Setup(x => x.AuthenticationState).Returns(authState);
contextMock.Setup(x => x.UserNameTransformRules).Returns(transformRules);
contextMock.Setup(x => x.PreAuthnMode).Returns(PreAuthModeDescriptor.Default);
contextMock.SetupProperty(x => x.MustChangePasswordDomain);
contextMock.Setup(x => x.Passphrase).Returns(UserPassphrase.Parse("123456", PreAuthModeDescriptor.Default));
contextMock.Setup(x => x.LdapSchema.LdapServerImplementation).Returns(LdapImplementation.ActiveDirectory);
var context = contextMock.Object;

//Act
await processor.ProcessFirstFactor(context);

//Assert
Assert.Equal(AuthenticationStatus.Reject, authState.FirstFactorStatus);
Assert.Equal("your.domain", context.MustChangePasswordDomain);
}

private LdapException GetLdapException()
{
var ex = new LdapException(1, "message", "data 773");
return ex;
await processor.ProcessFirstFactor(contextMock.Object);
Assert.Equal(AuthenticationStatus.Accept, authState.FirstFactorStatus);
}
}
Loading