using System; using System.Collections.Generic; using System.ComponentModel; using System.DirectoryServices; using System.DirectoryServices.AccountManagement; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Principal; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using C4IT.Logging; using static C4IT.Logging.cLogManager; namespace LiamNtfs { public class cActiveDirectoryBase { private cNtfsLogonInfo privLogonInfo = null; public PrincipalContext adContext = null; public DirectoryEntry directoryEntry = null; public Exception LastException { get; private set; } = null; public string LastErrorMessage { get; private set; } = null; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ResetError() { LastException = null; LastErrorMessage = null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetErrorException(string Action, Exception E, LogLevels lev = LogLevels.Error) { LastException = E; LastErrorMessage = Action + ": " + E.Message; cLogManager.LogEntry(Action, lev); } private async Task privLogonAsync(cNtfsLogonInfo LogonInfo) { try { //TODO: remove dummy delay? await Task.Delay(0); ResetError(); adContext = new PrincipalContext(ContextType.Domain, LogonInfo.Domain, LogonInfo.User, new NetworkCredential("", LogonInfo.UserSecret).Password); var ldapPath = $"LDAP://{LogonInfo.Domain}/{LogonInfo.TargetGroupPath}"; directoryEntry = new DirectoryEntry { Path = ldapPath, Username = LogonInfo.User, Password = new NetworkCredential(LogonInfo.User, LogonInfo.UserSecret).Password, AuthenticationType = AuthenticationTypes.Secure | AuthenticationTypes.Sealing }; return adContext != null; } catch (Exception E) { SetErrorException("exception error while ad login", E, LogLevels.Debug); cLogManager.LogException(E, LogLevels.Debug); } return false; } private async Task privRelogon() { if (privLogonInfo == null) return false; var RetVal = await privLogonAsync(privLogonInfo); return RetVal; } public async Task LogonAsync(cNtfsLogonInfo LogonInfo) { var RetVal = await privLogonAsync(LogonInfo); if (RetVal == true) privLogonInfo = LogonInfo; return RetVal; } internal AuthorizationRuleCollection GetAccessControlList(string path) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { DirectoryInfo dADir = new DirectoryInfo(path); var dAACL = dADir.GetAccessControl(); return dAACL.GetAccessRules(true, false, typeof(System.Security.Principal.SecurityIdentifier)); } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } internal string resolveSid(string sid) { try { return new System.Security.Principal.SecurityIdentifier(sid).Translate(typeof(System.Security.Principal.NTAccount)).ToString(); } catch (Exception E) { LogException(E); return null; } } internal async Task RequestSecurityGroupsListAsync(string groupFilter) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { await Task.Delay(0); var Result = privRequestSecurityGroupsListAsync(groupFilter); if (Result != null) { var RetVal = new cADCollectionBase(Result.Count); foreach (var Entry in Result) { var res = new cSecurityGroupResult(Entry); RetVal.Add(res); } return RetVal; } } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } return null; } private List privRequestSecurityGroupsListAsync(string groupFilter = null, string rawLDAPFilter = null) { ResetError(); List securityGroups = new List(); try { var res = new List(); if (String.IsNullOrEmpty(privLogonInfo.TargetGroupPath) || string.IsNullOrEmpty(groupFilter) && string.IsNullOrEmpty(rawLDAPFilter)) return res; try { var ctx = adContext; var entry = directoryEntry; DirectorySearcher dSearch = new DirectorySearcher(entry) { Filter = string.IsNullOrEmpty(rawLDAPFilter) ? "(&(" + groupFilter + ")(objectClass=group))" : rawLDAPFilter }; dSearch.PageSize = 100000; SearchResultCollection sr = dSearch.FindAll(); if (sr.Count > 0) { foreach (SearchResult k in sr) { var sid = new SecurityIdentifier(k.Properties["objectSid"][0] as byte[], 0).Value; var dn = k.Properties["distinguishedname"][0].ToString(); cSecurityGroupResult group = new cSecurityGroupResult() { ID = sid, Path = k.Properties["distinguishedname"][0].ToString(), DisplayName = k.Properties["Name"][0].ToString(), Scope = (GroupScope)GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, sid).GroupScope }; securityGroups.Add(group); } } } catch { return new List(securityGroups); } return new List(securityGroups); } catch (Exception E) { cLogManager.LogException(E); } return null; } public class cADCollectionBase : SortedList { public cADCollectionBase() { } public cADCollectionBase(int n) : base(n) { } public void Add(cADResultBase adr) { if (!this.ContainsKey(adr.ID)) this.Add(adr.ID, adr); } } public class cSecurityGroupResult : cADResultBase { public cSecurityGroupResult() { } public cSecurityGroupResult(cADResultBase b) : base(b) { } public GroupScope Scope { get; internal set; } } public class cADUserResult : cADResultBase { public string GivenName { get; internal set; } public string SurName { get; internal set; } public string UserPrincipalName { get; internal set; } public string Email { get; internal set; } public cADUserResult() { } public cADUserResult(cADResultBase b) : base(b) { } public cADUserResult(Principal Result) : base(Result) { UserPrincipalName = Result.UserPrincipalName; } public GroupScope Scope { get; internal set; } } public class cADResultBase { public string ID { get; set; } = null; public string DisplayName { get; set; } = null; public string Path { get; set; } = null; public cADResultBase() { } public cADResultBase(cADResultBase Result) { if (Result == null) return; ID = Result.ID; DisplayName = Result.DisplayName; Path = Result.Path; } public cADResultBase(Principal Result) { if (Result == null) return; ID = Result.Sid.ToString(); DisplayName = Result.DisplayName; Path = Result.DistinguishedName; } } internal async Task GetMembersAsync(string Sid) { try { await Task.Delay(0); var Result = privGetMembersAsync(Sid).ToList(); if (Result != null) { var RetVal = new cADCollectionBase(Result.Count); foreach (var Entry in Result) { var res = new cADUserResult(Entry); if (!string.IsNullOrEmpty(res.Path)) RetVal.Add(res); } return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } private PrincipalSearchResult privGetMembersAsync(string sid) { try { using (var group = GroupPrincipal.FindByIdentity(adContext,sid)) { if (group == null) { return null; } else { return group.GetMembers(true); } } } catch (Exception E) { cLogManager.LogException(E); } return null; } } }