Example #1
0
        /// <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));
                }
            }
        }