views:

61

answers:

2

Hello,

Until recently, I've used the "<impersonate >" tag in web.config, followed by proper credentials.

Now I'm trying to add another asmx file, that will impersonate to a different account, and trying to do that from code.

Question is -

How to impersonate (on every request) from code in an asmx file (webservice) ? (I'm using C#)

I guess the code should be in the ctor of the asmx class, but I'm not sure what the could should be. I've googled thru many examples but haven't found a decent code that do what I wants.

Thank you in advance!

A: 

If you have impersonate set to ON in your web.config you can specify a different credential via:

new System.Net.NetworkCredential("username", "password", "domain");

I have also found a good article How to impersonate a user given her token It shows how to attach a diffrent WindowsIdentity to a given thread

Rihan Meij
Thank you.And how do I make the code context impersonate into that new credentials I created?
Omer
I checked your code, just to insure, and it wasn't working.
Omer
Could you change the credentials of the application pool to the user you want to impersonate as?
Rihan Meij
No, I need to switch back and forth between different users to impersonate to, so a static hard coded credentials in the app pool won't help here...
Omer
A: 

See sample code how you can do it:

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;

[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
public class ImpersonationDemo
{
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
        String lpszUsername, 
        String lpszDomain, 
        String lpszPassword, 
        int dwLogonType, 
        int dwLogonProvider,
        ref IntPtr 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)
    {
        IntPtr tokenHandle = new IntPtr(0);
        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;

            tokenHandle = IntPtr.Zero;

            // Call LogonUser to obtain a handle to an access token.
            bool returnValue = LogonUser(
                userName, 
                domainName, 
                Console.ReadLine(),
                3,
                LOGON32_PROVIDER_DEFAULT,
                ref tokenHandle);

            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);
            }

            Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
            Console.WriteLine("Value of Windows NT token: " + tokenHandle);

            // Check the identity.
            Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name);
            // Use the token handle returned by LogonUser.

            WindowsIdentity newId = new WindowsIdentity(tokenHandle);

            using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
            {
                // Check the identity. Here you shoul place code that will be executed on belaf of other login.
                Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
                GC.KeepAlive(impersonatedUser);
            }

            // Check the identity.
            Console.WriteLine("After Undo: " + WindowsIdentity.GetCurrent().Name);

            // Free the tokens.
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);

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

    }
}
stasetz
Thank you for this code sample. I've seen something similar at CodeProject. Unfortunately, I need to do this for a web-service impersonation, and this code refers to a console app...
Omer
I've checked this code in the web service context, and it wasn't working.
Omer