My experiences with Mercurial

Brendan Cully brendan at kublai.com
Mon Jun 18 05:38:35 UTC 2007


On Monday, 18 June 2007 at 11:34, Bela Babik wrote:
> It seems to be easy to add ssl support to the server:
> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473

Here's a quick implementation following that recipe. With this patch,
you can activate SSL support by setting [web] certificate = foo.cert or
via the commandline via

hg serve --certificate foo.cert
-------------- next part --------------
# HG changeset patch
# User Brendan Cully <brendan at kublai.com>
# Date 1182144940 25200
# Node ID ac319013e1a2e845740d8f964f512a25c90d4892
# Parent  64c415d2553ae5dc90b244f37ad6e5c3dad94ce8
Add SSL support to hg serve, activated via --certificate option

diff -r 64c415d2553a -r ac319013e1a2 mercurial/commands.py
--- a/mercurial/commands.py	Sun Jun 17 20:09:35 2007 -0700
+++ b/mercurial/commands.py	Sun Jun 17 22:35:40 2007 -0700
@@ -2363,7 +2363,7 @@ def serve(ui, repo, **opts):
 
     parentui = ui.parentui or ui
     optlist = ("name templates style address port ipv6"
-               " accesslog errorlog webdir_conf")
+               " accesslog errorlog webdir_conf certificate")
     for o in optlist.split():
         if opts[o]:
             parentui.setconfig("web", o, str(opts[o]))
@@ -2947,7 +2947,8 @@ table = {
           ('', 'stdio', None, _('for remote clients')),
           ('t', 'templates', '', _('web templates to use')),
           ('', 'style', '', _('template style to use')),
-          ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
+          ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
+          ('', 'certificate', '', _('SSL certificate file'))],
          _('hg serve [OPTION]...')),
     "^status|st":
         (status,
diff -r 64c415d2553a -r ac319013e1a2 mercurial/hgweb/server.py
--- a/mercurial/hgweb/server.py	Sun Jun 17 20:09:35 2007 -0700
+++ b/mercurial/hgweb/server.py	Sun Jun 17 22:35:40 2007 -0700
@@ -164,6 +164,12 @@ class _hgwebhandler(object, BaseHTTPServ
         self.wfile.write(data)
         self.wfile.flush()
 
+class _shgwebhandler(_hgwebhandler):
+    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)
+
 def create_server(ui, repo):
     use_threads = True
 
@@ -176,6 +182,7 @@ def create_server(ui, repo):
     port = int(ui.config("web", "port", 8000))
     use_ipv6 = ui.configbool("web", "ipv6")
     webdir_conf = ui.config("web", "webdir_conf")
+    ssl_cert = ui.config("web", "certificate")
     accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout)
     errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr)
 
@@ -222,6 +229,20 @@ def create_server(ui, repo):
 
             self.addr, self.port = addr, port
 
+            if ssl_cert:
+                try:
+                    from OpenSSL import SSL
+                except ImportError:
+                    raise util.Abort("SSL support is unavailable")
+                ctx = SSL.Context(SSL.SSLv23_METHOD)
+                ctx.use_privatekey_file(ssl_cert)
+                ctx.use_certificate_file(ssl_cert)
+                self.socket = SSL.Connection(ctx,
+                                             socket.socket(self.address_family,
+                                                           self.socket_type))
+                self.server_bind()
+                self.server_activate()
+
     class IPv6HTTPServer(MercurialHTTPServer):
         address_family = getattr(socket, 'AF_INET6', None)
 
@@ -230,10 +251,15 @@ def create_server(ui, repo):
                 raise hg.RepoError(_('IPv6 not available on this system'))
             super(IPv6HTTPServer, self).__init__(*args, **kwargs)
 
+    if ssl_cert:
+        handler = _shgwebhandler
+    else:
+        handler = _hgwebhandler
+
     try:
         if use_ipv6:
-            return IPv6HTTPServer((address, port), _hgwebhandler)
-        else:
-            return MercurialHTTPServer((address, port), _hgwebhandler)
+            return IPv6HTTPServer((address, port), handler)
+        else:
+            return MercurialHTTPServer((address, port), handler)
     except socket.error, inst:
         raise util.Abort(_('cannot start server: %s') % inst.args[1])


More information about the Mercurial mailing list