Beispiel #1
0
        private static IdentityReferenceCollection TranslateToSids(IdentityReferenceCollection sourceAccounts, out bool someFailed)
        {
            if (sourceAccounts == null)
            {
                throw new ArgumentNullException(nameof(sourceAccounts));
            }

            if (sourceAccounts.Count == 0)
            {
                throw new ArgumentException(SR.Arg_EmptyCollection, nameof(sourceAccounts));
            }

            SafeLsaPolicyHandle LsaHandle            = SafeLsaPolicyHandle.InvalidHandle;
            SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
            SafeLsaMemoryHandle SidsPtr = SafeLsaMemoryHandle.InvalidHandle;

            try
            {
                //
                // Construct an array of unicode strings
                //

                Interop.UNICODE_STRING[] Names = new Interop.UNICODE_STRING[sourceAccounts.Count];

                int currentName = 0;
                foreach (IdentityReference id in sourceAccounts)
                {
                    NTAccount nta = id as NTAccount;

                    if (nta == null)
                    {
                        throw new ArgumentException(SR.Argument_ImproperType, nameof(sourceAccounts));
                    }

                    Names[currentName].Buffer = nta.ToString();

                    if (Names[currentName].Buffer.Length * 2 + 2 > ushort.MaxValue)
                    {
                        // this should never happen since we are already validating account name length in constructor and
                        // it is less than this limit
                        Debug.Assert(false, "NTAccount::TranslateToSids - source account name is too long.");
                        throw new InvalidOperationException();
                    }

                    Names[currentName].Length        = (ushort)(Names[currentName].Buffer.Length * 2);
                    Names[currentName].MaximumLength = (ushort)(Names[currentName].Length + 2);
                    currentName++;
                }

                //
                // Open LSA policy (for lookup requires it)
                //

                LsaHandle = Win32.LsaOpenPolicy(null, PolicyRights.POLICY_LOOKUP_NAMES);

                //
                // Now perform the actual lookup
                //

                someFailed = false;
                uint ReturnCode;

                ReturnCode = Interop.Advapi32.LsaLookupNames2(LsaHandle, 0, sourceAccounts.Count, Names, ref ReferencedDomainsPtr, ref SidsPtr);

                //
                // Make a decision regarding whether it makes sense to proceed
                // based on the return code and the value of the forceSuccess argument
                //

                if (ReturnCode == Interop.StatusOptions.STATUS_NO_MEMORY ||
                    ReturnCode == Interop.StatusOptions.STATUS_INSUFFICIENT_RESOURCES)
                {
                    throw new OutOfMemoryException();
                }
                else if (ReturnCode == Interop.StatusOptions.STATUS_ACCESS_DENIED)
                {
                    throw new UnauthorizedAccessException();
                }
                else if (ReturnCode == Interop.StatusOptions.STATUS_NONE_MAPPED ||
                         ReturnCode == Interop.StatusOptions.STATUS_SOME_NOT_MAPPED)
                {
                    someFailed = true;
                }
                else if (ReturnCode != 0)
                {
                    uint win32ErrorCode = Interop.Advapi32.LsaNtStatusToWinError(ReturnCode);

                    if (unchecked ((int)win32ErrorCode) != Interop.Errors.ERROR_TRUSTED_RELATIONSHIP_FAILURE)
                    {
                        Debug.Assert(false, string.Format(CultureInfo.InvariantCulture, "Interop.LsaLookupNames(2) returned unrecognized error {0}", win32ErrorCode));
                    }

                    throw new Win32Exception(unchecked ((int)win32ErrorCode));
                }

                //
                // Interpret the results and generate SID objects
                //

                IdentityReferenceCollection Result = new IdentityReferenceCollection(sourceAccounts.Count);

                if (ReturnCode == 0 || ReturnCode == Interop.StatusOptions.STATUS_SOME_NOT_MAPPED)
                {
                    SidsPtr.Initialize((uint)sourceAccounts.Count, (uint)Marshal.SizeOf <Interop.LSA_TRANSLATED_SID2>());
                    Win32.InitializeReferencedDomainsPointer(ReferencedDomainsPtr);
                    Interop.LSA_TRANSLATED_SID2[] translatedSids = new Interop.LSA_TRANSLATED_SID2[sourceAccounts.Count];
                    SidsPtr.ReadArray(0, translatedSids, 0, translatedSids.Length);

                    for (int i = 0; i < sourceAccounts.Count; i++)
                    {
                        Interop.LSA_TRANSLATED_SID2 Lts = translatedSids[i];

                        //
                        // Only some names are recognized as NTAccount objects
                        //

                        switch ((SidNameUse)Lts.Use)
                        {
                        case SidNameUse.User:
                        case SidNameUse.Group:
                        case SidNameUse.Alias:
                        case SidNameUse.Computer:
                        case SidNameUse.WellKnownGroup:
                            Result.Add(new SecurityIdentifier(Lts.Sid, true));
                            break;

                        default:
                            someFailed = true;
                            Result.Add(sourceAccounts[i]);
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < sourceAccounts.Count; i++)
                    {
                        Result.Add(sourceAccounts[i]);
                    }
                }

                return(Result);
            }
            finally
            {
                LsaHandle.Dispose();
                ReferencedDomainsPtr.Dispose();
                SidsPtr.Dispose();
            }
        }
Beispiel #2
0
        private static IdentityReferenceCollection TranslateToNTAccounts(IdentityReferenceCollection sourceSids, out bool someFailed)
        {
            if (sourceSids == null)
            {
                throw new ArgumentNullException(nameof(sourceSids));
            }

            if (sourceSids.Count == 0)
            {
                throw new ArgumentException(SR.Arg_EmptyCollection, nameof(sourceSids));
            }
            Contract.EndContractBlock();

            IntPtr[]            SidArrayPtr          = new IntPtr[sourceSids.Count];
            GCHandle[]          HandleArray          = new GCHandle[sourceSids.Count];
            SafeLsaPolicyHandle LsaHandle            = SafeLsaPolicyHandle.InvalidHandle;
            SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
            SafeLsaMemoryHandle NamesPtr             = SafeLsaMemoryHandle.InvalidHandle;

            try
            {
                //
                // Pin all elements in the array of SIDs
                //

                int currentSid = 0;
                foreach (IdentityReference id in sourceSids)
                {
                    SecurityIdentifier sid = id as SecurityIdentifier;

                    if (sid == null)
                    {
                        throw new ArgumentException(SR.Argument_ImproperType, nameof(sourceSids));
                    }

                    HandleArray[currentSid] = GCHandle.Alloc(sid.BinaryForm, GCHandleType.Pinned);
                    SidArrayPtr[currentSid] = HandleArray[currentSid].AddrOfPinnedObject();
                    currentSid++;
                }

                //
                // Open LSA policy (for lookup requires it)
                //

                LsaHandle = Win32.LsaOpenPolicy(null, PolicyRights.POLICY_LOOKUP_NAMES);

                //
                // Perform the actual lookup
                //

                someFailed = false;
                uint ReturnCode;
                ReturnCode = Interop.Advapi32.LsaLookupSids(LsaHandle, sourceSids.Count, SidArrayPtr, ref ReferencedDomainsPtr, ref NamesPtr);

                //
                // Make a decision regarding whether it makes sense to proceed
                // based on the return code and the value of the forceSuccess argument
                //

                if (ReturnCode == Interop.StatusOptions.STATUS_NO_MEMORY ||
                    ReturnCode == Interop.StatusOptions.STATUS_INSUFFICIENT_RESOURCES)
                {
                    throw new OutOfMemoryException();
                }
                else if (ReturnCode == Interop.StatusOptions.STATUS_ACCESS_DENIED)
                {
                    throw new UnauthorizedAccessException();
                }
                else if (ReturnCode == Interop.StatusOptions.STATUS_NONE_MAPPED ||
                         ReturnCode == Interop.StatusOptions.STATUS_SOME_NOT_MAPPED)
                {
                    someFailed = true;
                }
                else if (ReturnCode != 0)
                {
                    uint win32ErrorCode = Interop.Advapi32.LsaNtStatusToWinError(ReturnCode);

                    Debug.Assert(false, string.Format(CultureInfo.InvariantCulture, "Interop.LsaLookupSids returned {0}", win32ErrorCode));
                    throw new Win32Exception(unchecked ((int)win32ErrorCode));
                }


                NamesPtr.Initialize((uint)sourceSids.Count, (uint)Marshal.SizeOf <Interop.LSA_TRANSLATED_NAME>());
                Win32.InitializeReferencedDomainsPointer(ReferencedDomainsPtr);

                //
                // Interpret the results and generate NTAccount objects
                //

                IdentityReferenceCollection Result = new IdentityReferenceCollection(sourceSids.Count);

                if (ReturnCode == 0 || ReturnCode == Interop.StatusOptions.STATUS_SOME_NOT_MAPPED)
                {
                    //
                    // Interpret the results and generate NT Account objects
                    //

                    Interop.LSA_REFERENCED_DOMAIN_LIST rdl = ReferencedDomainsPtr.Read <Interop.LSA_REFERENCED_DOMAIN_LIST>(0);
                    string[] ReferencedDomains             = new string[rdl.Entries];

                    for (int i = 0; i < rdl.Entries; i++)
                    {
                        Interop.LSA_TRUST_INFORMATION ti = (Interop.LSA_TRUST_INFORMATION)Marshal.PtrToStructure <Interop.LSA_TRUST_INFORMATION>(new IntPtr((long)rdl.Domains + i * Marshal.SizeOf <Interop.LSA_TRUST_INFORMATION>()));
                        ReferencedDomains[i] = Marshal.PtrToStringUni(ti.Name.Buffer, ti.Name.Length / sizeof(char));
                    }

                    Interop.LSA_TRANSLATED_NAME[] translatedNames = new Interop.LSA_TRANSLATED_NAME[sourceSids.Count];
                    NamesPtr.ReadArray(0, translatedNames, 0, translatedNames.Length);

                    for (int i = 0; i < sourceSids.Count; i++)
                    {
                        Interop.LSA_TRANSLATED_NAME Ltn = translatedNames[i];

                        switch ((SidNameUse)Ltn.Use)
                        {
                        case SidNameUse.User:
                        case SidNameUse.Group:
                        case SidNameUse.Alias:
                        case SidNameUse.Computer:
                        case SidNameUse.WellKnownGroup:
                            string account = Marshal.PtrToStringUni(Ltn.Name.Buffer, Ltn.Name.Length / sizeof(char));;
                            string domain  = ReferencedDomains[Ltn.DomainIndex];
                            Result.Add(new NTAccount(domain, account));
                            break;

                        default:
                            someFailed = true;
                            Result.Add(sourceSids[i]);
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < sourceSids.Count; i++)
                    {
                        Result.Add(sourceSids[i]);
                    }
                }

                return(Result);
            }
            finally
            {
                for (int i = 0; i < sourceSids.Count; i++)
                {
                    if (HandleArray[i].IsAllocated)
                    {
                        HandleArray[i].Free();
                    }
                }

                LsaHandle.Dispose();
                ReferencedDomainsPtr.Dispose();
                NamesPtr.Dispose();
            }
        }
Beispiel #3
0
        private 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
            SafeLsaPolicyHandle policyHandle  = null;
            SafeLsaMemoryHandle domainsHandle = null;
            SafeLsaMemoryHandle namesHandle   = null;

            try
            {
                //
                // Get the policy handle
                //
                Interop.OBJECT_ATTRIBUTES oa = default;

                uint err = Interop.Advapi32.LsaOpenPolicy(
                    target,
                    ref oa,
                    (int)Interop.Advapi32.PolicyRights.POLICY_LOOKUP_NAMES,
                    out policyHandle);
                if (err != 0)
                {
                    policyHandle.Dispose();

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

                    throw new PrincipalOperationException(SR.Format(
                                                              SR.AuthZErrorEnumeratingGroups,
                                                              Interop.Advapi32.LsaNtStatusToWinError(err)));
                }

                Debug.Assert(!policyHandle.IsInvalid);

                //
                // Translate the SIDs
                //

                err = Interop.Advapi32.LsaLookupSids(
                    policyHandle,
                    sidCount,
                    pSids,
                    out domainsHandle,
                    out namesHandle);

                // Ignore error STATUS_SOME_NOT_MAPPED and STATUS_NONE_MAPPED
                if (err != Interop.StatusOptions.STATUS_SUCCESS &&
                    err != Interop.StatusOptions.STATUS_SOME_NOT_MAPPED &&
                    err != Interop.StatusOptions.STATUS_NONE_MAPPED)
                {
                    domainsHandle.Dispose();
                    namesHandle.Dispose();

                    GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: LsaLookupSids failed, err={0}", err);

                    throw new PrincipalOperationException(SR.Format(
                                                              SR.AuthZErrorEnumeratingGroups,
                                                              Interop.Advapi32.LsaNtStatusToWinError(err)));
                }

                //
                // Get the group names in managed form
                //
                namesHandle.Initialize((uint)sidCount, (uint)Marshal.SizeOf <Interop.LSA_TRANSLATED_NAME>());

                Interop.LSA_TRANSLATED_NAME[] names = new Interop.LSA_TRANSLATED_NAME[sidCount];
                namesHandle.ReadArray(0, names, 0, names.Length);

                //
                // Get the domain names in managed form
                //
                domainsHandle.InitializeReferencedDomainsList();
                Interop.LSA_REFERENCED_DOMAIN_LIST domainList = domainsHandle.Read <Interop.LSA_REFERENCED_DOMAIN_LIST>(0);

                // Extract LSA_REFERENCED_DOMAIN_LIST.Entries

                int domainCount = domainList.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.

                Interop.LSA_TRUST_INFORMATION[] domains = new Interop.LSA_TRUST_INFORMATION[domainCount];

                IntPtr pCurrentDomain = domainList.Domains;

                for (int i = 0; i < domainCount; i++)
                {
                    domains[i]     = (Interop.LSA_TRUST_INFORMATION)Marshal.PtrToStructure(pCurrentDomain, typeof(Interop.LSA_TRUST_INFORMATION));
                    pCurrentDomain = new IntPtr(pCurrentDomain.ToInt64() + Marshal.SizeOf(typeof(Interop.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++)
                {
                    Interop.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)
                    {
                        Interop.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
            {
                domainsHandle?.Dispose();
                namesHandle?.Dispose();
                policyHandle?.Dispose();
            }
        }
Beispiel #4
0
 public static extern uint LsaGetAppliedCAPIDs(
     [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string systemName,
     out SafeLsaMemoryHandle CAPIDs, out uint CAPIDCount);
Beispiel #5
0
        private static IdentityReferenceCollection TranslateToSids(IdentityReferenceCollection sourceAccounts, out bool someFailed)
        {
            if (sourceAccounts == null)
            {
                throw new ArgumentNullException("sourceAccounts");
            }
            if (sourceAccounts.Count == 0)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_EmptyCollection"), "sourceAccounts");
            }
            SafeLsaPolicyHandle         safeLsaPolicyHandle = SafeLsaPolicyHandle.InvalidHandle;
            SafeLsaMemoryHandle         invalidHandle       = SafeLsaMemoryHandle.InvalidHandle;
            SafeLsaMemoryHandle         invalidHandle2      = SafeLsaMemoryHandle.InvalidHandle;
            IdentityReferenceCollection result;

            try
            {
                Win32Native.UNICODE_STRING[] array = new Win32Native.UNICODE_STRING[sourceAccounts.Count];
                int num = 0;
                foreach (IdentityReference identityReference in sourceAccounts)
                {
                    NTAccount ntaccount = identityReference as NTAccount;
                    if (ntaccount == null)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Argument_ImproperType"), "sourceAccounts");
                    }
                    array[num].Buffer = ntaccount.ToString();
                    if (array[num].Buffer.Length * 2 + 2 > 65535)
                    {
                        throw new SystemException();
                    }
                    array[num].Length        = (ushort)(array[num].Buffer.Length * 2);
                    array[num].MaximumLength = array[num].Length + 2;
                    num++;
                }
                safeLsaPolicyHandle = Win32.LsaOpenPolicy(null, PolicyRights.POLICY_LOOKUP_NAMES);
                someFailed          = false;
                uint num2;
                if (Win32.LsaLookupNames2Supported)
                {
                    num2 = Win32Native.LsaLookupNames2(safeLsaPolicyHandle, 0, sourceAccounts.Count, array, ref invalidHandle, ref invalidHandle2);
                }
                else
                {
                    num2 = Win32Native.LsaLookupNames(safeLsaPolicyHandle, sourceAccounts.Count, array, ref invalidHandle, ref invalidHandle2);
                }
                if (num2 == 3221225495U || num2 == 3221225626U)
                {
                    throw new OutOfMemoryException();
                }
                if (num2 == 3221225506U)
                {
                    throw new UnauthorizedAccessException();
                }
                if (num2 == 3221225587U || num2 == 263U)
                {
                    someFailed = true;
                }
                else if (num2 != 0U)
                {
                    int errorCode = Win32Native.LsaNtStatusToWinError((int)num2);
                    throw new SystemException(Win32Native.GetMessage(errorCode));
                }
                IdentityReferenceCollection identityReferenceCollection = new IdentityReferenceCollection(sourceAccounts.Count);
                if (num2 == 0U || num2 == 263U)
                {
                    if (Win32.LsaLookupNames2Supported)
                    {
                        invalidHandle2.Initialize((uint)sourceAccounts.Count, (uint)Marshal.SizeOf(typeof(Win32Native.LSA_TRANSLATED_SID2)));
                        Win32.InitializeReferencedDomainsPointer(invalidHandle);
                        Win32Native.LSA_TRANSLATED_SID2[] array2 = new Win32Native.LSA_TRANSLATED_SID2[sourceAccounts.Count];
                        invalidHandle2.ReadArray <Win32Native.LSA_TRANSLATED_SID2>(0UL, array2, 0, array2.Length);
                        int i = 0;
                        while (i < sourceAccounts.Count)
                        {
                            Win32Native.LSA_TRANSLATED_SID2 lsa_TRANSLATED_SID = array2[i];
                            switch (lsa_TRANSLATED_SID.Use)
                            {
                            case 1:
                            case 2:
                            case 4:
                            case 5:
                            case 9:
                                identityReferenceCollection.Add(new SecurityIdentifier(lsa_TRANSLATED_SID.Sid, true));
                                break;

                            case 3:
                            case 6:
                            case 7:
                            case 8:
                                goto IL_282;

                            default:
                                goto IL_282;
                            }
IL_294:
                            i++;
                            continue;
IL_282:
                            someFailed = true;
                            identityReferenceCollection.Add(sourceAccounts[i]);
                            goto IL_294;
                        }
                    }
                    else
                    {
                        invalidHandle2.Initialize((uint)sourceAccounts.Count, (uint)Marshal.SizeOf(typeof(Win32Native.LSA_TRANSLATED_SID)));
                        Win32.InitializeReferencedDomainsPointer(invalidHandle);
                        Win32Native.LSA_REFERENCED_DOMAIN_LIST lsa_REFERENCED_DOMAIN_LIST = invalidHandle.Read <Win32Native.LSA_REFERENCED_DOMAIN_LIST>(0UL);
                        SecurityIdentifier[] array3 = new SecurityIdentifier[lsa_REFERENCED_DOMAIN_LIST.Entries];
                        for (int j = 0; j < lsa_REFERENCED_DOMAIN_LIST.Entries; j++)
                        {
                            Win32Native.LSA_TRUST_INFORMATION lsa_TRUST_INFORMATION = (Win32Native.LSA_TRUST_INFORMATION)Marshal.PtrToStructure(new IntPtr((long)lsa_REFERENCED_DOMAIN_LIST.Domains + (long)(j * Marshal.SizeOf(typeof(Win32Native.LSA_TRUST_INFORMATION)))), typeof(Win32Native.LSA_TRUST_INFORMATION));
                            array3[j] = new SecurityIdentifier(lsa_TRUST_INFORMATION.Sid, true);
                        }
                        Win32Native.LSA_TRANSLATED_SID[] array4 = new Win32Native.LSA_TRANSLATED_SID[sourceAccounts.Count];
                        invalidHandle2.ReadArray <Win32Native.LSA_TRANSLATED_SID>(0UL, array4, 0, array4.Length);
                        int k = 0;
                        while (k < sourceAccounts.Count)
                        {
                            Win32Native.LSA_TRANSLATED_SID lsa_TRANSLATED_SID2 = array4[k];
                            switch (lsa_TRANSLATED_SID2.Use)
                            {
                            case 1:
                            case 2:
                            case 4:
                            case 5:
                            case 9:
                                identityReferenceCollection.Add(new SecurityIdentifier(array3[lsa_TRANSLATED_SID2.DomainIndex], lsa_TRANSLATED_SID2.Rid));
                                break;

                            case 3:
                            case 6:
                            case 7:
                            case 8:
                                goto IL_3C8;

                            default:
                                goto IL_3C8;
                            }
IL_3DA:
                            k++;
                            continue;
IL_3C8:
                            someFailed = true;
                            identityReferenceCollection.Add(sourceAccounts[k]);
                            goto IL_3DA;
                        }
                    }
                }
                else
                {
                    for (int l = 0; l < sourceAccounts.Count; l++)
                    {
                        identityReferenceCollection.Add(sourceAccounts[l]);
                    }
                }
                result = identityReferenceCollection;
            }
            finally
            {
                safeLsaPolicyHandle.Dispose();
                invalidHandle.Dispose();
                invalidHandle2.Dispose();
            }
            return(result);
        }