Exemple #1
0
        // Helper method: given a typeof(User/Computer/etc.), returns the userCtx/computerCtx/etc.
        internal StoreCtx ContextForType(Type t)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "ContextForType: type is " + t.ToString());

            Initialize();

            if (t == typeof(System.DirectoryServices.AccountManagement.UserPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.UserPrincipal)))
            {
                return(_userCtx);
            }
            else if (t == typeof(System.DirectoryServices.AccountManagement.ComputerPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.ComputerPrincipal)))
            {
                return(_computerCtx);
            }
            else if (t == typeof(System.DirectoryServices.AccountManagement.AuthenticablePrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.AuthenticablePrincipal)))
            {
                return(_userCtx);
            }
            else
            {
                Debug.Assert(t == typeof(System.DirectoryServices.AccountManagement.GroupPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.GroupPrincipal)));
                return(_groupCtx);
            }
        }
Exemple #2
0
        public Type GetUnderlyingSearcherType()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering GetUnderlyingSearcherType");

            CheckDisposed();

            // We have to have a filter
            if (_qbeFilter == null)
            {
                throw new InvalidOperationException(StringResources.PrincipalSearcherMustSetFilter);
            }

            StoreCtx storeCtx = _ctx.QueryCtx;

            Debug.Assert(storeCtx != null);

            // The underlying context must actually support search (i.e., no MSAM/reg-SAM)
            if (storeCtx.SupportsSearchNatively == false)
            {
                throw new InvalidOperationException(StringResources.PrincipalSearcherNoUnderlying);
            }

            return(storeCtx.SearcherNativeType());
        }
        public bool Remove(PrincipalContext context, IdentityType identityType, string identityValue)
        {
            CheckDisposed();

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (identityValue == null)
            {
                throw new ArgumentNullException("identityValue");
            }

            Principal principal = Principal.FindByIdentity(context, identityType, identityValue);

            if (principal == null)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalCollection", "Remove(urn/urn): no match");
                throw new NoMatchingPrincipalException(StringResources.NoMatchingPrincipalExceptionText);
            }

            return(Remove(principal));
        }
Exemple #4
0
        static internal Principal ConstructFakePrincipalFromSID(
            byte[] sid,
            PrincipalContext ctx,
            string serverName,
            NetCred credentials,
            string authorityName)
        {
            GlobalDebug.WriteLineIf(
                GlobalDebug.Info,
                "Utils",
                "ConstructFakePrincipalFromSID: Build principal for SID={0}, server={1}, authority={2}",
                Utils.ByteArrayToString(sid),
                (serverName != null ? serverName : "NULL"),
                (authorityName != null ? authorityName : "NULL"));

            Debug.Assert(ClassifySID(sid) == SidType.FakeObject);

            // Get the name for it
            string nt4Name = "";

            int    accountUsage = 0;
            string name;
            string domainName;

            int err = Utils.LookupSid(serverName, credentials, sid, out name, out domainName, out accountUsage);

            if (err == 0)
            {
                // If it failed, we'll just live without a name
                //Debug.Assert(accountUsage == 5 /*WellKnownGroup*/);
                nt4Name = (!String.IsNullOrEmpty(domainName) ? domainName + "\\" : "") + name;
            }
            else
            {
                GlobalDebug.WriteLineIf(
                    GlobalDebug.Warn,
                    "Utils",
                    "ConstructFakePrincipalFromSID: LookupSid failed (ignoring), serverName=" + serverName + ", err=" + err);
            }

            // Since LookupAccountSid indicates all of the NT AUTHORITY, etc., SIDs are WellKnownGroups,
            // we'll map them all to Group.

            // Create a Principal object to represent it
            GroupPrincipal g = GroupPrincipal.MakeGroup(ctx);

            g.fakePrincipal = true;
            g.unpersisted   = false;

            // Set the display name on the object
            g.LoadValueIntoProperty(PropertyNames.PrincipalDisplayName, nt4Name);

            // Set the display name on the object
            g.LoadValueIntoProperty(PropertyNames.PrincipalName, name);

            // Set the display name on the object
            g.LoadValueIntoProperty(PropertyNames.PrincipalSamAccountName, name);

            // SID IdentityClaim
            SecurityIdentifier sidObj = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid));

            // Set the display name on the object
            g.LoadValueIntoProperty(PropertyNames.PrincipalSid, sidObj);

            g.LoadValueIntoProperty(PropertyNames.GroupIsSecurityGroup, true);
            return(g);
        }
Exemple #5
0
        internal static IntPtr GetMachineDomainSid()
        {
            IntPtr pPolicyHandle = IntPtr.Zero;
            IntPtr pBuffer       = IntPtr.Zero;
            IntPtr pOA           = IntPtr.Zero;

            try
            {
                UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES();

                pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES)));
                Marshal.StructureToPtr(oa, pOA, false);
                int err = UnsafeNativeMethods.LsaOpenPolicy(
                    IntPtr.Zero,
                    pOA,
                    1,                      // POLICY_VIEW_LOCAL_INFORMATION
                    ref pPolicyHandle);

                if (err != 0)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: LsaOpenPolicy failed, gle=" + SafeNativeMethods.LsaNtStatusToWinError(err));

                    throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
                                                                        StringResources.UnableToRetrievePolicy,
                                                                        SafeNativeMethods.LsaNtStatusToWinError(err)));
                }

                Debug.Assert(pPolicyHandle != IntPtr.Zero);
                err = UnsafeNativeMethods.LsaQueryInformationPolicy(
                    pPolicyHandle,
                    5,                          // PolicyAccountDomainInformation
                    ref pBuffer);

                if (err != 0)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: LsaQueryInformationPolicy failed, gle=" + SafeNativeMethods.LsaNtStatusToWinError(err));

                    throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
                                                                        StringResources.UnableToRetrievePolicy,
                                                                        SafeNativeMethods.LsaNtStatusToWinError(err)));
                }

                Debug.Assert(pBuffer != IntPtr.Zero);
                UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO info = (UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO)
                                                                      Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO));

                Debug.Assert(UnsafeNativeMethods.IsValidSid(info.domainSid));

                // Now we make a copy of the SID to return
                int    sidLength  = UnsafeNativeMethods.GetLengthSid(info.domainSid);
                IntPtr pCopyOfSid = Marshal.AllocHGlobal(sidLength);
                bool   success    = UnsafeNativeMethods.CopySid(sidLength, pCopyOfSid, info.domainSid);
                if (!success)
                {
                    int lastError = Marshal.GetLastWin32Error();
                    GlobalDebug.WriteLineIf(GlobalDebug.Error,
                                            "Utils",
                                            "GetMachineDomainSid: CopySid failed, errorcode=" + lastError);

                    throw new PrincipalOperationException(
                              String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrievePolicy, lastError));
                }

                return(pCopyOfSid);
            }
            finally
            {
                if (pPolicyHandle != IntPtr.Zero)
                {
                    UnsafeNativeMethods.LsaClose(pPolicyHandle);
                }

                if (pBuffer != IntPtr.Zero)
                {
                    UnsafeNativeMethods.LsaFreeMemory(pBuffer);
                }

                if (pOA != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pOA);
                }
            }
        }
