Need help with impersonation, please.

J

jeremiah johnson

I have a .net DLL that I've created (based on someone's post in this
group, sorry I've forgotten who) and I need a little help with making it
work.

I want to provide the same functionality as "runas /netonly" and I'm
using LOGON32_LOGON_NEW_CREDENTIALS as I've read here many times.

I'm trying to launch a MOM operator console that will connect to a
management server in a different domain. I've verified that this works
with runas /netonly.

I can't use the p.StartInfo.UserName, .Domain, and .Password properties
in my app (I'm using .net 2.0) because the domain that I wish to connect
to does not have a trust relationship with my own. (i get a
win32exception that says bad username or password when i *know* they're
correct and that i'm entering them properly in my code.)

Can anyone tell me what I'm doing wrong?

Here is the relevant code in my app:

//////////////

string user = username.Text;
string pass = password.Text;
string domain = "UNTOPR";

if (!ImpersonationUtil.Impersonate(user, pass, domain)) {
MessageBox.Show("Impersonation failed.");
return;
}
else {
Process p = new Process();
p.StartInfo.FileName = @"MOM.UI.OpsConsoleExe.exe";
p.Start();
p.WaitForExit();

ImpersonationUtil.UnImpersonate();
}

///////////////

and here is the ImpersonationUtil DLL code in its entirety. From the
app above I simply reference the DLL this creates.

///////////////////////////////
///////////////////////////////

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

public class ImpersonationUtil {

//private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
//private const int LOGON32_LOGON_NETWORK_CLEARTEXT = 4;
//private const int LOGON32_PROVIDER_DEFAULT = 0;
private static WindowsImpersonationContext impersonationContext;

public static bool Impersonate(
string user,
string password,
string domain) {

WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

// put ints here rather than consts to keep this line readable //
if (LogonUser(user, domain, password, 9, 0, ref token) != 0) {

if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) {
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();

if (null != impersonationContext) {
return true;
}

}
}

return false;
}

public static void UnImpersonate() {
impersonationContext.Undo();
}

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

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

}

////////////////////////////
////////////////////////////

Any help at all appreciated.

Many thanks.
 
W

Willy Denoyette [MVP]

This won't work, impersonation works at the thread level, not at the process
level. That means that your "new" process will run with the same access
token as it's parent process, not the impersonated token. More, when using
LOGON32_LOGON_NEW_CREDENTIALS you are not creating a new thread token, you
simply say which token (credentials) the current thread should use when
accessing the network.
If you need to mimic the "runas /netonly" behavior, you will need to call
CreateProcessWithLogonW using PInvoke specifying LOGON_NETCREDENTIALS_ONLY
for dwLogonFlags.

Willy.

|I have a .net DLL that I've created (based on someone's post in this
| group, sorry I've forgotten who) and I need a little help with making it
| work.
|
| I want to provide the same functionality as "runas /netonly" and I'm
| using LOGON32_LOGON_NEW_CREDENTIALS as I've read here many times.
|
| I'm trying to launch a MOM operator console that will connect to a
| management server in a different domain. I've verified that this works
| with runas /netonly.
|
| I can't use the p.StartInfo.UserName, .Domain, and .Password properties
| in my app (I'm using .net 2.0) because the domain that I wish to connect
| to does not have a trust relationship with my own. (i get a
| win32exception that says bad username or password when i *know* they're
| correct and that i'm entering them properly in my code.)
|
| Can anyone tell me what I'm doing wrong?
|
| Here is the relevant code in my app:
|
| //////////////
|
| string user = username.Text;
| string pass = password.Text;
| string domain = "UNTOPR";
|
| if (!ImpersonationUtil.Impersonate(user, pass, domain)) {
| MessageBox.Show("Impersonation failed.");
| return;
| }
| else {
| Process p = new Process();
| p.StartInfo.FileName = @"MOM.UI.OpsConsoleExe.exe";
| p.Start();
| p.WaitForExit();
|
| ImpersonationUtil.UnImpersonate();
| }
|
| ///////////////
|
| and here is the ImpersonationUtil DLL code in its entirety. From the
| app above I simply reference the DLL this creates.
|
| ///////////////////////////////
| ///////////////////////////////
|
| using System;
| using System.Security.Principal;
| using System.Runtime.InteropServices;
|
| public class ImpersonationUtil {
|
| //private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
| //private const int LOGON32_LOGON_NETWORK_CLEARTEXT = 4;
| //private const int LOGON32_PROVIDER_DEFAULT = 0;
| private static WindowsImpersonationContext impersonationContext;
|
| public static bool Impersonate(
| string user,
| string password,
| string domain) {
|
| WindowsIdentity tempWindowsIdentity;
| IntPtr token = IntPtr.Zero;
| IntPtr tokenDuplicate = IntPtr.Zero;
|
| // put ints here rather than consts to keep this line readable //
| if (LogonUser(user, domain, password, 9, 0, ref token) != 0) {
|
| if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) {
| tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
| impersonationContext = tempWindowsIdentity.Impersonate();
|
| if (null != impersonationContext) {
| return true;
| }
|
| }
| }
|
| return false;
| }
|
| public static void UnImpersonate() {
| impersonationContext.Undo();
| }
|
| [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
| public static extern int LogonUser(
| string lpszUserName,
| String lpszDomain,
| String lpszPassword,
| int dwLogonType,
| int dwLogonProvider,
| ref IntPtr phToken);
|
| [DllImport("advapi32.dll",
| CharSet = System.Runtime.InteropServices.CharSet.Auto,
| SetLastError = true)]
| public extern static int DuplicateToken(
| IntPtr hToken,
| int impersonationLevel,
| ref IntPtr hNewToken);
|
| }
|
| ////////////////////////////
| ////////////////////////////
|
| Any help at all appreciated.
|
| Many thanks.
 
J

jeremiah johnson

Thank you. Based on your response I was able to Google around a bit and
find what I needed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top