Using programmatic Impersonation from an ASP.NET Page
Several times I've heard the following question asked:
I have an ASP.NET application and I need access to network resources that my account running ASP.NET does not have. How can I change the permissions at runtime without setting up Impersonation or using a high privilige account for my ASP.NET user account?
In short, how can you raise permissions of an ASP.NET request at runtime to perform some task that requires rights that the standard account ASP.NET runs under cannot handle?
To accomplish this you can use various system API calls (LogonUser, ImpersonateLoggedOnUser and RevertToSelf) to change the currently active account ASP.NET runs under. This would be Environment.UserName as opposed to Page.User. Environment.UserName returns the threads currently logged on user. Page.User returns the name that ASP.NET verifies through Authentication and this user in most cases is independent of the Windows logon that is running the current thread. For anonymous requests Page.User is blank, while Environment.User will be NETWORK SERVICE (or ASPNET on IIS5).
The only time when Page.User reflects Environment.User is when Impersonation is enabled in which case the ASP.NET automatically changes the impersonation on the underlying ASP.NET thread to match of who's logged on. For anonymous users this will be the IUSR_ account or if logged on the user who logged on.
With the API calls mentioned above you can change the thread's security environment. The idea is, you can log on as a user, change the impersonation to that environment, do your thing then revert back. Let's look at how to do this first before going over some caveats. Given that you have rights to use PInvoke calls to make these API calls (NETWORK SERVICE generally does have these rights) the following code can be used to accomplish this:
}using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.Runtime.InteropServices; using System.Text; namespace Westwind.WebStore.Demos { /// <summary> /// Summary description for Test. /// </summary> public class Test : System.Web.UI.Page { const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_LOGON_NETWORK = 3; const int LOGON32_LOGON_BATCH = 4; const int LOGON32_LOGON_SERVICE = 5; const int LOGON32_LOGON_UNLOCK = 7; const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8; const int LOGON32_LOGON_NEW_CREDENTIALS = 9; const int LOGON32_PROVIDER_DEFAULT = 0; [DllImport("advapi32.dll", SetLastError=true)] public static extern int LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken ); [DllImport("advapi32.dll", SetLastError=true)] public static extern int ImpersonateLoggedOnUser( IntPtr hToken ); [DllImport("advapi32.dll", SetLastError=true)] static extern int RevertToSelf(); [DllImport("kernel32.dll", SetLastError=true)] static extern int CloseHandle(IntPtr hObject); private void Page_Load(object sender, System.EventArgs e) { Response.Write( Environment.UserName + "<hr>"); IntPtr lnToken; int TResult = LogonUser("ricks",".","supersecret",
LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT,
out lnToken); if ( TResult > 0 ) { ImpersonateLoggedOnUser(lnToken); StringBuilder sb = new StringBuilder(80,80); uint Size = 79; Response.Write( Environment.UserName + " - " +this.User.Identity.Name + "<hr>"); RevertToSelf(); Response.Write("<hr>" + Environment.UserName); CloseHandle(lnToken); } else { Response.Write("Not logged on: " + Environment.UserName); } return;}
To use this code change the username and password in the call to LogonUser to a valid local or domain account (see MSDN Docs for exact syntax to use for domain accounts and machine names).
When you run this code you should see:
NETWORK SERVICE
ricks
NETWORK SERVICE
which corresponds to the original account the page is running under, the Impersonation that I applied, and then after I reverted back to the original account.
Note that you should make sure to close the Token handle returned after you are done with your request, preferrably in a Finally section so you don't leak handles.
Actually you don't have to revert back - ASP.NET assigns security to the ASP.NET thread before your request starts, so Revert is not really required.
Caveats
Now is this a good idea to do this in your code? Not really, because it's obviously a potential security risk. There are two things that are a problem here.
First you need to run under an account that has rights to make PInvoke calls which is by no means guaranteed. Many multi-hosted ISPs will set up very low right accounts for their sites so that you may not be able to actually perform these tasks. OTOH, it's unlikely that in an ISP scenario you would actually need access to additional resources that require impersonation.
Second and maybe more importantly using LogonUser requires that you use a password and that password has to come from somewhere. This means somewhere in your system you have to store this password and retrieve that password which can be compromised and then potentially be used to further penetrate security. A fairly far fetched hack scenario that would require somebody pretty damn familiar with your architecture, but still a threat.
You can also impersonation system accounts like SYSTEM and NETWORK SERVICE which don't require passwords (pass "" for the password), but most likely these accounts are not what you need to get your job done - for example access another machine on the network.
Alternatives
Ultimately the solution to this problem is to set up your ASP.NET application with the right account with the exact rights it needs. While I think security is important it's always been my feeling that if someone can penetrate your network and compromise ASP.NET pages - they're in too far already to not be able to do the rest (like changing web.config and stepping down security), so I am usually not opposed to running ASP.NET in slightly elevated security modes to match my needs.
Another option for those one off requests is to use Impersonation and Windows Security in a separate directory. I do this in several of my applications where several admin requests require elevated rights. These pages sit off in a seperate directory with anonymous access off and Impersonation enabled in a separate web.config (or a Location section in the main web.config).
An example of this is my Configuration class manager which has the capability to write Config changes back into Web.Config. I don't want to give NETWORK SERVICE rights to write any files in my main application directory, so I have my Configuration page off in an Admin directory. Admin requires Windows Security and then uses Impersonation, which means it runs under my Admin account on the server once I've logged in with my username and password.
<location path="admin"> <system.web> <identity impersonate="true" /> <!-- WS: Allow only Authenticated users --> <authorization> <!-- allow users="*"/ --> <deny users="?" /> </authorization> </system.web> </location>
I can set this up in a couple of ways. Here I do it all through ASP.NET's impersonation and security settings which deny access to non-authenticated users to these Admin pages. I could also set this up with directory security on the Admin directory and simply remove IUSR_ to achieve the same effect although I would still need the impersonate setting in web.config.
This works well as long as the requests in question can be easily isolated and users are that are accessing these requests indeed can authenticate, which is not always the case.
Use with care... and don't impersonate GrandMa - it ain't nice!
The Voices of Reason
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
Greg
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
i badly need help. pls find the
code below
here i am passing the username and password to the network credential object inorder to authenticate the proxyserver. Instead I want to authenticate the proxy server using the currently logged in windows user. Do u have any clue abt how to do this ? pls help
Dim myHttpWebRequest As HttpWebRequest = CType(WebRequest.Create("http://www.testsite.com"), HttpWebRequest)
Dim myProxy As New WebProxy("http://isa:80", True)
Dim x As New NetworkCredential
myProxy.Credentials = New NetworkCredential("myusername", "mypassword", "mydomain")
myHttpWebRequest.Proxy = myProxy
Dim myHttpWebResponse As HttpWebResponse = CType(myHttpWebRequest.GetResponse(), HttpWebResponse)
Dim receiveStream As Stream = myHttpWebResponse.GetResponseStream()
Dim encode As Encoding = System.Text.Encoding.GetEncoding("utf-8")
Dim readStream As New StreamReader(receiveStream, encode)
Dim read(256) As [Char]
Dim count As Integer = readStream.Read(read, 0, 256)
# re: Using programmatic Impersonation from an ASP.NET Page
Please advise.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
An unhandled exception of type 'System.Web.Services.Protocols.SoapException' occurred in system.web.services.dll
Additional information: Server was unable to process request. --> Access to the path "\\serverName\BIER\BIER_PrintService\Queues\HTML\TEST.html" is denied.
here's my code:
WindowsImpersonationContext impContext = null;
try
{
impContext = NetworkSecurity.ImpersonateUser(
"DOMAIN",
"user",
"pwd",
LogonType.LOGON32_LOGON_NETWORK,
LogonProvider.LOGON32_PROVIDER_DEFAULT);
if (null != impContext)
{
try
{
File.Copy(FILE_NAME,REMOTE_FILE_NAME);
} //end try
catch (Exception ex)
{
//Response.Write(ex.Message);
throw(ex);
} //end try
finally
{
// Finally we have to revert the impersonation.
impContext.Undo();
File.Delete(FILE_NAME);
} //end finally
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
string REMOTE_FILE_NAME = @"\\remoteServer\BIER\BIER_PrintService\Queues\HTML\TEST.html";
string FILE_NAME = @"\\localServer\images\test.html";
No problem accessing UNC on the local server (XP development box), but I get the access denied error when trying to access the remote server(win 2k server).
BTW
Thanks for the help and the quick responses :)
# re: Using programmatic Impersonation from an ASP.NET Page
To do this requires a technique called "delegation", which is like impersonation except that the ASP.NET process now has to convince a -second- machine to act using the user's account.
You can find information on this with Google "trust for delegation" or similar. Not all accounts are allowed to delegate, and some accounts can't be delegated.
The reason for this is that an evil web designer could create a web page using impersonation that checked to see if the user happened to be a superadmin, then use that user's account to grant the web designer superadmin priveleges, and the admin would never be the wiser.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
Rick, Is there anyway I can automatically take user name who logged in to the system, This way I do not have to supply password. And also I do not need to supply the password whenever I change my AD password.
# re: Using programmatic Impersonation from an ASP.NET Page
ImpersonateLoggedOnUser(lnToken); ProcessStartInfo psInfo = new ProcessStartInfo("cmd.exe");
psInfo.UseShellExecute = false; psInfo.RedirectStandardOutput = true;
psInfo.RedirectStandardInput = true;
psInfo.RedirectStandardError = true;
Process pBatch = Process.Start(psInfo);
StreamReader srOutput = pBatch.StandardOutput;
StreamWriter sWriter = pBatch.StandardInput;
sWriter.WriteLine(@"date /t"); sWriter.WriteLine(@"whoami");
Yet the output of the whoami still shows Network Service as the user. I need this command prompt to be running as the account i'm attempting to impersonate. Any ideas?
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
In an ASP.Net page, iam instantiating a COM component. The COM component reads info from the HKCU reg key and populates it's properties.
Now, since ASPNET account doesnot have any keys under HKCU, this COM component fails. So, I decided to use impersonation.
I impersonated the ASPNET account to a known windows account (in web.config). However, the COM component still fails.
Interestingly, if i make the impersonation in machine.config, the COM component works perfectly, using the profile of the impersonated account. But i don't want to do this, as it is a global change and affects all the web applications on this machine.
Any suggessions?
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
Any additional information that may help explain the two logon calls would be much appreciated.
Thanks in advanced
Dean Dalby
# re: Using programmatic Impersonation from an ASP.NET Page
I have an aspx page with download button on my server. When the user clicks that download button, I am trying to download the file (PDF) from my network machine which is under same domain. I am getting this attached error message. I have given all the permission to folder which all the PDF files stroed . I try to ImpersonateUser that user account, that part working fine. after the impersonate, its giving the login failure problem.
Any idea to resolve this.
Here is the code which i am using for downloading the file.
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim path1 As String = "\\machine02\temp\test.pdf"
Dim name As String = Path.GetFileName(path1)
Dim ext As String = Path.GetExtension(path1)
Dim type As String = ""
If Not (ext Is Nothing) Then
Select Case ext.ToLower
Case ".htm", ".html"
type = "text/HTML"
' break
Case ".txt"
type = "text/plain"
' break
Case ".doc", ".rtf"
type = "Application/msword"
' break
Case ".pdf"
type = "Application/pdf"
End Select
End If
'If forceDownload Then
Response.AppendHeader("content-disposition", "attachment; filename = " + name)
'End If
If Not (type = "") Then
Response.ContentType = type
End If
Response.WriteFile(path1)
Response.End()
End Sub
Thanks
Bala
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
here is my code
int TResult = LogonUser("administrator", "domain", "pwd", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, out lnToken);
if (TResult > 0)
{
ImpersonateLoggedOnUser(lnToken);
StringBuilder sb = new StringBuilder(80, 80);
DirectoryEntry root = new DirectoryEntry("IIS://server/W3SVC","administrator","domain","pwd",AuthenticationTypes.Secure);
foreach (DirectoryEntry ent in root.Children)
{
if (ent.SchemaClassName == "IIsWebServer")
{
Response.Write(ent.Properties["ServerComment"].Value.ToString());
}
}
RevertToSelf();
Response.Write("<hr>" + Environment.UserName + " - " + this.User.Identity.Name + "<hr>");
CloseHandle(lnToken);
}
else
{
Response.Write("Not logged on: " + Environment.UserName);
}
return;
# Using programmatic Impersonation fo accessing LAN web application
My brief code is below,
WindowsImpersonationContext wic = CreateIdentity(User_Alias, Domain, Password).Impersonate();
webBrowser1.Navigate("http://machineName/app");
wic.Undo();
I don't want this window to pop-up , and access the web application by the impersonated user. Plz.Help
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
You guys are all working at a much higher level than me, but I was wondering if one of you could help me out with a sample peice of code to get me on my way.
I dont wish to elevate priveledge or impersonate anything. I work for a charter school as a administrator and we are filtering student web access using IAS. What we want to do is give the kids a little something to think about when they attempt to access filtered content and are redirected to the access denied page.
We want to put the logged on username and pcname & ip in message returned to them in the page, letting them know the attempt and thier username was logged. I thought I could do this easily just doing:
<%
Response.Write Request.ServerVariables("REMOTE_HOST")
Response.Write Request.ServerVariables("REMOTE_USER")
Response.Write Request.ServerVariables("REMOTE_ADDR")
Response.Write Request.ServerVariables("LOGON_USER")
%>
But alas even though I am trying to get the info from machines on a LAN that I administer, the only info returned was the IP.
I realize this is a security measure with modern servers to protect our info on the internet but on the LAN we (administraors) should have authority.
At any rate, the subject of this thread seems like it could be used (or something simular) to get the info I want to return. However I only have a basic understanding of ASP and no real ASP.NET experience. Any help or a referral in the right direction would be greatly appreciated.
Shane Hale MCSE
# re: Using programmatic Impersonation from an ASP.NET Page
You can do DNS lookups of IP Addresses to get machine or server names if they are registered in DNS.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
Even I put <identity impersonate="true" userName="User" password="password"/> in web.config, when calling a batch file from an asp.net page, the batch file is still run under ASPNET account. Actually before calling batch, I checked the environment.username on .net page, it is ¡°user¡± not ¡°ASPNET¡±.
The test batch file:
echo %time% >test.txt
echo %username% >> test.txt
In test.txt the username is always ASPNET.
Anybody knows if there is a way to run batch file under a user account other than ASPNET?
I'm thinking to call "CMD.EXE" then run "runas" command to change user. However, runas will prompt to input user password. Can we start an interactive mode from asp.net?
Thanks in advance for any help,
Arlean
# re: Using programmatic Impersonation from an ASP.NET Page
But I am not sure how I can use impersonation to access NTFS protected files like .gif and .jpg, resources that cannot be impersonated. But need impersonation to access them.
Can you point me in another direction?!
Thank you.
# re: Using programmatic Impersonation from an ASP.NET Page
</A> [ http://google.com ]
When you look at SQL Profiler it seems that there is two logon calls made when the connection is opened. One for the ASP.NET machine account and one for the user that we impersonated using the LogonUser function. Does anyone know why this happens? And how to avoid it?
# re: Using programmatic Impersonation from an ASP.NET Page
I'm using impersonation because i've had a problem with creating files on localhost. On the other side I have peace of code which creates win process, starts it and stops it. When I use impersonation, that code doesnt work (I can not start or stop the process). When I shut impersonation, I have problem with accessing the files (Access is denied)
Anyone can help?
Thanks in advance
# re: Using programmatic Impersonation from an ASP.NET Page
Page User ID is Authenticated: True
Page User ID Authentication Type: NTLM
Page User Id Name: Domain\Username
Environment Username: SYSTEM
Environment User Domain Name: NT AUTHORITY
Strange, I don't see NETWORK SERVICE anywhere. I'm getting this info by: Page.User.Identity.Name.ToString & "<BR>Environment Username: " & Environment.UserName.ToString & "<br>Environment User Domain Name: " & Environment.UserDomainName.ToString etc.
It scans the local server fine, but any other server says "Access Denied". I tried everything. Hope you can help Rick!
# re: Using programmatic Impersonation from an ASP.NET Page
In IIS 6 the OS account is configurable - and if you're running IIS 6 you might have your APplication Pool set to the Local System impersonation.
# re: Using programmatic Impersonation from an ASP.NET Page
could anyone help??
IntPtr lnToken;
int TResult = LogonUser("username","domain","Password",
LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT,
out lnToken);
if ( TResult > 0 )
{
ImpersonateLoggedOnUser(lnToken);
StringBuilder sb = new StringBuilder(80,80);
uint Size = 79;
Response.Write( Environment.UserName + " - " + this.User.Identity.Name + "<hr>");
string[] drives = Environment.GetLogicalDrives();
// Response.write("Available drives:");
foreach(string drive in drives)
Response.Write(drive);
// Console.ReadLine();
RevertToSelf();
Response.Write("<hr>" + Environment.UserName);
CloseHandle(lnToken);
}
else
{
Response.Write("Not logged on: " + Environment.UserName);
}
# re: Using programmatic Impersonation from an ASP.NET Page
I'm doing one file manager in ASP.Net. I put permissions to read/write some folder. I can create files, but I can't delete! I can resolve this with this web.config aproach?
# re: Using programmatic Impersonation from an ASP.NET Page
Anyone has idea, why above code doesn't want to work on W2K and IIS5, but deployed on W2K3 & IIS6 works exactly as described ?
I mean, on IIS5 LogonUser returns 0.
I both cases the same user/passw is configured and defined to be used. Also exactly the same web.config is used.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
To make ASPNET or IUSR_xxx user has this right, one need to:
1.
Open "Administrative Tools | Local Security Policy" and then double-click on "Local Policies".
2.
Open "User Rights Assignment" and then double-click on "Act as Part of the Operating System".
Add the wanted account to do list.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
http://www.codeproject.com/csharp/ZetaImpersonator.asp
NOTE: you should add domain user as a local administrator if you want to copy a local file to a network shared folder.
# Read and display the current logged on username
I hope someone can help. I don't need to use pass through to authenticate my application. I just want to be able to save the username into a variable for later use, for example when a user submits a form, I want to record the username who made the change. How can I do thi?
# re: Using programmatic Impersonation from an ASP.NET Page
# Accessing Shared Folders in ASP.NET
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/Q_20336491.html
http://corner-house.blogspot.com/2006/03/accessing-shared-folders-in-aspnet.html
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
The permissions are assigned the user through which impersonation is done.
Although the current thread is impersonated it is throwing access denied exception what may be the problem. on the network machine i assigned full rights to the user.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
If it is in the same machine or same domain it works fine but fails when the domain is different.
Any thoughts?
TIA,
Paresh
# re: Using programmatic Impersonation from an ASP.NET Page
If you can't you're SOL.
# re: Using programmatic Impersonation from an ASP.NET Page
<authentication mode="Windows" />
<authorization>
<allow users="*" />
</authorization>
The web server is running IIS and has the following settings. Anonymous Access is enabled and Integrated Windows Authentication is disabled.
What i need to return is the domain/username, so it returns the actual user like john.smith of mydomain/js.
Initially i have created a seperate directory in the solution with an aspx page an a seperate web.config with <identity impersonate="true"/>. Will this give me what i am looking for?
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
How does firewall affect impersonation? well, i have written a program which authenticates a user using ldap and stores the user password in session variable. for any action required - add/edit/delete of files, i am supplying the user name, domain and saved password. am able to access network resources as well but when i moved the program to production server, which is apparently outside the firewall, it can't impersonate. network resources are inside the firewall.
is it possible at all to do impersonation between firewall? maybe by opening ports? any help appreciated.
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
I appreciate your response. I will have a chat with system administrator and see how it goes.
# re: Using programmatic Impersonation from an ASP.NET Page
I have a situation here.
My Web applciation is running on two servers parallel for the purpose of NLB. Application needs to read/write files from local folders. since I cant put the files on both servers(it will replicate the data), I decided to create folders in my primary server and create a Network map drive on both servers with the same drive letter pointing to the folders in the primary server. Since NLB server will redirect the request to any of the two server, this is the only way i found. But now problem is ASP.NET is not able find the network drive, it throws the exception that Directory not found.
If I use IP Address instead of Network drive, it works fine. But I cant use it the reasone being, in case of any hardware failure switching the IP address is difficult....
Forgot to mention, my application is only an "Intranet" application.
Please suggest me any alternative...
# re: Using programmatic Impersonation from an ASP.NET Page
What is the differance between Impersonation and changing the "userName in ProcessModel" tag? Effectively, whether we change the useName in ProcessModel, or make the application Impersonatate, we are achieving the same thing right?
# re: Using programmatic Impersonation from an ASP.NET Page
string usr1=System.Security.Principal.WindowsIdentity.GetCurrent().Name;
string usr2 = System.Environment.UserName;
as a result of this
usr1=@"NT AUTHORITY\SYSTEM"
and usr2="SYSTEM"
But,still the ASP.NET code (C# code behind)doesnt seem to have all the privelidges ..for eg..when i do
System.Collections.IDictionary all_vars=System.Environment.GetEnvironmentVariables();
then,the ASP.NET code doesnt show the environment variables which i have manually created beforehand,while a simple C# code shows all the environment variables..similarly there are many cases where ASP.NET cant perform the expected task whereas a simple C# script does it....
any solutions to this???
# re: Using programmatic Impersonation from an ASP.NET Page
However, we want to access a share in a different domain, but when we specify an account in the local domain that matches an account and password in the remote domain, we still get an invalid path or file name from System.Data.OleDb.OleDbException (we're trying to access a data source on the remote domain)
I noticed you mentioned that it may be possible to do that programatically if the accounts match ID and password... But is it possible to do it in the web.config, as we are trying to do..? Since we cannot modify the source code of the application... Our only option is in the web.config.
We've also tried using a local account (instead of a domain account) that matches the remote domain account a password with similar (failed) results.
Any thoughts or suggestions much appreciated! :)
# re: Using programmatic Impersonation from an ASP.NET Page
On IIS 6 the machine account is determined by the IIS Application Pool Impersonation, and that can't be overridden as far as I know.
# How to pass Username and password when accessing Network Folder
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
Thanks,
Damian
# re: Using programmatic Impersonation from an ASP.NET Page
BUT when trying to connect to a remote db using a trusted connection it fails with the error 'NT AUTHORITY\ANONYMOUS LOGON'.
Any ideas?
# re: Using programmatic Impersonation from an ASP.NET Page
here is my code
int TResult = LogonUser("administrator", "domain", "pwd", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, out lnToken);
if (TResult > 0)
{
ImpersonateLoggedOnUser(lnToken);
StringBuilder sb = new StringBuilder(80, 80);
DirectoryEntry root = new DirectoryEntry("IIS://server/W3SVC","administrator","domain","pwd",AuthenticationTypes.Secure);
foreach (DirectoryEntry ent in root.Children)
{
if (ent.SchemaClassName == "IIsWebServer")
{
Response.Write(ent.Properties["ServerComment"].Value.ToString());
}
}
RevertToSelf();
Response.Write("<hr>" + Environment.UserName + " - " + this.User.Identity.Name + "<hr>");
CloseHandle(lnToken);
}
else
{
Response.Write("Not logged on: " + Environment.UserName);
}
return;
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
My entire site uses a web.config with forms based authentication. When I try and specify windows based inside a subfolder, the compiler throws an error. I want to keep everything together in one project, and don't want to have to resort to splitting it into another virtual dir.
# Using Impersonation in an application to verify folder permissions
In your article you write
"You can also impersonation system accounts like SYSTEM and NETWORK SERVICE which don't require passwords (pass "" for the password), but most likely these accounts are not what you need to get your job done - for example access another machine on the network."
My question to you is, how do i impersonate the built-in account NETWORK SERVICE.
I need to find a way to verify if the built-in system account "NETWORK SERVICE" has read and write rights to a specific folder, and a thought that if I could Impersonate the account then I could perform the nessary file operations as that user and thereby determine if the user has the nessary rights on the folder.
Hope i make sense, and that you can find the time to answer me.
Best Regards
Michael T.
# re: Using programmatic Impersonation from an ASP.NET Page
Great article, thanks so much.
Otto.
# re: Using programmatic Impersonation from an ASP.NET Page
The information on this page is brilliant.
I am also facing some IIS account heck, and dying to get it worked with already provided solution.
I have got a Web service, which calls a C++ DLL. C++ DLL calls a COM component, which is on another server.
Now while accessing the COM, I am getting "Access is denied" error. But if I run same C++ code from any development environment ( Not under IIS ) it works.
somewhere in this page, its written that I need to Impersonate ASPNET account. But still after adding impersonate = true in Machine.config and web.config, nothing is working.
It must be a simple configuration somewhere, but not getting proper direction.
Can someone help.
# re: Using programmatic Impersonation from an ASP.NET Page
I also tried Impersonation with asp.net and it is successful.
now i want to create a file on a network location with the impersonated credentials..I am providing proper UNC path but it cannot read or write to my network share folder. When i try to create a file, its says file \\servername\sharepath\file.doc cannot be created.
Can any one help please. its urgent
Thanks
# re: Using programmatic Impersonation from an ASP.NET Page
Go to this URL buried in the comments: http://corner-house.blogspot.com/2006/03/accessing-shared-folders-in-aspnet.html
I successfully implemented accessing a remote share and my ASP.NET pages are reading/writing files like champs.
# Impersonation NT AUTHORITY\SYSTEM
I'm trying to create an exe file using IExpress.
I create .sed file correctly (newsedfile parameter in the sub below), but then my following code (that implements impersonation with user NT AUTHORITY/SYSTEM) throws the error "Access is denied" and I don't undestand why!
Windows 2003R2 SP1 or Windows XP SP3; .net framework 2.0
That's All Folks! Thank you a lot!
Irene
private static void createEXE(string newsedfile)
{
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
try
{
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
const int SecurityImpersonation = 2;
tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser("SYSTEM","NT AUTHORITY","",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
if (false == returnValue)
{
int errorCode = 0x5; //ERROR_ACCESS_DENIED
throw new System.ComponentModel.Win32Exception(errorCode);
}
bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
if (false == retVal)
{
CloseHandle(tokenHandle);
throw new ApplicationException("Exception thrown in trying to duplicate token.");
}
// The token that is passed to the following constructor must
// be a primary token in order to use it for impersonation.
System.Security.Principal.WindowsIdentity newId = new System.Security.Principal.WindowsIdentity(dupeTokenHandle);
System.Security.Principal.WindowsImpersonationContext impersonatedUser = newId.Impersonate();
System.Diagnostics.Process p = new System.Diagnostics.Process();
// cfr. http://www.microsoft.com/technet/prodtechnol/ie/ieak/techinfo/deploy/60/en/iexpress.mspx?mfr=true
/* p.StartInfo.Domain = @"NT AUTHORITY";
p.StartInfo.UserName = @"SYSTEM";
System.Security.SecureString pwd = new System.Security.SecureString();
foreach (char c in "")
pwd.AppendChar(c);
p.StartInfo.Password = pwd; */
p.StartInfo.FileName = "iexpress.exe";
p.StartInfo.Arguments = "/N /Q " + newsedfile;
p.StartInfo.UseShellExecute = false;
//p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
if (p.Start())
{
p.WaitForExit();
}
else
{
throw new Exception("IExpress has not started");
}
// Stop impersonating the user.
impersonatedUser.Undo();
}
catch (Exception exc)
{
throw exc;
}
finally
{
// Free the tokens.
if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle);
if (dupeTokenHandle != IntPtr.Zero) CloseHandle(dupeTokenHandle);
}
}
# re: Using programmatic Impersonation from an ASP.NET Page
I am developing an application which uses exchange server 2007. I have created a web service on the remote m/c where exchange server is installed and then using command prompt i am running powershell scripts here's code snap
string command = "powershell.exe \"& 'D:\\Documents and Settings\\Administrator\\Desktop\\exchange2007\\test.ps1'\"";
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd","/c "+command);
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
try
{
proc.Start();
}
catch (Exception ex)
{
}
// Get the output into a string
while (!proc.StandardOutput.EndOfStream)
{
result += proc.StandardOutput.ReadLine();
}
i used your provided code it runs well but when the code tries to run the script it gives the following error
Get-MessageTrackingLog : Failed to connect to the Microsoft Exchange Transport Log Search service on computer "mycompany.mycompanyv2.com". Verify that a valid computer name was used and the Microsoft Exchange Transport Log Search service is started on the target computer. The error message is: Access is denied.At D:\Documents and Settings\Administrator\Desktop\exchange2007\test.ps1:2 char:23+ get-messagetrackinglog <<<< -messagesubject test | export-csv 'D:\Documents and Settings\Administrator\Desktop\exchange2007\Book1.csv'
plz help
# re: Using programmatic Impersonation from an ASP.NET Page
would the code here work for this purpose?
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
I am using word template automation using c# and i dont want to use username and password in the web.config and when i user username and password the application running fine, please tell me some solution so that i dont want use username and password, I deployed application in WinServer 2003
Thanks
Vish
# re: Using programmatic Impersonation from an ASP.NET Page
1.I am using your example to create a Directory in our shared network (FileServer is part of our network)
2.I followed all your steps. It is changing enviromnent user name in the correct order i.e. ASP.NET, myusername and back to ASP.NET.
3. It works successfully when I run the code from Visual studio. Able to create the Directory.
But, I am getting "access denied" error when I am running from IIS.
Any ideas/clues
Thanks a lot for your quick response
Sabarish
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
using (new Impersonator("uname", "domain", "password"))
{
try
{
....
}
catch (IOException ex)
{
// handle exception
}
}
public class Impersonator :
IDisposable
{
#region Public methods.
// ------------------------------------------------------------------
/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public Impersonator(
string userName,
string domainName,
string password)
{
ImpersonateValidUser(userName, domainName, password);
}
// ------------------------------------------------------------------
#endregion
#region IDisposable member.
// ------------------------------------------------------------------
public void Dispose()
{
UndoImpersonation();
}
// ------------------------------------------------------------------
#endregion
#region P/Invoke.
// ------------------------------------------------------------------
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
// ------------------------------------------------------------------
#endregion
#region Private member.
// ------------------------------------------------------------------
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password)
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
try
{
if (RevertToSelf())
{
if (LogonUser(
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();
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
if (token != IntPtr.Zero)
{
CloseHandle(token);
}
if (tokenDuplicate != IntPtr.Zero)
{
CloseHandle(tokenDuplicate);
}
}
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
private WindowsImpersonationContext impersonationContext = null;
// ------------------------------------------------------------------
#endregion
}
# re: Using programmatic Impersonation from an ASP.NET Page
my asp.net application is on system1
my sqldatabase on system2
everything works fine when i run the application frm system1 ie the system having asp.net application
my file copy code is
File.copy(source,destination)
my source is system2 and destination is system1
uisng the application frm system1 using localhost/copypage.aspx
it works fine i am able to copy frm source to destination
web config has
<identity impersonate="true" userName="system2" password="abc"/>
but if run the same application thr' some other system (mapped & configured thr' IIS) i get error
now i get access denied
how do i go abt
# re: Using programmatic Impersonation from an ASP.NET Page
Dim destFilePath As String = "\\destServerName\desttemp\srcfilename.TXT"
Try
File.Create(destFilePath)
Catch ex As Exception
UtilityTier.ApplicationError.ReportError("SIInitAndEduInterface-btnUploadFile", ex.Message)
End Try
Exception Message:- "Logon failure: unknown user name or bad password"
Server destServerName is running Windows 2003
Folder 'desttemp' is having fullcontrol to Everyone,Network Service account
# re: Using programmatic Impersonation from an ASP.NET Page
but i still don't know why did not work my previous code ... i am trying to run from asp.net page bat files .. i used this code:
Process p = new Process();
p.StartInfo.UserName = AdHelper.domainAdmin;
p.StartInfo.Password = WMIHelper.securePassword(AdHelper.domainAdminPwd);
p.StartInfo.Domain = AdHelper.domain;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "xxx.bat";
p.StartInfo.Arguments = "qwerty";
p.EnableRaisingEvents = false;
bool retVal = p.Start();
log.Info("process start called, result: " + retVal);
p.Close();
when i ran web site from Visual Studio, it works great .. when i moved it to IIS, i get Access Denied exception on the row with p.Start() .. but i am sure, that file permissions to bat file are OK - it works in VS - i saw xxx.bat in taskmanager running under domainAdmin ...
Anybody has idea why this does not work?
It started working when i put before Process declaration that LogonUser and ImpersonateLoggedOnUser stuff ... but i still believe it should work even without it, using startInfo.domain/domainUser/domainPassword...
Thanks a lot, Tomas
# re: Using programmatic Impersonation from an ASP.NET Page
I am using the exact code, as u have specified for impersonation, to connect to IBM WebSphere MQ, and it works fine in my local system XP, when I tried the same code on 64 bit Windows server 2003 it gives me bad image format exception, which I believe bcox of a 32 bit dll running on 64 bit OS. I am not sure, whether advapi32 dll or kernel32 dll is causing the problem?
and Will the code for impersonation works fine in 64bit computers?
# re: Using programmatic Impersonation from an ASP.NET Page
# re: Using programmatic Impersonation from an ASP.NET Page
I was wondering if you ever stumbled upon something similar. It seems to be directly or indirectly linked to IIS and impersonation.
# re: Using programmatic Impersonation from an ASP.NET Page
I have asp.net (impersonation = false) application with NTLM authorizaion so only authenticated domain users in group "A" can acces site. I have file system on network server which can acccess only users from group "A" with read/write access. Now i need temporarily impersonate user from group "A" to read files or directories on file server. Im doing it this way:
WindowsImpersonationContext ctx; ctx = ((WindowsIdentity)User.Identity).Impersonate(); if (System.IO.File.Exists(filePath)) { //... } ctx.Undo();
It succesfully impersonate current user (Enviroment.User changes from NETWORK_SERVICE to current user). But file operations doesnt work becouse of some Logon failure. What im doing wrong? Strange thing is if i dont use this impersonation , it works.
# re: Using programmatic Impersonation from an ASP.NET Page
My requirement is that once a user is logged in, he requests some pages and then he want to switch as another user, and will request more pages.
i am giving a seperate form to get user details (username, password, domain) to log in as a different user & i am changing impersonate as per your code. but this impersonate is limilted to that page only, when i am checking the same user on different page, its again givin me the origional impersonate and not the changed one.
thanks,
Banti