Exemple #6
0
        public bool Remove(Principal principal)
        {
            CheckDisposed();

            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }

            // Ask the StoreCtx to verify that this member can be removed.  Right now, the only
            // reason it couldn't is if it's actually a member by virtue of its primaryGroupId
            // pointing to this group.
            //
            // If storeCtxToUse == null, then we must be unpersisted, in which case there clearly
            // can't be any such primary group members pointing to this group on the store.
            StoreCtx storeCtxToUse = _owningGroup.GetStoreCtxToUse();
            string   explanation;

            Debug.Assert(storeCtxToUse != null || _owningGroup.unpersisted == true);

            if ((storeCtxToUse != null) && (!storeCtxToUse.CanGroupMemberBeRemoved(_owningGroup, principal, out explanation)))
            {
                throw new InvalidOperationException(explanation);
            }

            bool removed = false;

            // If the value was previously inserted, we just remove it from insertedValuesPending.
            if (_insertedValuesPending.Contains(principal))
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: removing from insertedValuesPending");

                MarkChange();
                _insertedValuesPending.Remove(principal);
                removed = true;

                // If they did a Remove(x) --> Save() --> Add(x) --> Remove(x), we'll end up with x in neither
                // the ResultSet or the removedValuesCompleted list.  This is bad.  Avoid that by adding x
                // back to the removedValuesCompleted list here.
                //
                // At worst, we end up with x on the removedValuesCompleted list even though it's not even in
                // resultSet.  That's not a problem.  The only thing we use the removedValuesCompleted list for
                // is deciding which values in resultSet to skip, anyway.
                if (!_removedValuesCompleted.Contains(principal))
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: adding to removedValuesCompleted");
                    _removedValuesCompleted.Add(principal);
                }
            }
            else
            {
                // They're trying to remove a already-persisted value.  We add it to the
                // removedValues list.  Then, if it's already been loaded into insertedValuesCompleted,
                // we remove it from insertedValuesCompleted.

                removed = Contains(principal);
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: making it a pending remove, removed={0}", removed);

                if (removed)
                {
                    MarkChange();

                    _removedValuesPending.Add(principal);

                    // in case it's the result of a previous-but-already-committed insert
                    _insertedValuesCompleted.Remove(principal);
                }
            }

            return(removed);
        }
Exemple #7
0
        internal static bool GetOSVersion(DirectoryEntry computerDE, out int versionMajor, out int versionMinor)
        {
            Debug.Assert(SAMUtils.IsOfObjectClass(computerDE, "Computer"));

            versionMajor = 0;
            versionMinor = 0;

            string version = null;

            try
            {
                if (computerDE.Properties["OperatingSystemVersion"].Count > 0)
                {
                    Debug.Assert(computerDE.Properties["OperatingSystemVersion"].Count == 1);

                    version = (string)computerDE.Properties["OperatingSystemVersion"].Value;
                }
            }
            catch (COMException e)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Error, "SAMUtils", "GetOSVersion: caught COMException with message " + e.Message);

                // Couldn't retrieve the value
                if (e.ErrorCode == unchecked ((int)0x80070035))  // ERROR_BAD_NETPATH
                {
                    return(false);
                }

                throw;
            }

            // Couldn't retrieve the value
            if (version == null || version.Length == 0)
            {
                return(false);
            }

            // This string should be in the form "M.N", where M and N are integers.
            // We'll also accept "M", which we'll treat as "M.0".
            //
            // We'll split the string into its period-separated components, and parse
            // each component into an int.
            string[] versionComponents = version.Split(new char[] { '.' });

            Debug.Assert(versionComponents.Length >= 1);    // since version was a non-empty string

            try
            {
                versionMajor = Int32.Parse(versionComponents[0], CultureInfo.InvariantCulture);

                if (versionComponents.Length > 1)
                {
                    versionMinor = Int32.Parse(versionComponents[1], CultureInfo.InvariantCulture);
                }

                // Sanity check: there are no negetive OS versions, nor is there a version "0".
                if (versionMajor <= 0 || versionMinor < 0)
                {
                    Debug.Fail(String.Format(
                                   CultureInfo.CurrentCulture,
                                   "SAMUtils.GetOSVersion: {0} claims to have negetive OS version, {1}",
                                   computerDE.Path,
                                   version));

                    return(false);
                }
            }
            catch (FormatException)
            {
                Debug.Fail(String.Format(
                               CultureInfo.CurrentCulture,
                               "SAMUtils.GetOSVersion: FormatException on {0} for {1}",
                               version,
                               computerDE.Path));

                return(false);
            }
            catch (OverflowException)
            {
                Debug.Fail(String.Format(
                               CultureInfo.CurrentCulture,
                               "SAMUtils.GetOSVersion: OverflowException on {0} for {1}",
                               version,
                               computerDE.Path));
                return(false);
            }

            return(true);
        }
Exemple #8
0
        internal ADEntriesSet(SearchResultCollection src, ADStoreCtx storeCtx, object discriminant) : this(src, storeCtx)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "Ctor");

            _discriminant = discriminant;
        }
Exemple #9
0
        internal override bool MoveNext()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Entering MoveNext");
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Filter {0}", _constraintData);
            bool   match = false;
            string dn    = "NotSet";

            if (!base.MoveNext())
            {
                return(false);
            }
            else
            {
                while (!match)
                {
                    if (null == this.current)
                    {
                        return(false);
                    }

                    switch (_constraint)
                    {
                    case ConstraintType.ContainerStringMatch:

                        if (this.current is SearchResult)
                        {
                            dn = ((SearchResult)this.current).Properties["distinguishedName"][0].ToString();
                        }
                        else
                        {
                            dn = ((DirectoryEntry)this.current).Properties["distinguishedName"].Value.ToString();
                        }

                        if (dn.EndsWith((string)_constraintData, StringComparison.Ordinal))
                        {
                            match = true;
                        }

                        break;

                    case ConstraintType.ResultValidatorDelegateMatch:
                    {
                        ResultValidator resultValidator = _constraintData as ResultValidator;
                        if (resultValidator != null)
                        {
                            dSPropertyCollection resultPropCollection = null;
                            if (this.current is SearchResult)
                            {
                                resultPropCollection = new dSPropertyCollection(((SearchResult)this.current).Properties);
                            }
                            else
                            {
                                resultPropCollection = new dSPropertyCollection(((DirectoryEntry)this.current).Properties);
                            }
                            match = resultValidator.Invoke(resultPropCollection);
                        }
                        else
                        {
                            Debug.Fail("ADStoreCtx.ADDNConstraintLinkedAttrSet: Invalid constraint data. Expected: object of type ResultValidator");
                        }
                        break;
                    }

                    default:
                        Debug.Fail("ADStoreCtx.ADDNConstraintLinkedAttrSet: fell off end looking for " + _constraint.ToString());
                        break;
                    }

                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Found {0} Match {1}", dn, match.ToString());

                    if (!match)
                    {
                        if (!this.MoveNext())
                        {
                            return(false);
                        }
                    }
                }

                return(match);
            }
        }
        //
        // Cross-store support
        //

        // Given a native store object that represents a "foreign" principal (e.g., a FPO object in this store that
        // represents a pointer to another store), maps that representation to the other store's StoreCtx and returns
        // a Principal from that other StoreCtx.  The implementation of this method is highly dependent on the
        // details of the particular store, and must have knowledge not only of this StoreCtx, but also of how to
        // interact with other StoreCtxs to fulfill the request.
        //
        // This method is typically used by ResultSet implementations, when they're iterating over a collection
        // (e.g., of group membership) and encounter an entry that represents a foreign principal.
        internal override Principal ResolveCrossStoreRefToPrincipal(object o)
        {
            Debug.Assert(o is DirectoryEntry);

            // Get the SID of the foreign principal
            DirectoryEntry foreignDE = (DirectoryEntry)o;

            if (foreignDE.Properties["objectSid"].Count == 0)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: no objectSid found");
                throw new PrincipalOperationException(SR.SAMStoreCtxCantRetrieveObjectSidForCrossStore);
            }

            Debug.Assert(foreignDE.Properties["objectSid"].Count == 1);

            byte[] sid = (byte[])foreignDE.Properties["objectSid"].Value;

            // Ask the OS to resolve the SID to its target.
            int    accountUsage = 0;
            string name;
            string domainName;

            int err = Utils.LookupSid(this.MachineUserSuppliedName, _credentials, sid, out name, out domainName, out accountUsage);

            if (err != 0)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Warn,
                                        "SAMStoreCtx",
                                        "ResolveCrossStoreRefToPrincipal: LookupSid failed, err={0}, server={1}",
                                        err,
                                        this.MachineUserSuppliedName);

                throw new PrincipalOperationException(
                          SR.Format(SR.SAMStoreCtxCantResolveSidForCrossStore, err));
            }

            GlobalDebug.WriteLineIf(GlobalDebug.Info,
                                    "SAMStoreCtx",
                                    "ResolveCrossStoreRefToPrincipal: LookupSid found {0} in {1}",
                                    name,
                                    domainName);

            // Since this is SAM, the remote principal must be an AD principal.
            // Build a PrincipalContext for the store which owns the principal
            // Use the ad default options so we turn sign and seal back on.
