[PATCH 1 of 1 RFC] url: debug print ssl certificate info if verify failed

Gilles Moris gilles.moris at free.fr
Sun Jan 9 11:09:50 CST 2011


On Sunday 09 January 2011 04:12:00 pm Yuya Nishihara wrote:
> +def _debugservercert(ui, addr):
> +    if not ui.debugflag:
> +        return
> +    try:
> +        import ssl
> +    except ImportError:
> +        return
> +    try:
> +        pem = ssl.get_server_certificate(addr)
> +    except SSLError:
> +        return
> +    cert = _decodecert(pem)
> +    if cert:
> +        ui.debug(_formatcert(cert))

I would prefer a function getservercert(addr) instead, that just
 return _decodecert(pem)

That would be more reusable like below.
This implements a list of trusted SSL self-signed hosts that would
not be validated, as described in the other thread.

--- a/mercurial/url.py  Sun Jan 09 23:26:24 2011 +0900
+++ b/mercurial/url.py  Sun Jan 09 18:01:16 2011 +0100
@@ -591,13 +591,37 @@
     if cert:
         ui.debug(_formatcert(cert))

+def _getservercert(addr):
+    try:
+        import ssl
+    except ImportError:
+        return {}
+    try:
+        pem = ssl.get_server_certificate(addr)
+    except SSLError:
+        return {}
+    return _decodecert(pem)
+
+def _selfsignedcert(cert):
+    subject = cert.get('subject', [])
+    issuer = cert.get('issuer', [])
+    return issuer and subject == issuer
+
 if has_https:
     class BetterHTTPS(httplib.HTTPSConnection):
         send = keepalive.safesend

         def connect(self):
+            trusted = False
             if hasattr(self, 'ui'):
-                cacerts = self.ui.config('web', 'cacerts')
+                cert = _getservercert((self.host, self.port))
+                addr = "%s:%d" % (self.host, self.port)
+                if _selfsignedcert(cert) and \
+                   addr in self.ui.configlist('web', 'trustedsslhosts', []):
+                    trusted = True
+                    cacerts = None
+                else:
+                    cacerts = self.ui.config('web', 'cacerts')
                 if cacerts:
                     cacerts = util.expandpath(cacerts)
             else:
@@ -619,8 +643,9 @@
                 self.ui.debug('%s certificate successfully verified\n' %
                               self.host)
             else:
-                self.ui.warn(_("warning: %s certificate not verified "
-                               "(check web.cacerts config setting)\n") %
+                if not trusted:
+                    self.ui.warn(_("warning: %s certificate not verified "
+                                   "(check web.cacerts config setting)\n") %
                              self.host)
                 httplib.HTTPSConnection.connect(self)




More information about the Mercurial-devel mailing list