IIS 7.5 Mercurial setup ignoring maxAllowedContentLength

cgi, iis, mercurial

Solution

I found a few ways of dealing with this issue:

To fix this server-side in IIS, download and install https://www.nartac.com/Products/IISCrypto/Default.aspx and click the BEAST button, or force SSL3.0 by disabling other protocols.

If you don't have access to the IIS server, you can fix it by rolling back Python to version 2.7.2 or earlier.

If you are adventurous, you can modify the mercurial source in sslutil.py, near the top, change the line

sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
            cert_reqs=cert_reqs, ca_certs=ca_certs)

to

from _ssl import PROTOCOL_SSLv3
sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
            cert_reqs=cert_reqs, ca_certs=ca_certs, ssl_version=PROTOCOL_SSLv3)

This will work around the problem and fix the push limit to mercurial behind IIS.

If you are interested in why Python 2.7.3 broke this, look at http://bugs.python.org/issue13885 for the explanation (it is security-related). If you want to modify Python itself, in Modules/_ssl.c change the line

SSL_CTX_set_options(self->ctx,
                    SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);

back to how it was prior to 2.7.3:

SSL_CTX_set_options(self->ctx, SSL_OP_ALL);

Compile and reinstall python, etc. This adds more SSL compatibility at the expense of potential security risks, if I understand the OpenSSL docs correctly.

Problem

I'm trying to setup Mercurial on IIS 7.5. I have a web.config for an application directory that is ignoring the `maxAllowedContentLength` attribute and I simply cannot get IIS to accept it! I've tried it a thousand different ways at global, local, and every level. It sticks by its default of 30MB and refuses to let me push changesets that are larger than that. It doesn't even close the connection, it just gets to 30MB and stalls completely. It's not a timeout issue, I've tried pushing from the local machine to its IP address. What the hell is going on? ``` <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <add name="Python" path="*.cgi" verb="*" modules="CgiModule" scriptProcessor="C:\Python27\python.exe -u &quot;%s&quot;" resourceType="Unspecified" requireAccess="Script" /> </handlers> <security> <requestFiltering> <requestLimits maxAllowedContentLength="1073741824" /> </requestFiltering> </security> <rewrite> <rules> <rule name="rewrite to hgwebdir" patternSyntax="Wildcard"> <match url="*" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> </conditions> <action type="Rewrite" url="hgweb.cgi/{R:1}" /> </rule> </rules> </rewrite> </system.webServer> <!-- I don't know if this is supposed to work... it doesn't matter where I put the settings. --> <location path="*"> <system.web> <!-- maxRequestLength is in kilobytes (KB) --> <httpRuntime maxRequestLength="1048576" /> <!-- 1GB --> </system.web> <system.webServer> <security> <requestFiltering> <!-- maxAllowedContentLength is in bytes (B) --> <requestLimits maxAllowedContentLength="1073741824"/> <!-- 1GB --> </requestFiltering> </security> </system.webServer> </location> </configuration> ```

Original source