示例#1
0
        // Resets the enumerator to before the first result in the set.  This potentially can be an expensive
        // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
        // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
        // a no-op.
        internal override void Reset()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Reset");

            if (!_atBeginning)
            {
                _groupsToVisit.Clear();
                string originalGroupPath = _groupsVisited[0];
                _groupsVisited.Clear();
                _groupsVisited.Add(originalGroupPath);

                _group = _originalGroup;
                UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members();
                _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();

                _current = null;
                _currentFakePrincipal = null;
                _currentForeign       = null;

                _foreignMembers.Clear();
                _foreignGroups.Clear();

                if (_foreignResultSet != null)
                {
                    _foreignResultSet.Dispose();
                    _foreignResultSet = null;
                }

                _atBeginning = true;
            }
        }
示例#2
0
 internal SAMGroupsSet(UnsafeNativeMethods.IADsMembers iADsMembers, SAMStoreCtx storeCtx, DirectoryEntry ctxBase)
 {
     this.atBeginning      = true;
     this.groupsEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
     this.storeCtx         = storeCtx;
     this.ctxBase          = ctxBase;
 }
示例#3
0
        internal override ResultSetBookmark BookmarkAndReset()
        {
            SAMMembersSetBookmark sAMMembersSetBookmark = new SAMMembersSetBookmark();

            sAMMembersSetBookmark.groupsToVisit = this.groupsToVisit;
            this.groupsToVisit = new List <string>();
            string item = this.groupsVisited[0];

            sAMMembersSetBookmark.groupsVisited = this.groupsVisited;
            this.groupsVisited = new List <string>();
            this.groupsVisited.Add(item);
            sAMMembersSetBookmark.@group            = this.@group;
            sAMMembersSetBookmark.membersEnumerator = this.membersEnumerator;
            this.@group = this.originalGroup;
            UnsafeNativeMethods.IADsMembers aDsMember = [email protected]();
            this.membersEnumerator        = ((IEnumerable)aDsMember).GetEnumerator();
            sAMMembersSetBookmark.current = this.current;
            sAMMembersSetBookmark.currentFakePrincipal = this.currentFakePrincipal;
            sAMMembersSetBookmark.currentForeign       = this.currentForeign;
            this.current = null;
            this.currentFakePrincipal              = null;
            this.currentForeign                    = null;
            sAMMembersSetBookmark.foreignMembers   = this.foreignMembers;
            sAMMembersSetBookmark.foreignGroups    = this.foreignGroups;
            sAMMembersSetBookmark.foreignResultSet = this.foreignResultSet;
            this.foreignMembers                    = new List <DirectoryEntry>();
            this.foreignGroups                = new List <GroupPrincipal>();
            this.foreignResultSet             = null;
            sAMMembersSetBookmark.atBeginning = this.atBeginning;
            this.atBeginning = true;
            return(sAMMembersSetBookmark);
        }
示例#4
0
        internal SAMGroupsSet(UnsafeNativeMethods.IADsMembers iADsMembers, SAMStoreCtx storeCtx, DirectoryEntry ctxBase)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMGroupsSet", "SAMGroupsSet: creating for path={0}", ctxBase.Path);

            _groupsEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();

            _storeCtx = storeCtx;
            _ctxBase  = ctxBase;
        }
示例#5
0
 internal SAMMembersSet(string groupPath, UnsafeNativeMethods.IADsGroup group, bool recursive, SAMStoreCtx storeCtx, DirectoryEntry ctxBase)
 {
     this.atBeginning    = true;
     this.groupsVisited  = new List <string>();
     this.groupsToVisit  = new List <string>();
     this.foreignMembers = new List <DirectoryEntry>();
     this.foreignGroups  = new List <GroupPrincipal>();
     this.storeCtx       = storeCtx;
     this.ctxBase        = ctxBase;
     this.@group         = group;
     this.originalGroup  = group;
     this.recursive      = recursive;
     this.groupsVisited.Add(groupPath);
     UnsafeNativeMethods.IADsMembers aDsMember = group.Members();
     this.membersEnumerator = ((IEnumerable)aDsMember).GetEnumerator();
 }
