[Jython-checkins] jython: Better compliance with CPython on parsing certs

jim.baker jython-checkins at python.org
Fri Dec 11 00:47:33 EST 2015


https://hg.python.org/jython/rev/48de29dc0a56
changeset:   7833:48de29dc0a56
user:        Jim Baker <jim.baker at rackspace.com>
date:        Thu Dec 10 22:47:30 2015 -0700
summary:
  Better compliance with CPython on parsing certs

files:
  Lib/ssl.py           |  37 ++++++++++-----------------
  Lib/test/test_ssl.py |  41 +++++++++++++++++--------------
  2 files changed, 36 insertions(+), 42 deletions(-)


diff --git a/Lib/ssl.py b/Lib/ssl.py
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -123,6 +123,7 @@
 _ldap_rdn_display_names = {
     # list from RFC 2253
     "CN": "commonName",
+    "E": "emailAddress",
     "L": "localityName",
     "ST": "stateOrProvinceName",
     "O": "organizationName",
@@ -146,6 +147,11 @@
     "ipAddress",
     "registeredID"]
 
+def _str_or_unicode(s):
+    try:
+        return s.encode('ascii')
+    except UnicodeEncodeError:
+        return s
 
 class CertificateError(ValueError):
     pass
@@ -649,17 +655,13 @@
             return {}
 
         dn = cert.getSubjectX500Principal().getName()
-        ldapDN = LdapName(dn)
-        # FIXME given this tuple of a single element tuple structure assumed here, is it possible this is
-        # not actually the case, eg because of multi value attributes?
-        rdns = tuple((((_ldap_rdn_display_names.get(rdn.type), rdn.value),) for rdn in ldapDN.getRdns()))
-        # FIXME is it str? or utf8? or some other encoding? maybe a bug in cpython?
+        rdns = self._parse_dn(dn)
         alt_names = tuple()
         if cert.getSubjectAlternativeNames():
             alt_names = tuple(((_cert_name_types[type], str(name)) for (type, name) in cert.getSubjectAlternativeNames()))
 
         pycert = {
-            "notAfter": _rfc2822_date_format.format(cert.getNotAfter()),
+            "notAfter": str(_rfc2822_date_format.format(cert.getNotAfter())),
             "subject": rdns,
             "subjectAltName": alt_names,
         }
@@ -1023,13 +1025,11 @@
         NOTE: Certificates in a capath directory aren't loaded unless they have been used at least once.
         """
         certs = []
-        enumerator = self._trust_store.aliases()
-        while enumerator.hasMoreElements():
-            alias = enumerator.next()
+        for alias in self._trust_store.aliases():
             if self._trust_store.isCertificateEntry(alias):
                 cert = self._trust_store.getCertificate(alias)
                 if binary_form:
-                    certs.append(cert.getEncoded())
+                    certs.append(cert.getEncoded().tostring())
                 else:
                     issuer_info = self._parse_dn(cert.issuerDN)
                     subject_info = self._parse_dn(cert.subjectDN)
@@ -1039,7 +1039,7 @@
                         cert_info[k] = getattr(cert, k)
 
                     for k in ('notBefore', 'notAfter'):
-                        cert_info[k] = str(getattr(cert, k))
+                        cert_info[k] = str(_rfc2822_date_format.format(getattr(cert, k)))
 
                     certs.append(cert_info)
 
@@ -1085,16 +1085,7 @@
 
     @classmethod
     def _parse_dn(cls, dn):
-        dn_lst = []
-
         ln = LdapName(unicode(dn))
-        ln_iter = ln.getAll()
-        try:
-            ln_value = ln_iter.nextElement()
-            while ln_value:
-                dn_lst.append(tuple(ln_value.split('=', 1)))
-                ln_value = ln_iter.nextElement()
-        except NoSuchElementException:
-            pass
-
-        return tuple(dn_lst)
+        # FIXME given this tuple of a single element tuple structure assumed here, is it possible this is
+        # not actually the case, eg because of multi value attributes?
+        return tuple((((_ldap_rdn_display_names.get(rdn.type), _str_or_unicode(rdn.value)),) for rdn in ln.getRdns()))
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1033,26 +1033,29 @@
         self.assertEqual(ctx.get_ca_certs(), [])
         # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
         ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
-        self.assertEqual(ctx.get_ca_certs(), [
-            {'version': 3,
-             'serialNumber': 0,
-             'subject': ((u'E', u'support at cacert.org'),
-                         (u'CN', u'CA Cert Signing Authority'),
-                         (u'OU', u'http://www.cacert.org'),
-                         (u'O', u'Root CA')),
-             'notBefore': asn1time('Sun Mar 30 22:29:49 AEST 2003'),
-             'issuer': ((u'E', u'support at cacert.org'),
-                        (u'CN', u'CA Cert Signing Authority'),
-                        (u'OU', u'http://www.cacert.org'),
-                        (u'O', u'Root CA')),
-             'notAfter': asn1time('Tue Mar 29 23:29:49 AEDT 2033')}
-        ])
+        self.assertEqual(ctx.get_ca_certs(),
+            [{'version': 3,
+              'serialNumber': 0L,
+              'subject': ((('emailAddress', 'support at cacert.org'),),
+                          (('commonName', 'CA Cert Signing Authority'),),
+                          (('organizationalUnitName', 'http://www.cacert.org'),),
+                          (('organizationName', 'Root CA'),)),
+              'notBefore': 'Mar 30 12:29:49 2003 GMT',
+              'issuer': ((('emailAddress', 'support at cacert.org'),),
+                         (('commonName', 'CA Cert Signing Authority'),),
+                         (('organizationalUnitName', 'http://www.cacert.org'),),
+                         (('organizationName', 'Root CA'),)), 
+              'notAfter': 'Mar 29 12:29:49 2033 GMT'}])
+            # FIXME not currently collecting this aspect of the certificate
+            # 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
+            #
+            # see this sample code on how we might be able to decode:
+            # https://svn.apache.org/repos/asf/cxf/tags/cxf-2.4.4/distribution/src/main/release/samples/sts_issue_operation/src/main/java/demo/sts/provider/cert/CRLVerifier.java
 
-        return  # TODO jython binary form not supported
-        # with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
-        #     pem = f.read()
-        # der = ssl.PEM_cert_to_DER_cert(pem)
-        # self.assertEqual(ctx.get_ca_certs(True), [der])
+        with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
+            pem = f.read()
+            der = ssl.PEM_cert_to_DER_cert(pem)
+            self.assertEqual(ctx.get_ca_certs(True), [der])
 
     def test_load_default_certs(self):
         ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list