I am writing a native module in C++ for IIS7/8 whose purpose is to reject file uploads coming into IIS with specific extensions.
I have gotten the Module working using OnReadEntity and can see the request body on the post request uploading the files.
However, being pretty inexperienced with c++ I have no idea how I am suppose to reliably parse out the Content-Disposition Fields from the request body so that I can get all of the file names.
Below is an example request:
------WebKitFormBoundaryUomVPwKHGvBwvDhP
Content-Disposition: form-data; name="attach1"; filename="YSMIsapiFilter.sln"
Content-Type: text/plain
SomeDataHere
------WebKitFormBoundaryUomVPwKHGvBwvDhP
Content-Disposition: form-data; name="attach2"; filename="ysmISAPIFilter.log"
Content-Type: application/octet-stream
I AM A LOG
------WebKitFormBoundaryUomVPwKHGvBwvDhP
Content-Disposition: form-data; name="enter_a_number"
------WebKitFormBoundaryUomVPwKHGvBwvDhP--
ol: max-age=0
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cookie: ASPSESSIONIDSSSRCTRS=GHMFFGABJAAOAEHFCFIOOJIO
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
Upgrade-Insecure-Requests: 1
Does anyone know if there is something in the httpserv.h API to do this for me already. Or if there is a free non-commercial mime type parser to do this that builds in Visual Studio 2015.
Or would I need to parse it myself.
From what I can gather, Content-Disposition and content-type should always be the 2nd and 3rd lines after a line that starts with ------, The webkitformBoundary differs pending the client making the post (IE, Chrome, FireFox, etc etc). Then I would just need to skip to the next ------ if there is one.
Content-Disposition via the RFC spec states it will always be form-data; followed by the name of the form field "attach1", and then any data that goes with that input "filename" in the case of an input of type "file".
Just looking for points in the right direction on this one.
I already tried using Mimetic, but I couldn't get it to build when I add it's header to my project. The Win32 project it comes with builds, but it won't build in mine.
I was able to solve this problem by mixing the CLR with C++ and making my Native Http module a mixed mode DLL. So it is a native DLL that uses the .Net CLR.
Then using module preConditions I set the module to only run if the .Net CLR is loaded and bitness is 32.
With .Net Enabled I was able to add a reference to System.Net.Http.Formatting, which has a built in MimeType Parser library.
Using that I was able to easily parse the Mime type coming in on Post Requests in Begin Request in my Native Http Module, giving me access to the fileName fields on file uploads, which I then used to reject the request if the filename's are blocked extensions and throw a custom 500 internal server error.
One caveat I found is that sometimes the Entity Body request did not end with a new line character and that breaks the .Net Mime Parsing library, causing an error. So I check the buffer after I read the Request Entity Body to determine if the last character is a new line character, if not I add one to the buffer by appending it to my .Net Memory Stream after populating it with the raw buffer for use in the .Net Mime Type Parser.