This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author nbareil
Recipients nbareil
Date 2011-05-04.11:35:51
SpamBayes Score 4.5962064e-08
Marked as misclassified No
Message-id <1304508952.88.0.678717772317.issue12000@psf.upfronthosting.co.za>
In-reply-to
Content
When connecting to a SSL server, the certificate verification failed if
it has a subjectAltName extension without any dNSName entry inside: it
should fallback to the Common Name.

Example:

    >>> cert = conn.getpeercert()
    >>> cert
    {'notAfter': 'May 15 14:31:42 2011 GMT',
     'subject': ((('countryName', u'FR'),),
                 (('stateOrProvinceName', u'Ile-de-France'),),
                 (('localityName', u'Paris'),),
                 (('organizationName', 'xxx'),),
                 (('organizationalUnitName', 'xxx'),),
                 (('commonName', 'foobar.corp'),),
                 (('emailAddress', u'test@test.net'),)),
     'subjectAltName': (('email', text@test.net'),)}


This certificate is valid according to RFC 2818:

    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. Although
    the use of the Common Name is existing practice, it is deprecated and
    Certification Authorities are encouraged to use the dNSName instead.

Even if the use of CommonName is deprecated, we should not break
existing systems.

Current revision of Lib/ssl.py :

    108 def match_hostname(cert, hostname):
    ...
    119     san = cert.get('subjectAltName', ())
    120     for key, value in san:
    121         if key == 'DNS':
    122             if _dnsname_to_pat(value).match(hostname):
    123                 return
    124             dnsnames.append(value)
    125     if not san:
    126         # The subject is only checked when subjectAltName is empty
    127         for sub in cert.get('subject', ()):
    128             for key, value in sub:
    129                 # XXX according to RFC 2818, the most specific Common Name
    130                 # must be used.
    131                 if key == 'commonName':
    132                     if _dnsname_to_pat(value).match(hostname):
    133                         return
    134                     dnsnames.append(value)
    ...

Proposed patch is:


diff -r 513f6dfd3173 Lib/ssl.py
--- a/Lib/ssl.py        Sun May 01 20:24:59 2011 -0500
+++ b/Lib/ssl.py        Mon May 02 11:16:46 2011 +0200
@@ -122,8 +122,9 @@
             if _dnsname_to_pat(value).match(hostname):
                 return
             dnsnames.append(value)
- if not san:
- # The subject is only checked when subjectAltName is empty
+ if not san and not dnsnames:
+ # The subject is only checked when there is no dNSName entry
+ # in subjectAltName
  for sub in cert.get('subject', ()):
      for key, value in sub:
          # XXX according to RFC 2818, the most specific Common Name
History
Date User Action Args
2011-05-04 11:35:52nbareilsetrecipients: + nbareil
2011-05-04 11:35:52nbareilsetmessageid: <1304508952.88.0.678717772317.issue12000@psf.upfronthosting.co.za>
2011-05-04 11:35:52nbareillinkissue12000 messages
2011-05-04 11:35:51nbareilcreate