#if USE_CTX_CACHE
            PrincipalContext remoteCtx = SDSCache.Domain.GetContext(domainName, _credentials, DefaultContextOptions.ADDefaultContextOption);
#else
            PrincipalContext remoteCtx = new PrincipalContext(
                ContextType.Domain,
                domainName,
                null,
                (this.credentials != null ? credentials.UserName : null),
                (this.credentials != null ? credentials.Password : null),
                DefaultContextOptions.ADDefaultContextOption);
#endif

            SecurityIdentifier sidObj = new SecurityIdentifier(sid, 0);

            Principal p = remoteCtx.QueryCtx.FindPrincipalByIdentRef(
                typeof(Principal),
                UrnScheme.SidScheme,
                sidObj.ToString(),
                DateTime.UtcNow);

            if (p != null)
            {
                return(p);
            }
            else
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: no matching principal");
                throw new PrincipalOperationException(SR.SAMStoreCtxFailedFindCrossStoreTarget);
            }
        }
        // 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);
            }
        }
 internal override void Move(StoreCtx originalStore, Principal p)
 {
     GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Move");
 }
        // computerInfoLock must be held coming in here
        private void LoadComputerInfo()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo");

            Debug.Assert(_ctxBase != null);
            Debug.Assert(SAMUtils.IsOfObjectClass(_ctxBase, "Computer"));

            //
            // Target OS version
            //
            int versionMajor;
            int versionMinor;

            if (!SAMUtils.GetOSVersion(_ctxBase, out versionMajor, out versionMinor))
            {
                throw new PrincipalOperationException(SR.SAMStoreCtxUnableToRetrieveVersion);
            }

            Debug.Assert(versionMajor > 0);
            Debug.Assert(versionMinor >= 0);

            if (versionMajor >= 6)      // 6.0 == Longhorn
            {
                _isLSAM = true;
            }
            else
            {
                _isLSAM = false;
            }

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: ver={0}.{1}", versionMajor, versionMinor);

            //
            // Machine user-supplied name
            //

            // This ADSI property stores the machine name as supplied by the user in the ADsPath.
            // It could be a flat name or a DNS name.
            if (_ctxBase.Properties["Name"].Count > 0)
            {
                Debug.Assert(_ctxBase.Properties["Name"].Count == 1);

                _machineUserSuppliedName = (string)_ctxBase.Properties["Name"].Value;
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: machineUserSuppliedName={0}", _machineUserSuppliedName);
            }
            else
            {
                throw new PrincipalOperationException(SR.SAMStoreCtxUnableToRetrieveMachineName);
            }

            //
            // Machine flat name
            //
            IntPtr buffer = IntPtr.Zero;

            try
            {
                // This function takes in a flat or DNS name, and returns the flat name of the computer
                int err = UnsafeNativeMethods.NetWkstaGetInfo(_machineUserSuppliedName, 100, ref buffer);
                if (err == 0)
                {
                    UnsafeNativeMethods.WKSTA_INFO_100 wkstaInfo =
                        (UnsafeNativeMethods.WKSTA_INFO_100)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.WKSTA_INFO_100));

                    _machineFlatName = wkstaInfo.wki100_computername;
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: machineFlatName={0}", _machineFlatName);
                }
                else
                {
                    throw new PrincipalOperationException(
                              SR.Format(
                                  SR.SAMStoreCtxUnableToRetrieveFlatMachineName,
                                  err));
                }
            }
            finally
            {
                if (buffer != IntPtr.Zero)
                {
                    UnsafeNativeMethods.NetApiBufferFree(buffer);
                }
            }
        }
Exemple #14
0
        // Advance the enumerator to the next principal in the result set, pulling in additional pages
        // of results (or ranges of attribute values) as needed.
        // Returns true if successful, false if no more results to return.
        override internal bool MoveNext()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "Entering MoveNext");

            Debug.Assert(_enumerator != null);

            bool needToRetry = false;
            bool f;

            // Have we exceeded the requested size limit?
            if ((_sizeLimit != -1) && (_resultsReturned >= _sizeLimit))
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info,
                                        "SAMQuerySet",
                                        "MoveNext: exceeded sizelimit, ret={0}, limit={1}",
                                        _resultsReturned,
                                        _sizeLimit);
                _endReached = true;
            }

            // End was reached previously.  Nothing more to do.
            if (_endReached)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: endReached");
                return(false);
            }

            // Pull the next result.  We may have to repeat this several times
            // until we find a result that matches the user's filter.
            do
            {
                f           = _enumerator.MoveNext();
                needToRetry = false;

                if (f)
                {
                    DirectoryEntry entry = (DirectoryEntry)_enumerator.Current;

                    // Does it match the user's properties?
                    //
                    // We'd like to use DirectoryEntries.SchemaFilter rather than calling
                    // IsOfCorrectType here, but SchemaFilter has a bug
                    // where multiple DirectoryEntries all share the same SchemaFilter ---
                    // which would create multithreading issues for us.
                    if (IsOfCorrectType(entry) && _matcher.Matches(entry))
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: found a match on {0}", entry.Path);

                        // Yes.  It's our new current object
                        _current = entry;
                        _resultsReturned++;
                    }
                    else
                    {
                        // No.  Retry.
                        needToRetry = true;
                    }
                }
            }while (needToRetry);

            if (!f)
            {
                /*
                 * // One more to try: the root object
                 * if (IsOfCorrectType(this.ctxBase) && this.matcher.Matches(this.ctxBase))
                 * {
                 *  GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: found a match on root {0}", this.ctxBase);
                 *
                 *  this.current = this.ctxBase;
                 *  this.resultsReturned++;
                 *  f = true;
                 * }
                 * else
                 * {
                 *  endReached = true;
                 * }
                 * */
            }

            return(f);
        }
