public static extern UInt32 LsaLogonUser( SafeLsaHandle LsaHandle, NativeHelpers.LSA_STRING OriginName, LogonType LogonType, UInt32 AuthenticationPackage, IntPtr AuthenticationInformation, UInt32 AuthenticationInformationLength, IntPtr LocalGroups, NativeHelpers.TOKEN_SOURCE SourceContext, out SafeLsaMemoryBuffer ProfileBuffer, out UInt32 ProfileBufferLength, out Luid LogonId, out SafeNativeHandle Token, out IntPtr Quotas, out UInt32 SubStatus);
private static SafeNativeHandle GetS4UTokenForUser(SecurityIdentifier sid, LogonType logonType) { NTAccount becomeAccount = (NTAccount)sid.Translate(typeof(NTAccount)); string[] userSplit = becomeAccount.Value.Split(new char[1] { '\\' }, 2); string domainName = userSplit[0]; string username = userSplit[1]; bool domainUser = domainName.ToLowerInvariant() != Environment.MachineName.ToLowerInvariant(); NativeHelpers.LSA_STRING logonProcessName = "ansible"; SafeLsaHandle lsaHandle; IntPtr securityMode; UInt32 res = NativeMethods.LsaRegisterLogonProcess(logonProcessName, out lsaHandle, out securityMode); if (res != 0) { throw new Process.Win32Exception((int)NativeMethods.LsaNtStatusToWinError(res), "LsaRegisterLogonProcess() failed"); } using (lsaHandle) { NativeHelpers.LSA_STRING packageName = domainUser ? "Kerberos" : "MICROSOFT_AUTHENTICATION_PACKAGE_V1_0"; UInt32 authPackage; res = NativeMethods.LsaLookupAuthenticationPackage(lsaHandle, packageName, out authPackage); if (res != 0) { throw new Process.Win32Exception((int)NativeMethods.LsaNtStatusToWinError(res), String.Format("LsaLookupAuthenticationPackage({0}) failed", (string)packageName)); } int usernameLength = username.Length * sizeof(char); int domainLength = domainName.Length * sizeof(char); int authInfoLength = (Marshal.SizeOf(typeof(NativeHelpers.KERB_S4U_LOGON)) + usernameLength + domainLength); IntPtr authInfo = Marshal.AllocHGlobal((int)authInfoLength); try { IntPtr usernamePtr = IntPtr.Add(authInfo, Marshal.SizeOf(typeof(NativeHelpers.KERB_S4U_LOGON))); IntPtr domainPtr = IntPtr.Add(usernamePtr, usernameLength); // KERB_S4U_LOGON has the same structure as MSV1_0_S4U_LOGON (local accounts) NativeHelpers.KERB_S4U_LOGON s4uLogon = new NativeHelpers.KERB_S4U_LOGON { MessageType = 12, // KerbS4ULogon Flags = 0, ClientUpn = new NativeHelpers.LSA_UNICODE_STRING { Length = (UInt16)usernameLength, MaximumLength = (UInt16)usernameLength, Buffer = usernamePtr, }, ClientRealm = new NativeHelpers.LSA_UNICODE_STRING { Length = (UInt16)domainLength, MaximumLength = (UInt16)domainLength, Buffer = domainPtr, }, }; Marshal.StructureToPtr(s4uLogon, authInfo, false); Marshal.Copy(username.ToCharArray(), 0, usernamePtr, username.Length); Marshal.Copy(domainName.ToCharArray(), 0, domainPtr, domainName.Length); Luid sourceLuid; if (!NativeMethods.AllocateLocallyUniqueId(out sourceLuid)) { throw new Process.Win32Exception("AllocateLocallyUniqueId() failed"); } NativeHelpers.TOKEN_SOURCE tokenSource = new NativeHelpers.TOKEN_SOURCE { SourceName = "ansible\0".ToCharArray(), SourceIdentifier = sourceLuid, }; // Only Batch or Network will work with S4U, prefer Batch but use Network if asked LogonType lsaLogonType = logonType == LogonType.Network ? LogonType.Network : LogonType.Batch; SafeLsaMemoryBuffer profileBuffer; UInt32 profileBufferLength; Luid logonId; SafeNativeHandle hToken; IntPtr quotas; UInt32 subStatus; res = NativeMethods.LsaLogonUser(lsaHandle, logonProcessName, lsaLogonType, authPackage, authInfo, (UInt32)authInfoLength, IntPtr.Zero, tokenSource, out profileBuffer, out profileBufferLength, out logonId, out hToken, out quotas, out subStatus); if (res != 0) { throw new Process.Win32Exception((int)NativeMethods.LsaNtStatusToWinError(res), String.Format("LsaLogonUser() failed with substatus {0}", subStatus)); } profileBuffer.Dispose(); return(hToken); } finally { Marshal.FreeHGlobal(authInfo); } } }
public static extern UInt32 LsaRegisterLogonProcess( NativeHelpers.LSA_STRING LogonProcessName, out SafeLsaHandle LsaHandle, out IntPtr SecurityMode);
public static extern UInt32 LsaLookupAuthenticationPackage( SafeLsaHandle LsaHandle, NativeHelpers.LSA_STRING PackageName, out UInt32 AuthenticationPackage);