// // Wrapper around advapi32.LsaOpenPolicy // internal static SafeLsaPolicyHandle LsaOpenPolicy( string?systemName, Interop.Advapi32.PolicyRights rights) { Interop.OBJECT_ATTRIBUTES attributes = default; uint error = Interop.Advapi32.LsaOpenPolicy(systemName, ref attributes, (int)rights, out SafeLsaPolicyHandle policyHandle); if (error == 0) { return(policyHandle); } policyHandle.Dispose(); if (error == Interop.StatusOptions.STATUS_ACCESS_DENIED) { throw new UnauthorizedAccessException(); } else if (error == Interop.StatusOptions.STATUS_INSUFFICIENT_RESOURCES || error == Interop.StatusOptions.STATUS_NO_MEMORY) { throw new OutOfMemoryException(); } else { uint win32ErrorCode = Interop.Advapi32.LsaNtStatusToWinError(error); throw new Win32Exception(unchecked ((int)win32ErrorCode)); } }
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) { 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) { 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 { if (domainsHandle != null) { domainsHandle.Dispose(); } if (namesHandle != null) { namesHandle.Dispose(); } if (policyHandle != null) { policyHandle.Dispose(); } } }