HOWTO: Allow file downloads (including .exe) on IIS 6.0, Part 2


Some users have reported that IIS6 still refuses to allow an EXE file to download even after removing “Scripts and Executables” Execute Permission and making sure that .EXE has a MIME Type. Alright… I will have to come up with some more non-obvious reasons as possible explanations, as I now detail…


Question:


I have read your blog on how to make exe downloadable in IIS 6.0. I have followed your instructions to the letter and I can get everything to download except the exe files. I have made sure that only scripts are allowed in the execute permissions, I have made sure that a mime exist for .exe application/octet-stream. When I rename the executable from lets say x.exe to x.bin I am able to download the file so I know IIS is finding the file, however it will not download it as an executable. If you know of anywhere else I should be checking I would greatly appreciate it. I know you must be inundated with request.


Thanking you ahead of time


Answer:


Hmm… you are suggesting an interesting mystery that looks like an issue with IIS6, but I am not yet convinced that we have ruled out user misconfiguration. We all know how clever users can be at shooting themselves in the foot. 😉


So, what you are saying is that:



  1. Only “Scripts” Execute permissions are enabled for the URL.
  2. MIME Type definitely exists for the .EXE extension.
  3. Yet .EXE resource is still not downloading.

Well, according to my previous discussion on how IIS decides to handle a given request, IIS is either executing the code on the server or it is sending it as download to the client. And since you say that it is not downloading to the client, I can only presume that IIS is still executing the EXE file on the server.


You can confirm this by looking up the IIS log file entry for the request, located at %SYSTEMROOT%\System32\LogFiles\W3SVC#\*.log . It probably has either “404 2 1260” or “404 0 2” as the Status, Sub-Status, and Win32 error codes.


Well, if the .EXE is still executing on the server and you only have “Scripts” Execute Permission, then you must have configured an application mapping for the .EXE extension to run some Script Engine, and either that Script Engine does not exist (resulting in “404 0 2”), or it is not allowed in the Web Service Extension (“404 2 1260”). I consider both to be more clever user misconfiguration.


Now, I do not know WHY you have .EXE configured as an application mapping. All you need to do is enable “Scripts and Executables” Execute Permission and the .EXE will execute on the server. In other words, the following two configurations are pretty much the same logically (though they are different in terms of ACL requirements and other NT permissions, but let’s ignore that for now, for the sake of conceptual clarity):



  1. Configure .EXE application mapping to be run by CMD.EXE and Execute Permission is “Script”.
  2. No application mapping for .EXE and Execute Permission is “Scripts and Executables”.

#1 is a misconfiguration that I have seen some users make, but I do not understand why. I would really like to hear some user comments as to why you are configuring #1 to logically accomplish #2.


If you truly want .EXE to be downloadable, then you should just configure Execute Permission to “None”. In that case, IIS never bothers trying to execute anything on the server – all requests should download. If that still does not work, then I can only presume that you have some custom ISAPI Filter running on the server performing arbitrary behavior, and I cannot give reasonable advice on arbitrary behavior…


//David

