473,799 Members | 3,832 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

User Impersonation on Win XP SP2

I am having some issues, when I try to launch another process using
Process.Start(P rocessStartInfo psi) on win xp sp2 box (Other versions
of xp have no issue).

Here is the detail.
Main app checks for updates on startup and if updates are available, it
launches separate exe to copy files.

Before launching new process(exe), I am impersonating admin user as
main app is being launched by non-admin user.

User identity is changed after impersonation, but during update,
"Access is denied" win32Exception is being thrown when main code tries
to launch copier exe.

Impersonation is implemented using following win32 api.
<code>
string domainName = string.Empty;
try
{
// Get current windows identity
string currentWindowsI dentity = WindowsIdentity .GetCurrent().N ame;

domainName = currentWindowsI dentity.Substri ng(0,
currentWindowsI dentity.IndexOf ('\\'));

const int LOGON32_PROVIDE R_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_I NTERACTIVE = 2;
const int SecurityImperso nation = 2;
tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(_impe rsonationUserna me,
domainName,_imp ersonationPassw ord, LOGON32_LOGON_I NTERACTIVE,
LOGON32_PROVIDE R_DEFAULT,ref tokenHandle);

if (false == returnValue)
{
int ret = Marshal.GetLast Win32Error();
int errorCode = 0x5; //ERROR_ACCESS_DE NIED
throw new System.Componen tModel.Win32Exc eption(errorCod e);
}

// Check the identity.
bool retVal = DuplicateToken( tokenHandle, SecurityImperso nation, ref
dupeTokenHandle );
if (false == retVal)
{
CloseHandle(tok enHandle);
return;
}

// The token that is passed to the following constructor must
// be a primary token in order to use it for impersonation.
WindowsIdentity newId = new WindowsIdentity (dupeTokenHandl e);
_impersonatedUs er = newId.Impersona te();
}
catch(Exception ex)
{

}
</code>
I have enabled following security policies for non-admin user:

1) Replace a process level token.

2) Debug programs

3) Adjust memory quotas for a process

NOTE: 'Launching another exe' works fine, if no user impersonation is
used.

Any ideas, what might be wrong ?

~ViPuL

Feb 9 '06
27 6714
Willy,
As I had mentioned in my first post, I am impersonating as ADMIN user
who has explicit debug privileges.

Main App is launched by regular user and "admin" user is being
impersonated before app tries to launch another exe.

anyway, I will try your suggestion.

Thanks for your help.
~ViPuL

Feb 14 '06 #11

"vipleo" <vn*****@gmail. com> wrote in message
news:11******** *************@o 13g2000cwo.goog legroups.com...
| Willy,
| As I had mentioned in my first post, I am impersonating as ADMIN user
| who has explicit debug privileges.
|
| Main App is launched by regular user and "admin" user is being
| impersonated before app tries to launch another exe.
|
| anyway, I will try your suggestion.
|
| Thanks for your help.
| ~ViPuL
|

Impersonating is not sufficient, you also need to "enable" the privilege,
it's not because a user has debug privileges that they are enabled.

Willy.
Feb 14 '06 #12
Willy,
How i can 'enable' this privilege?

Feb 14 '06 #13
vipleo-
I feel your pain...I spent weeks on this very issue - trying to get an
application updater going when the users didn't have permission to
install it. Our old impersonation broke when users started upgrading
to SP2, so I had to redo it.

It has been over a year, and there were so many issues they all kind of
blend together, but as I recall, impersonating then starting the
install process did not do the job because impersonation only changes
the permissions of the thread, not the process, and the process.start
gets started under the process' permissions. Again, it's a bit fuzzy
so I may be completely off there. I remember testing it by just
impersonating a different user than myself to start a process, then
that process popped a message box indicating what the current user was.

Also noteworthy was that if you had v 2.0, the Process.Start now takes
username, password, and domain parameters - obviously MS noticed this
was sorely missed.

Anyway, the silver bullet was to use WMI to install the new version -
that way the installation could happen on the current thread and the
admin user's privileges were used appropriately. It's been tried and
tested with 2000 users every two weeks, with no problems. I've seen
examples of using WMI to run the process as well, but I never got them
to work for me - I don't remember why.

If this is an option for you let me know and I'll post some code.

Good luck,
Jared

