internal static extern int LsaLogonUser( [In] SafeLsaLogonProcessHandle LsaHandle, [In] ref UNICODE_INTPTR_STRING OriginName, [In] SecurityLogonType LogonType, [In] uint AuthenticationPackage, [In] IntPtr AuthenticationInformation, [In] uint AuthenticationInformationLength, [In] IntPtr LocalGroups, [In] ref TOKEN_SOURCE SourceContext, [Out] out SafeLsaReturnBufferHandle ProfileBuffer, [Out] out uint ProfileBufferLength, [Out] out LUID LogonId, [Out] out SafeCloseHandle Token, [Out] out QUOTA_LIMITS Quotas, [Out] out int SubStatus );
private static bool GetLsaLogonUserHandle(string username, SafeHGlobalHandle pLogonInfo, int logonInfoSize) { if (null == pLogonInfo) { throw new ArgumentNullException("pLogonInfo"); } int status; SafeHGlobalHandle pSourceName = null; SafeHGlobalHandle pPackageName = null; SafeLsaLogonProcessHandle logonHandle = null; SafeLsaReturnBufferHandle profileHandle = null; SafeCloseHandle tokenHandle = null; try { UNICODE_INTPTR_STRING sourceName = NativeMethods.ConvertByteStringToUnicodeIntPtrString(NativeMethods.LsaSourceName, out pSourceName); logonHandle = NativeMethods.RegisterProcess(sourceName); RuntimeHelpers.PrepareConstrainedRegions(); //get packageId UNICODE_INTPTR_STRING packageName = NativeMethods.ConvertByteStringToUnicodeIntPtrString(NativeMethods.LsaNegotiateName, out pPackageName); uint packageId = 0; status = NativeMethods.LsaLookupAuthenticationPackage(logonHandle, ref packageName, out packageId); if (status < 0) // non-negative numbers indicate success { Trace.TraceError(string.Format("LsaLookupAuthenticationPackage failed for user {0} with status {1}", username, status)); throw new Win32Exception(NativeMethods.LsaNtStatusToWinError(status)); } //get Source context TOKEN_SOURCE sourceContext = new TOKEN_SOURCE(); if (!NativeMethods.AllocateLocallyUniqueId(out sourceContext.SourceIdentifier)) { int dwErrorCode = Marshal.GetLastWin32Error(); Trace.TraceError(string.Format("AllocateLocallyUniqueId failed for user {0} with status {1}", username, dwErrorCode)); throw new Win32Exception(dwErrorCode); } sourceContext.Name = new char[8]; sourceContext.Name[0] = 'A'; sourceContext.Name[1] = 'D'; sourceContext.Name[2] = 'F'; sourceContext.Name[2] = 'S'; //other parameters QUOTA_LIMITS quotas = new QUOTA_LIMITS(); LUID logonId = new LUID(); uint profileBufferLength; int subStatus = 0; // Call LsaLogonUser status = NativeMethods.LsaLogonUser( logonHandle, ref sourceName, SecurityLogonType.Network, packageId, pLogonInfo.DangerousGetHandle(), (uint)logonInfoSize, IntPtr.Zero, ref sourceContext, out profileHandle, out profileBufferLength, out logonId, out tokenHandle, out quotas, out subStatus ); // LsaLogon has restriction (eg. password expired). SubStatus indicates the reason. if ((uint)status == NativeMethods.STATUS_ACCOUNT_RESTRICTION && subStatus < 0) { status = subStatus; Trace.TraceError(string.Format("Authentication failed for user {0} with account restriction error {1}", username, status)); return(false); } if (status < 0) // non-negative numbers indicate success { Trace.TraceError(string.Format("Authentication failed for user {0} with status {1}", username, status)); return(false); } if (subStatus < 0) // non-negative numbers indicate success { Trace.TraceError(string.Format("Authentication failed for user {0} with subStatus {1}", username, subStatus)); return(false); } return(true); } finally { pSourceName?.Close(); pPackageName?.Close(); tokenHandle?.Close(); profileHandle?.Close(); } }