Comments (26)

  1. Gabor says:

    I can confirm that there is definitely something fishy going on with the octet-stream mime type. I was trying to make .cab files available (for mobile auto-installation) and while octet-stream didn’t work, (and application/x-msdownload didn’t work either) screwed up mime type such as application/msdownload did. Needless to say there’s no mime associated on the server side for CAB, and it never tried to execute on the server side. It actually happened when I tried to publish msi and exe files (where you could argue about the execute attempt).

  2. David Wang says:

    Gabor – Unfortunately, your observation is merely "something is wrong" while we really need to determine whether the issue lies on the client, server, or network to make any progress.

    Remember, the server cares nothing about the MIME Type – it is just a string sent as response headers. By default, .CAB has a MIME Type in the system Registry and in the IIS global MIME Type table, so that is why it is even downloadable.

    So, as far as server-correctness is concerned, IIS just needs to make sure the exact bits of the file was sent over the wire according to HTTP protocol. What the client does on the other end – that is not IIS’s concern.

    My recommendation is to use Network Monitor from Add/Remove Programs on Windows Server 2003 to diagnose this.

    If IIS6 sent the right bits, your problem is totally on the client side, and you need to look at the actual response headers of the Network Monitor capture for clues on how the client interprets the download.

    If IIS6 sent the wrong bits, then we can look further at IIS6 configuration.

    //David

  3. Gabor says:

    David, one question – do you agree IIS should or should not return my beloved cab file when on the given website, a mime type ".cab" is manually set to "application/octet-stream"? Without defining a mime for the file, I think we both agree that IIS returns a 404 since it’s not in its list of allowed extensions. So – should application/octet-stream work for this file type? Because it did not.

  4. David Wang says:

    Gabor – The issue of "it did not work" is tangential to your question. Let me explain.

    IIS6 will return the CAB file when you have a specific MIMEType for that extension. Just be aware that global MIMEType changes require restarting IIS to take effect while per-URL MIMEType changes take effect immediately.

    On a default IIS6 installation, CAB files should download with no additional configuration. This is because both the Registry and the global MIMEMap provide definitions for the MIMEType.

    I went and tested it out and it worked as expected. I just did ‘DIR > test.cab’, made a request for /test.cab, and I saw that it downloaded just fine with the correct Content-Type header. No idea where you are seeing 404 from.

    As to whether "application/octet-stream" works for this file type, that depends on the client. As I said earlier, the only thing IIS is responsible for is to send the bits of the resource faithfully, and also to decorate the response Header with the Content-Type header representing the MIMEType. What the client does with the information at that point, it is totally up to the client.

    I realize that from your perspective it is simply "not working" so you want a solution, but please realize from my perspective I am not seeing anything wrong from IIS6 at all.

    Maybe you are having problems with IE’s automatic content-sniffing algorithm and the resource extension.

    I can just say that without using Network Monitor to examine your problematic request / responses, we are simply going to go around in circles and not make progress.

    //David

  5. Jeff Parker says:

    You know David I have seen this behavior of the executing exe even though only scripts are allowed to run before. I can’t remember exactly where but there is another setting somewhere in the Front Page Server Extensions which can cause this as well I thought it was quite odd because it would trump the actual IIS settings. This could have also been on an older version of Server Extensions I seen but I distinctly remember it because it caused me so much grief. Sorry I can not remember where exactly this was because I chased this around for a long time and a couple years ago. Turning it off turning it on in IIS trying to figure out why the exe was still executing. I remember though it had to do with the FP Extensions though.

  6. David Wang says:

    Jeff – Thanks for the additional possibilities.

    The key thing to remember is that ISAPI Filters and Extensions CAN alter "normally expected" IIS behavior, and that is by-design. ISAPI need to be able to do this to extend server functionality.

    This is why I always say that if the behavior of the web server does not make logical sense according to IIS rules, then there is probably an ISAPI involved somewhere… at which point all bets are off since it can implement arbitrary behavior.

    //David

  7. Steve says:

    To make exe files being able to download from IIS 6. Open your IIS, on the Virtual Directory property sheet of the publishing directory, change the Execute Permissions to Scripts Only.

    That’s it. It works.

  8. David Wang says:

    Steve – Yup, on normal situations, that should be all that is necessary. Make sure that Execute Permissions does *not* include "Execute".

    However, I have seen situations where people mistakenly Scriptmap .EXE , so even changing to "Scripts" can be insufficient. I can only think of changing Execute Permission to "None" and making sure "Read" permission is enabled to ensure that all resources are read and served by the IIS Static File Handler.

    Of course, that is barring any custom modifications made by ISAPI Filters installed on the machine…

    Yeah, the idea is simple; the details… complicated. 🙂

    //David

  9. Prasad Sali says:

    I am not able to call .exe file using IIS6, using command promp it is execute successfully. but using asp code it is not executed and not alos give any error. I set the virtual directory executable properties from scripts only to Scripts and Executable, but then also it is not executed. What i will do? Plz help me.

  10. Tim says:

    I have found (on IIS 5 at least) that the IIS lockdown tool will prevent .exe files being downloaded.

  11. Indeed Tim is right:

    – IIS lockdown tool  prevents .exe files being downloaded.

    For example on my computer, the:

    %WinFolder%system32inetsrvurlscanurlscan.022106.log file says:

    -URLs must contain only ANSI characters.

    -URLs must not contain any dot except for the file extension.

    – Requests for following extensions will be rejected:

    ‘.exe’

    ‘.bat’

    ‘.cmd’

    ‘.com’

    ‘.htw’

    ‘.ida’

    ‘.idq’

    ‘.htr’

    ‘.idc’

    ‘.shtm’

    ‘.shtml’

    ‘.stm’

    ‘.printer’

    ‘.ini’

                   .log’

    ‘.pol’

    ‘.dat’

    Alexandru Matei

  12. S Walsh says:

    Thanks, your idea worked great.  Saved me a lot of time and trouble.   Kudos.

  13. joey says:

    i disabled ‘enable content expiration’ and it fixed my exe download problem.

  14. David.Wang says:

    joey – If you look in the IIS log file you will see that a 200 OK is recorded for that request. So, IIS actually served the file download successfully (and from my perspective, allowed the file download). What the client does with the download is arbitrary.

    In this case, this is due to a known behavior of IE. IE has various settings that cause it to not accept a download – for example, if you set:

    – Cache-Control: no-cache (like via Content-Expiration or dynamic code that generates)

    – Compression enabled with Cache-Control: no-cache

    – SSL download with IE’s "Don’t save encrypted pages to disk" checked

    In these cases, IIS actually sends the content over the wire as requested and the browser received the content, but the browser REFUSES to let the user get the content as a download.

    //David

  15. RA says:

    I have make step-by-step all the operations as described in your post. But my  IIS still does not carry out the .exe file.

    In my IIS log I have

    #Fields: date time s-sitename s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status

    2006-04-11 10:21:27 W3SVC1 127.0.0.1 GET /barid/algocgi/style1.css – 80 – 127.0.0.1 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 200 0 0

    2006-04-11 10:21:27 W3SVC1 127.0.0.1 GET /test/test/test.exe – 80 – 127.0.0.1 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 200 0 0

    2006-04-11 10:21:27 W3SVC1 127.0.0.1 GET /test/test/test/01.gif – 80 – 127.0.0.1 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 200 0 0

    2006-04-11 10:21:27 W3SVC1 127.0.0.1 GET /test/test/test/BD11.gif – 80 – 127.0.0.1 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 200 0 0

    2006-04-11 10:21:27 W3SVC1 127.0.0.1 GET /test/test/test/BF11.gif – 80 – 127.0.0.1 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 200 0 0

    and afer a few minutes i have this log in IIS log file.

    #Fields: date time s-sitename s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status

    2006-04-13 10:02:54 W3SVC1 127.0.0.1 GET /test/test/test.exe – 80 – 127.0.0.1 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 502 1 233

    2006-04-13 10:07:34 W3SVC1 127.0.0.1 OPTIONS /test/test/test.exe – 80 – 127.0.0.1 – 502 1 233

    and in my broswer i have this error message

    CGI Timeout

    The specified CGI application exceeded the allowed time for processing. The server has deleted the process.

    Im sorry for my orthography, but im verry bad in anglish.

    Thanks.

  16. David.Wang says:

    RA – The 502 indicates that something changed your IIS configuration between 4/11 and 4/13 such that for /test/test vdir to now try to execute test.exe on the server (instead of serving it for a download).

    And since the test.exe is not meant to be executed as a CGI, it probably does not generate the necessary output to be considered proper CGI and IIS will return 502 for that.

    I suspect that Execute Permissions changed to "Scripts and Executables" somewhere on the server, either at / , /test , or /test/test.

    You need to read my previous discussion mentioned in the blog entry for what is going on with your configuration.

    //David

  17. RA says:

    Hi,

    My Executions permissions are in "Scripts and Executables"  for the racine folder and subfolders and files.

    When i execute test.exe in command line i have this execution

    Content-Type: text/html

    <html>

    <head>

    <meta name=’Generator’ content=’TEST’><link href=’style1.css’ rel=’STYLESHEET’ type=’text/css’><title>APPS : Identification ÇáÊÚÑíÝ</title>

    </head>

    <body topmargin=’0′ leftmargin=’0′ onLoad=’javascript:StrMessage();’>

    <form name=” method=’POST’ action=’test.exe’>

    <table border=’0′ width=’100%’ bgcolor=’navy’><tr><td>

    <p style=’font-size:8pt;color:white;font-weight:bold’>APPS &gt; </p>

    </td></tr></table><table border=’0′ cellspacing=’0′ cellpadding=’0′ background=’test/BM1.gif’><tr>

    <td><img border=’0′ src=’test/BD11.gif’></td>

    <td width=’100%’>Identification</td>

    <td><img border=’0′ src=’test/BF11.gif’></td>

    </tr></table><p></p>

    <input type=’hidden’ name=’PN’ value=’PageData’><input type=’hidden’ name=’EL’ value=’1′><table border=0 cellspacing=0>

    <tr><td nowrap valign=’top’ style=’font-size:x-small’ >Votre Nom :</td><td nowrap valign=’top’ style=’font-size:x-small’ ><input name=’UN’ value=” size=’20’ dir=’ltr’></td></tr>

    <tr><td nowrap valign=’top’ style=’font-size:x-small’ >Votre code d’accès :</td><td nowrap valign=’top’ style=’font-size:x-small’ ><input type=’password’ name=’PW’ value=” size=’20’ dir=’ltr’>&nbsp;<input type=’submit’ name=” value=’Valider’></td></tr>

    </table><p><p>

    <table width=’100%’ height=’5pt’ bordercolorlight=’white’ border=’1′ bordercolordark=’gray’ bgcolor=’silver’ cellspacing=’0′ cellpadding=’0′><tr><td bordercolorlight=’silver’ bordercolordark=’silver’></td></tr></table>

    <input type=’hidden’ name=’PN’ value=”><input type=’hidden’ name=’EL’ value=’1′><input type=’hidden’ name=’UN’ value=”><input type=’hidden’ name=’PW’ value=”><input type=’hidden’ name=’NM’ value=’0′><input type=’hidden’ name=’DT’ value=’0′><input type=’hidden’ name=’DN’ value=’0′><input type=’hidden’ name=’ND’ value=’0′><input type=’hidden’ name=’SPV’ value=’0′></form>

    <script>function StrMessage(){}</script></body>

    </html>

    For information this application is write with WebDEV and it is not me which A develop this application.

    When I set Executions permissions are in "Scripts Only" i can download the .exe file, but when i change permission on "Scripts and Executables" the application be not carried out.

  18. David.Wang says:

    RA –

    1. Do you want test.exe to be downloaded to the browser, or do you want test.exe executed on the server to generate a response that is sent to the browser.

    Assuming you want to execute test.exe on the server:

    2. Do you have SP1 installed on the machine.

    3. IS test.exe sending CRLF (0x0D0A) after the response header "Content-Type: text/html"

    4. If you rename test.exe to nph-test.exe and then make a request to nph-test.exe, what happens?

    //David

  19. RA says:

    Hi,

    01 – Ii want to execute test.exe on the server to generate a reponse that is sent to the browser..

    02 – yes i have SP1 for 2003 Server and all patch

    03 – When a remane test.exe to nph-test.exe I have a same problem.

  20. David.Wang says:

    RA – What is the answer to my question #3.

    nph-test.exe should work because no parsing happens by IIS — what your CGI sends to stdout is what gets back to the browser — so a 502 suggests your CGI fundamentally fails to work on the web server:

    – Is your test.exe writing output to stdout and how is it doing it.

    – Is your test.exe relying on something like PHP or Perl which is known to work on commandline but returns 502 when run from web server due to PHP misconfiguration.

    Since I have seen CGIs which behave one way when run on commandline but another way when run from web server, I do not trust your commandline execution test at all. The nph- test is more accurate, and if it still returns 502, it usually means your CGI is broken.

    //David

  21. RA says:

    I have make oder tests

    I added a one application extention mapping for test.exe in my IIS server and i allow all verbs, in this case my application turn correctely and when i run nph-test.exe in my browser a have Content-Type: text/html in top of my page and and right after the authentification part.

    But if I puts my username and password the application blocks again.

    In IIS 5.0 that functions correctly I dont have any problem.

  22. David.Wang says:

    RA – Then, it sounds like your problem is not with execution of test.exe but some other custom configuration on your server.

    Though your steps seems unnecessary (you do not need an application mapping to execute a CGI), you managed to show that test.exe runs on IIS6, which pretty much proves that the problem is not with IIS6 execution of test.exe.

    I have no idea what you mean by "right after the authentication part." nph CGI does not behave like that.

    I can only suggest you figure out what is configured differently between IIS5 and IIS6 and fix your server configuration. You either have custom ISAPI Filter running on IIS6 that is failing, or maybe some proxy or network device that is goofing up. Based on your descriptions, I see no problems with IIS6 at this point.

    //David

  23. Nausher says:

    Possibly your .exe’s can get blocked by URLScan

    Then your log would contain <Rejected-By-UrlScan>

    E.g.

    2006-04-26 01:32:39 10.254.48.61 – 10.108.117.202 80 GET /<Rejected-By-UrlScan> ~/dir/application.exe 404

    In such a case have URLScan.ini configured to allow *.exe or whatever it is by following this article.

    http://support.microsoft.com/kb/326444/

    URLScan.ini location – %WINDIR%System32InetsrvURLscan

    Log files location –

  24. Ngon Do says:

    I was having similar issue and needed to adjust the URLscan.ini as Nausher suggested.

  25. IIS WORKER GEEKS says:

    1) Change the Website or application Virtual Directory permission to "Scripts Only" (Whichever is applicable).

    2) Restart IIS

    3) Download .exe's & Enjoy  !!

  26. wittawat says:

    i'm  configure IIS 7 to allow downloading .exe files  –>>

    Handler Mappings -> Add Module Mapping

      Request path: *.exe

      Module : CgiModule

      Name : Test

    Request Restrictions..

      Mapping : File

      Verbs : All verbs

      Access : None

    but can not download exe file