示例#6
0
        internal override bool Matches(DirectoryEntry groupDE)
        {
            // If it has no SID, it's not a security principal, and we're not interested in it.
            // (In reg-SAM, computers don't have accounts and therefore don't have SIDs, but ADSI
            // creates fake Computer objects for them.  In LSAM, computers CAN have accounts, and thus
            // SIDs).
            if (groupDE.Properties["objectSid"] == null || groupDE.Properties["objectSid"].Count == 0)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "GroupMemberMatcher: Matches: skipping no-SID group={0}", groupDE.Path);
                return(false);
            }

            // Enumerate the members of the group, looking for a match
            UnsafeNativeMethods.IADsGroup   iADsGroup   = (UnsafeNativeMethods.IADsGroup)groupDE.NativeObject;
            UnsafeNativeMethods.IADsMembers iADsMembers = iADsGroup.Members();

            foreach (UnsafeNativeMethods.IADs nativeMember in ((IEnumerable)iADsMembers))
            {
                // Wrap the DirectoryEntry around the native ADSI object
                // (which already has the correct credentials)
                DirectoryEntry memberDE = new DirectoryEntry(nativeMember);

                // No SID --> not interesting
                if (memberDE.Properties["objectSid"] == null || memberDE.Properties["objectSid"].Count == 0)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "GroupMemberMatcher: Matches: skipping member no-SID member={0}", memberDE.Path);
                    continue;
                }

                byte[] memberSid = (byte[])memberDE.Properties["objectSid"].Value;

                // Did we find a matching member in the group?
                if (Utils.AreBytesEqual(memberSid, _memberSidToMatch))
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info,
                                            "SAMQuerySet",
                                            "GroupMemberMatcher: Matches: match member={0}, group={1)",
                                            memberDE.Path,
                                            groupDE.Path);
                    return(true);
                }
            }

            // We tried all the members in the group and didn't get a match on any
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: no match, group={0}", groupDE.Path);
            return(false);
        }
示例#7
0
        internal override bool Matches(DirectoryEntry groupDE)
        {
            bool flag;

            if (groupDE.Properties["objectSid"] == null || groupDE.Properties["objectSid"].Count == 0)
            {
                return(false);
            }
            else
            {
                UnsafeNativeMethods.IADsGroup   nativeObject = (UnsafeNativeMethods.IADsGroup)groupDE.NativeObject;
                UnsafeNativeMethods.IADsMembers aDsMember    = nativeObject.Members();
                IEnumerator enumerator = ((IEnumerable)aDsMember).GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        UnsafeNativeMethods.IADs current        = (UnsafeNativeMethods.IADs)enumerator.Current;
                        DirectoryEntry           directoryEntry = new DirectoryEntry(current);
                        if (directoryEntry.Properties["objectSid"] == null || directoryEntry.Properties["objectSid"].Count == 0)
                        {
                            continue;
                        }
                        byte[] value = (byte[])directoryEntry.Properties["objectSid"].Value;
                        if (!Utils.AreBytesEqual(value, this.memberSidToMatch))
                        {
                            continue;
                        }
                        flag = true;
                        return(flag);
                    }
                    return(false);
                }
                finally
                {
                    IDisposable disposable = enumerator as IDisposable;
                    if (disposable != null)
                    {
                        disposable.Dispose();
                    }
                }
                return(flag);
            }
        }
示例#8
0
        internal SAMMembersSet(string groupPath, UnsafeNativeMethods.IADsGroup group, bool recursive, SAMStoreCtx storeCtx, DirectoryEntry ctxBase)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info,
                                    "SAMMembersSet",
                                    "SAMMembersSet: groupPath={0}, recursive={1}, base={2}",
                                    groupPath,
                                    recursive,
                                    ctxBase.Path);

            _storeCtx = storeCtx;

            _group         = group;
            _originalGroup = group;
            _recursive     = recursive;

            _groupsVisited.Add(groupPath);    // so we don't revisit it

            UnsafeNativeMethods.IADsMembers iADsMembers = group.Members();
            _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
        }
示例#9
0
        internal override ResultSetBookmark BookmarkAndReset()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Bookmarking");

            SAMMembersSetBookmark bookmark = new SAMMembersSetBookmark();

            bookmark.groupsToVisit = _groupsToVisit;
            _groupsToVisit         = new List <string>();

            string originalGroupPath = _groupsVisited[0];

            bookmark.groupsVisited = _groupsVisited;
            _groupsVisited         = new List <string>();
            _groupsVisited.Add(originalGroupPath);

            bookmark.group             = _group;
            bookmark.membersEnumerator = _membersEnumerator;
            _group = _originalGroup;
            UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members();
            _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();

            bookmark.current = _current;
            bookmark.currentFakePrincipal = _currentFakePrincipal;
            bookmark.currentForeign       = _currentForeign;
            _current = null;
            _currentFakePrincipal = null;
            _currentForeign       = null;

            bookmark.foreignMembers   = _foreignMembers;
            bookmark.foreignGroups    = _foreignGroups;
            bookmark.foreignResultSet = _foreignResultSet;
            _foreignMembers           = new List <DirectoryEntry>();
            _foreignGroups            = new List <GroupPrincipal>();
            _foreignResultSet         = null;

            bookmark.atBeginning = _atBeginning;
            _atBeginning         = true;

            return(bookmark);
        }