Exemple #15
0
        //
        // Internal Constructors
        //

        // Note that resultSet can be null
        internal PrincipalSearchResult(ResultSet resultSet)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearchResult", "Ctor");

            _resultSet = resultSet;
        }
Exemple #16
0
        private void BuildFilterSet(Principal p, string[] propertySet, QbeFilterDescription qbeFilterDescription)
        {
            foreach (string propertyName in propertySet)
            {
                if (p.GetChangeStatusForProperty(propertyName))
                {
                    // Property has changed.  Add it to the filter set.
                    object value = p.GetValueForProperty(propertyName);

                    GlobalDebug.WriteLineIf(
                        GlobalDebug.Info,
                        "StoreCtx",
                        "BuildFilterSet: type={0}, property name={1}, property value={2} of type {3}",
                        p.GetType().ToString(),
                        propertyName,
                        value.ToString(),
                        value.GetType().ToString());

                    // Build the right filter based on type of the property value
                    if (value is PrincipalValueCollection <string> )
                    {
                        PrincipalValueCollection <string> trackingList = (PrincipalValueCollection <string>)value;
                        foreach (string s in trackingList.Inserted)
                        {
                            object filter = FilterFactory.CreateFilter(propertyName);
                            ((FilterBase)filter).Value = (string)s;
                            qbeFilterDescription.FiltersToApply.Add(filter);
                        }
                    }
                    else if (value is X509Certificate2Collection)
                    {
                        // Since QBE filter objects are always unpersisted, any certs in the collection
                        // must have been inserted by the application.
                        X509Certificate2Collection certCollection = (X509Certificate2Collection)value;
                        foreach (X509Certificate2 cert in certCollection)
                        {
                            object filter = FilterFactory.CreateFilter(propertyName);
                            ((FilterBase)filter).Value = (X509Certificate2)cert;
                            qbeFilterDescription.FiltersToApply.Add(filter);
                        }
                    }
                    else
                    {
                        // It's not one of the multivalued cases.  Try the scalar cases.

                        object filter = FilterFactory.CreateFilter(propertyName);

                        if (value == null)
                        {
                            ((FilterBase)filter).Value = null;
                        }
                        else if (value is bool)
                        {
                            ((FilterBase)filter).Value = (bool)value;
                        }
                        else if (value is string)
                        {
                            ((FilterBase)filter).Value = (string)value;
                        }
                        else if (value is GroupScope)
                        {
                            ((FilterBase)filter).Value = (GroupScope)value;
                        }
                        else if (value is byte[])
                        {
                            ((FilterBase)filter).Value = (byte[])value;
                        }
                        else if (value is Nullable <DateTime> )
                        {
                            ((FilterBase)filter).Value = (Nullable <DateTime>)value;
                        }
                        else if (value is ExtensionCache)
                        {
                            ((FilterBase)filter).Value = (ExtensionCache)value;
                        }
                        else if (value is QbeMatchType)
                        {
                            ((FilterBase)filter).Value = (QbeMatchType)value;
                        }
                        else
                        {
                            // Internal error.  Didn't match either the known multivalued or scalar cases.
                            Debug.Fail(String.Format(
                                           CultureInfo.CurrentCulture,
                                           "StoreCtx.BuildFilterSet: fell off end looking for {0} of type {1}",
                                           propertyName,
                                           value.GetType().ToString()
                                           ));
                        }

                        qbeFilterDescription.FiltersToApply.Add(filter);
                    }
                }
            }
        }
Exemple #17
0
        static internal void InsertPrincipal(
            Principal p,
            StoreCtx storeCtx,
            GroupMembershipUpdater updateGroupMembership,
            NetCred credentials,
            AuthenticationTypes authTypes,
            bool needToSetPassword)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "Entering InsertPrincipal");

            Debug.Assert(storeCtx != null);
            Debug.Assert(storeCtx is ADStoreCtx || storeCtx is SAMStoreCtx);
            Debug.Assert(p != null);

            if ((!(p is UserPrincipal)) &&
                (!(p is GroupPrincipal)) &&
                (!(p is AuthenticablePrincipal)) &&
                (!(p is ComputerPrincipal)))
            {
                // It's not a type of Principal that we support
                GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SDSUtils", "InsertPrincipal: Bad principal type:" + p.GetType().ToString());

                throw new InvalidOperationException(
                          String.Format(CultureInfo.CurrentCulture, SR.StoreCtxUnsupportedPrincipalTypeForSave, p.GetType().ToString()));
            }

            // Commit the properties
            SDSUtils.ApplyChangesToDirectory(
                p,
                storeCtx,
                updateGroupMembership,
                credentials,
                authTypes
                );

            // Handle any saved-off operations

            // For SAM, we set password elsewhere prior to creating the principal, so needToSetPassword == false
            // For AD, we have to set the password after creating the principal, so needToSetPassword == true
            if (needToSetPassword && p.GetChangeStatusForProperty(PropertyNames.PwdInfoPassword))
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting password");

                // Only AuthenticablePrincipals can have PasswordInfo
                Debug.Assert(p is AuthenticablePrincipal);

                string password = (string)p.GetValueForProperty(PropertyNames.PwdInfoPassword);
                Debug.Assert(password != null); // if null, PasswordInfo should not have indicated it was changed

                storeCtx.SetPassword((AuthenticablePrincipal)p, password);
            }

            if (p.GetChangeStatusForProperty(PropertyNames.PwdInfoExpireImmediately))
            {
                // Only AuthenticablePrincipals can have PasswordInfo
                Debug.Assert(p is AuthenticablePrincipal);

                bool expireImmediately = (bool)p.GetValueForProperty(PropertyNames.PwdInfoExpireImmediately);

                if (expireImmediately)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting pwd expired");

                    storeCtx.ExpirePassword((AuthenticablePrincipal)p);
                }
            }
        }
