sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
authorNicolas Bareil <nico@chdir.org>
Sat, 18 Jun 2011 01:03:03 +0200
changeset 14666 27b080aa880a
parent 14665 d89f80898178
child 14667 8f12dac18d13
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798) Any entries in subjectAltName would prevent fallback to using commonName, but RFC 2818 says: If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. We now only consider dNSNames in subjectAltName. (dNSName is known as 'DNS' in OpenSSL/Python.)
mercurial/sslutil.py
tests/test-url.py
--- a/mercurial/sslutil.py	Fri Jun 17 15:43:50 2011 -0500
+++ b/mercurial/sslutil.py	Sat Jun 18 01:03:03 2011 +0200
@@ -48,7 +48,8 @@
         for name in certnames:
             if matchdnsname(name):
                 return None
-        return _('certificate is for %s') % ', '.join(certnames)
+        if certnames:
+            return _('certificate is for %s') % ', '.join(certnames)
 
     # subject is only checked when subjectAltName is empty
     for s in cert.get('subject', []):
--- a/tests/test-url.py	Fri Jun 17 15:43:50 2011 -0500
+++ b/tests/test-url.py	Sat Jun 18 01:03:03 2011 +0200
@@ -33,9 +33,13 @@
       None)
 check(_verifycert(san_cert, 'foo.example.net'),
       None)
-# subject is only checked when subjectAltName is empty
+# no fallback to subject commonName when subjectAltName has DNS
 check(_verifycert(san_cert, 'example.com'),
       'certificate is for *.example.net, example.net')
+# fallback to subject commonName when no DNS in subjectAltName
+san_cert = {'subject': ((('commonName', 'example.com'),),),
+            'subjectAltName': (('IP Address', '8.8.8.8'),)}
+check(_verifycert(san_cert, 'example.com'), None)
 
 # Avoid some pitfalls
 check(_verifycert(cert('*.foo'), 'foo'),
@@ -49,6 +53,10 @@
 check(_verifycert(None, 'example.com'),
       'no certificate received')
 
+# Unicode (IDN) certname isn't supported
+check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
+      'IDN in certificate not supported')
+
 import doctest
 
 def test_url():
@@ -211,7 +219,3 @@
     """
 
 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
-
-# Unicode (IDN) certname isn't supported
-check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
-      'IDN in certificate not supported')