Can user schmoe_j run an app that copies files to a directory that schmoe_j can't write to?
No, permissions on files are handled by the file system which is at a much lower level in the system than C# code runs as. C# code can't directly bypass file system security. If the application runs as schmoe_j it can't write to locations on disk that schmoe_j doesn't have write-access to.
One exception is if schmoe_j has backup & restore privileges, in which case he can write to anywhere on disk. Normal users don't have this privilege because it is a very dangerous privilege to grant.
There are other theoretical ways - for example, if an insecure service is on the box that can be persuaded by a standard user to write to an arbitrary place on disk. Any such cases is a security hole that should be fixed.
You can include an Manifest with your executable to request that the application is run with higher privileges.
See Adding a UAC Manifest to Managed Code.
I think normally the way this is handed is to use a service (or service application) which runs under elevated permissions but with a very small surface area and no GUI. The user interacts with an application running under lower permissions which would do things that user's account can do - place files in a dropoff folder, write to a database, etc. Think IIS, MMC, TrustedInstaller, etc.
The application will run under the user's rights, if the user can;t do it, the application can't do it.
HOWEVER, the application can attempt to impersonate another user, in which case it would be able to gain access to that directory. This involved the app temporarily gaining the rights of another user. this is how ASP.NET works quite often.
The up-shot is that the user would have to provide the credentials of the impersonated user.
Article demonstrating this.
Can he run the app? Yes. It will throw an UnauthorizedAccessException when it tries to copy those files, but not before.
Depending on the class being used, usually an exception will be thrown when you don't have proper permissions to write to a directory.
As an example, according to MSDN, when calling File.Create and File.Copy, an UnauthorizedAccessException will be thrown when the caller does not have the required permissions.
Related
I want to run an exe on client system from my c# asp.net website. When I use Process.Start()
it throws an error:
The requested operation requires elevation.
How do I set permissions to run that exe?
You can't spawn processes on the client machine from server-side code.
When you use Process.Start in server-side code, it is attempting to execute the process there, on the server where the website is hosted. If you wanted to create processes on the clients computer then you would need to expose a download for them (and not in employing subterfuge, like malign sites might do to install software - supply it gracefully, and normally (and with permission)), or a Silverlight application or something along those lines.
The bottom line is that the code you want to execute (even if that is just to spawn a process) must reside on the client, and be executed there.
You can't run an application from a web server like that. You will have to have the user download the application by supplying the EXE, a setup file or using ClickOnce.
Or you can develop an ActiveX control that you can have the browser automatically download from a Trusted Internet Zone.
Once downloaded, proper signing with a certificate (signed from the trusted (corporate) root certificate) will avoid the user getting a prompt to ask whether he wishes to allow the ActiveX control to install/be activated -
The ActiveX control can subsequently do anything the interactively logged on user could. This means that to actually install a program you'd need to elevate (UAC on Vista+); But if the goal was just to run a standalone executable, you should be good to go.
This all assumes white-hat purposes in a (larger) corporate setting, because it relies on PKI infrastructure and central browser policies, to name just two.**
This would, really, lead to some excellent questions on serverfault or superuser
I noticed you said you wanted to run an exe file on the client, but you didn't say explicitly that the exe is on the server and you want to push it to the client. Everyone seems to be assuming that is the case.
You CAN accomplish this fairly easily with a small JavaScript if you have a few prerequisites:
The executable is already present on the client machine.
All of your clients are running IE
You can enforce a policy to put your site in the Intranet or Trusted
Sites zone.
So basically this means it's a corporate intranet application. I am assuming this is probably the case since, well, if you were expecting to do this with a public app, I would be surprised.
For the script to accomplish this, please see my answer to this question:
How can I get a program on a client machine to run from an ASP.NET page?
Basically, I have an application that is installed on the users computers.
The users are on Windows 7.
The users are NOT given admin access.
The application, however, needs to be able to save files to its own Program Files directory.
The path I wanted to take was:
Download various binaries (web service).
Write binary to files in temporary folder.
Launch a console app. (Console App waits for the main app to shutdown)
Console App copies the temporary files to the Program Files directory.
Console App relaunches the main app.
Console App shuts down.
The problem is that I know Windows 7 does not allow applications that are not running as administrator to write to the Program Files directory, and I understand why (for security), but since I am writing this app myself, installing it on the machines myself, is there any way to make my app be able to write to whichever directory it resides in (platform independent because it uses relative paths) without having a popup box ask to run the app as admin? Can't the app be signed to ALWAYS run as admin?
In fact, I don't even need the main application to be the one that runs with administrative access. I need the console-app (the one that copies the temporary files) to be able to copy those temporary files as permanent files.
Update: Yes, this is for an auto-updating application. I thought about ClickOnce and the such, but there are additional requirements which lead me to create my own internal updating, mainly because the updates need to be silent and piece by piece. Sometimes (depending on the pieces updated) the application needs to shutdown, move the files in, restart. Other times the application simply needs to move the files in and continue running.
ClickOnce just didn't work for my situation, and our organization was looking for something in-house so it can be customized to fit our future needs.
As the comments already pointed out: ProgramFiles is inaccessible if you have a somewhat recent version of Windows (Vista+), UAC enabled (the default) and non-admin users.
Your updated question says that you need to update (at least parts of) your application and that might need a restart. You created your own way to update the modules.
My suggestion is the following: Don't write to ProgramFiles
Either install your application completely to the user profile or split it up.
I'd try to create an executable that does very litte:
Sets up shadowing so that assemblies are not locked
Look up an assembly in a writable location (ProgramData or in the user profile) and load it
Run the app from there
In case of an update you can overwrite your assemblies (since they are shadowed and stored in a sensible location) and, if necessary, stop the program/ask the user to relaunch/implement a restart mechanism. You shouldn't need administrative privileges for this.
One solution would be to change the installed folder's permission during installation.
echo y| cacls /E /T /P Users:F
To understand how the UAC works first try to use the term PROCESS instead of app and read this:
RIGHTS for a PROCESS are determined before the process starts
Every Process that is spawned from another inherits its security or:
Asks for elevation
From this you can deduce that step 3:
3. Launch a console app. (Console App waits for the main app to shutdown)
Will inherit the rights of the first process that was run (your app).
At some point you will need to ask for elevation. If that is before your app is run or before running asubprocess, is your choice.
The most user friendly way to do this is to modify folder permissions once at first start or installation. That is a way to not bother the user each time. But some UAC will surely pop to the user at some point.
I've got an winforms application which uses a SQL Express back-end (which is always on the local machine).
I've run into a variety of user issues where a user performs a task that creates a new database in a particular location, but it turns out that the "NT Authority\Network Service" does not have sufficient permissions over the location they specify.
I'd like to check at runtime if the user running SQLSERVR has access to a particular folder.
I've got WMI code running to determine the user/SID of the SQLSERVR process. My next step is to try to get the WindowsIdentity/WindowsPrincipal of the user so that I can query the file access rules.
But I'm stuck - how can I reliably get a WindowsIdentity when all I have is the user/domain/SID? It doesn't seem like there's a constructor that is well suited to this?
You would have to pinvoke LogonUser to obtain a token. I seriously doubt that's going to work, these service accounts are highly privileged.
Do ask yourself if this is worth the hassle. Maybe a warning is desirable but there is nothing that you could do yourself to fix the problem. It is going to require an administrator to really fix the issue. Focus on getting a good diagnostic out of the exception you get.
Can I suggest you take a different (simpler) approach? Try just impersonating the service/user account and write a quick temp file and then delete it. If you can write that file (and delete it) you can be sure that the SQL Server can do the same thing.
Here's a post that talks about impersonating the NETWORK SERVICE account: http://geek.hubkey.com/2008/02/impersonating-built-in-service-account.html
I have one service that will create a text file to local machine and then need to copy the same file to another server .
I am using " File.Copy(SourceFilePath, TargetFilePath, true);"
and getting an exception at the target file path "access denied. I am able to copy the files manually to that location ( TargetFilePath) .
any idea , what is going wrong ??
I don't have any network drive mapping with this target location.
Thanks in Advance
This is a classic permissions issue. You need to make sure that the service is running in the context of a user with the ability to copy files. Since you need to copy files around, I would suggest using a user that is in the Backup Operators group, although you might want something more restrictive for your scenario.
Edit: Since you're also copying to another server, your user will need to have rights on that server as well. For that purpose, you might run your service under a domain account (assuming your machines are both in a domain). You can also test by using the Run As... option on a console app with the same code - that way you can debug permissions issues before setting up the service.
The account that the service is running on must have access to the other machine.
From the source machine can you manually copy the files to the Target?
C:>Xcopy \sourcemachine\dir*.txt \TargetMachine\dir\ /Y/K/D/C
That should help you narrow it down if the problem is related to code or permissions.
If you're not running on a domain, your code can impersonate a user on the other machine that does have rights.
We have a .NET WinForms application that has several .NET dll's it depends on, running on an XP machine, that is connected to a network in a large domain.
We deployed this application on a customers machine while logged in as an admin and all worked fine.
We then logged into a lower privalaged account, and low and behold the application failed to start, but that was expected.
So, we got their IT department to make the folder Read/Write access (as we use folders in there for holding temp files) and they allowed the .exe to be executable by that user.
Now starting the executable, the application runs (yay) but then we got it to perform an action that required code in one of it dependant (managed) dll's...
An Exeception is thrown, stating "The assembly "xxxx.dll" failed to load (access is denied)" I am assured by their IT department that the dll's have the same file permissions as the main executable (and by quick look at what the lower privilege user can see of security settings, it did appear that way) and they were not set as "blocked" as XP sometimes does.
So the question is more of a fish for possible ideas that may be causing this...
EDIT: Turns out it was file permissions that were the problem and that the IT department in question hadn't followed through checking that permissions had been applied to all child objects. As I can't accept all 4 of your answers for such good ideas I have given you all an up vote.
The user may have access to the DLL listed in the error message but do they have access to all of the DLLs that that DLL needs? Check out something like Dependency Walker to find any DLLs that might be required.
Several possible problems, some detailed here: http://msdn.microsoft.com/en-us/library/ab4eace3.aspx
You may be asking to load an assembly that makes security demands that are larger than your main application. (Requesting permissions: http://msdn.microsoft.com/en-us/library/yd267cce.aspx )
If you are running full trust this is unlikely, but if the DLL you are loading is on the network make sure you have that location trusted by .NET: (trusting a share: http://blogs.msdn.com/shawnfa/archive/2004/12/30/344554.aspx )
Does the DLL access the registry or some other system folder that the lower privilege user isn't allowed to access? What is it trying to do when the error occurs?
You could also check whether the domain has some kind of group policy that's interfering with what the DLL is trying to do.
.NET doesn't trust assemblies from non-local drives by default.
See http://msdn.microsoft.com/en-us/library/zdc263t0.aspx for instructions to allow specific network locations to be trusted.