Exemple #18
0
        protected void TranslateSids(string target, IntPtr[] pSids)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: processing {0} SIDs", pSids.Length);

            // if there are no SIDs to translate return
            if (pSids.Length == 0)
            {
                return;
            }

            // Build the list of SIDs to resolve
            int sidCount = pSids.Length;

            // Translate the SIDs in bulk
            IntPtr pOA           = IntPtr.Zero;
            IntPtr pPolicyHandle = IntPtr.Zero;

            IntPtr pDomains = IntPtr.Zero;

            UnsafeNativeMethods.LSA_TRUST_INFORMATION[] domains;

            IntPtr pNames = IntPtr.Zero;

            UnsafeNativeMethods.LSA_TRANSLATED_NAME[] names;

            try
            {
                //
                // Get the policy handle
                //
                UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES();

                pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES)));
                Marshal.StructureToPtr(oa, pOA, false);

                int err = 0;
                if (target == null)
                {
                    err = UnsafeNativeMethods.LsaOpenPolicy(
                        IntPtr.Zero,
                        pOA,
                        0x800,                    // POLICY_LOOKUP_NAMES
                        ref pPolicyHandle);
                }
                else
                {
                    // Build an entry.  Note that LSA_UNICODE_STRING.length is in bytes,
                    // while PtrToStringUni expects a length in characters.
                    UnsafeNativeMethods.LSA_UNICODE_STRING_Managed lsaTargetString = new UnsafeNativeMethods.LSA_UNICODE_STRING_Managed();
                    lsaTargetString.buffer        = target;
                    lsaTargetString.length        = (ushort)(target.Length * 2);
                    lsaTargetString.maximumLength = lsaTargetString.length;

                    IntPtr lsaTargetPr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_UNICODE_STRING)));

                    try
                    {
                        Marshal.StructureToPtr(lsaTargetString, lsaTargetPr, false);

                        err = UnsafeNativeMethods.LsaOpenPolicy(
                            lsaTargetPr,
                            pOA,
                            0x800,                    // POLICY_LOOKUP_NAMES
                            ref pPolicyHandle);
                    }
                    finally
                    {
                        if (lsaTargetPr != IntPtr.Zero)
                        {
                            UnsafeNativeMethods.LSA_UNICODE_STRING lsaTargetUnmanagedPtr =
                                (UnsafeNativeMethods.LSA_UNICODE_STRING)Marshal.PtrToStructure(lsaTargetPr, typeof(UnsafeNativeMethods.LSA_UNICODE_STRING));
                            if (lsaTargetUnmanagedPtr.buffer != IntPtr.Zero)
                            {
                                Marshal.FreeHGlobal(lsaTargetUnmanagedPtr.buffer);
                                lsaTargetUnmanagedPtr.buffer = IntPtr.Zero;
                            }
                            Marshal.FreeHGlobal(lsaTargetPr);
                        }
                    }
                }

                if (err != 0)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: couldn't get policy handle, err={0}", err);

                    throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
                                                                        StringResources.AuthZErrorEnumeratingGroups,
                                                                        SafeNativeMethods.LsaNtStatusToWinError(err)));
                }

                Debug.Assert(pPolicyHandle != IntPtr.Zero);

                //
                // Translate the SIDs
                //

                err = UnsafeNativeMethods.LsaLookupSids(
                    pPolicyHandle,
                    sidCount,
                    pSids,
                    out pDomains,
                    out pNames);

                // ignore error STATUS_SOME_NOT_MAPPED = 0x00000107 and
                // STATUS_NONE_MAPPED = 0xC0000073
                if (err != 0 &&
                    err != 263 &&
                    err != -1073741709)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: LsaLookupSids failed, err={0}", err);

                    throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
                                                                        StringResources.AuthZErrorEnumeratingGroups,
                                                                        SafeNativeMethods.LsaNtStatusToWinError(err)));
                }

                //
                // Get the group names in managed form
                //
                names = new UnsafeNativeMethods.LSA_TRANSLATED_NAME[sidCount];
                IntPtr pCurrentName = pNames;

                for (int i = 0; i < sidCount; i++)
                {
                    names[i] = (UnsafeNativeMethods.LSA_TRANSLATED_NAME)
                               Marshal.PtrToStructure(pCurrentName, typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME));

                    pCurrentName = new IntPtr(pCurrentName.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME)));
                }

                //
                // Get the domain names in managed form
                //

                // Extract LSA_REFERENCED_DOMAIN_LIST.Entries

                UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST referencedDomains = (UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST)Marshal.PtrToStructure(pDomains, typeof(UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST));

                int domainCount = referencedDomains.entries;

                // Extract LSA_REFERENCED_DOMAIN_LIST.Domains, by iterating over the array and marshalling
                // each native LSA_TRUST_INFORMATION into a managed LSA_TRUST_INFORMATION.

                domains = new UnsafeNativeMethods.LSA_TRUST_INFORMATION[domainCount];

                IntPtr pCurrentDomain = referencedDomains.domains;

                for (int i = 0; i < domainCount; i++)
                {
                    domains[i]     = (UnsafeNativeMethods.LSA_TRUST_INFORMATION)Marshal.PtrToStructure(pCurrentDomain, typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION));
                    pCurrentDomain = new IntPtr(pCurrentDomain.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION)));
                }

                GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: got {0} groups in {1} domains", sidCount, domainCount);

                //
                // Build the list of entries
                //
                Debug.Assert(names.Length == sidCount);

                for (int i = 0; i < names.Length; i++)
                {
                    UnsafeNativeMethods.LSA_TRANSLATED_NAME name = names[i];

                    // Build an entry.  Note that LSA_UNICODE_STRING.length is in bytes,
                    // while PtrToStringUni expects a length in characters.
                    SidListEntry entry = new SidListEntry();

                    Debug.Assert(name.name.length % 2 == 0);
                    entry.name = Marshal.PtrToStringUni(name.name.buffer, name.name.length / 2);

                    // Get the domain associated with this name
                    Debug.Assert(name.domainIndex < domains.Length);
                    if (name.domainIndex >= 0)
                    {
                        UnsafeNativeMethods.LSA_TRUST_INFORMATION domain = domains[name.domainIndex];
                        Debug.Assert(domain.name.length % 2 == 0);
                        entry.sidIssuerName = Marshal.PtrToStringUni(domain.name.buffer, domain.name.length / 2);
                    }

                    entry.pSid = pSids[i];

                    _entries.Add(entry);
                }

                // Sort the list so they are oriented by the issuer name.
                // this.entries.Sort( new SidListComparer());
            }
            finally
            {
                if (pDomains != IntPtr.Zero)
                {
                    UnsafeNativeMethods.LsaFreeMemory(pDomains);
                }

                if (pNames != IntPtr.Zero)
                {
                    UnsafeNativeMethods.LsaFreeMemory(pNames);
                }

                if (pPolicyHandle != IntPtr.Zero)
                {
                    UnsafeNativeMethods.LsaClose(pPolicyHandle);
                }

                if (pOA != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pOA);
                }
            }
        }
Exemple #19
0
        public void Save(PrincipalContext context)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Entering Save(Context)");

            // Make sure we're not disposed or deleted.
            CheckDisposedOrDeleted();

            // Make sure we're not a fake principal
            CheckFakePrincipal();

            // We must have a PrincipalContext to save into.  This should always be the case, unless we're unpersisted
            // and they never set a PrincipalContext.
            if (context == null)
            {
                Debug.Assert(this.unpersisted == true);
                throw new InvalidOperationException(SR.NullArguments);
            }

            if (context.ContextType == ContextType.Machine || _ctx.ContextType == ContextType.Machine)
            {
                throw new InvalidOperationException(SR.SaveToNotSupportedAgainstMachineStore);
            }

            // If the user is trying to save to the same context we are already set to then just save the changes
            if (context == _ctx)
            {
                Save();
                return;
            }

            // If we already have a context set on this object then make sure the new
            // context is of the same type.
            if (context.ContextType != _ctx.ContextType)
            {
                Debug.Assert(this.unpersisted == true);
                throw new InvalidOperationException(SR.SaveToMustHaveSamecontextType);
            }

            StoreCtx originalStoreCtx = GetStoreCtxToUse();

            _ctx = context;

            // Call the appropriate operation depending on whether this is an insert or update
            StoreCtx newStoreCtx = GetStoreCtxToUse();

            Debug.Assert(newStoreCtx != null);      // since we know this.ctx isn't null
            Debug.Assert(originalStoreCtx != null); // since we know this.ctx isn't null

            if (this.unpersisted)
            {
                // We have an unpersisted principal so we just want to create a principal in the new store.
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save(context): inserting new principal of type {0} using {1}", this.GetType(), newStoreCtx.GetType());
                Debug.Assert(newStoreCtx == _ctx.ContextForType(this.GetType()));
                newStoreCtx.Insert(this);
                this.unpersisted = false;  // once we persist, we're no longer in the unpersisted state
            }
            else
            {
                // We have a principal that already exists.  We need to move it to the new store.
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save(context): Moving principal of type {0} using {1}", this.GetType(), newStoreCtx.GetType());

                // we are now saving to a new store so this principal is unpersisted.
                this.unpersisted = true;

                // If the user has modified the name save away the current name so
                // if the move succeeds and the update fails we will move the item back to the original
                // store with the original name.
                bool   nameModified = _nameChanged == LoadState.Changed;
                string previousName = null;

                if (nameModified)
                {
                    string newName = _name;
                    _ctx.QueryCtx.Load(this, PropertyNames.PrincipalName);
                    previousName = _name;
                    this.Name    = newName;
                }

                newStoreCtx.Move(originalStoreCtx, this);

                try
                {
                    this.unpersisted = false;  // once we persist, we're no longer in the unpersisted state

                    newStoreCtx.Update(this);
                }
                catch (System.SystemException e)
                {
                    try
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Error, "Principal", "Save(context):,  Update Failed (attempting to move back) Exception {0} ", e.Message);

                        if (nameModified)
                        {
                            this.Name = previousName;
                        }

                        originalStoreCtx.Move(newStoreCtx, this);

                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Move back succeeded");
                    }
                    catch (System.SystemException deleteFail)
                    {
                        // The move back failed.  Just continue we will throw the original exception below.
                        GlobalDebug.WriteLineIf(GlobalDebug.Error, "Principal", "Save(context):,  Move back Failed {0} ", deleteFail.Message);
                    }

                    if (e is System.Runtime.InteropServices.COMException)
                    {
                        throw ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e);
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            _ctx.QueryCtx = newStoreCtx;  // so Updates go to the right StoreCtx
        }
