/// <summary> /// Logon user using S4U /// </summary> /// <param name="user">The username.</param> /// <param name="realm">The user's realm.</param> /// <param name="type">The type of logon token.</param> /// <param name="auth_package">The name of the auth package to user.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The logged on token.</returns> public static NtResult <NtToken> LsaLogonS4U(string user, string realm, SecurityLogonType type, string auth_package, bool throw_on_error) { if (user is null) { throw new ArgumentNullException(nameof(user)); } if (realm is null) { throw new ArgumentNullException(nameof(realm)); } byte[] user_bytes = Encoding.Unicode.GetBytes(user); byte[] realm_bytes = Encoding.Unicode.GetBytes(realm); using (var buffer = new SafeStructureInOutBuffer <KERB_S4U_LOGON>(user_bytes.Length + realm_bytes.Length, true)) { KERB_S4U_LOGON logon_struct = new KERB_S4U_LOGON { MessageType = KERB_LOGON_SUBMIT_TYPE.KerbS4ULogon }; SafeHGlobalBuffer data_buffer = buffer.Data; logon_struct.ClientUpn.Buffer = data_buffer.DangerousGetHandle(); data_buffer.WriteArray(0, user_bytes, 0, user_bytes.Length); logon_struct.ClientUpn.Length = (ushort)user_bytes.Length; logon_struct.ClientUpn.MaximumLength = (ushort)user_bytes.Length; logon_struct.ClientRealm.Buffer = data_buffer.DangerousGetHandle() + user_bytes.Length; data_buffer.WriteArray((ulong)user_bytes.Length, realm_bytes, 0, realm_bytes.Length); logon_struct.ClientRealm.Length = (ushort)realm_bytes.Length; logon_struct.ClientRealm.MaximumLength = (ushort)realm_bytes.Length; buffer.Result = logon_struct; return(LsaLogonUser(type, auth_package, "S4U", buffer, null, throw_on_error)); } }
/// <summary> /// Logon user using S4U /// </summary> /// <param name="user">The username.</param> /// <param name="realm">The user's realm.</param> /// <param name="type">The type of logon token.</param> /// <returns>The logged on token.</returns> public static NtToken LogonS4U(string user, string realm, SecurityLogonType type) { LsaString pkgName = new LsaString("Negotiate"); Win32NativeMethods.LsaConnectUntrusted(out SafeLsaHandle hlsa).ToNtException(); using (hlsa) { uint authnPkg; Win32NativeMethods.LsaLookupAuthenticationPackage(hlsa, pkgName, out authnPkg).ToNtException(); byte[] user_bytes = Encoding.Unicode.GetBytes(user); byte[] realm_bytes = Encoding.Unicode.GetBytes(realm); using (var buffer = new SafeStructureInOutBuffer <KERB_S4U_LOGON>(user_bytes.Length + realm_bytes.Length, true)) { KERB_S4U_LOGON logon_struct = new KERB_S4U_LOGON { MessageType = KERB_LOGON_SUBMIT_TYPE.KerbS4ULogon }; SafeHGlobalBuffer data_buffer = buffer.Data; logon_struct.ClientUpn.Buffer = data_buffer.DangerousGetHandle(); data_buffer.WriteArray(0, user_bytes, 0, user_bytes.Length); logon_struct.ClientUpn.Length = (ushort)user_bytes.Length; logon_struct.ClientUpn.MaximumLength = (ushort)user_bytes.Length; logon_struct.ClientRealm.Buffer = data_buffer.DangerousGetHandle() + user_bytes.Length; data_buffer.WriteArray((ulong)user_bytes.Length, realm_bytes, 0, realm_bytes.Length); logon_struct.ClientRealm.Length = (ushort)realm_bytes.Length; logon_struct.ClientRealm.MaximumLength = (ushort)realm_bytes.Length; Marshal.StructureToPtr(logon_struct, buffer.DangerousGetHandle(), false); TOKEN_SOURCE tokenSource = new TOKEN_SOURCE("NtLmSsp"); Win32NativeMethods.AllocateLocallyUniqueId(out tokenSource.SourceIdentifier); LsaString originName = new LsaString("S4U"); QUOTA_LIMITS quota_limits = new QUOTA_LIMITS(); Win32NativeMethods.LsaLogonUser(hlsa, originName, type, authnPkg, buffer, buffer.Length, IntPtr.Zero, tokenSource, out IntPtr profile, out int cbProfile, out Luid logon_id, out SafeKernelObjectHandle token_handle, quota_limits, out NtStatus subStatus).ToNtException(); Win32NativeMethods.LsaFreeReturnBuffer(profile); return(NtToken.FromHandle(token_handle)); } } }