// // NOTE: although there is a P/Invoke call involved in the implementation of this method, // there is no security risk involved, so no security demand is being made. // public bool IsEqualDomainSid(SecurityIdentifier sid) { return(Win32.IsEqualDomainSid(this, sid)); }
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)); } IntPtr[] SidArrayPtr = new IntPtr[sourceSids.Count]; GCHandle[] HandleArray = new GCHandle[sourceSids.Count]; SafeLsaPolicyHandle?LsaHandle = null; SafeLsaMemoryHandle?ReferencedDomainsPtr = null; SafeLsaMemoryHandle?NamesPtr = null; try { // // Pin all elements in the array of SIDs // int currentSid = 0; foreach (IdentityReference id in sourceSids) { if (!(id is SecurityIdentifier sid)) { 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, out ReferencedDomainsPtr, out 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.Fail($"Interop.LsaLookupSids returned {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(); } }
// // Constructs a well-known SID // The 'domainSid' parameter is optional and only used // by the well-known types that require it // NOTE: although there is a P/Invoke call involved in the implementation of this constructor, // there is no security risk involved, so no security demand is being made. // public SecurityIdentifier(WellKnownSidType sidType, SecurityIdentifier?domainSid) { // // sidType must not be equal to LogonIdsSid // if (sidType == WellKnownSidType.LogonIdsSid) { throw new ArgumentException(SR.IdentityReference_CannotCreateLogonIdsSid, nameof(sidType)); } // // sidType should not exceed the max defined value // if ((sidType < WellKnownSidType.NullSid) || (sidType > WellKnownSidType.WinCapabilityRemovableStorageSid)) { throw new ArgumentException(SR.Argument_InvalidValue, nameof(sidType)); } // // for sidType between 38 to 50, the domainSid parameter must be specified // int error; if ((sidType >= WellKnownSidType.AccountAdministratorSid) && (sidType <= WellKnownSidType.AccountRasAndIasServersSid)) { if (domainSid == null) { throw new ArgumentNullException(nameof(domainSid), SR.Format(SR.IdentityReference_DomainSidRequired, sidType)); } // // verify that the domain sid is a valid windows domain sid // to do that we call GetAccountDomainSid and the return value should be the same as the domainSid // error = Win32.GetWindowsAccountDomainSid(domainSid, out SecurityIdentifier? resultDomainSid); if (error == Interop.Errors.ERROR_INSUFFICIENT_BUFFER) { throw new OutOfMemoryException(); } else if (error == Interop.Errors.ERROR_NON_ACCOUNT_SID) { // this means that the domain sid is not valid throw new ArgumentException(SR.IdentityReference_NotAWindowsDomain, nameof(domainSid)); } else if (error != Interop.Errors.ERROR_SUCCESS) { Debug.Fail($"Win32.GetWindowsAccountDomainSid returned unrecognized error {error}"); throw new Win32Exception(error); } // // if domainSid is passed in as S-1-5-21-3-4-5-6, the above api will return S-1-5-21-3-4-5 as the domainSid // Since these do not match S-1-5-21-3-4-5-6 is not a valid domainSid (wrong number of subauthorities) // if (resultDomainSid != domainSid) { throw new ArgumentException(SR.IdentityReference_NotAWindowsDomain, nameof(domainSid)); } } error = Win32.CreateWellKnownSid(sidType, domainSid, out byte[]? resultSid); if (error == Interop.Errors.ERROR_INVALID_PARAMETER) { #pragma warning disable CA2208 // Instantiate argument exceptions correctly, combination of arguments used throw new ArgumentException(new Win32Exception(error).Message, "sidType/domainSid"); #pragma warning restore CS2208 } else if (error != Interop.Errors.ERROR_SUCCESS) { Debug.Fail($"Win32.CreateWellKnownSid returned unrecognized error {error}"); throw new Win32Exception(error); } CreateFromBinaryForm(resultSid !, 0); }
// // Determines whether this SID is a well-known SID of the specified type // // NOTE: although there is a P/Invoke call involved in the implementation of this method, // there is no security risk involved, so no security demand is being made. // public bool IsWellKnown(WellKnownSidType type) { return(Win32.IsWellKnownSid(this, type)); }
// // Constructs a SecurityIdentifier object from an IntPtr // public SecurityIdentifier(IntPtr binaryForm) : this(Win32.ConvertIntPtrSidToByteArraySid(binaryForm), 0) { }
public TlsContents() { int error = 0; int cachingError = 0; bool success = true; if (processHandle.IsInvalid) { lock (syncRoot) { if (processHandle.IsInvalid) { SafeTokenHandle localProcessHandle; if (false == Interop.Advapi32.OpenProcessToken( Interop.Kernel32.GetCurrentProcess(), TokenAccessLevels.Duplicate, out localProcessHandle)) { cachingError = Marshal.GetLastWin32Error(); success = false; } processHandle = localProcessHandle; } } } try { // Make the sequence non-interruptible } finally { try { // // Open the thread token; if there is no thread token, get one from // the process token by impersonating self. // SafeTokenHandle threadHandleBefore = this.threadHandle; error = FCall.OpenThreadToken( TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, WinSecurityContext.Process, out this.threadHandle); unchecked { error &= ~(int)0x80070000; } if (error != 0) { if (success == true) { this.threadHandle = threadHandleBefore; if (error != Interop.Errors.ERROR_NO_TOKEN) { success = false; } System.Diagnostics.Debug.Assert(this.isImpersonating == false, "Incorrect isImpersonating state"); if (success == true) { error = 0; if (false == Interop.Advapi32.DuplicateTokenEx( processHandle, TokenAccessLevels.Impersonate | TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, IntPtr.Zero, Interop.Advapi32.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, System.Security.Principal.TokenType.TokenImpersonation, ref this.threadHandle)) { error = Marshal.GetLastWin32Error(); success = false; } } if (success == true) { error = FCall.SetThreadToken(this.threadHandle); unchecked { error &= ~(int)0x80070000; } if (error != 0) { success = false; } } if (success == true) { this.isImpersonating = true; } } else { error = cachingError; } } else { success = true; } } finally { if (!success) { Dispose(); } } } if (error == Interop.Errors.ERROR_NOT_ENOUGH_MEMORY) { throw new OutOfMemoryException(); } else if (error == Interop.Errors.ERROR_ACCESS_DENIED || error == Interop.Errors.ERROR_CANT_OPEN_ANONYMOUS) { throw new UnauthorizedAccessException(); } else if (error != 0) { System.Diagnostics.Debug.Fail($"WindowsIdentity.GetCurrentThreadToken() failed with unrecognized error code {error}"); throw new InvalidOperationException(); } }
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); }
internal SecurityIdentifier(IntPtr binaryForm, bool noDemand) : this(Win32.ConvertIntPtrSidToByteArraySid(binaryForm), 0) { }
[System.Security.SecurityCritical] // auto-generated 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"); } Contract.EndContractBlock(); SafeLsaPolicyHandle LsaHandle = SafeLsaPolicyHandle.InvalidHandle; SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle; SafeLsaMemoryHandle SidsPtr = SafeLsaMemoryHandle.InvalidHandle; try { // // Construct an array of unicode strings // Win32Native.UNICODE_STRING[] Names = new Win32Native.UNICODE_STRING[sourceAccounts.Count]; int currentName = 0; foreach (IdentityReference id in sourceAccounts) { NTAccount nta = id as NTAccount; if (nta == null) { throw new ArgumentException(Environment.GetResourceString("Argument_ImproperType"), "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 Contract.Assert(false, "NTAccount::TranslateToSids - source account name is too long."); throw new SystemException(); } 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; if (Win32.LsaLookupNames2Supported) { ReturnCode = Win32Native.LsaLookupNames2(LsaHandle, 0, sourceAccounts.Count, Names, ref ReferencedDomainsPtr, ref SidsPtr); } else { ReturnCode = Win32Native.LsaLookupNames(LsaHandle, 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 == Win32Native.STATUS_NO_MEMORY || ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES) { throw new OutOfMemoryException(); } else if (ReturnCode == Win32Native.STATUS_ACCESS_DENIED) { throw new UnauthorizedAccessException(); } else if (ReturnCode == Win32Native.STATUS_NONE_MAPPED || ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED) { someFailed = true; } else if (ReturnCode != 0) { int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked ((int)ReturnCode)); if (win32ErrorCode != Win32Native.ERROR_TRUSTED_RELATIONSHIP_FAILURE) { Contract.Assert(false, string.Format(CultureInfo.InvariantCulture, "Win32Native.LsaLookupNames(2) returned unrecognized error {0}", win32ErrorCode)); } throw new SystemException(Win32Native.GetMessage(win32ErrorCode)); } // // Interpret the results and generate SID objects // IdentityReferenceCollection Result = new IdentityReferenceCollection(sourceAccounts.Count); if (ReturnCode == 0 || ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED) { if (Win32.LsaLookupNames2Supported) { SidsPtr.Initialize((uint)sourceAccounts.Count, (uint)Marshal.SizeOf(typeof(Win32Native.LSA_TRANSLATED_SID2))); Win32.InitializeReferencedDomainsPointer(ReferencedDomainsPtr); Win32Native.LSA_TRANSLATED_SID2[] translatedSids = new Win32Native.LSA_TRANSLATED_SID2[sourceAccounts.Count]; SidsPtr.ReadArray(0, translatedSids, 0, translatedSids.Length); for (int i = 0; i < sourceAccounts.Count; i++) { Win32Native.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 { SidsPtr.Initialize((uint)sourceAccounts.Count, (uint)Marshal.SizeOf(typeof(Win32Native.LSA_TRANSLATED_SID))); Win32.InitializeReferencedDomainsPointer(ReferencedDomainsPtr); Win32Native.LSA_REFERENCED_DOMAIN_LIST rdl = ReferencedDomainsPtr.Read <Win32Native.LSA_REFERENCED_DOMAIN_LIST>(0); SecurityIdentifier[] ReferencedDomains = new SecurityIdentifier[rdl.Entries]; for (int i = 0; i < rdl.Entries; i++) { Win32Native.LSA_TRUST_INFORMATION ti = (Win32Native.LSA_TRUST_INFORMATION)Marshal.PtrToStructure(new IntPtr(( long )rdl.Domains + i * Marshal.SizeOf(typeof(Win32Native.LSA_TRUST_INFORMATION))), typeof(Win32Native.LSA_TRUST_INFORMATION)); ReferencedDomains[i] = new SecurityIdentifier(ti.Sid, true); } Win32Native.LSA_TRANSLATED_SID[] translatedSids = new Win32Native.LSA_TRANSLATED_SID[sourceAccounts.Count]; SidsPtr.ReadArray(0, translatedSids, 0, translatedSids.Length); for (int i = 0; i < sourceAccounts.Count; i++) { Win32Native.LSA_TRANSLATED_SID Lts = translatedSids[i]; switch ((SidNameUse)Lts.Use) { case SidNameUse.User: case SidNameUse.Group: case SidNameUse.Alias: case SidNameUse.Computer: case SidNameUse.WellKnownGroup: Result.Add(new SecurityIdentifier(ReferencedDomains[Lts.DomainIndex], Lts.Rid)); 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(); } }