Exemple #20
0
        public PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions)
        {
            string contextName   = name;
            string userName      = null;
            bool   explicitCreds = false;

            if (credentials != null && credentials.UserName != null)
            {
                if (credentials.Domain != null)
                {
                    userName = credentials.Domain + "\\" + credentials.UserName;
                }
                else
                {
                    userName = credentials.UserName;
                }

                explicitCreds = true;
            }
            else
            {
                userName = Utils.GetNT4UserName();
            }

            GlobalDebug.WriteLineIf(
                GlobalDebug.Info,
                "SDSCache",
                "GetContext: looking for context for server {0}, user {1}, explicitCreds={2}, options={3}",
                name,
                userName,
                explicitCreds.ToString(),
                contextOptions.ToString());

            if (!_isSAM)
            {
                // Determine the domain DNS name

                // DS_RETURN_DNS_NAME | DS_DIRECTORY_SERVICE_REQUIRED | DS_BACKGROUND_ONLY
                int flags = unchecked ((int)(0x40000000 | 0x00000010 | 0x00000100));
                UnsafeNativeMethods.DomainControllerInfo info = Utils.GetDcName(null, contextName, null, flags);
                contextName = info.DomainName;
            }

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: final contextName is " + contextName);

            ManualResetEvent contextReadyEvent = null;

            while (true)
            {
                Hashtable        credTable = null;
                PrincipalContext ctx       = null;

                // Wait for the PrincipalContext to be ready
                if (contextReadyEvent != null)
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: waiting");

                    contextReadyEvent.WaitOne();
                }

                contextReadyEvent = null;

                lock (_tableLock)
                {
                    CredHolder credHolder = (CredHolder)_table[contextName];

                    if (credHolder != null)
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: found a credHolder for " + contextName);

                        credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds);
                        Debug.Assert(credTable != null);

                        object o = credTable[userName];

                        if (o is Placeholder)
                        {
                            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: credHolder for " + contextName + " has a Placeholder");

                            // A PrincipalContext is currently being constructed by another thread.
                            // Wait for it.
                            contextReadyEvent = ((Placeholder)o).contextReadyEvent;
                            continue;
                        }

                        WeakReference refToContext = o as WeakReference;
                        if (refToContext != null)
                        {
                            GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is non-null");

                            ctx = (PrincipalContext)refToContext.Target;  // null if GC'ed

                            // If the PrincipalContext hasn't been GCed or disposed, use it.
                            // Otherwise, we'll need to create a new one
                            if (ctx != null && ctx.Disposed == false)
                            {
                                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: using found refToContext");
                                return(ctx);
                            }
                            else
                            {
                                GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is GCed/disposed, removing");
                                credTable.Remove(userName);
                            }
                        }
                    }

                    // Either credHolder/credTable are null (no contexts exist for the contextName), or credHolder/credTable
                    // are non-null (contexts exist, but none for the userName).  Either way, we need to create a PrincipalContext.

                    if (credHolder == null)
                    {
                        GlobalDebug.WriteLineIf(
                            GlobalDebug.Info,
                            "SDSCache",
                            "GetContext: null credHolder for " + contextName + ", explicitCreds=" + explicitCreds.ToString());

                        // No contexts exist for the contextName.  Create a CredHolder for the contextName so we have a place
                        // to store the PrincipalContext we'll be creating.
                        credHolder          = new CredHolder();
                        _table[contextName] = credHolder;

                        credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds);
                    }

                    // Put a placeholder on the contextName/userName slot, so that other threads that come along after
                    // we release the tableLock know we're in the process of creating the needed PrincipalContext and will wait for us
                    credTable[userName] = new Placeholder();
                }

                // Now we just need to create a PrincipalContext for the contextName and credentials
                GlobalDebug.WriteLineIf(
                    GlobalDebug.Info,
                    "SDSCache",
                    "GetContext: creating context, contextName=" + contextName + ", options=" + contextOptions.ToString());

                ctx = new PrincipalContext(
                    (_isSAM ? ContextType.Machine : ContextType.Domain),
                    contextName,
                    null,
                    contextOptions,
                    credentials?.UserName,
                    credentials?.Password
                    );

                lock (_tableLock)
                {
                    Placeholder placeHolder = (Placeholder)credTable[userName];

                    // Replace the placeholder with the newly-created PrincipalContext
                    credTable[userName] = new WeakReference(ctx);

                    // Signal waiting threads to continue.  We do this after inserting the PrincipalContext
                    // into the table, so that the PrincipalContext is ready as soon as the other threads wake up.
                    // (Actually, the order probably doesn't matter, since even if we did it in the
                    // opposite order and the other thread woke up before we inserted the PrincipalContext, it would
                    // just block as soon as it tries to acquire the tableLock that we're currently holding.)
                    bool f = placeHolder.contextReadyEvent.Set();
                    Debug.Assert(f);
                }

                return(ctx);
            }
        }
