Skip to content

Commit

Permalink
Partial privacy mode was added (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
apashkov-ext authored Apr 25, 2023
1 parent e73a30e commit 9a453d1
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//Please see licence at
//https://github.com/MultifactorLab/MultiFactor.Radius.Adapter/blob/master/LICENSE.md

using MultiFactor.Radius.Adapter.Configuration.Features.PrivacyModeFeature;
using MultiFactor.Radius.Adapter.Server;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -51,7 +52,7 @@ public ClientConfiguration()
/// </summary>
public bool BypassSecondFactorWhenApiUnreachable { get; set; }

public PrivacyMode PrivacyMode { get; set; }
public PrivacyModeDescriptor PrivacyMode { get; set; }


#region ActiveDirectory Authentication settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public enum PrivacyMode
/// <summary>
/// Disable all but identity
/// </summary>
Full
Full,

/// <summary>
/// Disable all but identity and specified fields.
/// </summary>
Partial
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Linq;

namespace MultiFactor.Radius.Adapter.Configuration.Features.PrivacyModeFeature
{
public class PrivacyModeDescriptor
{
private readonly string[] _fields;
public PrivacyMode Mode { get; }

public bool HasField(string field)
{
if (string.IsNullOrWhiteSpace(field))
{
return false;
}

return _fields.Any(x => x.Equals(field, StringComparison.OrdinalIgnoreCase));
}

private PrivacyModeDescriptor(PrivacyMode mode, params string[] fields)
{
Mode = mode;
_fields = fields ?? throw new ArgumentNullException(nameof(fields));
}

public static PrivacyModeDescriptor Create(string value)
{
if (string.IsNullOrWhiteSpace(value)) return new PrivacyModeDescriptor(PrivacyMode.None);

var mode = GetMode(value);
if (mode != PrivacyMode.Partial) return new PrivacyModeDescriptor(mode);

var fields = GetFields(value);
return new PrivacyModeDescriptor(mode, fields);
}

private static PrivacyMode GetMode(string value)
{
var index = value.IndexOf(':');
if (index == -1)
{
if (!Enum.TryParse<PrivacyMode>(value, true, out var parsed1)) throw new Exception("Unexpected privacy-mode value");
return parsed1;
}

var sub = value.Substring(0, index);
if (!Enum.TryParse<PrivacyMode>(sub, true, out var parsed2)) throw new Exception("Unexpected privacy-mode value");

return parsed2;
}

private static string[] GetFields(string value)
{
var index = value.IndexOf(':');
if (index == -1 || value.Length <= index + 1)
{
return Array.Empty<string>();
}

var sub = value.Substring(index + 1);
return sub.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToArray();
}
}
}
15 changes: 8 additions & 7 deletions MultiFactor.Radius.Adapter/Configuration/ServiceConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
using System.IO;
using NetTools;
using System.Text.RegularExpressions;
using MultiFactor.Radius.Adapter.Configuration.Features.PrivacyModeFeature;
using MultiFactor.Radius.Adapter.Services.MultiFactorApi;

namespace MultiFactor.Radius.Adapter.Configuration
{
Expand Down Expand Up @@ -288,7 +290,6 @@ public static ClientConfiguration Load(string name, IRadiusDictionary dictionary
var radiusPapEncodingSetting = appSettings.Settings["radius-pap-encoding"]?.Value;
var firstFactorAuthenticationSourceSettings = appSettings.Settings["first-factor-authentication-source"]?.Value;
var bypassSecondFactorWhenApiUnreachableSetting = appSettings.Settings["bypass-second-factor-when-api-unreachable"]?.Value;
var privacyModeSetting = appSettings.Settings["privacy-mode"]?.Value;
var multiFactorApiKeySetting = appSettings.Settings["multifactor-nas-identifier"]?.Value;
var multiFactorApiSecretSetting = appSettings.Settings["multifactor-shared-secret"]?.Value;

Expand Down Expand Up @@ -346,13 +347,13 @@ public static ClientConfiguration Load(string name, IRadiusDictionary dictionary
}
}

if (!string.IsNullOrEmpty(privacyModeSetting))
try
{
if (!Enum.TryParse<PrivacyMode>(privacyModeSetting, true, out var privacyMode))
{
throw new Exception("Configuration error: Can't parse 'privacy-mode' value. Must be one of: Full, None");
}
configuration.PrivacyMode = privacyMode;
configuration.PrivacyMode = PrivacyModeDescriptor.Create(appSettings.Settings[Literals.Configuration.PrivacyMode]?.Value);
}
catch
{
throw new Exception($"Configuration error: Can't parse '{Literals.Configuration.PrivacyMode}' value. Must be one of: Full, None, Partial:Field1,Field2");
}

switch (configuration.FirstFactorAuthenticationSource)
Expand Down
3 changes: 2 additions & 1 deletion MultiFactor.Radius.Adapter/MultiFactor.Radius.Adapter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@
<Compile Include="Configuration\AuthenticatedClientCacheConfig.cs" />
<Compile Include="Configuration\AuthenticationSource.cs" />
<Compile Include="Configuration\ClientConfiguration.cs" />
<Compile Include="Configuration\PrivacyMode.cs" />
<Compile Include="Configuration\Features\PrivacyModeFeature\PrivacyMode.cs" />
<Compile Include="Configuration\Features\PrivacyModeFeature\PrivacyModeDescriptor.cs" />
<Compile Include="Configuration\RadiusReplyAttributeElement.cs" />
<Compile Include="Configuration\RadiusReplyAttributesCollection.cs" />
<Compile Include="Configuration\RadiusReplyAttributesSection.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@ public static class RadiusCode
public const string Denied = "Denied";
public const string AwaitingAuthentication = "AwaitingAuthentication";
}

public static class Configuration
{
public const string PrivacyMode = "privacy-mode";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Newtonsoft.Json;
using Serilog;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Text;
Expand Down Expand Up @@ -61,7 +60,7 @@ public async Task<PacketCode> CreateSecondFactorRequest(PendingRequest request,
}

//remove user information for privacy
switch (clientConfig.PrivacyMode)
switch (clientConfig.PrivacyMode.Mode)
{
case PrivacyMode.Full:
displayName = null;
Expand All @@ -70,6 +69,31 @@ public async Task<PacketCode> CreateSecondFactorRequest(PendingRequest request,
callingStationId = "";
calledStationId = null;
break;

case PrivacyMode.Partial:
if (!clientConfig.PrivacyMode.HasField("Name"))
{
displayName = null;
}

if (!clientConfig.PrivacyMode.HasField("Email"))
{
email = null;
}

if (!clientConfig.PrivacyMode.HasField("Phone"))
{
userPhone = null;
}

if (!clientConfig.PrivacyMode.HasField("RemoteHost"))
{
callingStationId = "";
}

calledStationId = null;

break;
}

//try to get authenticated client to bypass second factor if configured
Expand Down

0 comments on commit 9a453d1

Please sign in to comment.