I deployed my internal web application to server A and got an error when creating a file to a network drive on server B. If I run locally, the file got created on server B successfully.
System.UnauthorizedAccessException: Access to the path '\\b\folder\test.pdf' is denied.
The identity of the application pool is networkservice. And I gave networkservice full control on the destination folder on server B. I even gave Everyone full control, but it still got the error.
Server A runs .NET 7.5. Code to create file:
var byteArray = generateArray();
var destination = "\\\\b\\folder\\test.pdf";
try {
var destinationFile = new FileInfo(destination);
if (destinationFile.Exists) {
destinationFile.Delete();
}
System.IO.File.WriteAllBytes(destination, byteArray);
} catch (UnauthorizedAccessException) {
//
}
I've seen someone got the exact same problem here. But it didn't solve mine.
Solution:
I changed the identity to administrator account instead of using network service for the application pool. It works but I don't fully understand why it works. Because the network service on A is different than the one on B?
Even though you provided access to everyone, certain applications have to receive specific permission. This was apart of the UAC System introduced in Window's Vista. This move was to increase security, so an application couldn't run under any user and basically have full access.
What you should do, is on the directory provide the following access:
IIS AppPool\NameOfAppPool
That will provide specific access to your hosted web application to that directory, for IIS will be able to correctly manipulate the directory. Some code you could implement to help validate before you write or read, would be:
public static bool ValidateIOPermission(string path)
{
try
{
if(Directory.Exist(path))
return true;
else { Directory.CreateDirectory(path); }
}
catch(Exception ex) { return false; }
}
The above code is a small sample, basically try to perform the action and catch the exception, that way you know if you have access or not.
Related
is there a way in C# to see what credentials are used to access a file in a network share?
I'm trying to debug a scenario where most of CIS Windows L1 hardening settings are applied to a system. This system only has local users and one of them (a member of local Administrators group) is used to run a C# app (.NET Framework 4.7.2) that accesses a network share, say \\myserver\some\path\foo.xml. Without hardening, it all works fine, even though when I have a look at who can access the network share, the local user is not listed.
With hardening applied, it does not work. More concretely: in File Explorer, when trying to access the foo.xml, a CredUI prompt for credentials appears. I have to submit my own credentials (AD user) to get access.
What the app does is essentially
string[] possiblePaths = ... // load possible network paths of desired file
foreach (string possiblePath in possiblePaths)
{
if (File.Exists(possiblePath))
{
return possiblePath;
}
}
I figured out how to deal with the SeTcbPrivilege policy violation (that gave me errors in the Event Log), but after that, I am lost.
To debug, I have created a test app:
string path = #"\\myserver\some\path\foo.xml";
if (File.Exists(path))
{
Console.WriteLine($"Path {path} exists!");
}
else
{
Console.WriteLine($"Path {path} does not exist!");
}
try
{
var fh = File.Open(path, FileMode.Open);
fh.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.WriteLine(ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine(ex.InnerException.Message);
}
}
When I restart the system and try to run the app without providing my credentials to File Explorer, it says "The path does not exist" and IOException that the network path does not exist. However, when I submit my own credentials (not the local user, but mine, as an AD user) in File Explorer to access that location, the output of the test app says "The path exists" and UnauthorizedAccessException: Access to the path ... is denied. Which is weird, as I don't run the app as me, but as the local user.
I know I can use trial-error (and probably will) to identify the policy messing it up, but I would like to constrain it as much as possible - and also to understand why exactly it is causing trouble (maybe there used to be some anonymous/guest access on the share that is not permitted now on the system?).
To that extent, I would very welcome any nudge as how to see what credentials a C# app is using to authenticate elsewhere, how to get more debug info, or how the File.Exists()/File.Open() work under the hood.
Thanks!
I have an interactive windows service which run on a Local System account and with Interact with desktop checkbox checked(this is mandatory for my project as my service needs to invoke .exe with UI ). I am getting an exception as Access denied while writing to network drive. I am passing the UNC path from config file. i tried giving full control access to anonymous user on the folder which i want to access but its still not working. i cannot run my windows service under Network service account or under any other account as suggested in some other posts because i want it interact with desktop check box checked. is there any way to achieve this?
Edit: UNC path of network drive: //server/ABC/pqr
my service should create .txt file in pqr folder. should have access to delete it afterwords too.
i have tried creating anonymous user for pqr folder and giving it full control but still i am getting access denied exception. as i mentioned before i cannot run it under any other account other than local system account because it will automatically disable interact with desktop option in the properties of that service. is there any way to make it run under Network Service Account and still keep it interactive(interact with desktop option checked in the properties of service)?
Try using the following nugget package named SimpleImpersonation
This way you could wrap the code you use to access your remote file location like this:
using (Impersonation.LogonUser(domain, username, password, logonType))
{
// do whatever you want as this user.
}
It worked for me. I used it to turn on and turn off a windows service remotely. Like this:
await Task.Factory.StartNew(() =>
{
using (
Impersonation.LogonUser(serviceInfo.Domain, serviceInfo.User, serviceInfo.Pswd,
Environment.MachineName.Equals(serviceInfo.ComputerName,
StringComparison.InvariantCultureIgnoreCase)
? LogonType.Network
: LogonType.Interactive))
{
var service = new ServiceController(serviceInfo.ServiceName, serviceInfo.ComputerName);
if (service.Status == ServiceControllerStatus.Stopped)
{
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(60));
}
else
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60));
}
}
});
(the snippet was taken from the project site)
I'm calling the following code from Windows service that was written with C#:
try
{
ServerManager m = new ServerManager();
if(m != null)
{
SiteCollection sites = m.Sites; //I get exception here
}
}
catch (Exception ex)
{
}
I get this exception:
{"Filename: redirection.config\r\nError: Cannot read configuration
file\r\n\r\n":null}
What does that mean? And is there any way to predict it in ServerManager or my m variable before it's thrown?
Update: After looking at your comment now I can answer the question fully, the problem is your application is referencing the wrong Microsoft.Web.Administration.dll, seeing the error tells me you are referencing the IIS Express version and not the "full" IIS Version (7.0.0.0). So please modify your application code to add a reference to the one that is in c:\windows\system32\inetsrv\Microsoft.Web.Administration.dll instead.
This is a permissions problem.
You will need to make sure to run the Windows Service as an identity that is either a member of the Administrators group or SYSTEM. My guess is you might be running the service as Local Serivce or Network Service and those do not have permission to read the configuration files that sit in %windows%\system32\inetsrv\config.
Other Info:
Redirection.config is a file that IIS uses to determine if it should read its configuration from the normal path (%windir%\system32\inetsrv\config\applicationHost.config) or should read it from say an external UNC file share when centralized configuration is used for many servers. That is why this is one of the first files to be parsed and hence you get that access denied error for that specific file.
Regarding the predicting, the best thing to do would be to create it within a try/catch and handle that. There are many exceptions that could happen when reading configuration, such as permissions (you could predict this one by making sure you can read (say File.OpenText()) to Redirection.config, ApplicationHost.config in %windir%\system32\inetsrv\config but that is guessing and there are others such as access to encryption keys for passwords, invalid config, etc, etc.)
I am new to Silverlight and I am trying to do a directory listing of the contents of a directory. However when the first list of this code runs, it throws an exception:
The application itself runs inside of a Browser.
File operation not permitted. Access
to path 'C:\Program Files\AppName' is
denied.
I checked permissions and they are readable so I'm not sure why it's not working.
DirectoryInfo di = new DirectoryInfo(#"C:\Program Files\AppName");
try
{
if (di.Exists)
{
Console.WriteLine("That path exists already.");
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
finally { }
Silverlight doesn't let you just access any old directory you want. Silverlight 4 added the ability to access certain well-known paths under the user profile but only in out-of-browser elevated trust applications.
Silverlight is probably not the technology you want to use for this purpose. Look into WPF instead.
If you want to save/load files in silverlight and your app owns the files, you can use isolated storage.
silverlight isolated storage example
Generally, this is useful to store cross-session data locally, or store user settings. Like Josh's answer says, there is no solution to your problem if you need to access other app's files.
public class UploadHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
...
// Create the directory if needed...
if (!Directory.Exists(uploadDir))
{
System.Security.AccessControl.DirectorySecurity ds = new System.Security.AccessControl.DirectorySecurity(RivWorks.AppSettings.UploadRoot, System.Security.AccessControl.AccessControlSections.All);
Directory.CreateDirectory(uploadDir, ds);
}
...
}
I have the above snippet of code for a ASHX file and it works fine in my local environment. As soon as I push it to a server environment I don't get an error, it appears to have built the directory, yet when I check for it - well - it is not there. When I run it via a FLEX app we are getting this error:
Error #2038: File I/O Error. URL:
http://[ourdomain].com/UploadHandler.ashx?CompanyID=d229cc80-ca96-4a8a-992c-80c94ac2c6b4
Is there anything I am missing?
UPDATE:
I can create files anywhere on disk
I cannot create directories
anywhere on disk.
I get this error now when trying to create a directory:
The process does not possess the
'SeSecurityPrivilege' privilege which
is required for this operation.
Have you checked that your program has the correct access rights to the relevant directories on the server?
If you don't have the right permissions either because the account you are using is restricted or the directories are locked down you will see this error.
Is the site runs with identity impersonation=true? If so it runs under your credentials/authorization in your environment
Just simple use mkdir() function to create directory. to define a path you may use SERVERMAPPATH attribute.
use within try catch endtry block to avoid already existing or any other Error.