Exemple #21
0
        //  These are verbatim C# string ( @ ) where \ is actually \\
        // Input            Matches                 RegEx
        // -----            -------                -----
        //   *                any ( 1 or more )     .*
        //
        //   \*                *                           \*
        //   \                 \                            \\
        //   (                 (                            \(
        //   \(                (                            \(
        //   )                 )                            \)
        //   \)                )                            \)
        //   \\                \                             \\
        //   x                 x                             x      (where x is anything else)
        // Add \G to beginning and \z to the end so that the regex will be anchored at the either end of the property
        // \G = Regex must match at the beginning
        // \z = Regex must match at the end
        // ( ) * are special characters to Regex so they must be escaped with \\.  We support these from teh user either raw or already escaped.
        // Any other \ in the input string are translated to an actual \ in the match because we cannot determine usage except for  ( ) *
        // The user cannot enter any regex escape sequence they would like in their match string.  Only * is supported.
        //
        //  @"c:\Home" -> "c:\\\\Home" OR @"c:\\Home"
        //
        //

        static internal string PAPIQueryToRegexString(string papiString)
        {
            StringBuilder sb = new StringBuilder(papiString.Length);

            sb.Append(@"\G");

            bool escapeMode = false;

            foreach (char c in papiString)
            {
                if (escapeMode == false)
                {
                    switch (c)
                    {
                    case '(':
                        sb.Append(@"\(");              //   (  --> \(
                        break;

                    case ')':
                        sb.Append(@"\)");              //   )  --> \)
                        break;

                    case '\\':
                        escapeMode = true;
                        break;

                    case '*':
                        sb.Append(@".*");              //   * --> .*
                        break;

                    default:
                        sb.Append(c.ToString());       //   x  --> x
                        break;
                    }
                }
                else
                {
                    escapeMode = false;

                    switch (c)
                    {
                    case '(':
                        sb.Append(@"\(");              //      \( --> \(
                        break;

                    case ')':
                        sb.Append(@"\)");              //      \) --> \)
                        break;

                    case '*':
                        sb.Append(@"\*");              //      \* --> \*
                        break;

                    case '\\':
                        sb.Append(@"\\\\");              //      \\ --> \\
                        break;

                    default:
                        sb.Append(@"\\");
                        sb.Append(c.ToString());        //      \x --> \x
                        break;
                    }
                }
            }

            // There was a '\\' but no character after it because we were at the
            // end of the string.
            // Append '\\\\' to match the '\\'.
            if (escapeMode)
            {
                sb.Append(@"\\");
            }

            GlobalDebug.WriteLineIf(
                GlobalDebug.Info,
                "SAMUtils",
                "PAPIQueryToRegexString: mapped '{0}' to '{1}'",
                papiString,
                sb.ToString());

            sb.Append(@"\z");

            return(sb.ToString());
        }
Exemple #22
0
        internal static unsafe int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage)
        {
            int nameLength       = 0;
            int domainNameLength = 0;

            accountUsage = 0;
            name         = null;
            domainName   = null;

            IntPtr hUser = IntPtr.Zero;

            try
            {
                Utils.BeginImpersonation(credentials, out hUser);

                // hUser could be null if no credentials were specified
                Debug.Assert(hUser != IntPtr.Zero ||
                             (credentials == null || (credentials.UserName == null && credentials.Password == null)));

                int f = Interop.Advapi32.LookupAccountSid(serverName, sid, null, ref nameLength, null, ref domainNameLength, out accountUsage);

                int lastErr = Marshal.GetLastWin32Error();
                if (lastErr != 122) // ERROR_INSUFFICIENT_BUFFER
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (1st try) failed, gle=" + lastErr);
                    return(lastErr);
                }

                Debug.Assert(f == 0);   // should never succeed, with a 0 buffer size

                Debug.Assert(nameLength > 0);
                Debug.Assert(domainNameLength > 0);

                fixed(char *sbName = new char[nameLength])
                fixed(char *sbDomainName = new char[domainNameLength])
                {
                    f = Interop.Advapi32.LookupAccountSid(serverName, sid, sbName, ref nameLength, sbDomainName, ref domainNameLength, out accountUsage);

                    if (f == 0)
                    {
                        lastErr = Marshal.GetLastWin32Error();
                        Debug.Assert(lastErr != 0);

                        GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (2nd try) failed, gle=" + lastErr);
                        return(lastErr);
                    }

                    name       = new string(sbName);
                    domainName = new string(sbDomainName);
                }

                return(0);
            }
            finally
            {
                if (hUser != IntPtr.Zero)
                {
                    Utils.EndImpersonation(hUser);
                }
            }
        }
Exemple #23
0
        void ICollection.CopyTo(Array array, int index)
        {
            CheckDisposed();

            // Parameter validation
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            if (array == null)
            {
                throw new ArgumentNullException("array");
            }

            if (array.Rank != 1)
            {
                throw new ArgumentException(SR.PrincipalCollectionNotOneDimensional);
            }

            if (index >= array.GetLength(0))
            {
                throw new ArgumentException(SR.PrincipalCollectionIndexNotInArray);
            }

            ArrayList tempArray = new ArrayList();

            lock (_resultSet)
            {
                ResultSetBookmark bookmark = null;

                try
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "CopyTo: bookmarking");

                    bookmark = _resultSet.BookmarkAndReset();

                    PrincipalCollectionEnumerator containmentEnumerator =
                        new PrincipalCollectionEnumerator(
                            _resultSet,
                            this,
                            _removedValuesCompleted,
                            _removedValuesPending,
                            _insertedValuesCompleted,
                            _insertedValuesPending);

                    int arraySize     = array.GetLength(0) - index;
                    int tempArraySize = 0;

                    while (containmentEnumerator.MoveNext())
                    {
                        tempArray.Add(containmentEnumerator.Current);
                        checked { tempArraySize++; }

                        // Make sure the array has enough space, allowing for the "index" offset.
                        // We check inline, rather than doing a PrincipalCollection.Count upfront,
                        // because counting is just as expensive as enumerating over all the results, so we
                        // only want to do it once.
                        if (arraySize < tempArraySize)
                        {
                            GlobalDebug.WriteLineIf(GlobalDebug.Warn,
                                                    "PrincipalCollection",
                                                    "CopyTo: array too small (has {0}, need >= {1}",
                                                    arraySize,
                                                    tempArraySize);

                            throw new ArgumentException(SR.PrincipalCollectionArrayTooSmall);
                        }
                    }
                }
                finally
                {
                    if (bookmark != null)
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "CopyTo: restoring from bookmark");
                        _resultSet.RestoreBookmark(bookmark);
                    }
                }
            }

            foreach (object o in tempArray)
            {
                array.SetValue(o, index);
                checked { index++; }
            }
        }
        //
        // Public methods
        //

        public bool MoveNext()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering MoveNext");
            return(_inner.MoveNext());
        }
