/// <summary> /// Attempts to parse all LDAP attributes outside of the ones already collected and converts them to a human readable /// format using a best guess /// </summary> /// <param name="entry"></param> private static Dictionary <string, object> ParseAllProperties(ISearchResultEntry entry) { var flag = IsTextUnicodeFlags.IS_TEXT_UNICODE_STATISTICS; var props = new Dictionary <string, object>(); foreach (var property in entry.PropertyNames()) { if (ReservedAttributes.Contains(property)) { continue; } var collCount = entry.PropCount(property); if (collCount == 0) { continue; } if (collCount == 1) { var testBytes = entry.GetByteProperty(property); if (testBytes == null || testBytes.Length == 0 || !IsTextUnicode(testBytes, testBytes.Length, ref flag)) { continue; } var testString = entry.GetProperty(property); if (!string.IsNullOrEmpty(testString)) { if (property == "badpasswordtime") { props.Add(property, Helpers.ConvertFileTimeToUnixEpoch(testString)); } else { props.Add(property, BestGuessConvert(testString)); } } } else { var arrBytes = entry.GetByteArrayProperty(property); if (arrBytes.Length == 0 || !IsTextUnicode(arrBytes[0], arrBytes[0].Length, ref flag)) { continue; } var arr = entry.GetArrayProperty(property); if (arr.Length > 0) { props.Add(property, arr.Select(BestGuessConvert).ToArray()); } } } return(props); }
private async Task <User> ProcessUserObject(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) { var ret = new User { ObjectIdentifier = resolvedSearchResult.ObjectId }; ret.Properties.Add("domain", resolvedSearchResult.Domain); ret.Properties.Add("name", resolvedSearchResult.DisplayName); ret.Properties.Add("distinguishedname", entry.DistinguishedName.ToUpper()); ret.Properties.Add("domainsid", resolvedSearchResult.DomainSid); if ((_methods & ResolvedCollectionMethod.ACL) != 0) { var aces = _aclProcessor.ProcessACL(resolvedSearchResult, entry); var gmsa = entry.GetByteProperty(LDAPProperties.GroupMSAMembership); ret.Aces = aces.Concat(_aclProcessor.ProcessGMSAReaders(gmsa, resolvedSearchResult.Domain)).ToArray(); ret.IsACLProtected = _aclProcessor.IsACLProtected(entry); } if ((_methods & ResolvedCollectionMethod.Group) != 0) { var pg = entry.GetProperty(LDAPProperties.PrimaryGroupID); ret.PrimaryGroupSID = GroupProcessor.GetPrimaryGroupInfo(pg, resolvedSearchResult.ObjectId); } if ((_methods & ResolvedCollectionMethod.ObjectProps) != 0) { var userProps = await _ldapPropertyProcessor.ReadUserProperties(entry); ret.Properties = ContextUtils.Merge(ret.Properties, userProps.Props); ret.HasSIDHistory = userProps.SidHistory; ret.AllowedToDelegate = userProps.AllowedToDelegate; } if ((_methods & ResolvedCollectionMethod.SPNTargets) != 0) { var spn = entry.GetArrayProperty(LDAPProperties.ServicePrincipalNames); var targets = new List <SPNPrivilege>(); var enumerator = _spnProcessor.ReadSPNTargets(spn, entry.DistinguishedName) .GetAsyncEnumerator(_cancellationToken); while (await enumerator.MoveNextAsync()) { targets.Add(enumerator.Current); } ret.SPNTargets = targets.ToArray(); } return(ret); }
/// <summary> /// Reads specific LDAP properties related to Computers /// </summary> /// <param name="entry"></param> /// <returns></returns> public async Task <ComputerProperties> ReadComputerProperties(ISearchResultEntry entry) { var compProps = new ComputerProperties(); var props = GetCommonProps(entry); var uac = entry.GetProperty(LDAPProperties.UserAccountControl); bool enabled, unconstrained, trustedToAuth; if (int.TryParse(uac, out var flag)) { var flags = (UacFlags)flag; enabled = (flags & UacFlags.AccountDisable) == 0; unconstrained = (flags & UacFlags.TrustedForDelegation) == UacFlags.TrustedForDelegation; trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0; } else { unconstrained = false; enabled = true; trustedToAuth = false; } var domain = Helpers.DistinguishedNameToDomain(entry.DistinguishedName); var comps = new List <TypedPrincipal>(); if (trustedToAuth) { var delegates = entry.GetArrayProperty(LDAPProperties.AllowedToDelegateTo); props.Add("allowedtodelegate", delegates); foreach (var d in delegates) { var hname = d.Contains("/") ? d.Split('/')[1] : d; hname = hname.Split(':')[0]; var resolvedHost = await _utils.ResolveHostToSid(hname, domain); if (resolvedHost != null && (resolvedHost.Contains(".") || resolvedHost.Contains("S-1"))) { comps.Add(new TypedPrincipal { ObjectIdentifier = resolvedHost, ObjectType = Label.Computer }); } } } compProps.AllowedToDelegate = comps.Distinct().ToArray(); var allowedToActPrincipals = new List <TypedPrincipal>(); var rawAllowedToAct = entry.GetByteProperty(LDAPProperties.AllowedToActOnBehalfOfOtherIdentity); if (rawAllowedToAct != null) { var sd = _utils.MakeSecurityDescriptor(); sd.SetSecurityDescriptorBinaryForm(rawAllowedToAct, AccessControlSections.Access); foreach (var rule in sd.GetAccessRules(true, true, typeof(SecurityIdentifier))) { var res = _utils.ResolveIDAndType(rule.IdentityReference(), domain); allowedToActPrincipals.Add(res); } } compProps.AllowedToAct = allowedToActPrincipals.ToArray(); props.Add("enabled", enabled); props.Add("unconstraineddelegation", unconstrained); props.Add("trustedtoauth", trustedToAuth); props.Add("lastlogon", Helpers.ConvertFileTimeToUnixEpoch(entry.GetProperty(LDAPProperties.LastLogon))); props.Add("lastlogontimestamp", Helpers.ConvertFileTimeToUnixEpoch(entry.GetProperty(LDAPProperties.LastLogonTimestamp))); props.Add("pwdlastset", Helpers.ConvertFileTimeToUnixEpoch(entry.GetProperty(LDAPProperties.PasswordLastSet))); props.Add("serviceprincipalnames", entry.GetArrayProperty(LDAPProperties.ServicePrincipalNames)); var os = entry.GetProperty(LDAPProperties.OperatingSystem); var sp = entry.GetProperty(LDAPProperties.ServicePack); if (sp != null) { os = $"{os} {sp}"; } props.Add("operatingsystem", os); var sh = entry.GetByteArrayProperty(LDAPProperties.SIDHistory); var sidHistoryList = new List <string>(); var sidHistoryPrincipals = new List <TypedPrincipal>(); foreach (var sid in sh) { string sSid; try { sSid = new SecurityIdentifier(sid, 0).Value; } catch { continue; } sidHistoryList.Add(sSid); var res = _utils.ResolveIDAndType(sSid, domain); sidHistoryPrincipals.Add(res); } compProps.SidHistory = sidHistoryPrincipals.ToArray(); props.Add("sidhistory", sidHistoryList.ToArray()); compProps.Props = props; return(compProps); }