Files
LIAM/LiamNtfs/C4IT.LIAM.Ntfs.cs
2026-03-13 14:36:23 +01:00

1054 lines
43 KiB
C#

using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.AccessControl;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using C4IT.Logging;
using C4IT.Matrix42.ServerInfo;
using C4IT_IAM;
using C4IT_IAM_Engine;
using C4IT_IAM_SET;
using LiamNtfs;
using static C4IT.Logging.cLogManager;
using static LiamNtfs.cActiveDirectoryBase;
namespace C4IT.LIAM
{
public static class LiamInitializer
{
static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
{
return new cLiamProviderNtfs(LiamConfiguration, ProviderData);
}
}
public class cLiamProviderNtfs : cLiamProviderBase
{
private enum eNtfsPathKind
{
Unknown = 0,
ServerRoot = 1,
ClassicShare = 2,
DfsNamespaceRoot = 3,
DfsLink = 4,
Folder = 5
}
private sealed class cNtfsPathClassification
{
public string NormalizedPath { get; set; } = string.Empty;
public eNtfsPathKind Kind { get; set; } = eNtfsPathKind.Unknown;
public string BoundaryPath { get; set; } = string.Empty;
public string ParentBoundaryPath { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public int Level { get; set; } = -1;
}
public static Guid nftsModuleId = new Guid("77e213a1-6517-ea11-4881-000c2980fd94");
public readonly cNtfsBase ntfsBase = new cNtfsBase();
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
private readonly Dictionary<string, HashSet<string>> publishedShareCache = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
//public readonly bool WithoutPrivateFolders = true;
public cLiamProviderNtfs(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
base(LiamConfiguration, ProviderData)
{
this.ReplaceNtfsCustomTags();
}
public override async Task<bool> LogonAsync()
{
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(nftsModuleId))
{
LogEntry($"Error: License not valid", LogLevels.Error);
return false;
}
return await LogonAsync(true);
}
private void ReplaceNtfsCustomTags()
{
foreach (var namingConvention in NamingConventions)
{
String key = null;
String value = null;
key = "GROUPTYPEPOSTFIX";
if (namingConvention.AccessRole == eLiamAccessRoles.Owner)
{
value = CustomTags["Filesystem_GroupOwnerTag"];
}
else if (namingConvention.AccessRole == eLiamAccessRoles.Write)
{
value = CustomTags["Filesystem_GroupWriteTag"];
}
else if (namingConvention.AccessRole == eLiamAccessRoles.Read)
{
value = CustomTags["Filesystem_GroupReadTag"];
}
else if (namingConvention.AccessRole == eLiamAccessRoles.Traverse)
{
value = CustomTags["Filesystem_GroupTraverseTag"];
}
if (!String.IsNullOrEmpty(key) && !String.IsNullOrEmpty(value))
{
namingConvention.DescriptionTemplate = namingConvention.DescriptionTemplate.Replace($"{{{{{key}}}}}", value);
namingConvention.NamingTemplate = namingConvention.NamingTemplate.Replace($"{{{{{key}}}}}", value);
namingConvention.Wildcard = namingConvention.Wildcard.Replace($"{{{{{key}}}}}", value);
}
value = null;
key = "SCOPE";
if (namingConvention.Scope == eLiamAccessRoleScopes.DomainLocal)
{
value = CustomTags["Filesystem_GroupDomainLocalTag"];
}
else if (namingConvention.Scope == eLiamAccessRoleScopes.Global)
{
value = CustomTags["Filesystem_GroupGlobalTag"];
}
if (!String.IsNullOrEmpty(key) && !String.IsNullOrEmpty(value))
{
namingConvention.DescriptionTemplate = namingConvention.DescriptionTemplate.Replace($"{{{{{key}}}}}", value);
namingConvention.NamingTemplate = namingConvention.NamingTemplate.Replace($"{{{{{key}}}}}", value);
namingConvention.Wildcard = namingConvention.Wildcard.Replace($"{{{{{key}}}}}", value);
}
}
}
public async Task<bool> LogonAsync(bool force = false)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var LI = new cNtfsLogonInfo()
{
Domain = Domain,
User = Credential?.Identification,
UserSecret = Credential?.Secret,
TargetNetworkName = RootPath,
TargetGroupPath = this.GroupPath
};
var RetVal = await ntfsBase.LogonAsync(LI) && await activeDirectoryBase.LogonAsync(LI);
return RetVal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
return false;
}
public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int Depth = -1)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(nftsModuleId))
{
LogEntry($"Error: License not valid", LogLevels.Error);
return new List<cLiamDataAreaBase>();
}
if (!await LogonAsync())
return null;
if (string.IsNullOrEmpty(this.RootPath))
return null;
var DataAreas = new List<cLiamDataAreaBase>();
var rootClassification = ClassifyPath(this.RootPath);
var rootDataArea = await BuildDataAreaAsync(rootClassification);
if (rootDataArea == null)
return null;
DataAreas.Add(rootDataArea);
if (Depth == 0)
return DataAreas;
var DAL = await ntfsBase.RequestFoldersListAsync(this.RootPath, Depth);
if (DAL == null)
return null;
foreach (var Entry in DAL)
{
if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(Entry.Value.DisplayName, this.DataAreaRegEx).Success)
continue;
var classification = ClassifyPath(Entry.Value.Path);
var dataArea = await BuildDataAreaAsync(classification, Entry.Value as cNtfsResultFolder);
if (dataArea != null)
DataAreas.Add(dataArea);
}
return DataAreas;
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
return null;
}
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(nftsModuleId))
{
LogEntry($"Error: License not valid", LogLevels.Error);
return null;
}
if (!await LogonAsync())
return null;
var classification = ClassifyPath(UID);
return await BuildDataAreaAsync(classification);
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
private async Task<cLiamDataAreaBase> BuildDataAreaAsync(cNtfsPathClassification classification, cNtfsResultFolder folderResult = null)
{
if (classification == null)
return null;
switch (classification.Kind)
{
case eNtfsPathKind.ClassicShare:
case eNtfsPathKind.DfsLink:
{
var share = new cLiamNtfsShare(this, new cNtfsResultShare()
{
DisplayName = classification.DisplayName,
Path = classification.NormalizedPath,
Level = classification.Level
}, classification.ParentBoundaryPath);
await share.ResolvePermissionGroupsAsync(share.TechnicalName);
return share;
}
case eNtfsPathKind.DfsNamespaceRoot:
{
var namespaceRoot = new cLiamNtfsDfsNamespaceRoot(this, new cNtfsResultShare()
{
DisplayName = classification.DisplayName,
Path = classification.NormalizedPath,
Level = classification.Level
});
await namespaceRoot.ResolvePermissionGroupsAsync(namespaceRoot.TechnicalName);
return namespaceRoot;
}
case eNtfsPathKind.Folder:
{
var folderData = folderResult ?? new cNtfsResultFolder()
{
DisplayName = classification.DisplayName,
Path = classification.NormalizedPath,
Level = classification.Level,
CreatedDate = Directory.Exists(classification.NormalizedPath)
? new DirectoryInfo(classification.NormalizedPath).CreationTimeUtc.ToString("s")
: DateTime.MinValue.ToString("s")
};
var folder = new cLiamNtfsFolder(this, null, null, folderData, classification.ParentBoundaryPath);
await folder.ResolvePermissionGroupsAsync(folder.TechnicalName);
return folder;
}
default:
return null;
}
}
private cNtfsPathClassification ClassifyPath(string path)
{
var normalizedPath = NormalizeUncPath(path);
var segments = GetUncSegments(normalizedPath);
var classification = new cNtfsPathClassification()
{
NormalizedPath = normalizedPath,
DisplayName = GetDisplayName(normalizedPath),
Level = getDepth(normalizedPath)
};
if (segments.Length == 1)
{
classification.Kind = eNtfsPathKind.ServerRoot;
return classification;
}
if (segments.Length < 2)
return classification;
var serverName = segments[0];
var publishedShares = GetPublishedShareNames(serverName);
var firstBoundaryPath = BuildUncPath(segments, 2);
if (segments.Length == 2)
{
if (publishedShares.Contains(segments[1]))
{
classification.Kind = eNtfsPathKind.ClassicShare;
classification.BoundaryPath = normalizedPath;
return classification;
}
if (Directory.Exists(normalizedPath))
{
classification.Kind = eNtfsPathKind.DfsNamespaceRoot;
classification.BoundaryPath = normalizedPath;
}
return classification;
}
if (publishedShares.Contains(segments[1]))
{
classification.Kind = eNtfsPathKind.Folder;
classification.BoundaryPath = firstBoundaryPath;
classification.ParentBoundaryPath = segments.Length == 3
? firstBoundaryPath
: BuildUncPath(segments, segments.Length - 1);
return classification;
}
if (Directory.Exists(firstBoundaryPath))
{
if (segments.Length == 3)
{
classification.Kind = eNtfsPathKind.DfsLink;
classification.BoundaryPath = normalizedPath;
classification.ParentBoundaryPath = firstBoundaryPath;
return classification;
}
classification.Kind = eNtfsPathKind.Folder;
classification.BoundaryPath = BuildUncPath(segments, 3);
classification.ParentBoundaryPath = segments.Length == 4
? BuildUncPath(segments, 3)
: BuildUncPath(segments, segments.Length - 1);
return classification;
}
return classification;
}
private string NormalizeUncPath(string path)
{
if (string.IsNullOrWhiteSpace(path))
return string.Empty;
var segments = path.Trim().Replace('/', '\\').Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length == 0)
return string.Empty;
return @"\\" + string.Join("\\", segments);
}
private string[] GetUncSegments(string path)
{
var normalized = NormalizeUncPath(path);
return normalized.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
}
private string BuildUncPath(string[] segments, int segmentCount)
{
if (segments == null || segmentCount <= 0 || segments.Length < segmentCount)
return string.Empty;
return @"\\" + string.Join("\\", segments.Take(segmentCount));
}
private string GetDisplayName(string path)
{
var segments = GetUncSegments(path);
if (segments.Length == 0)
return string.Empty;
return segments.Last();
}
private HashSet<string> GetPublishedShareNames(string serverName)
{
HashSet<string> shares;
if (publishedShareCache.TryGetValue(serverName, out shares))
return shares;
shares = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
try
{
using (var connection = new cNetworkConnection(this.RootPath, this.Credential?.Identification, this.Credential?.Secret))
{
foreach (var share in connection.EnumNetShares(serverName))
{
if (!IsVisibleDiskShare(share))
continue;
shares.Add(share.shi1_netname);
}
}
}
catch (Exception ex)
{
LogException(ex);
}
publishedShareCache[serverName] = shares;
return shares;
}
private bool IsVisibleDiskShare(C4IT_IAM.SHARE_INFO_1 share)
{
if (string.IsNullOrWhiteSpace(share.shi1_netname))
return false;
if (share.shi1_netname.StartsWith("ERROR=", StringComparison.OrdinalIgnoreCase))
return false;
if (share.shi1_netname.EndsWith("$", StringComparison.OrdinalIgnoreCase))
return false;
var shareType = share.shi1_type & 0xFF;
return shareType == (uint)C4IT_IAM.SHARE_TYPE.STYPE_DISKTREE;
}
public override async Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(nftsModuleId))
{
LogEntry($"Error: License not valid", LogLevels.Error);
return new List<cLiamDataAreaBase>();
}
if (!await LogonAsync())
return null;
if (string.IsNullOrEmpty(this.GroupPath))
return null;
var SecurityGroups = new List<cLiamDataAreaBase>();
var SGL = await activeDirectoryBase.RequestSecurityGroupsListAsync(groupFilter);
if (SGL == null)
return null;
foreach (var Entry in SGL)
{
if (!string.IsNullOrEmpty(this.GroupRegEx) && !Regex.Match(Entry.Value.DisplayName, this.GroupRegEx).Success)
continue;
var SecurityGroup = new cLiamAdGroup(this, (cSecurityGroupResult)Entry.Value);
SecurityGroups.Add(SecurityGroup);
}
return SecurityGroups;
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
return null;
}
public Task<ResultToken> CreateDataAreaAsync(
string newFolderPath,
string newFolderParent,
IDictionary<string, string> customTags,
IEnumerable<string> ownerSids,
IEnumerable<string> readerSids,
IEnumerable<string> writerSids
)
{
var engine = CreateFilesystemEngine(
newFolderPath,
newFolderParent,
customTags,
ownerSids,
readerSids,
writerSids);
var result = engine.createDataArea();
return Task.FromResult(result);
}
public Task<ResultToken> EnsureMissingPermissionGroupsAsync(
string folderPath,
IDictionary<string, string> customTags,
IEnumerable<string> ownerSids,
IEnumerable<string> readerSids,
IEnumerable<string> writerSids,
bool ensureTraverseGroups = false)
{
var parentPath = Directory.GetParent(folderPath)?.FullName;
var engine = CreateFilesystemEngine(
folderPath,
parentPath,
customTags,
ownerSids,
readerSids,
writerSids);
return Task.FromResult(engine.ensureDataAreaPermissions(ensureTraverseGroups));
}
private DataArea_FileSystem CreateFilesystemEngine(
string folderPath,
string parentFolderPath,
IDictionary<string, string> customTags,
IEnumerable<string> ownerSids,
IEnumerable<string> readerSids,
IEnumerable<string> writerSids)
{
var requiresDomainLocalTag = this.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP
|| (NamingConventions ?? Enumerable.Empty<cLiamNamingConvention>())
.Any(i => i.Scope == eLiamAccessRoleScopes.DomainLocal);
var mergedCustomTags = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var tag in CustomTags)
mergedCustomTags[tag.Key] = tag.Value;
if (customTags != null)
{
foreach (var tag in customTags)
mergedCustomTags[tag.Key] = tag.Value;
}
var engine = new DataArea_FileSystem
{
ConfigID = "manual",
domainName = this.Domain,
username = this.Credential.Identification,
password = new NetworkCredential("", this.Credential.Secret).SecurePassword,
baseFolder = this.RootPath,
newFolderPath = folderPath,
newFolderParent = parentFolderPath,
groupPrefix = GetRequiredCustomTag("Filesystem_GroupPrefixTag"),
groupOUPath = this.GroupPath,
groupPermissionStrategy = (C4IT_IAM_GET.PermissionGroupStrategy)this.GroupStrategy,
groupCustomTags = mergedCustomTags,
ownerUserSids = ownerSids?.Where(i => !string.IsNullOrWhiteSpace(i)).Distinct(StringComparer.OrdinalIgnoreCase).ToList() ?? new List<string>(),
readerUserSids = readerSids?.Where(i => !string.IsNullOrWhiteSpace(i)).Distinct(StringComparer.OrdinalIgnoreCase).ToList() ?? new List<string>(),
writerUserSids = writerSids?.Where(i => !string.IsNullOrWhiteSpace(i)).Distinct(StringComparer.OrdinalIgnoreCase).ToList() ?? new List<string>(),
groupOwnerTag = GetRequiredCustomTag("Filesystem_GroupOwnerTag"),
groupWriteTag = GetRequiredCustomTag("Filesystem_GroupWriteTag"),
groupReadTag = GetRequiredCustomTag("Filesystem_GroupReadTag"),
groupTraverseTag = GetRequiredCustomTag("Filesystem_GroupTraverseTag"),
groupDLTag = requiresDomainLocalTag ? GetRequiredCustomTag("Filesystem_GroupDomainLocalTag") : string.Empty,
groupGTag = GetRequiredCustomTag("Filesystem_GroupGlobalTag"),
allowExistingGroupWildcardMatch = IsAdditionalConfigurationEnabled("EnsureNtfsPermissionGroupsAllowRegexMatch")
};
foreach (var template in BuildSecurityGroupTemplates())
engine.templates.Add(template);
return engine;
}
private bool IsAdditionalConfigurationEnabled(string key)
{
if (AdditionalConfiguration == null || string.IsNullOrWhiteSpace(key))
return false;
if (!AdditionalConfiguration.TryGetValue(key, out var rawValue) || string.IsNullOrWhiteSpace(rawValue))
return false;
return rawValue.Equals("true", StringComparison.OrdinalIgnoreCase)
|| rawValue.Equals("1", StringComparison.OrdinalIgnoreCase)
|| rawValue.Equals("yes", StringComparison.OrdinalIgnoreCase);
}
private IEnumerable<IAM_SecurityGroupTemplate> BuildSecurityGroupTemplates()
{
var templates = new List<IAM_SecurityGroupTemplate>();
foreach (var namingConvention in NamingConventions ?? Enumerable.Empty<cLiamNamingConvention>())
{
if (!TryMapSecurityGroupType(namingConvention.AccessRole, out var securityGroupType))
continue;
if (!TryMapGroupScope(namingConvention.Scope, securityGroupType, out var groupScope))
continue;
templates.Add(new IAM_SecurityGroupTemplate(
namingConvention.NamingTemplate,
namingConvention.DescriptionTemplate,
namingConvention.Wildcard,
securityGroupType,
groupScope));
}
return templates;
}
private bool TryMapSecurityGroupType(eLiamAccessRoles accessRole, out SecurityGroupType securityGroupType)
{
securityGroupType = SecurityGroupType.Read;
switch (accessRole)
{
case eLiamAccessRoles.Owner:
securityGroupType = SecurityGroupType.Owner;
return true;
case eLiamAccessRoles.Write:
securityGroupType = SecurityGroupType.Write;
return true;
case eLiamAccessRoles.Read:
securityGroupType = SecurityGroupType.Read;
return true;
case eLiamAccessRoles.Traverse:
securityGroupType = SecurityGroupType.Traverse;
return true;
default:
return false;
}
}
private bool TryMapGroupScope(eLiamAccessRoleScopes scope, SecurityGroupType type, out GroupScope groupScope)
{
groupScope = GroupScope.Global;
switch (scope)
{
case eLiamAccessRoleScopes.Global:
groupScope = GroupScope.Global;
return true;
case eLiamAccessRoleScopes.DomainLocal:
groupScope = GroupScope.Local;
return true;
case eLiamAccessRoleScopes.Unknown:
if (type == SecurityGroupType.Traverse)
{
groupScope = this.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP ? GroupScope.Local : GroupScope.Global;
return true;
}
return false;
default:
return false;
}
}
private string GetRequiredCustomTag(string key)
{
if (CustomTags.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value))
return value;
if (string.Equals(key, "Filesystem_GroupPrefixTag", StringComparison.OrdinalIgnoreCase)
&& CustomTags.TryGetValue("ADGroupPrefix", out value)
&& !string.IsNullOrWhiteSpace(value))
{
return value;
}
throw new InvalidOperationException($"Missing NTFS custom tag '{key}'.");
}
public int getDepth(string path)
{
return getDepth(this.RootPath, path);
}
public static int getDepth(DirectoryInfo root, DirectoryInfo folder)
{
var rootDepth = root.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length;
var folderDepth = folder.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length;
return folderDepth - rootDepth;
}
public static int getDepth(string root, string folder)
{
return getDepth(new DirectoryInfo(root), new DirectoryInfo(folder));
}
public override string GetLastErrorMessage()
{
var messages = new List<string>();
if (!string.IsNullOrEmpty(ntfsBase?.LastErrorMessage))
messages.Add(ntfsBase.LastErrorMessage);
if (!string.IsNullOrEmpty(activeDirectoryBase?.LastErrorMessage))
messages.Add(activeDirectoryBase.LastErrorMessage);
return messages.Count > 0 ? string.Join(" | ", messages) : null;
}
}
public abstract class cLiamNtfsPermissionDataAreaBase : cLiamDataAreaBase
{
public new readonly cLiamProviderNtfs Provider = null;
public string OwnerGroupIdentifier = "S-1-0-0";
public string WriteGroupIdentifier = "S-1-0-0";
public string ReadGroupIdentifier = "S-1-0-0";
public string TraverseGroupIdentifier = "S-1-0-0";
protected cLiamNtfsPermissionDataAreaBase(cLiamProviderNtfs Provider) :
base(Provider)
{
this.Provider = Provider;
this.SupportsOwners = true;
this.SupportsPermissions = true;
}
public override async Task<List<cLiamUserInfo>> GetOwnersAsync()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
return await GetMembersAsync(true);
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
protected async Task<List<cLiamUserInfo>> GetMembersAsync(bool owners)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var AD = this.Provider?.activeDirectoryBase;
if (AD == null)
{
LogEntry($"Could not get ad class from Provider for data area '{this.TechnicalName}'", LogLevels.Warning);
return null;
}
cADCollectionBase lstMembers;
this.OwnerGroupIdentifier = this.OwnerRef ?? this.OwnerGroupIdentifier;
if (owners && !String.IsNullOrEmpty(this.OwnerGroupIdentifier))
lstMembers = await AD.GetMembersAsync(this.OwnerGroupIdentifier);
else
lstMembers = null;
if (lstMembers == null)
{
LogEntry($"Could not get owner list for data area '{this.TechnicalName}'", LogLevels.Warning);
return null;
}
var RetVal = new List<cLiamUserInfo>(lstMembers.Count);
LogEntry($"Owners for data area found: {lstMembers.Count}", LogLevels.Debug);
foreach (var MemberEntry in lstMembers.Values)
{
var User = new cLiamUserInfo()
{
DisplayName = MemberEntry.DisplayName,
UserPrincipalName = (MemberEntry as cADUserResult).UserPrincipalName,
SID = MemberEntry.ID
};
RetVal.Add(User);
}
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public async Task ResolvePermissionGroupsAsync(string path)
{
var ACLs = Provider.activeDirectoryBase.GetAccessControlList(path);
if (ACLs == null)
return;
var ownerNamingConvention = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Owner && (Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGP && i.Scope == eLiamAccessRoleScopes.Global || Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP && i.Scope == eLiamAccessRoleScopes.DomainLocal));
var writeNamingConvention = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Write && (Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGP && i.Scope == eLiamAccessRoleScopes.Global || Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP && i.Scope == eLiamAccessRoleScopes.DomainLocal));
var readNamingConvention = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Read && (Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGP && i.Scope == eLiamAccessRoleScopes.Global || Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP && i.Scope == eLiamAccessRoleScopes.DomainLocal));
var traverseNamingConvention = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Traverse);
foreach (FileSystemAccessRule rule in ACLs)
{
if (rule.IdentityReference.Value == "S-1-1-0")
continue;
GroupPrincipal grp = GroupPrincipal.FindByIdentity(Provider.activeDirectoryBase.adContext, IdentityType.Sid, rule.IdentityReference.Value);
if (grp == null)
continue;
DefaultLogger.LogEntry(LogLevels.Debug, $"Try matching: {grp.Name}");
if (Regex.IsMatch(grp.SamAccountName, ownerNamingConvention.Wildcard, RegexOptions.IgnoreCase))
{
this.OwnerGroupIdentifier = rule.IdentityReference.Value;
if (Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP)
{
var ldapFilter = String.Format("memberOf={0}", grp.DistinguishedName);
var res = await Provider.activeDirectoryBase.RequestSecurityGroupsListAsync(ldapFilter);
var ownerNamingConventionGlobal = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Owner && i.Scope == eLiamAccessRoleScopes.Global);
foreach (var memberItem in res)
{
var SecurityGroup = new cLiamAdGroup(this.Provider, (cSecurityGroupResult)memberItem.Value);
if (Regex.IsMatch(SecurityGroup.TechnicalName, ownerNamingConventionGlobal.Wildcard, RegexOptions.IgnoreCase))
this.OwnerGroupIdentifier = SecurityGroup.UID;
}
}
}
else if (Regex.IsMatch(grp.SamAccountName, writeNamingConvention.Wildcard, RegexOptions.IgnoreCase))
{
this.WriteGroupIdentifier = rule.IdentityReference.Value;
if (Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP)
{
var ldapFilter = String.Format("memberOf={0}", grp.DistinguishedName);
var res = await Provider.activeDirectoryBase.RequestSecurityGroupsListAsync(ldapFilter);
var writeNamingConventionGlobal = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Write && i.Scope == eLiamAccessRoleScopes.Global);
foreach (var memberItem in res)
{
var SecurityGroup = new cLiamAdGroup(this.Provider, (cSecurityGroupResult)memberItem.Value);
if (Regex.IsMatch(SecurityGroup.TechnicalName, writeNamingConventionGlobal.Wildcard, RegexOptions.IgnoreCase))
this.WriteGroupIdentifier = SecurityGroup.UID;
}
}
}
else if (Regex.IsMatch(grp.SamAccountName, readNamingConvention.Wildcard, RegexOptions.IgnoreCase))
{
this.ReadGroupIdentifier = rule.IdentityReference.Value;
if (Provider.GroupStrategy == eLiamGroupStrategies.Ntfs_AGDLP)
{
var ldapFilter = String.Format("memberOf={0}", grp.DistinguishedName);
var res = await Provider.activeDirectoryBase.RequestSecurityGroupsListAsync(ldapFilter);
var readNamingConventionGlobal = Provider.NamingConventions.First(i => i.AccessRole == eLiamAccessRoles.Read && i.Scope == eLiamAccessRoleScopes.Global);
foreach (var memberItem in res)
{
var SecurityGroup = new cLiamAdGroup(this.Provider, (cSecurityGroupResult)memberItem.Value);
if (Regex.IsMatch(SecurityGroup.TechnicalName, readNamingConventionGlobal.Wildcard, RegexOptions.IgnoreCase))
this.ReadGroupIdentifier = SecurityGroup.UID;
}
}
}
else if (Regex.IsMatch(grp.SamAccountName, traverseNamingConvention.Wildcard, RegexOptions.IgnoreCase))
{
this.TraverseGroupIdentifier = rule.IdentityReference.Value;
}
else
{
DefaultLogger.LogEntry(LogLevels.Debug, $"No match for: {grp.Name}");
}
}
}
}
public class cLiamNtfsShare : cLiamNtfsPermissionDataAreaBase
{
private readonly cNtfsResultBase Share = null;
public cLiamNtfsShare(cLiamProviderNtfs Provider, cNtfsResultBase Share, string parentPath = null) :
base(Provider)
{
this.Share = Share;
this.DisplayName = Share.Path.Split('\\').Last();
this.TechnicalName = Share.Path;
this.UID = cLiamNtfsFolder.GetUniqueDataAreaID(Share.Path);
this.Level = Share.Level;
this.DataType = eLiamDataAreaTypes.NtfsShare;
if (Directory.Exists(Share.Path))
this.CreatedDate = new DirectoryInfo(Share.Path).CreationTimeUtc.ToString("s");
if (!string.IsNullOrWhiteSpace(parentPath))
this.ParentUID = cLiamNtfsFolder.GetUniqueDataAreaID(parentPath);
}
internal async Task<List<cLiamDataAreaBase>> getFolders()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
var RetVal = new List<cLiamDataAreaBase>(0);
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
var RetVal = new List<cLiamDataAreaBase>();
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
}
public class cLiamNtfsDfsNamespaceRoot : cLiamNtfsPermissionDataAreaBase
{
private readonly cNtfsResultBase NamespaceRoot = null;
public cLiamNtfsDfsNamespaceRoot(cLiamProviderNtfs Provider, cNtfsResultBase NamespaceRoot) :
base(Provider)
{
this.NamespaceRoot = NamespaceRoot;
this.DisplayName = NamespaceRoot.Path.Split('\\').Last();
this.TechnicalName = NamespaceRoot.Path;
this.UID = cLiamNtfsFolder.GetUniqueDataAreaID(NamespaceRoot.Path);
this.Level = NamespaceRoot.Level;
this.DataType = eLiamDataAreaTypes.DfsNamespaceRoot;
if (Directory.Exists(NamespaceRoot.Path))
this.CreatedDate = new DirectoryInfo(NamespaceRoot.Path).CreationTimeUtc.ToString("s");
}
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
await Task.Delay(0);
return new List<cLiamDataAreaBase>();
}
}
public class cLiamAdGroup : cLiamDataAreaBase
{
public new readonly cLiamProviderNtfs Provider = null;
public readonly string dn = null;
public readonly string scope = null;
public override Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
throw new NotImplementedException();
}
public cLiamAdGroup(cLiamProviderNtfs Provider, cSecurityGroupResult secGroup) : base(Provider)
{
this.UID = secGroup.ID;
this.TechnicalName = secGroup.DisplayName;
this.Provider = Provider;
this.dn = secGroup.Path;
this.scope = secGroup.Scope.ToString();
}
}
public class cLiamNtfsFolder : cLiamNtfsPermissionDataAreaBase
{
public readonly cLiamNtfsShare Share = null;
public readonly cLiamNtfsFolder NtfsRootFolder = null;
public cLiamNtfsFolder(cLiamProviderNtfs Provider, cLiamNtfsShare share, cLiamNtfsFolder ntfsRootFolder, cNtfsResultFolder NtfsFolder, string parentPathOverride = null) : base(Provider)
{
var ntfsParent = NtfsFolder.Parent;
this.NtfsRootFolder = ntfsRootFolder;
this.Share = share;
this.TechnicalName = NtfsFolder.Path;
this.UID =GetUniqueDataAreaID(NtfsFolder.Path);
this.DisplayName = new DirectoryInfo(NtfsFolder.Path).Name;
this.Level = NtfsFolder.Level;
this.DataType = eLiamDataAreaTypes.NtfsFolder;
this.CreatedDate = NtfsFolder.CreatedDate;
if (ntfsParent != null)
{
this.ParentUID = GetUniqueDataAreaID(ntfsParent.Path);
}
else if (this.Level == 1)
{
this.ParentUID = GetUniqueDataAreaID(this.Provider.RootPath);
}
if (string.IsNullOrWhiteSpace(this.ParentUID) && !string.IsNullOrWhiteSpace(parentPathOverride))
this.ParentUID = GetUniqueDataAreaID(parentPathOverride);
}
public static string GetUniqueDataAreaID(string fullPath)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
var utf8 = new System.Text.UTF8Encoding();
var hash = BitConverter.ToString(md5.ComputeHash(utf8.GetBytes(fullPath)));
hash = hash.ToLower().Replace("-", "");
return hash;
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
throw;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
public string GetUniqueDataAreaID()
{
return GetUniqueDataAreaID(this.TechnicalName);
}
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = 1)
{
//TODO implement getChildrenAsync
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
await Task.Delay(0);
var DataAreas = new List<cLiamDataAreaBase>();
return DataAreas;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
}
}