[PATCH 5 of 6 V2] hgweb: use sslutil module for creating wrapped socket
Gregory Szorc
gregory.szorc at gmail.com
Wed Jul 13 03:18:11 EDT 2016
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1468390323 25200
# Tue Jul 12 23:12:03 2016 -0700
# Node ID e9578504292e6280c96812f3e64f9fb51dcf8446
# Parent 6955c5d8d037f824d3cc8e6f2abb53f77010eec3
hgweb: use sslutil module for creating wrapped socket
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
@@ -219,25 +219,33 @@ class _httprequesthandler(BaseHTTPServer
class _httprequesthandlerssl(_httprequesthandler):
"""HTTPS handler based on Python's ssl module"""
url_scheme = 'https'
@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
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
try:
import threading
diff --git a/tests/test-https.t b/tests/test-https.t
--- a/tests/test-https.t
+++ b/tests/test-https.t
@@ -392,37 +392,21 @@ Test https with cert problems through pr
abort: error: *certificate verify failed* (glob)
[255]
$ killdaemons.py hg0.pid
#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 ..
without client certificate:
$ P="$CERTSDIR" hg id https://localhost:$HGPORT/
abort: error: *handshake failure* (glob)
[255]
More information about the Mercurial-devel
mailing list