impersonate a user

12144 ワード

// This sample demonstrates the use of the WindowsIdentity class to impersonate a user. 

// IMPORTANT NOTES: 

// This sample requests the user to enter a password on the console screen. 

// Because the console window does not support methods allowing the password to be masked, 

// it will be visible to anyone viewing the screen. 

// On Windows Vista and later this sample must be run as an administrator.  





using System;

using System.Runtime.InteropServices;

using System.Security.Principal;

using System.Security.Permissions;

using Microsoft.Win32.SafeHandles;

using System.Runtime.ConstrainedExecution;

using System.Security;





public class ImpersonationDemo

{

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]

    public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,

        int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);



    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]

    public extern static bool CloseHandle(IntPtr handle);



    // Test harness. 

    // If you incorporate this code into a DLL, be sure to demand FullTrust.

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]

    public static void Main(string[] args)

    {

        SafeTokenHandle safeTokenHandle;

        try

        {

            string userName, domainName;

            // Get the user token for the specified user, domain, and password using the 

            // unmanaged LogonUser method. 

            // The local machine name can be used for the domain name to impersonate a user on this machine.

            Console.Write("Enter the name of the domain on which to log on: ");

            domainName = Console.ReadLine();



            Console.Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName);

            userName = Console.ReadLine();



            Console.Write("Enter the password for {0}: ", userName);



            const int LOGON32_PROVIDER_DEFAULT = 0;

            //This parameter causes LogonUser to create a primary token. 

            const int LOGON32_LOGON_INTERACTIVE = 2;



            // Call LogonUser to obtain a handle to an access token. 

            bool returnValue = LogonUser(userName, domainName, Console.ReadLine(),

                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,

                out safeTokenHandle);



            Console.WriteLine("LogonUser called.");



            if (false == returnValue)

            {

                int ret = Marshal.GetLastWin32Error();

                Console.WriteLine("LogonUser failed with error code : {0}", ret);

                throw new System.ComponentModel.Win32Exception(ret);

            }



            using (safeTokenHandle)

            {

                Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));

                Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);



                // Check the identity.

                Console.WriteLine("Before impersonation: "

                    + WindowsIdentity.GetCurrent().Name);

                // Use the token handle returned by LogonUser. 

                using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))

                {

                    using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())

                    {



                        // Check the identity.

                        Console.WriteLine("After impersonation: "

                            + WindowsIdentity.GetCurrent().Name);

                    }

                }

                // Releasing the context object stops the impersonation 

                // Check the identity.

                Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);

            }

        }

        catch (Exception ex)

        {

            Console.WriteLine("Exception occurred. " + ex.Message);

        }

        finally

        {

            Console.ReadKey();

        }

    }

}



public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid

{

    private SafeTokenHandle()

        : base(true)

    {

    }



    [DllImport("kernel32.dll")]

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

    [SuppressUnmanagedCodeSecurity]

    [return: MarshalAs(UnmanagedType.Bool)]

    private static extern bool CloseHandle(IntPtr handle);



    protected override bool ReleaseHandle()

    {

        return CloseHandle(handle);

    }

}