예제 #1
0
 public static unsafe extern int LsaCallAuthenticationPackage(
     LsaSafeHandle LsaHandle,
     int AuthenticationPackage,
     void *ProtocolSubmitBuffer,
     int SubmitBufferLength,
     out LsaBufferSafeHandle ProtocolReturnBuffer,
     out int ReturnBufferLength,
     out int ProtocolStatus
     );
예제 #2
0
 public static extern int LsaLogonUser(
     LsaSafeHandle LsaHandle,
     ref LSA_STRING OriginName,
     SECURITY_LOGON_TYPE LogonType,
     int AuthenticationPackage,
     void *AuthenticationInformation,
     int AuthenticationInformationLength,
     IntPtr LocalGroups,
     ref TOKEN_SOURCE SourceContext,
     out LsaBufferSafeHandle ProfileBuffer,
     ref int ProfileBufferLength,
     out LUID LogonId,
     out LsaTokenSafeHandle Token,
     out IntPtr Quotas,
     out int SubStatus
     );
예제 #3
0
        private unsafe void LsaCallAuthenticationPackage(void *pBuffer, int bufferSize)
        {
            LsaBufferSafeHandle returnBuffer = null;

            try
            {
                var result = NativeMethods.LsaCallAuthenticationPackage(
                    this.lsaHandle,
                    this.selectedAuthPackage,
                    pBuffer,
                    bufferSize,
                    out returnBuffer,
                    out int returnBufferLength,
                    out int protocolStatus
                    );

                LsaThrowIfError(result);
                LsaThrowIfError(protocolStatus);
            }
            finally
            {
                returnBuffer?.Dispose();
            }
        }
