Running into a problem where on certain servers we get an error that the directory name is invalid when using Path.GetTempFileName. Further investigation shows that it is trying to write a file to c:\Documents and Setting\computername\aspnet\local settings\temp (found by using Path.GetTempPath). This folder exists so I'm assuming this must be a permissions issue with respect to the asp.net account.
I've been told by some that Path.GetTempFileName should be pointing to C:\Windows\Microsoft.NET\Framework\v2.0.50727\temporaryasp.net files.
I've also been told that this problem may be due to the order in which IIS and .NET where installed on the server. I've done the typical 'aspnet_regiis -i' and checked security on the folders etc. At this point I'm stuck.
Can anyone shed some light on this?
**Update:**Turns out that providing 'IUSR_ComputerName' access to the folder does the trick. Is that the correct procedure? I don't seem to recall doing that in the past, and obviously, want to follow best practices to maintain security. This is, after all, part of a file upload process.
This is probably a combination of impersonation and a mismatch of different authentication methods occurring.
There are many pieces; I'll try to go over them one by one.
Impersonation is a technique to "temporarily" switch the user account under which a thread is running. Essentially, the thread briefly gains the same rights and access -- no more, no less -- as the account that is being impersonated. As soon as the thread is done creating the web page, it "reverts" back to the original account and gets ready for the next call. This technique is used to access resources that only the user logged into your web site has access to. Hold onto the concept for a minute.
Now, by default ASP.NET runs a web site under a local account called ASPNET. Again, by default, only the ASPNET account and members of the Administrators group can write to that folder. Your temporary folder is under that account's purview. This is the second piece of the puzzle.
Impersonation doesn't happen on its own. It needs to be turn on intentionally in your web.config.
<identity impersonate="true" />
If the setting is missing or set to false, your code will execute pure and simply under the ASPNET account mentioned above. Given your error message, I'm positive that you have impersonation=true. There is nothing wrong with that! Impersonation has advantages and disadvantages that go beyond this discussion.
There is one question left: when you use impersonation, which account gets impersonated?
Unless you specify the account in the web.config (full syntax of the identity element here), the account impersonated is the one that the IIS handed over to ASP.NET. And that depends on how the user has authenticated (or not) into the site. That is your third and final piece.
The IUSR_ComputerName account is a low-rights account created by IIS. By default, this account is the account under which a web call runs if the user could not be authenticated. That is, the user comes in as an "anonymous".
In summary, this is what is happening to you:
Your user is trying to access the web site, and IIS could not authenticate the person for some reason. Because Anonymous access is ON, (or you would not see IUSRComputerName accessing the temp folder), IIS allows the user in anyway, but as a generic user. Your ASP.NET code runs and impersonates this generic IUSR___ComputerName "guest" account; only now the code doesn't have access to the things that the ASPNET account had access to, including its own temporary folder.
Granting IUSR_ComputerName WRITE access to the folder makes your symptoms go away.
But that just the symptoms. You need to review why is the person coming as "Anonymous/Guest"?
There are two likely scenarios:
a) You intended to use IIS for authentication, but the authentication settings in IIS for some of your servers are wrong.
In that case, you need to disable Anonymous access on those servers so that the usual authentication mechanisms take place. Note that you might still need to grant to your users access to that temporary folder, or use another folder instead, one to which your users already have access.
I have worked with this scenario many times, and quite frankly it gives you less headaches to forgo the Temp folder; create a dedicated folder in the server, set the proper permissions, and set its location in web.config.
b) You didn't want to authenticate people anyway, or you wanted to use ASP.NET Forms Authentication (which uses IIS's Anonymous access to bypass checks in IIS and lets ASP.NET handle the authentication directly)
This case is a bit more complicated.
You should go to IIS and disable all forms of authentication other than "Anonymous Access". Note that you can't do that in the developer's box, because the debugger needs Integrated Authentication to be enabled. So your debugging box will behave a bit different than the real server; just be aware of that.
Then, you need to decide whether you should turn impersonation OFF, or conversely, to specify the account to impersonate in the web.config. Do the first if your web server doesn't need outside resources (like a database). Do the latter if your web site does need to run under an account that has access to a database (or some other outside resource).
You have two more alternatives to specify the account to impersonate. One, you could go to IIS and change the "anonymous" account to be one with access to the resource instead of the one IIS manages for you. The second alternative is to stash the account and password encrypted in the registry. That step is a bit complicated and also goes beyond the scope of this discussion.
Good luck!
I encountered this error while diagnosing a console app that was writing in temp files. In one of my test iterations I purged all the files/directories in temp for a 'clean-slate' run. I resolved this self inflicted issue by logging out and back in again.
Could be because IIS_WPG does not have access to a temp folder. If you think it is a permission issue, run a Procmon on asp.net worker process and check for AccessDenied errors.
I was having the same problem with one of my ASP.Net applications. I was getting Path.GetTempPath() but it was throwing an exception of:
"Could not write to file "C:\Windows\Temp\somefilename", exception: Access to the path "C:\Windows\Temp\somefilename" is denied."
I tried a few suggestions on this page, but nothing helped.
In the end, I went onto the web server (IIS server) and changed permissions on the server's "C:\Windows\Temp" directory to give the "Everyone" user full read-write permissions.
And then, finally, the exception went away, and my users could download files from the application. Phew!
You can use Path.GetTempPath() to find out which directory to which it's trying to write.
Related
TL;DR: I need to call CreateProcessWithLogonW from my IIS-hosted ASP.NET application in order to call an external executable under a different account and delegate a job to it. How can I do this?
The reason I can't simply use Process.Start API is that the external executable has a number of COM dependencies that need to be configured. This entails making sure a number of registry entries are there and that the account has required launch and activation permissions which need to be set via DCOM config. Suffice to say this has proven quite unmanageable to do for each of the AppPool identities on every server we have.
The idea is to create a single additional interactive account on each system, configure it as necessary, and then test that the external executable can be successfully run by hand.
The problem now becomes how to start this executable from ASP.NET app and have it run under the new account (just the executable, not the whole ASP.NET app!).
Simply calling CreateProcessWithLogonW results in "Access denied" error, which I've been told is the consequence of the AppPool identity's under-privileged nature.
I've been searching the internet and I've seen a lot of answers on how to grant file-system permissions to AppPool identities. Nothing about permissions for CreateProcessWithLogonW, however, short of changing the identity to something else.
But I'm still wondering if there is a way to configure the AppPool identity for this?
I don't feel comfortable changing the identity to Local Service or Local System as has been suggested elsewhere. I'm worried it could enable unknown additional permissions that are not really needed by the ASP.NET app, which could in turn change the security implications of a rather large code base.
I admit I'm probably having a "Here be dragons!!!" type of reaction to identity changing, but I'm also honestly wondering why I couldn't simply add one additional permission to an existing identity instead?
I have an MVC web application that is supposed to allow users to download files that are stored as UNC paths in a database. These files can be in any number of locations on remote servers/shares.
E.g. Server 1 hosts the web application that is used to download a file stored on Server 2
I do not want to give permissions to these folders to the hosting service account, as the security should be dependent on what the user has access to. Therefore, I'm attempting to use Impersonation to retrieve the file.
When I debug on my local machine, everything works great. It impersonates my user and downloads the file.
When I deploy to my test server, I'm getting the following error:
Access to the path '\\Server2\SharedFolder\somefile.txt' is denied
I've tried various pieces from this Microsoft link, but am not having much luck.
Scenarios I've tried:
Just giving the permission to the service account of the AppPool works fine, but as I said, isn't ideal
Implementing the Impersonate a Specific User in Code from the above article, which works perfectly with a hard-coded user and password. This situation is also not ideal.
Implementing the Impersonate the Authenticating User in Code from the above article. This seems to be exactly what I need, but this is what generates the Access Denied error.
The Code that I want to work:
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Code to read all bytes from the file path
impersonationContext.Undo();
I have logging, and System.Security.Principal.WindowsIdentity.GetCurrent().Name after the impersonation does return the intended user (my account instead of the service account), so it does appear to be working.
I thought maybe it was a double-hop thing, so I have also added SPNs for the server and the service account, making sure their Delegation in AD was set to allow for any service. That hasn't helped either.
This question seems to have the exact same problem as me, but there's no follow-up on what the final solution was. I did try the Process Monitor part, but it didn't help at all.
I'm at a loss to why Impersonation seems to be working, but I'm denied access to a file on a second server.
Update 1
I've played around more with my IIS settings and trying to get Kerberos properly set up. The only thing enabled in my IIS Authentication is "Windows Authentication".
When I spit out details after my Impersonate() call, I'm finding that ImpersonationLevel = Impersonation
Is that how it should be, or should that be returning Delegation ?
It would seem the issue was mostly due to my setup with Kerberos and SPNs. I undid all my settings and re-registered my service account, and the Impersonation ended up working properly.
The issue now is that it only seems to work with Internet Explorer. Chrome and MobileIron are doing something different that prevents the ImpersonationLevel of Delegation. That's a whole other question...
I have a .NET a web app that i built for files processing .I am using IIS 7 anonymous user authentication , i also did not require the users to log in, so pretty much any user who has access to the intranet can access the web app.
The users said when two of them try to run their files on app at the same time they receive an error( did not specify it).
My question is :
If i use anonymous authentication is it by default every user will have his\her own session while accessing the app?
Yes, by default every user will have their own session. And anonymous authentication is the default scheme for the web. It is unlikely that any web server, by default, would only allow 1 anonymous user at a time.
Most likely, if your app is doing file processing, you may be dealing with file locks and not an issue with IIS. You want to make sure that your code is written so that, if two or more people access it simultaneously, they can not request to same file. Also, you need to make sure that you are properly closing any file streams you open, even in the case of exceptions. Without seeing the code in question, it would be difficult to impossible to give more specific guidance, but hopefully this will help point you in the correct direction.
Install Elmah to get error report of ypur app!
I use this simple line of code inside my HttpHandler:
Directory.CreateDirectory(#"\\srv-001\dev\folderToCreate\");
I receive an UnauthoridezAccessException telling me that the access to the path is denied.
From here, I create a little Dos application in C# doing the same thing and I was able to create the folder. So, I thought that it might be that IIS is running on a different user than myself. I went to IIS and changed the Application pool to a Custom user, myself. But, unfortunately, I got the same exception.
I have try to create a Share folder on my computer and I can create directory. Also, when debugging I can see that System.Threading.Thread.CurrentPrincipal.Identity have its AuthenticationType to "", IsAuthenticated to false and name to "".
So, with all those tests I can conclude that the HttpHandler that receive the file cannot create a directory because of some security access.
How can I grand access to my HttpHandler to be able to create a directory (and files) to a network folder?
actually, i thought of one other thing to check. not only is there the app pool identity, but there is also an identity associated with anonymous authentication. if you are on iis 7/7.5, you should be able to see the authentication icon for the web application and doubleclick that. selecting anonymous authentication and then clicking edit will reveal a dialog that gives you the option of specifying a user or the app pool user. i bet if you choose app pool user, that will fix it.
if you are on iis 6, i don't recall as clearly, but i'll give it a shot. don't have iis 6 in front of me to verify, but i remember there being an anonymous access button you can click that would bring up a dialog where you could specify the user. don't think you had the option there of using the app pool identity and had to specify the account explicitly.
I am trying to create a program similar to Folder Lock which prevents users from accessing a particular folder. I tried using DirectorySecurity class and AccessRules to change the AccessControl for folders.
However, the settings which i assign can easily be changed by going to "Security Tab" and changing the permissions.
Is there any secure way of preventing access to directories ?
I think my answer to this question: "How could I prevent a folder from being created using a windows service?" is probably what you'd need to do to achieve what you want:
Unfortunately I don't know anywhere
near enough about the how to help you,
but I'm fairly sure that you'll need
to either write or obtain a File
System Filter Driver that can
communicate with your windows service
to tell it that someone has attempted
to create a directory/file so that
your service can make a decision for
it. This way when someone/something
attempts to create a file or folder
that's not allowed they could be
returned "Access Denied" or another
Win32 error of your choice.
If you did go down the route of using
a driver, I'd guess it'd still be best
to do the heavy lifting of deciding if
the creation/modification in the
service, i.e. outside of Kernel mode.
As long as a user is the owner of directories or files, he can change the permissions. You'd have to change the ownership of the directories in order to really secure the directories (and making this change of ownership requires administrative rights).
But a user with administrator right can always take the ownership back.
If you are in an enterprise and people are not admins of their machines, you could write a Windows service that runs as domain admin and makes the needed changes. In a home environment, there's no way.
There are 2 things which can overrule the rights of a local administrator.
The domain policy (but your pc has to be a member of a domain)
A process running under SYSTEM privileges (drivers for example), this is the way virus scanners and rootkits work, they analyse your file system request before the results reached the user, and intercept it if deemed necessary.
But the second option you can't do with c#, and the first option is more a Active Directory configuration solution.
No, you can't prevent the computers administrator account from accessing or taking ownership of any folder.
You can prevent restricted accounts (as you have described), but the administrator will always be able to change the security settings.