Impersonation in a console app

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hello


Can anyone shed any light onto why I can Impersonate succesfully from an
Asp.Net form, but it fails when I try and do the same from a console
application?

Both applications call into the same com component which checks the Account
Name of the original caller. The aspnet app succesfully logs the account I
have set it to impersonate, but the console app appears to execute correctly
as it succesfully returns data but it logs the account I am logged on to the
pc as.

I am running version one of the framework on a windows 2000 machine.

Here is the code I use to do the impersonation

using System;
using System.Web;
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Data;

namespace Spicers.Systems.ProductLoadFileProcessor
{
/// <summary>
/// Summary description for ImpersonateUser.
/// </summary>
public class ImpersonateUser
{
public ImpersonateUser()
{
}

public const int LOGON32_LOGON_INTERACTIVE =2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

public bool ImpersonateValidUser(String userName, String domain, String
password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if(LogonUserA(userName,domain,password,LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,ref token) != 0)
{
if(DuplicateToken(token,2,ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if(impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}

if(token != IntPtr.Zero)
CloseHandle(token);

if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);

return false;
}

public void UndoImpersonation()
{
impersonationContext.Undo();

}



}
}

and I call it like so...

ImpersonateUser imp = new ImpersonateUser();

if(imp.ImpersonateValidUser("username","domainname",""password))
{
// Get the feedback file directory
Data.IProductLoad prodLoad = new Data.ProductLoad();
dsDirectories = prodLoad.GetDirectories();
imp.UndoImpersonation();
}
else
{
throw new System.Exception("Impersonation didn't work");
}

the function prodLoad.GetDirectories() checks the original caller like so: -

originalCaller = SecurityCallContext.CurrentCall.OriginalCaller.AccountName;

this successfully returns the Impersonated account from an asp.net page, but
not from my console app


Thanks for your help

David
 
Hi David,

I can not reproduce the problem.
Here is my reproduce code.
[Console]
using System;
using ImpersonateDll;
using System.EnterpriseServices;
using CallerServicedComponent;
namespace TestImpersonate
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
ImpersonateUser imp = new ImpersonateUser();
if(imp.ImpersonateValidUser("username","domain","Password"))
{
Account acc = new Account();
acc.Post(1,1.1);
}
}
}
}

[Serviced Component]
using System.EnterpriseServices;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
[assembly: ApplicationName("CallerServicedComponent")]

namespace CallerServicedComponent
{
[ClassInterface(ClassInterfaceType.AutoDual),ComVisible(true)]
public class Account : ServicedComponent
{
public bool Post(int accountNum, double amount)
{
string an = SecurityCallContext.CurrentCall.OriginalCaller.AccountName;
Debug.WriteLine(an);
return false;
}
}
}

You may try my suggestion and let me know the result.
Also what did you get when you call the component in Console?

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Peter

Sorry for the delay in my response, but I've been distracted by other issues

I tried your test and the same results occured, the user I was logged on as
was displayed, not the one I was Impersonating. I tried this on a Windows
2000 machine with version 1 of the framework and an xp machine with v 1.1 and
got the same results.

When I call the code from the console app it appears to execute fine, it
does not generate any exceptions it just doesn't run as the impersonated user.

Do the rules for impersonating accounts differ between a console application
and an asp.net application?

Thanks

David
 
Hi

Basically there is no different between impersonate between console and
asp.net.
The LogonUser API will run the current thread under another user's
credentials.
The only different is that there is an element in web.config which will set
the impersonate role.
INFO: Implementing Impersonation in an ASP.NET Application
http://support.microsoft.com/?id=306158

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Back
Top