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(); } }
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(); } }
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(); } }
public static extern uint LsaGetAppliedCAPIDs( [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string systemName, out SafeLsaMemoryHandle CAPIDs, out uint CAPIDCount);
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); }