예제 #4
0
        /// <summary>
        /// Create a "NewCredentials" logon session for the current LSA Handle. This does not authenticate the user
        /// and only uses the credentials provided for outbound calls similar to the /netonly flag for runas.exe.
        ///
        /// Note: this will call <see cref="ImpersonateLoggedOnUser(LsaTokenSafeHandle)" /> and set the current
        /// thread's primary token to the generated NT Token.
        /// </summary>
        /// <param name="username">The username to be used. Note leaving this null will use the default value "user".
        /// Passing an empty string will cause LSA to treat this as an anonymous user.</param>
        /// <param name="password">The password to be used by LSA for any future outbound ticket requests not already cached.</param>
        /// <param name="realm">The default realm to be used by LSA for the any outbound ticket requests not already cached.</param>
        public unsafe void LogonUser(string username = null, string password = null, string realm = null)
        {
            if (username == null)
            {
                username = DefaultUserName;
            }

            if (password == null)
            {
                password = string.Empty;
            }

            if (realm == null)
            {
                realm = string.Empty;
            }

            var originName = new LSA_STRING
            {
                Buffer        = ProcessName,
                Length        = (ushort)(ProcessName.Length * 2),
                MaximumLength = (ushort)(ProcessName.Length * 2)
            };

            var bufferSize = Marshal.SizeOf(typeof(KERB_INTERACTIVE_LOGON)) +
                             (realm.Length * 2) +
                             (username.Length * 2) +
                             (password.Length * 2);

            if (this.impersonationContext != null)
            {
                this.impersonationContext.Dispose();
                this.impersonationContext = null;
            }

            LsaBufferSafeHandle profileBuffer = null;

            WithFixedBuffer(bufferSize, (p, _) =>
            {
                try
                {
                    var pLogon = (KERB_INTERACTIVE_LOGON *)p;

                    pLogon->MessageType = KERB_LOGON_SUBMIT_TYPE.KerbInteractiveLogon;

                    int offset = Marshal.SizeOf(typeof(KERB_INTERACTIVE_LOGON));

                    SetString(realm, pLogon, ref pLogon->LogonDomainName, ref offset);
                    SetString(username, pLogon, ref pLogon->UserName, ref offset);
                    SetString(password, pLogon, ref pLogon->Password, ref offset);

                    var tokenSource = new TOKEN_SOURCE()
                    {
                        SourceName = Encoding.UTF8.GetBytes("kerb.net")
                    };

                    int profileLength = 0;

                    int result = LsaLogonUser(
                        this.lsaHandle,
                        ref originName,
                        SECURITY_LOGON_TYPE.NewCredentials,
                        this.negotiateAuthPackage,
                        pLogon,
                        bufferSize,
                        IntPtr.Zero,
                        ref tokenSource,
                        out profileBuffer,
                        ref profileLength,
                        out this.luid,
                        out this.impersonationContext,
                        out IntPtr pQuotas,
                        out int subStatus
                        );

                    LsaThrowIfError(result);
                }
예제 #5
0
        /// <summary>
        /// Create a "NewCredentials" logon session for the current LSA Handle. This does not authenticate the user
        /// and only uses the credentials provided for outbound calls similar to the /netonly flag for runas.exe.
        ///
        /// Note: this will call <see cref="ImpersonateLoggedOnUser(LsaTokenSafeHandle)" /> and set the current
        /// thread's primary token to the generated NT Token.
        /// </summary>
        /// <param name="username">The username to be used. Note leaving this null will use the default value "user".
        /// Passing an empty string will cause LSA to treat this as an anonymous user.</param>
        /// <param name="password">The password to be used by LSA for any future outbound ticket requests not already cached.</param>
        /// <param name="realm">The default realm to be used by LSA for the any outbound ticket requests not already cached.</param>
        public unsafe void LogonUser(string username = null, string password = null, string realm = null)
        {
            if (username == null)
            {
                username = DefaultUserName;
            }

            if (password == null)
            {
                password = string.Empty;
            }

            if (realm == null)
            {
                realm = string.Empty;
            }

            var originName = new LSA_STRING
            {
                Buffer        = ProcessName,
                Length        = (ushort)(ProcessName.Length * 2),
                MaximumLength = (ushort)(ProcessName.Length * 2)
            };

            var bufferSize = Marshal.SizeOf(typeof(KERB_INTERACTIVE_LOGON)) +
                             (realm.Length * 2) +
                             (username.Length * 2) +
                             (password.Length * 2);

            if (this.impersonationContext != null)
            {
                this.impersonationContext.Dispose();
                this.impersonationContext = null;
            }

            LsaBufferSafeHandle profileBuffer = null;

            using (var pool = CryptoPool.Rent <byte>(bufferSize))
            {
                var buffer = pool.Memory.Slice(0, bufferSize);

                try
                {
                    fixed(byte *pBuffer = &MemoryMarshal.GetReference(buffer.Span))
                    {
                        KERB_INTERACTIVE_LOGON *pLogon = (KERB_INTERACTIVE_LOGON *)pBuffer;

                        pLogon->MessageType = KERB_LOGON_SUBMIT_TYPE.KerbInteractiveLogon;

                        int offset = Marshal.SizeOf(typeof(KERB_INTERACTIVE_LOGON));

                        SetString(realm, (IntPtr)pLogon, ref pLogon->LogonDomainName, ref offset);
                        SetString(username, (IntPtr)pLogon, ref pLogon->UserName, ref offset);
                        SetString(password, (IntPtr)pLogon, ref pLogon->Password, ref offset);

                        var tokenSource = new TOKEN_SOURCE()
                        {
                            SourceName = Encoding.UTF8.GetBytes("kerb.net")
                        };

                        int profileLength = 0;

                        int result = LsaLogonUser(
                            this.lsaHandle,
                            ref originName,
                            SECURITY_LOGON_TYPE.NewCredentials,
                            this.negotiateAuthPackage,
                            pLogon,
                            bufferSize,
                            IntPtr.Zero,
                            ref tokenSource,
                            out profileBuffer,
                            ref profileLength,
                            out this.luid,
                            out this.impersonationContext,
                            out IntPtr pQuotas,
                            out int subStatus
                            );

                        LsaThrowIfError(result);
                    }
                }
                finally
                {
                    profileBuffer?.Dispose();
                }
            }

            // this call to impersonate will set the current thread token to be the token out of LsaLogonUser
            // do we need to do anything special if this gets used within an async context?

            this.impersonationContext.Impersonate();
        }