How to write the response to a file in HTTP Handler - c#

I have HTTP Handler where I want to log the response. I know there is option context.Request.SaveAs(filename... But I never tried this before. How can I use this, I mean someone can be more specific about file name?

Well, the documentation is pretty straight forward about this:
The [SaveAs] call specifies that the request be saved as a text file
in a directory where the ASP.NET process identity has been granted
write permissions, and that any header information included in the
request is included in the file.
You can thus simply save the entire HttpRequest (including the headers in a file). You can simply determine the path and a boolean indicating whether you want to incude the headers as well:
context.Request.SaveAs(#"c://myLogFile.log",true)

Related

Why bother inspecting an uploaded file's content-type if the sender can lie about what it is?

I'm writing an API that is hidden behind Azure's API Management tool. It can't be accessed unless APIM verifies the requester's access token as well as Azure subscription. In the API, we want to verify with the requester that we will only accept zip files.
if (request.PayloadFile.ContentType != "application/zip")
{
throw new BadRequestException("Unable to accept payload content type");
}
This is not a process attempting to mitigate a bad actor. The purpose is to simply verify that the developer is sending the expected data type. With that said, I made a small client that sends a non-zip format file and I simply set the content-type header in the request:
var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
fileContent.Headers.Remove("Content-Type");
fileContent.Headers.Add("Content-Type", "application/zip");
fileAsFormData.Add(fileContent, "payLoad", fileName: Path.GetFileName(filePath));
The API happily accepts this. So my question is twofold:
Why would we even bother checking ContentType if it can be spoofed?
Is there a way to get the true file type of the payload?
Content-Type is a way for a client to indicate for the server what content you wish to send. Of course you might maliciously "lie" about it, but it would be against your own interest as a client. Servers might implement appropriate logics to parse file content, depending on the Content-Type header.
There are several things to consider:
A server is expected to work properly, only if the client sends valid data: i.e.: clients that want the server behave properly should not lie about the real Content-Type of uploaded files.
It is easier for servers to check a Content-Type header, compared to specifying file types using other methods.
Servers should also validate data and mitigate risks in case of possible misuse of an API. For example, in your case, you should add try-catch around unzipping content, and respond with error if unzipping was not successful.
For your other question, whether real Content-Types can be checked, the answer is generally: no. There are some file types, where the file itself contains some kind of "magic string" that can be used as a signiture for that Content-Type.
You can check some of these common file signitures: https://en.wikipedia.org/wiki/List_of_file_signatures
Please note that, a malicious user might be able to modify file signatures as well. There can be additional security measures to defend against spoofing file contents, e.g.: checksums, but there is no 100% security, unless some private secret is shared among servers and trusted clients, which can be used to securely sign contents.
The real question here is: why would anyone maliciously spoof Content-Types? Or file contents? And what level of security measure is needed to avoid associated risks?

How can I save an HttpRequestMessage to file?

I am using OWIN to self host an API within a WPF application. This is for a tool for a tester who doesn't want to have to enable IIS7.
Inside my Post action I want to be able to save the HTTP Request (ApiController.Request) to a file like I can with
System.Web.HttpRequest using SaveAs.
However OWIN doesn't provide HttpContext.Current(nor HttpContext.Current.Request), it's null, and I can't find any other way to get at a System.Web.HttpRequest.
Is there a way I can save a System.Net.Http.HttpRequestMessage to a file, or just read it as text from a Stream?
You can simply serialize any HttpRequestMessage and then store it wherever you want, e.g. in a text file. Later, you can read the file and deserialize its contents back into an HttpRequestMessage instance.

Getting a raw socket from an IIS request

I'm trying to get the raw data sent to IIS using a HttpHandler. However, because the request is an "GET"-request without the "Content-Length" header set it reports that there is no data to read (TotalBytes), and the inputstream is empty. Is there any way I can plug into the IIS-pipeline (maybe even before the request is parsed) and just kind of take control over the request and read it's raw data? I don't care if I need to parse headers and stuff like that myself, I just want to get my hands on the actual request and tell IIS to ignore this one. Is that at all possible? Cause right now it looks like I need to do the alternative, which is developing a custom standalone server, and I really don't want to do that.
Most web servers will ignore (and rarely give you access to) the body of a GET request, because the HTTP semantics imply that it is to be ignored anyway. You should consider another method (for example POST or PUT).
See this question and the link in this answer:
HTTP GET with request body

Get redirected url from code

I'm using an API which, given a url, redirects to a file on the server. The file names have "_s,_m and _l" appended to the end (small, medium, large). However, since the url's querystring is parsed dynamically, I don't retrieve the actual file name. The image displays correctly, but is it possible to retrieve the filename of the image file from the code? (i.e. where the url has redirected to)?
e.g. http://api.somesite.com/getimage?small (this is what I enter)
"http://somesite.com/images/userimage_s.png" (this is where it redirects to. I would like to get this address from code)
Thanks for any advice
Sounds to me like you are trying to access some images you shouldn't access programmatically ;-)
You could access the given URL with an HTTP client (opening the stream with a stream reader might already suffice) and watch out for a Location header, which will most likely contain the URL you are searching for.

Static files and authentication in ASP.net

Say I have a virtual folder /topFolder/ in IIS7, and in that folder there can be any file that can be displayed in a browser (xml, html, swf, doc etc - typically "unmanaged" resources from the IIS perspective).
Before giving the request permission to open any file below the folder, I need to check some session variables in order to see if the user has a "license" for the subfolder and file in question.
I've tried implementing a module with IHttpModule and IReadOnlySessionState interfaces, but the Session is always null on the AcquireRequestState event when the file is "static" and not IIS managed (like aspx, ashx etc).
If I use a custom HttpHandler, I get the session, but then I also need to implement how the content is sent to response. Edit: Since the user isn't downloading the file, I just want IIS to serve the file like it does with its StaticFileModule. The Handler/Module should really be a StaticFileModuleWithAuthorizationHook...
So I really want to do the following:
1. For request /topFolder/* : check session and licenses etc
a) If ok, continue serving file
b) If not ok, interrupt request, or just send FORBIDDEN in response.
Hope someone can help.
You should be able to handle this via the httphandler, the simple way is to use the built in methods to send the file down to the user if they have access.
This article (at the bottom) shows an example of how to do this.

Categories