Upload a new file to a file share using FileWebRequest - c#

I'm trying to use C#'s FileWebRequest to create a new directory on a file share and upload a new file to that directory. Does anyone know if this is possible?
I can successfully upload a new file if it sits directly in the file share, but when I try to upload it inside a new directory, I get an exception.
For example, uploading newfile.txt to this location works fine:
\\servername\sharename\newfile.txt
But if I try to upload it to this location: \\servername\sharename\newfolder\newfile.txt'.
...then I get an exception: Could not find a part of the path \\servername\sharename\newfolder\newfile.txt'.
Background:
I have a web service that needs to generate a file and copy it to a file share. For security reasons, the web service impersonates the specific users who initiate the generation requests, and it needs to copy the file to the share using these (delegated) impersonated identities.
Apparently delegating the impersonated user identity from the web service to the file system doesn't work as-is, so instead, I'm attempting to use the FileWebRequest to upload the file using the URI of the share, so I can use the AuthenticationManager.CustomTargetNameDictionary to register the SPN of the file server so delegation can be achieved.
EDIT: I'm currently using the FileWebRequest to upload the file thus:
var uploadRequest = (FileWebRequest)WebRequest.Create(#"file://servername/sharename/newfolder/newfile.txt");
//...snip
using (var outputStream = uploadRequest.GetRequestStream())
{
outputStream.Write(buffer, 0, buffer.Length);
}

Related

Read Files from Remote Drive in Intranet App

I want to read file names of pdfs from a folder on a network share that match certain parameters and provide a link to view them on a details page for my model. All I need to get is the file name. I don't need any file management/read/write at this time.
I'm able to display a .pdf in the browser if I have the path (IE will open "file://" links). The part I'm missing is getting file names from the remote (but same domain) directory at run-time.
We've set up a virtual directory for the app to use and that has worked fine in the past if the resolved physical folder is on the same server, but that is not the case here.
I've tried Impersonation, but that doesn't seem to work as I'm still getting an access is denied error.
I realize this would probably be a security issue and is why it isn't allowed, but is there an IIS configuration or other avenue that needs to be set-up to allow this? I can't seem to find a way with just code that opens the directory for reading.
Example code of how I might normally read some info from one file in a virtual directory:
// This example code is inside a controller action, so Server refers to HttpContextBase
var path = Server.MapPath("~/MyVirtualDirectory/" + fileName);
var fileExists = System.IO.File.Exists(path);
var fileLastModified = System.IO.File.LastWriteTime(path);
To enumerate over matching files in a directory, I've used DirectoryInfo
var pdfFileNames = new List<string>();
var dir = new DirectoryInfo(Server.MapPath("~/VirtualDirectory/"));
var pdfs = dir.EnumerateFiles("*.pdf");
foreach (var pdf in pdfs)
{
pdfFileNames.Add(pdf.Name);
}
As I mentioned, these methods work fine when the physical folder is on the same server, but once the directory is on a remote drive, then it no longer works. I have permissions to open the desired directory and my collegue said he gave the appropriate permissions to the virtual directory and server. Not sure what else to try at this point.
Edit: Now that it is working, I display the files using the Virtual Directory
http://server/appName/virtualDirectory/pdfFileName
By default, IIS application pools run under a specific local Windows identity named IIS APPPOOL\[NameOfYourAppPool]. This is a local user and it will not be possible to grant permissions to this identity to access resources located on a different machine.
If both servers are inside the same domain, you can try the following solutions:
Run the IIS application under a domain user and grant the required permissions to this domain user.
Run the IIS application under the NetworkService identity and grant permissions to the DOMAIN\MACHINENAME$ account of the IIS server.

Access Denied in .NET writing file to file share

I have a web service that is trying to write a file to a file share.
The application pool for the site in iis is running as a custom domain account: "domain\domainaccount"
I'm operating under the assumption and hope that when the code tries to write the file it will use the "domain\domainaccount" user to do so.
Executing the following line of code produces the error: Access to the path [filename] is denied
FileStream stream = File.Create(fileName, result.Length);
I have confirmed that the "domain\domainaccount" account has access to [filename] which is the full path of the file including the file name. I have even given the account access from the very top of the share structure, not just the specific folder the file needs to be written to. In fact, if I run notepad as "domain\domainaccount" I can save a file to that exact location.
What might I be doing incorrectly? Is it not using the domain account to write the file? If not, can I change something so that it does?
I should note that if I log into the iis server and run the web service from there, I do not get the access denied message and the file is created.

How to deny access to directory contents (IIS served site) via browser

I have some files kept in SiteFolder/ which I need to access through the C# project but I do not want them to be listed via browser at those path. How can I accomplish this? Is there any setting in IIS that could be changed?
Also, as I gave full control to IIS user to access/read/write this directory files, what is the solution then?
Basically I do not want anyone to access this directory's content via browser but should be accessible by IIS.
Thanks in advance.
Edit 1: This is the file write functionality which should remain unaffected -
FileStream file = new FileStream(Server.MapPath("~/SiteFolder/example.txt"), FileMode.Append, FileAccess.Write, FileShare.Write);
using (StreamWriter fileWriter = new StreamWriter(file))
{
fileWriter.WriteLine("Something");
}
Additionally, as this code is running on Amazon EC2, I had to provide full control of the folder and file to these users -
IUSR
MyProjectName
I am going to assume that you're impersonating the caller when trying to write to the file in question. Otherwise, if you were running as the system account, it doesn't seem like write permission should be affected.
Therefore, what I suggest in addition to the configuration mentioned above (https://serverfault.com/questions/37762/block-access-to-subdirectory-using-web-config) is to run the code block that writes the file as the system account by temporarily undoing impersonation like this:
using (System.Security.Principal.WindowsImpersonationContext wic =
System.Security.Principal.WindowsIdentity.Impersonate(IntPtr.Zero))
{
FileStream file = new FileStream(Server.MapPath("~/SiteFolder/example.txt"), FileMode.Append, FileAccess.Write, FileShare.Write);
using (StreamWriter fileWriter = new StreamWriter(file))
{
fileWriter.WriteLine("Something");
}
}
If your utilizing a default Internet Information System, the default folder wwwroot is locked directly to the designated user through your Application Pool. Which in most instances, will be a Network Service Account.
Your specific application will have a degree of permission, but your web-application by default shouldn't have access to the other contents of wwwroot.
The directory would be:
inetpub - wwwroot - Example
inetpub - wwwroot - Demo
So Example and Demo are both two separate web-sites that are hosted. So if you attempt to navigate to another directory, from one application, it should protect you automatically.
However, if you need to block a web-site from particular users or an application it is indeed possible. In the current state, the question is too broad.
Request Filtering
URL Rewrite
Those are two approaches, however if your utilizing Virtual Directories you should take a look at the following here.
Without a Virtual Directory, my above protection stands true:
A site is a container for applications and virtual directories, and
you can access it through one or more unique bindings.
The binding includes two attributes important for communication: the
binding protocol and the binding information. The binding protocol
defines the protocol over which communication between the server and
client occurs. The binding information defines the information that is
used to access the site. For example, the binding protocol of a Web
site can be either HTTP or HTTPS, and the binding information is the
combination of IP address, port, and optional host header.

Permission error when uploading files

I have the following code:
var saveFolder = Path.Combine(Properties.Settings.Default.DropBoxFolder, guid.ToString("N"));
// Create folder, if it does not exist (for the first attachment, it shouldn't exist)
if (!Directory.Exists(saveFolder))
{
Directory.CreateDirectory(saveFolder);
}
var saveFilePath = Path.Combine(saveFolder, file.FileName);
file.SaveAs(saveFilePath);
I'm using GUIDs to generate folders for uploads on my IIS server. The .NET web application is configured to impersonate the user. I granted modify permissions to the target folder (it is a local path on the web server) for Domain Users, Local Service and Everyone, but some users still can't upload files. I can and other people on my team can.
The weird part is that the exception says this:
Could not find a part of the path 'C:\Users\USERID\Desktop\FILENAME'
That path is the path to the file the user selected to upload (their local file path). I feel it is safe to say that the user has permission to his own file on his own desktop. I don't use user impersonation much, so I am wondering what I missed in my configuration or permissions. Any suggestions for debugging this issue? Thanks!
Note: the CreateDirectory method works just fine, even when the exception is thrown. I would have thought that if the user didn't have permission the directory creation would have failed first.

Issue while reading a xml file in WCF service

WCF service has one method ( Let's say TestMethod) in which I try to create a File Stream like this :
System.IO.FileStream fs = new System.IO.FileStream(#"D:\Test.xml", System.IO.FileMode.Open);
My Client and Service is on the same solution.
When the Client makes a call to TestMethod ( Exposed in Web service ) it will give this error:
Access to the path 'D:\DXDirectoryAuth.xml' is denied.
Please Help!!
Okay, if you have put the file in the directory or a sub-directory of your WCF service you should be able to access the file without any permissions issues.
The question is how are you attempting to access the file?
You should probably get the current directory of the service then append the relative file location onto the current directory and then attempt to open the file something like this:
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
bodyFile = Path.Combine(appPath, #"templates\email.txt");
var body = File.OpenText(bodyFile).ReadToEnd();
HTH
Ollie
Have you tried:
System.IO.FileStream fs = new System.IO.FileStream(#"D:\Test.xml", System.IO.FileMode.Open, System.IO.FileAccess.Read);
The default constructor of FileStream() asks for read and write access.
Security!
The reason being you are trying to access a file location outside of the directory where you have hosted your WCF service...
You are either going to have to grant the account the WCF runs under permissions to that directory or move the file into the directory\sub-directory where you are hosting the WCF service.
Ollie

Categories

Resources