示例#10
0
 internal override void Reset()
 {
     if (!this.atBeginning)
     {
         this.groupsToVisit.Clear();
         string item = this.groupsVisited[0];
         this.groupsVisited.Clear();
         this.groupsVisited.Add(item);
         this.@group = this.originalGroup;
         UnsafeNativeMethods.IADsMembers aDsMember = [email protected]();
         this.membersEnumerator    = ((IEnumerable)aDsMember).GetEnumerator();
         this.current              = null;
         this.currentFakePrincipal = null;
         this.currentForeign       = null;
         this.foreignMembers.Clear();
         this.foreignGroups.Clear();
         if (this.foreignResultSet != null)
         {
             this.foreignResultSet.Dispose();
             this.foreignResultSet = null;
         }
         this.atBeginning = true;
     }
 }
示例#11
0
        // Get groups of which p is a direct member
        internal override ResultSet GetGroupsMemberOf(Principal p)
        {
            // Enforced by the methods that call us
            Debug.Assert(p.unpersisted == false);

            if (!p.fakePrincipal)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf: is real principal");

                // No nested groups or computers as members of groups in SAM
                if (!(p is UserPrincipal))
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf: not a user, returning empty set");
                    return(new EmptySet());
                }

                Debug.Assert(p.UnderlyingObject != null);

                DirectoryEntry userDE = (DirectoryEntry)p.UnderlyingObject;

                UnsafeNativeMethods.IADsMembers iadsMembers = (UnsafeNativeMethods.IADsMembers)userDE.Invoke("Groups");

                ResultSet resultSet = new SAMGroupsSet(iadsMembers, this, _ctxBase);
                return(resultSet);
            }
            else
            {
                // ADSI's IADsGroups doesn't work for fake principals like NT AUTHORITY\NETWORK SERVICE

                // We use the same SAMQuery set that we use for query-by-example, but with a different
                // SAMMatcher class to match groups which contain the specified principal as a member

                // Get the entries we'll iterate over.  Write access to Children is controlled through the
                // ctxBaseLock, but we don't want to have to hold that lock while we're iterating over all
                // the child entries.  So we have to clone the ctxBase --- not ideal, but it prevents
                // multithreading issues.
                DirectoryEntries entries = SDSUtils.BuildDirectoryEntry(_ctxBase.Path, _credentials, _authTypes).Children;
                Debug.Assert(entries != null);

                // The SAMQuerySet will use this to restrict the types of DirectoryEntry objects returned.
                List <string> schemaTypes = GetSchemaFilter(typeof(GroupPrincipal));

                SecurityIdentifier principalSid = p.Sid;
                byte[]             SidB         = new byte[principalSid.BinaryLength];
                principalSid.GetBinaryForm(SidB, 0);

                if (principalSid == null)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOf: bad SID IC");
                    throw new InvalidOperationException(SR.StoreCtxNeedValueSecurityIdentityClaimToQuery);
                }

                // Create the ResultSet that will perform the client-side filtering
                SAMQuerySet resultSet = new SAMQuerySet(
                    schemaTypes,
                    entries,
                    _ctxBase,
                    -1,                                             // no size limit
                    this,
                    new GroupMemberMatcher(SidB));

                return(resultSet);
            }
        }