Exemple #25
0
        internal static IntPtr GetCurrentUserSid()
        {
            IntPtr pTokenHandle = IntPtr.Zero;
            IntPtr pBuffer      = IntPtr.Zero;

            try
            {
                //
                // Get the current user's SID
                //
                int error = 0;

                // Get the current thread's token
                if (!UnsafeNativeMethods.OpenThreadToken(
                        UnsafeNativeMethods.GetCurrentThread(),
                        0x8,         // TOKEN_QUERY
                        true,
                        ref pTokenHandle
                        ))
                {
                    if ((error = Marshal.GetLastWin32Error()) == 1008) // ERROR_NO_TOKEN
                    {
                        Debug.Assert(pTokenHandle == IntPtr.Zero);

                        // Current thread doesn't have a token, try the process
                        if (!UnsafeNativeMethods.OpenProcessToken(
                                UnsafeNativeMethods.GetCurrentProcess(),
                                0x8,         // TOKEN_QUERY
                                ref pTokenHandle
                                ))
                        {
                            int lastError = Marshal.GetLastWin32Error();
                            GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: OpenProcessToken failed, gle=" + lastError);

                            throw new PrincipalOperationException(
                                      String.Format(CultureInfo.CurrentCulture,
                                                    StringResources.UnableToOpenToken,
                                                    lastError));
                        }
                    }
                    else
                    {
                        GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: OpenThreadToken failed, gle=" + error);

                        throw new PrincipalOperationException(
                                  String.Format(CultureInfo.CurrentCulture,
                                                StringResources.UnableToOpenToken,
                                                error));
                    }
                }

                Debug.Assert(pTokenHandle != IntPtr.Zero);

                int neededBufferSize = 0;

                // Retrieve the user info from the current thread's token
                // First, determine how big a buffer we need.
                bool success = UnsafeNativeMethods.GetTokenInformation(
                    pTokenHandle,
                    1,                       // TokenUser
                    IntPtr.Zero,
                    0,
                    ref neededBufferSize);

                int getTokenInfoError = 0;
                if ((getTokenInfoError = Marshal.GetLastWin32Error()) != 122) // ERROR_INSUFFICIENT_BUFFER
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: GetTokenInformation (1st try) failed, gle=" + getTokenInfoError);

                    throw new PrincipalOperationException(
                              String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, getTokenInfoError));
                }

                // Allocate the necessary buffer.
                Debug.Assert(neededBufferSize > 0);
                pBuffer = Marshal.AllocHGlobal(neededBufferSize);

                // Load the user info into the buffer
                success = UnsafeNativeMethods.GetTokenInformation(
                    pTokenHandle,
                    1,                       // TokenUser
                    pBuffer,
                    neededBufferSize,
                    ref neededBufferSize);

                if (!success)
                {
                    int lastError = Marshal.GetLastWin32Error();
                    GlobalDebug.WriteLineIf(GlobalDebug.Error,
                                            "Utils",
                                            "GetCurrentUserSid: GetTokenInformation (2nd try) failed, neededBufferSize=" + neededBufferSize + ", gle=" + lastError);

                    throw new PrincipalOperationException(
                              String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, lastError));
                }

                // Retrieve the user's SID from the user info
                UnsafeNativeMethods.TOKEN_USER tokenUser = (UnsafeNativeMethods.TOKEN_USER)Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.TOKEN_USER));
                IntPtr pUserSid = tokenUser.sidAndAttributes.pSid;   // this is a reference into the NATIVE memory (into pBuffer)

                Debug.Assert(UnsafeNativeMethods.IsValidSid(pUserSid));

                // Now we make a copy of the SID to return
                int    userSidLength  = UnsafeNativeMethods.GetLengthSid(pUserSid);
                IntPtr pCopyOfUserSid = Marshal.AllocHGlobal(userSidLength);
                success = UnsafeNativeMethods.CopySid(userSidLength, pCopyOfUserSid, pUserSid);
                if (!success)
                {
                    int lastError = Marshal.GetLastWin32Error();
                    GlobalDebug.WriteLineIf(GlobalDebug.Error,
                                            "Utils",
                                            "GetCurrentUserSid: CopySid failed, errorcode=" + lastError);

                    throw new PrincipalOperationException(
                              String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, lastError));
                }

                return(pCopyOfUserSid);
            }
            finally
            {
                if (pTokenHandle != IntPtr.Zero)
                {
                    UnsafeNativeMethods.CloseHandle(pTokenHandle);
                }

                if (pBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pBuffer);
                }
            }
        }
 public void Reset()
 {
     GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Reset");
     _inner.Reset();
 }
Exemple #27
0
        internal static int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage)
        {
            IntPtr pSid = IntPtr.Zero;

            int nameLength       = 0;
            int domainNameLength = 0;

            StringBuilder sbName;
            StringBuilder sbDomainName;

            accountUsage = 0;
            name         = null;
            domainName   = null;

            IntPtr hUser = IntPtr.Zero;

            try
            {
                pSid = ConvertByteArrayToIntPtr(sid);

                Utils.BeginImpersonation(credentials, out hUser);

                // hUser could be null if no credentials were specified
                Debug.Assert(hUser != IntPtr.Zero ||
                             (credentials == null || (credentials.UserName == null && credentials.Password == null)));

                bool f = UnsafeNativeMethods.LookupAccountSid(serverName, pSid, null, ref nameLength, null, ref domainNameLength, ref accountUsage);

                int lastErr = Marshal.GetLastWin32Error();
                if (lastErr != 122) // ERROR_INSUFFICIENT_BUFFER
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (1st try) failed, gle=" + lastErr);
                    return(lastErr);
                }

                Debug.Assert(f == false);   // should never succeed, with a 0 buffer size

                Debug.Assert(nameLength > 0);
                Debug.Assert(domainNameLength > 0);

                sbName       = new StringBuilder(nameLength);
                sbDomainName = new StringBuilder(domainNameLength);

                f = UnsafeNativeMethods.LookupAccountSid(serverName, pSid, sbName, ref nameLength, sbDomainName, ref domainNameLength, ref accountUsage);

                if (f == false)
                {
                    lastErr = Marshal.GetLastWin32Error();
                    Debug.Assert(lastErr != 0);

                    GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (2nd try) failed, gle=" + lastErr);
                    return(lastErr);
                }

                name       = sbName.ToString();
                domainName = sbDomainName.ToString();

                return(0);
            }
            finally
            {
                if (pSid != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pSid);
                }

                if (hUser != IntPtr.Zero)
                {
                    Utils.EndImpersonation(hUser);
                }
            }
        }
 public void Dispose()
 {
     GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Dispose");
     _inner.Dispose();
 }
Exemple #29
0
        internal static bool BeginImpersonation(NetCred credential, out IntPtr hUserToken)
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "Entering BeginImpersonation");

            hUserToken = IntPtr.Zero;
            IntPtr hToken = IntPtr.Zero;

            // default credential is specified, no need to do impersonation
            if (credential == null)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: nothing to impersonate");
                return(false);
            }

            // Retrive the parsed username which has had the domain removed because LogonUser
            // expects creds this way.
            string userName   = credential.ParsedUserName;
            string password   = credential.Password;
            string domainName = credential.Domain;

            // no need to do impersonation as username and password are both null
            if (userName == null && password == null)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: nothing to impersonate (2)");
                return(false);
            }

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: trying to impersonate " + userName);

            int result = UnsafeNativeMethods.LogonUser(
                userName,
                domainName,
                password,
                9,                             /* LOGON32_LOGON_NEW_CREDENTIALS */
                3,                             /* LOGON32_PROVIDER_WINNT50 */
                ref hToken);

            // check the result
            if (result == 0)
            {
                int lastError = Marshal.GetLastWin32Error();
                GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "BeginImpersonation: LogonUser failed, gle=" + lastError);

                throw new PrincipalOperationException(
                          String.Format(CultureInfo.CurrentCulture,
                                        StringResources.UnableToImpersonateCredentials,
                                        lastError));
            }

            result = UnsafeNativeMethods.ImpersonateLoggedOnUser(hToken);
            if (result == 0)
            {
                int lastError = Marshal.GetLastWin32Error();
                GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "BeginImpersonation: ImpersonateLoggedOnUser failed, gle=" + lastError);

                // Close the token the was created above....
                UnsafeNativeMethods.CloseHandle(hToken);

                throw new PrincipalOperationException(
                          String.Format(CultureInfo.CurrentCulture,
                                        StringResources.UnableToImpersonateCredentials,
                                        lastError));
            }

            hUserToken = hToken;
            return(true);
        }
 //
 // Internal constructors
 //
 internal ValueCollectionEnumerator(TrackedCollection <T> trackingList, List <TrackedCollection <T> .ValueEl> combinedValues)
 {
     GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Ctor");
     _inner = new TrackedCollectionEnumerator <T>("ValueCollectionEnumerator", trackingList, combinedValues);
 }