# HG changeset patch # User Gregory Szorc # Date 2016-07-13 06:12:03 # Node ID 121d11814c62ed29636aabbc8af801ee80126225 # Parent 4a7b0c696fbcd732972b479db211c2b030c1c2fa hgweb: use sslutil.wrapserversocket() This patch transitions the built-in HTTPS server to use sslutil for creating the server socket. As part of this transition, we implement developer-only config options to control CA loading and whether to require client certificates. This eliminates the need for the custom extension in test-https.t to define these. There is a slight change in behavior with regards to protocol selection. Before, we would always use the TLS 1.0 constant to define the protocol version. This would *only* use TLS 1.0. sslutil defaults to TLS 1.0+. So this patch improves the security of `hg serve` out of the box by allowing it to use TLS 1.1 and 1.2 (if available). diff --git a/mercurial/hgweb/server.py b/mercurial/hgweb/server.py --- a/mercurial/hgweb/server.py +++ b/mercurial/hgweb/server.py @@ -224,15 +224,23 @@ class _httprequesthandlerssl(_httpreques @staticmethod def preparehttpserver(httpserver, ui): try: - import ssl - ssl.wrap_socket + from .. import sslutil + sslutil.modernssl except ImportError: raise error.Abort(_("SSL support is unavailable")) certfile = ui.config('web', 'certificate') - httpserver.socket = ssl.wrap_socket( - httpserver.socket, server_side=True, - certfile=certfile, ssl_version=ssl.PROTOCOL_TLSv1) + + # These config options are currently only meant for testing. Use + # at your own risk. + cafile = ui.config('devel', 'servercafile') + reqcert = ui.configbool('devel', 'serverrequirecert') + + httpserver.socket = sslutil.wrapserversocket(httpserver.socket, + ui, + certfile=certfile, + cafile=cafile, + requireclientcert=reqcert) def setup(self): self.connection = self.request diff --git a/tests/test-https.t b/tests/test-https.t --- a/tests/test-https.t +++ b/tests/test-https.t @@ -397,27 +397,11 @@ Test https with cert problems through pr #if sslcontext -Start patched hgweb that requires client certificates: +Start hgweb that requires client certificates: - $ cat << EOT > reqclientcert.py - > import ssl - > from mercurial.hgweb import server - > class _httprequesthandlersslclientcert(server._httprequesthandlerssl): - > @staticmethod - > def preparehttpserver(httpserver, ui): - > certfile = ui.config('web', 'certificate') - > sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1) - > sslcontext.verify_mode = ssl.CERT_REQUIRED - > sslcontext.load_cert_chain(certfile) - > # verify clients by server certificate - > sslcontext.load_verify_locations(certfile) - > httpserver.socket = sslcontext.wrap_socket(httpserver.socket, - > server_side=True) - > server._httprequesthandlerssl = _httprequesthandlersslclientcert - > EOT $ cd test $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \ - > --config extensions.reqclientcert=../reqclientcert.py + > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true $ cat ../hg0.pid >> $DAEMON_PIDS $ cd ..