private static List <Sid> GetUserDomainSids(string domain, Sid user_sid)
        {
            List <Sid> ret = new List <Sid>();

            ret.Add(KnownSids.World);
            ret.Add(KnownSids.AuthenticatedUsers);
            ret.AddRange(DirectoryServiceUtils.FindTokenGroupsForSid(user_sid, false));
            HashSet <DirectoryServiceSecurityPrincipal> members = new HashSet <DirectoryServiceSecurityPrincipal>();

            foreach (var next_sid in ret)
            {
                var principal_name = NtSecurity.IsDomainSid(next_sid) ? DirectoryServiceUtils.FindObjectFromSid(null, next_sid)
                    : DirectoryServiceUtils.FindObjectFromSid(domain, next_sid);
                if (principal_name?.DistinguishedName == null)
                {
                    continue;
                }
                members.Add(principal_name);
            }

            var user_name = DirectoryServiceUtils.FindObjectFromSid(null, user_sid);

            if (user_name?.DistinguishedName != null)
            {
                members.Add(user_name);
            }

            Queue <string> remaining_checks = new Queue <string>(members.Select(m => m.DistinguishedName));

            while (remaining_checks.Count > 0)
            {
                string dn = remaining_checks.Dequeue();
                foreach (var local_group in DirectoryServiceUtils.FindDomainLocalGroupForMember(domain, dn))
                {
                    if (members.Add(local_group))
                    {
                        ret.Add(local_group.Sid);
                        remaining_checks.Enqueue(local_group.DistinguishedName);
                    }
                }
            }
            return(ret);
        }
        private void BuildAuthZContext()
        {
            _resource_manager = string.IsNullOrWhiteSpace(Server) ? AuthZResourceManager.Create(GetType().Name,
                                                                                                AuthZResourceManagerInitializeFlags.NoAudit | AuthZResourceManagerInitializeFlags.NoCentralAccessPolicies,
                                                                                                null) : AuthZResourceManager.Create(Server, null, AuthZResourceManagerRemoteServiceType.Default);

            var sids = new HashSet <Sid>();

            if (UserSid != null)
            {
                foreach (var sid in UserSid)
                {
                    sids.Add(sid);
                }
            }
            if (UserName != null)
            {
                foreach (var name in UserName)
                {
                    sids.Add(NtSecurity.LookupAccountName(name));
                }
            }
            if (sids.Count == 0)
            {
                sids.Add(NtToken.CurrentUser.Sid);
            }

            if (_resource_manager.Remote || UseLocalGroup)
            {
                _context.AddRange(sids.Select(s => _resource_manager.CreateContext(s, AuthZContextInitializeSidFlags.None)));
            }
            else
            {
                foreach (var sid in sids)
                {
                    if (!NtSecurity.IsDomainSid(sid) || NtSecurity.IsLocalDomainSid(sid))
                    {
                        _context.AddResource(_resource_manager.CreateContext(sid, AuthZContextInitializeSidFlags.None));
                        continue;
                    }

                    WriteProgress($"Building security context for {sid.Name}");
                    var context = _context.AddResource(_resource_manager.CreateContext(sid, AuthZContextInitializeSidFlags.SkipTokenGroups));
                    context.AddSids(_cached_user_groups.GetOrAdd(Tuple.Create(Domain, sid), _ => GetUserDomainSids(Domain, sid)));
                }
            }

            foreach (var context in Context)
            {
                if (sids.Add(context.User.Sid))
                {
                    var next_ctx = _context.AddResource(_resource_manager.CreateContext(context.User.Sid, AuthZContextInitializeSidFlags.SkipTokenGroups));
                    foreach (var group in context.Groups)
                    {
                        next_ctx.AddSid(group.Sid);
                    }
                }
            }

            _token_info = _context.Select(c => new TokenInformation(c)).ToList();
        }