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.
Related
I use the following code to build a desired path for an XML file:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
When executed from a Windows Forms application, it returns:
C:\Users\MyUsername\AppData\Roaming\...\Database.xml
When executed from within a Windows Service, it returns:
C:\Windows\system32\config\systemprofile\AppData\Roaming\...\Database.xml
I am now resorting to having a custom installer action persist the path in a registry key since the custom action will have a desktop context. If there is a better approach, please let me know.
What I am really interested in finding out is why the behavior is different in the first place. The Windows Service in question is set up to use the LocalSystem account in case that matters.
Only you know what the specific requirements are for this folder, but if it's to share data between multiple users, ApplicationData is the wrong choice:
The directory that serves as a common repository for application-specific data for the current roaming user.
A roaming user works on more than one computer on a network. A roaming user's profile is kept on a server on the network and is loaded onto a system when the user logs on
See the SpecialFolder enumeration and pick an appropriate value that fits your requirements - one that doesn't depend on a specific user. Most of these start with Common.
I suggest that you should check and make sure that two apps are running by the same user.
I tested your code in both winform app and webservice app, but their values are the same, so I can't find your real problem.
good luck!
I have built an application using C# which accesses the registry and installation folder for read/write information. A normal user having limited privileges is getting an error while accessing/writing the information (in registry or installation folder).
Is there a way in which all types of users are able to run that application smoothly?
It is possible, although it's not completely straightforward.
You're gonna have to impersonate another user (who, in turn, has to have all the required privileges).
Check this question for details: Windows Impersonation from C#
There are two ways, the simple and complex. First - install the program per user rather than per computer. Second - to write a service that will operate under the privileged user and perform the necessary procedures (accessing/writing the information) for your application.
Some Background
We have a team of four developers and we have two web application projects in our visual studio solution. We decided to centralize resources between these two applications like images and video, etc. How we did this was we created a directory on another server ("\\devfileshare\WebFileShare\Content"). We then add this directory as a virtual directory at the root of both web applications in IIS. Essentially this makes "~/Content" point to "\\devfileshare\WebFileShare\Content".
The Problem
The problem we had was with the security permissions. What we had to do was create a user on devfileshare called "fileshare" and give that user read and write permissions to the content directory. Then on every developer's computer we had to add that same user ("fileshare") with the same password. After that we had to set each application pool to run under that user instead of the default. Then finally we had to add the virtual directory, setting the "Connect As" user to "fileshare".
This actually works and our projects can write to and read from the virtual directory. My question is, is there an easier way to accomplish this? Currently we have to add a new user to every new developer computer we set up, then modify IIS application pools and virtual directories to use this new user. It's a bit of a pain and it seems like there would be an easier way to set up virtual directories to point to another server on the network.
Thanks in advance! Let me know if you have any questions or if I did not make something very clear.
Two part approach here: Domain Users the developers(1) and IIS server access(2)
1) Using active directory coordinate with your network administrator to create security groups, like "XProjectDevelopers" and add all developers to this group and give read-write permissions for the directory to this group instead of to individuals. You get a new developer, the network admins just adds them to the group and your done.
2) IIS operates under a domain account, grant that domain account (on the server, it is in service settings, here again, your network admins should be able to help) read-only privileges to the target directory.
This should get you pointed in the right direction. Remember it is often helpful to bribe your network administrators with cookies or brownies.
I have a web service using .net c# and I want to write to a text file on the server, but I cannot get this to work. I believe it's a permission problem.
Specifically, I think the problem is I am using System.IO.Directory.GetCurrentDirectory().
Is there a better alternative?
Try granting the ASP.NET user (or whatever account IIS is running as) permission to write to the folder you are trying to write to.
If this is a network share, try to run IIS as a domain user that can write to the share.
Remember the principle of granting minimal permission (dont use Admin level access).
If you don't specify a destination folder I assume your web service wants to write to "C:\Windows\System32\" or something of that kind. That's why a UnauthorizedAccessException will be thrown on the server. In order to write to the "home"-directory of the web service you have to find out where that is first.
The following works for me but you also find other suggestions here.
Add the reference System.Web, and get the current directory by calling:
strFileDestination = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + strFileName;
Remember to give your service write permission in IIS.
If you're running on Windows 2003 and haven't turned on ASP.NET impersonation, and are running the app in the DefaultAppPool or an application pool that is configured to run under the identity of "Network Service", then you'll need to give the "Network Service" account write permission to the destination folder. If you're running the site in an app pool that is using an identity other than "Network Service" then that account may require write permissions to the destination folder.
If you're running windows 2000 then the '<MACHINENAME>\ASPNET' account will need write permissions to the destination folder.
If you've got impersonation turned on then you'll need to give the site's anonymous user account write permissions to the destination folder instead.
To check if impersonation is turned on, open (assuming ASP.NET 2.0) then check your machine.config file (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG) to see if you have the following setting:
<identity impersonate="true"/>
This may also be overridden in your application's web.config.
Additionally if you're running in a partial trust environment then you'll likely only be able to write to the website's application folder because the default FileIOPermission is usually set to $AppDir$, i.e. you can't modify files anywhere else, even with the correct NTFS permissions.
If you're writing to a network share then StingyJack has the answer for you, but the partial trust environment considerations still apply.
But check your NTFS perms first, that's probably the best bet.
Hope this helps
Kev
Stuart, instead of using System.IO.Directory.GetCurrentDirectory(), you may want to use Server.MapPath. You can give Server.MapPath the directory relative to the location of your web service where you want to save the file, otherwise you probably need to pass a full file path "C:\Files\file.txt". As far as the permissions issue, I am usually able to resolve this by adding write access to the folder I'm writing the file to for IIS_WPG and ASPNET users (These usernames may be different on your server).
You should be able to write files from web services. This is most likely a permissions or trust issue. If you are in a limited trust (i.e., Medium trust) ensure that you are writing to a patch in or below your web root. If you are already doing that, or are in a full trust environment check to make sure that the directory has permissions for the IIS worker process to write to it.
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.