示例#12
0
        private bool MoveNextLocal()
        {
            bool needToRetry;

            do
            {
                needToRetry = false;

                bool f = _membersEnumerator.MoveNext();

                if (f) // got a value
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: got a value from the enumerator");

                    UnsafeNativeMethods.IADs nativeMember = (UnsafeNativeMethods.IADs)_membersEnumerator.Current;

                    // If we encountered a group member corresponding to a fake principal such as
                    // NT AUTHORITY/NETWORK SERVICE, construct and prepare to return the fake principal.
                    byte[]  sid     = (byte[])nativeMember.Get("objectSid");
                    SidType sidType = Utils.ClassifySID(sid);
                    if (sidType == SidType.FakeObject)
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: fake principal, sid={0}", Utils.ByteArrayToString(sid));

                        _currentFakePrincipal = _storeCtx.ConstructFakePrincipalFromSID(sid);
                        _current        = null;
                        _currentForeign = null;

                        if (_foreignResultSet != null)
                        {
                            _foreignResultSet.Dispose();
                        }
                        _foreignResultSet = null;
                        return(true);
                    }

                    // We do this, rather than using the DirectoryEntry constructor that takes a native IADs object,
                    // is so the credentials get transferred to the new DirectoryEntry.  If we just use the native
                    // object constructor, the native object will have the right credentials, but the DirectoryEntry
                    // will have default (null) credentials, which it'll use anytime it needs to use credentials.
                    DirectoryEntry de = SDSUtils.BuildDirectoryEntry(
                        _storeCtx.Credentials,
                        _storeCtx.AuthTypes);

                    if (sidType == SidType.RealObjectFakeDomain)
                    {
                        // Transform the "WinNT://BUILTIN/foo" path to "WinNT://machineName/foo"
                        string builtinADsPath = nativeMember.ADsPath;

                        UnsafeNativeMethods.Pathname     pathCracker = new UnsafeNativeMethods.Pathname();
                        UnsafeNativeMethods.IADsPathname pathName    = (UnsafeNativeMethods.IADsPathname)pathCracker;

                        pathName.Set(builtinADsPath, 1 /* ADS_SETTYPE_FULL */);

                        // Build the "WinNT://" portion of the new path
                        StringBuilder adsPath = new StringBuilder();
                        adsPath.Append("WinNT://");
                        //adsPath.Append(pathName.Retrieve(9 /*ADS_FORMAT_SERVER */));

                        // Build the "WinNT://machineName/" portion of the new path
                        adsPath.Append(_storeCtx.MachineUserSuppliedName);
                        adsPath.Append('/');

                        // Build the "WinNT://machineName/foo" portion of the new path
                        int cElements = pathName.GetNumElements();

                        Debug.Assert(cElements >= 2);       // "WinNT://BUILTIN/foo" == 2 elements

                        // Note that the ADSI WinNT provider indexes them backwards, e.g., in
                        // "WinNT://BUILTIN/A/B", BUILTIN == 2, A == 1, B == 0.
                        for (int i = cElements - 2; i >= 0; i--)
                        {
                            adsPath.Append(pathName.GetElement(i));
                            adsPath.Append('/');
                        }

                        adsPath.Remove(adsPath.Length - 1, 1);  // remove the trailing "/"

                        de.Path = adsPath.ToString();

                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: fake domain: {0} --> {1}", builtinADsPath, adsPath);
                    }
                    else
                    {
                        Debug.Assert(sidType == SidType.RealObject);
                        de.Path = nativeMember.ADsPath;

                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: real domain {0}", de.Path);
                    }

                    //  Debug.Assert(Utils.AreBytesEqual(sid, (byte[]) de.Properties["objectSid"].Value));

                    if (IsLocalMember(sid))
                    {
                        // If we're processing recursively, and the member is a group,
                        // we don't return it but instead treat it as something to recursively
                        // visit (expand) later.
                        if (!_recursive || !SAMUtils.IsOfObjectClass(de, "Group"))
                        {
                            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: setting current to {0}", de.Path);

                            // Not recursive, or not a group.  Return the principal.
                            _current = de;
                            _currentFakePrincipal = null;
                            _currentForeign       = null;

                            if (_foreignResultSet != null)
                            {
                                _foreignResultSet.Dispose();
                            }
                            _foreignResultSet = null;
                            return(true);
                        }
                        else
                        {
                            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: adding {0} to groupsToVisit", de.Path);

                            // Save off for later, if we haven't done so already.
                            if (!_groupsVisited.Contains(de.Path) && !_groupsToVisit.Contains(de.Path))
                            {
                                _groupsToVisit.Add(de.Path);
                            }

                            needToRetry = true;
                            continue;
                        }
                    }
                    else
                    {
                        // It's a foreign principal (e..g, an AD user or group).
                        // Save it off for later.

                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: adding {0} to foreignMembers", de.Path);

                        _foreignMembers.Add(de);
                        needToRetry = true;
                        continue;
                    }
                }
                else
                {
                    // We reached the end of this group's membership.
                    // If we're supposed to be recursively expanding, we need to expand
                    // any remaining non-foreign groups we earlier visited.
                    if (_recursive)
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: recursive processing, groupsToVisit={0}", _groupsToVisit.Count);

                        if (_groupsToVisit.Count > 0)
                        {
                            // Pull off the next group to visit
                            string groupPath = _groupsToVisit[0];
                            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: recursively processing {0}", groupPath);

                            _groupsToVisit.RemoveAt(0);
                            _groupsVisited.Add(groupPath);

                            // Set up for the next round of enumeration
                            DirectoryEntry de = SDSUtils.BuildDirectoryEntry(
                                groupPath,
                                _storeCtx.Credentials,
                                _storeCtx.AuthTypes);

                            _group = (UnsafeNativeMethods.IADsGroup)de.NativeObject;

                            UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members();
                            _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();

                            // and go on to the first member of this new group
                            needToRetry = true;
                            continue;
                        }
                    }
                }
            }while (needToRetry);

            return(false);
        }