Feb 14 '06 #14
Jared,
Thanks a lot for your help & feeling my pain. <g>

In our implementation, we are not using multiple thread to do app
auto-update.

We are doing auto-update(xCopy deployment) in same thread, so I don't
understand how user context could be different.

Btwn, if you(or anybody else) can post some code sample for 'how to use
wmi to auto-update app' or 'how to launch another process using wmi',
that would be really great!

Thanks,
~ViPuL

Feb 14 '06 #15
We weren't using multi-threading either, but your code still runs on a
thread (even if it's the only one in the process), so it could still be
causing a problem. Read the "Pitfalls to watch for" section at
http://pluralsight.com/wiki/default....sImpersonation.
Note that I'm fairly certain that the suggestion to use
createprocessas user no longer works on SP2 - that's what caused me to
have to do a rewrite in the first place. This is documented on MSDN,
if you care to search for it.

OK...Here's the code that I'm 100% sure works. I've stripped out a lot
of the stuff that was implementation specific, but I think all the
pertinent parts are in here:

Impersonation class: This one does the actual installing and
uninstalling.
using System;
using System.Runtime. InteropServices ;
using System.Diagnost ics;
using System.Windows. Forms;
using System.Manageme nt;
using System.Collecti ons;
using ROOT.CIMV2.Win3 2;
namespace Extensions.Clie nt.ApplicationU pdater
{
public class Impersonate
{
[DllImport("adva pi32.dll", SetLastError=tr ue)]
private static extern bool LogonUser(Strin g lpszUsername, String
lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider , ref IntPtr phToken);

public static void UninstallProduc t(string productCode, string name,
string version)
{
//get error codes at
http://msdn.microsoft.com/library/de...rror_codes.asp
const int ERROR_SUCCESS_R EBOOT_REQUIRED = 3010;
const int ERROR_SUCCESS_R EBOOT_INITIATED = 1641;
const int ERROR_SUCCESS = 0;

uint retValue = 0;
try
{
ManagementScope scope = new ManagementScope ();
ROOT.CIMV2.Win3 2.Product prod = new Product(product Code, name,
version);
prod.Scope = scope;
retValue = prod.Uninstall( );
}
catch(Exception e)
{
MessageBox.Show ("Uninstall failed. Verify that " + name + " is
installed for all users on this machine. Details: " + e.Message);
}
if (retValue != ERROR_SUCCESS_R EBOOT_REQUIRED && retValue !=
ERROR_SUCCESS_R EBOOT_INITIATED && retValue != ERROR_SUCCESS)
{
MessageBox.Show ("Uninstall failed. Please contact helpdesk to get
updates. The returned error was: " + retValue);
}
}

public static void InstallProduct( string path, string options, bool
allUsers)
{
//get error codes at
http://msdn.microsoft.com/library/de...rror_codes.asp
uint retValue = 0;
const int ERROR_SUCCESS_R EBOOT_REQUIRED = 3010;
const int ERROR_SUCCESS_R EBOOT_INITIATED = 1641;
const int ERROR_SUCCESS = 0;

try
{
if (System.IO.File .Exists(path))
{
retValue = Product.Install (allUsers, options, path);
if (retValue != ERROR_SUCCESS_R EBOOT_REQUIRED && retValue !=
ERROR_SUCCESS_R EBOOT_INITIATED && retValue != ERROR_SUCCESS)
{
MessageBox.Show ("Install failed. Please contact helpdesk to get
updates. The returned error was: " + retValue);
}
}
else
MessageBox.Show ("Couldn't find file " + path + ". Please contact
helpdesk to get updates.");
}
catch(Exception e)
{
MessageBox.Show ("Install failed. Please contact helpdesk to get
updates. Details: " + e.Message);
}
}

public static IntPtr LogonUser(strin g UserName, string Password,
string Domain)
{
IntPtr token = IntPtr.Zero;
try
{
// Call LogonUser to obtain a handle to an access token.
LogonUser(UserN ame, Domain, Password, 2, 1, ref token);
return token;
}
catch
{
return IntPtr.Zero;
}
}
}
}

And here how the impersonation class was used to actually install the
product:
private void Install()
{

try
{
if (!System.IO.Fil e.Exists(this.m siPath))
{
MessageBox.Show ("Could not find the installation file " +
this.msiPath + ". Please contact the helpdesk to get updates.", "New
version of " + this.applicatio nTitle + " not found.");
return;
}
StatusWindow statusForm = null;

statusForm = new StatusWindow();
statusForm.Stat us = "Preparing to install " + this.applicatio nTitle +
"...";
statusForm.Show ();

statusForm.Stat us = "Logging On...";
statusForm.Perf ormStep();

IntPtr token = Impersonate.Log onUser(UserName , Password, Domain);

if (token != IntPtr.Zero)
{
WindowsIdentity newId = new WindowsIdentity (token);
WindowsImperson ationContext impersonatedUse r = newId.Impersona te();
//EVERTHING YOU DO FROM HERE ON OUT IS IMPERSONATED

//You probably can ignore all this productCode stuff...It's a long
story. But if your MSI is set to remove previous versions, you don't
need this.
if (this.productCo de != null && this.productCod e.Length > 0)
{
statusForm.Stat us = "Uninstalli ng old version of " +
this.applicatio nTitle + " ...";
statusForm.Perf ormStep();
Impersonate.Uni nstallProduct(t his.productCode ,
this.applicatio nTitle, this.oldVersion );
}

statusForm.Stat us = "Installing new version of " +
this.applicatio nTitle + "...";
statusForm.Perf ormStep();

//The second parameter are the options sent to msiexec.
Impersonate.Ins tallProduct(thi s.msiPath, "REBOOT=R", true);

impersonatedUse r.Undo();
//BACK TO RUNNING UNDER THE ORIGINAL USER
}
else
{
MessageBox.Show ("Impersonat e user failed. Please contact HelpDesk
to obtain the latest version.");
}

statusForm.Clos e();
}
catch(Exception e)
{
MessageBox.Show (this.applicati onTitle + " update failed: " + e);
WriteEvent(e);
}
}

I'll look around for the example of doing it with a process.

Good luck,
Jared

Feb 14 '06 #16
Here's the example that served as my bible for much of the time I spent
working on this issue:
http://www.dotnet247.com/247referenc...55/275561.aspx

Even though WMI may not be your solution, the concept may still work
for you. Instead of using the Process.Start, you need to duplicate the
action in-process (or, more accurately, in-thread.) So if you were
xcopying the files over, I believe that just using the
System.IO.File. Copy method will accomplish the same thing, while
allowing you to do it under the impersonated user's credentials.

Good luck,
Jared

Feb 14 '06 #17

"vipleo" <vn*****@gmail. com> wrote in message
news:11******** *************@f 14g2000cwb.goog legroups.com...
| Willy,
| How i can 'enable' this privilege?
|

You have to call AdjustTokenPriv ileges through PInvoke to do this from C#,
but you also need to get at the Process token because this fnction needs
this token, and you need to do this before impersonating, because once you
are impersonating you can't open the process to get at the token, see what I
mean? You can do all this using PInvoke, but it's not trivial, you better do
it in C++, or just don't do it at all and do as I said, get the module name
before you impersonate.

Willy.

Feb 14 '06 #18
As I said to vipleo, impersonation isn't the issue here, and is probably not
related to your problem. The OP's problem is that he tries to open the
'current process' while impersonating, this isn't allowed, unless the
impersonating user has Debug Privileges (he isn't the owner of the process)
and that these are explicitely enabled.
Willy.

"JaredHite1 " <ja***@sharingd s.org> wrote in message
news:11******** **************@ f14g2000cwb.goo glegroups.com.. .
| vipleo-
| I feel your pain...I spent weeks on this very issue - trying to get an
| application updater going when the users didn't have permission to
| install it. Our old impersonation broke when users started upgrading
| to SP2, so I had to redo it.
|
| It has been over a year, and there were so many issues they all kind of
| blend together, but as I recall, impersonating then starting the
| install process did not do the job because impersonation only changes
| the permissions of the thread, not the process, and the process.start
| gets started under the process' permissions. Again, it's a bit fuzzy
| so I may be completely off there. I remember testing it by just
| impersonating a different user than myself to start a process, then
| that process popped a message box indicating what the current user was.
|
| Also noteworthy was that if you had v 2.0, the Process.Start now takes
| username, password, and domain parameters - obviously MS noticed this
| was sorely missed.
|
| Anyway, the silver bullet was to use WMI to install the new version -
| that way the installation could happen on the current thread and the
| admin user's privileges were used appropriately. It's been tried and
| tested with 2000 users every two weeks, with no problems. I've seen
| examples of using WMI to run the process as well, but I never got them
| to work for me - I don't remember why.
|
| If this is an option for you let me know and I'll post some code.
|
| Good luck,
| Jared
|
Feb 14 '06 #19

"vipleo" <vn*****@gmail. com> wrote in message
news:11******** **************@ o13g2000cwo.goo glegroups.com.. .
| Jared,
| Thanks a lot for your help & feeling my pain. <g>
|
| In our implementation, we are not using multiple thread to do app
| auto-update.
|
| We are doing auto-update(xCopy deployment) in same thread, so I don't
| understand how user context could be different.
|
| Btwn, if you(or anybody else) can post some code sample for 'how to use
| wmi to auto-update app' or 'how to launch another process using wmi',
| that would be really great!
|
| Thanks,
| ~ViPuL
|

I don't think this will help you anyway, what you are after is the filename
of the current executable, right? Well, you should get this one before
impersonating and you are done.
Also, you shouldn't even use Process.GetCurr entProcess().Ma inModule.FileNa me
to get the exe name of the current process, you simply have to get the name
of the default application domain, this one is by default the same as the
..exe assembly name.

Willy.

Feb 14 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
3279
by: David Meier | last post by:
Hi, is it possible to get the environment variables for users other than the user that is currently executing the application? For example if I run a system service, how can the service find the SpecialFolder.InternetCache of a certain user? Thanks for input. Dave.
5
3206
by: Markus Stehle | last post by:
Hi all! I have asp.net web application that uses static impersonation. Is it possible to change the impersonated user during runtime? Within some parts of my application I would like to impersonate another user in order to access certain ressources and then switch back to the originally impersonated user. How can I do this? Thanks
8
9479
by: Razak | last post by:
Hi, I have a class which basically do Impersonation in my web application. From MS KB sample:- ++++++++++++++++++++code starts Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext Dim currentWindowsIdentity As System.Security.Principal.WindowsIdentity
8
17163
by: RTT | last post by:
i'm writing a windows form but codebased a iwant to run the code as a different user. like in a webapplication you can impersonate a user so the website does not run on the standard ASP.NET user. is it possible to do the same for a windows form and define a user codebased and run the code like that user is running the application.
6
2427
by: CJM | last post by:
I use the following technique to impersonate a user in ASP, in order to query active directory: http://support.microsoft.com/default.aspx?scid=kb;EN-US;248187 Although the article indicates that this technique is supported by IIS4 & IIS5, I actually run it successfully on Windows Server 2003 (IIS6). However, I've got a new development machine which is running XP Pro x64 Edition, and now this technique doesnt work ('Cannot create...
7
3879
by: John.NET | last post by:
Hi, First please forgive that this is a repost as the first time I didn't have my proper nospam email configured... I'm writing a web service where one method will launch another .NET program under a specified user's account. It launches fine as the NT AUTHORITY\NETWORK SERVICE user when I dont specify a username/password for the ProcessStartInfo but I am having trouble getting it to work when I specify any other username/password...
3
10926
by: Dmitry | last post by:
I am trying to figure out how to pass set of credentials to System.IO Challenge is: App is running under one set of credentials, but via GUI user have a chance to enter another set. I would like to be able to use supplied credentials with System.IO versus using default credentials that app is running under. So far I am forced to use WMI which is less convenient and slower then System.IO, but it's providing me with "Connection Options"
0
1519
by: Daniel Knöpfel | last post by:
Hello On our asp.net 2.0 website we impersonate every request to the identity of the user logged in. This works this way: 1. user logs in, providing username, password 2. user is authenticated against an active directory and the windows identity is retrieved (and stored in the session!!) 3. user is impersonated using the windows identity (thread is now running under the identity of the user)
4
5815
by: =?Utf-8?B?QXZhRGV2?= | last post by:
ASP.Net 2. We are migrating to Windows 2008 64 bit Server with IIS 7 from Windows 2003 32 Bit with IIS 6. A few library classes we wrote uses impersonation in code like explained in this article: http://support.microsoft.com/?id=306158#4 This doesn't work in Windows 2008 Server, we receive the following exception:
0
9687
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9543
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10488
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10029
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7567
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6808
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5588
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3761
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2941
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.