示例#13
0
        private bool MoveNextLocal()
        {
            bool flag;

            do
            {
                flag = false;
                bool flag1 = this.membersEnumerator.MoveNext();
                if (!flag1)
                {
                    if (!this.recursive || this.groupsToVisit.Count <= 0)
                    {
                        continue;
                    }
                    string item = this.groupsToVisit[0];
                    this.groupsToVisit.RemoveAt(0);
                    this.groupsVisited.Add(item);
                    DirectoryEntry directoryEntry = SDSUtils.BuildDirectoryEntry(item, this.storeCtx.Credentials, this.storeCtx.AuthTypes);
                    this.@group = (UnsafeNativeMethods.IADsGroup)directoryEntry.NativeObject;
                    UnsafeNativeMethods.IADsMembers aDsMember = [email protected]();
                    this.membersEnumerator = ((IEnumerable)aDsMember).GetEnumerator();
                    flag = true;
                }
                else
                {
                    UnsafeNativeMethods.IADs current = (UnsafeNativeMethods.IADs) this.membersEnumerator.Current;
                    byte[]  numArray = (byte[])current.Get("objectSid");
                    SidType sidType  = Utils.ClassifySID(numArray);
                    if (sidType != SidType.FakeObject)
                    {
                        DirectoryEntry aDsPath = SDSUtils.BuildDirectoryEntry(this.storeCtx.Credentials, this.storeCtx.AuthTypes);
                        if (sidType != SidType.RealObjectFakeDomain)
                        {
                            aDsPath.Path = current.ADsPath;
                        }
                        else
                        {
                            string str = current.ADsPath;
                            UnsafeNativeMethods.Pathname     pathname    = new UnsafeNativeMethods.Pathname();
                            UnsafeNativeMethods.IADsPathname aDsPathname = (UnsafeNativeMethods.IADsPathname)pathname;
                            aDsPathname.Set(str, 1);
                            StringBuilder stringBuilder = new StringBuilder();
                            stringBuilder.Append("WinNT://");
                            stringBuilder.Append(this.storeCtx.MachineUserSuppliedName);
                            stringBuilder.Append("/");
                            int numElements = aDsPathname.GetNumElements();
                            for (int i = numElements - 2; i >= 0; i--)
                            {
                                stringBuilder.Append(aDsPathname.GetElement(i));
                                stringBuilder.Append("/");
                            }
                            stringBuilder.Remove(stringBuilder.Length - 1, 1);
                            aDsPath.Path = stringBuilder.ToString();
                        }
                        if (!this.IsLocalMember(numArray))
                        {
                            this.foreignMembers.Add(aDsPath);
                            flag = true;
                        }
                        else
                        {
                            if (!this.recursive || !SAMUtils.IsOfObjectClass(aDsPath, "Group"))
                            {
                                this.current = aDsPath;
                                this.currentFakePrincipal = null;
                                this.currentForeign       = null;
                                if (this.foreignResultSet != null)
                                {
                                    this.foreignResultSet.Dispose();
                                }
                                this.foreignResultSet = null;
                                return(true);
                            }
                            else
                            {
                                if (!this.groupsVisited.Contains(aDsPath.Path) && !this.groupsToVisit.Contains(aDsPath.Path))
                                {
                                    this.groupsToVisit.Add(aDsPath.Path);
                                }
                                flag = true;
                            }
                        }
                    }
                    else
                    {
                        this.currentFakePrincipal = this.storeCtx.ConstructFakePrincipalFromSID(numArray);
                        this.current        = null;
                        this.currentForeign = null;
                        if (this.foreignResultSet != null)
                        {
                            this.foreignResultSet.Dispose();
                        }
                        this.foreignResultSet = null;
                        return(true);
                    }
                }
            }while (flag);
            return(false);
        }