]> granicus.if.org Git - python/commitdiff
Issue #10022: The dictionary returned by the `getpeercert()` method
authorAntoine Pitrou <solipsis@pitrou.net>
Tue, 9 Nov 2010 20:21:19 +0000 (20:21 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Tue, 9 Nov 2010 20:21:19 +0000 (20:21 +0000)
of SSL sockets now has additional items such as `issuer` and `notBefore`.

Doc/library/ssl.rst
Lib/test/test_ssl.py
Misc/NEWS
Modules/_ssl.c

index 57a17bc79807f3b8edc379f9f7b6eb064220a023..39d1cfec96b4ee2f37bd07ce156da44506fab9c4 100644 (file)
@@ -433,11 +433,9 @@ They also have the following additional methods and attributes:
    certificate was not validated, the dict is empty.  If the certificate was
    validated, it returns a dict with the keys ``subject`` (the principal for
    which the certificate was issued), and ``notAfter`` (the time after which the
-   certificate should not be trusted).  The certificate was already validated,
-   so the ``notBefore`` and ``issuer`` fields are not returned.  If a
-   certificate contains an instance of the *Subject Alternative Name* extension
-   (see :rfc:`3280`), there will also be a ``subjectAltName`` key in the
-   dictionary.
+   certificate should not be trusted).  If a certificate contains an instance
+   of the *Subject Alternative Name* extension (see :rfc:`3280`), there will
+   also be a ``subjectAltName`` key in the dictionary.
 
    The "subject" field is a tuple containing the sequence of relative
    distinguished names (RDNs) given in the certificate's data structure for the
@@ -459,6 +457,10 @@ They also have the following additional methods and attributes:
    been validated, but if :const:`CERT_NONE` was used to establish the
    connection, the certificate, if present, will not have been validated.
 
+   .. versionchanged:: 3.2
+      The returned dictionary includes additional items such as ``issuer``
+      and ``notBefore``.
+
 .. method:: SSLSocket.cipher()
 
    Returns a three-value tuple containing the name of the cipher being used, the
index bb9cebf76b41ee52b8dd84505715ecddf0dbabf2..df9b98728947a1eb6b8b3fc8a6119437c0eccce8 100644 (file)
@@ -109,7 +109,7 @@ class BasicSocketTests(unittest.TestCase):
         # note that this uses an 'unofficial' function in _ssl.c,
         # provided solely for this test, to exercise the certificate
         # parsing code
-        p = ssl._ssl._test_decode_cert(CERTFILE, False)
+        p = ssl._ssl._test_decode_cert(CERTFILE)
         if support.verbose:
             sys.stdout.write("\n" + pprint.pformat(p) + "\n")
 
@@ -1059,6 +1059,11 @@ else:
                     self.fail(
                         "Missing or invalid 'organizationName' field in certificate subject; "
                         "should be 'Python Software Foundation'.")
+                self.assertIn('notBefore', cert)
+                self.assertIn('notAfter', cert)
+                before = ssl.cert_time_to_seconds(cert['notBefore'])
+                after = ssl.cert_time_to_seconds(cert['notAfter'])
+                self.assertLess(before, after)
                 s.close()
             finally:
                 server.stop()
index 519c1899e9f0ebcf428aa5e3f384941d7d8d3263..1faf2956d225b0b718e5dc3cc48ffe596d9feb11 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -60,6 +60,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #10022: The dictionary returned by the ``getpeercert()`` method
+  of SSL sockets now has additional items such as ``issuer`` and ``notBefore``.
+
 - ``usenetrc`` is now false by default for NNTP objects.
 
 - Issue #1926: Add support for NNTP over SSL on port 563, as well as
index 6fa65b294de9bb3fa4a4a99a3bbad15ed97ae02a..78ea293b39a849e650b9b3dc14eb044227991099 100644 (file)
@@ -700,7 +700,7 @@ _get_peer_alt_names (X509 *certificate) {
 }
 
 static PyObject *
-_decode_certificate (X509 *certificate, int verbose) {
+_decode_certificate(X509 *certificate) {
 
     PyObject *retval = NULL;
     BIO *biobuf = NULL;
@@ -729,65 +729,60 @@ _decode_certificate (X509 *certificate, int verbose) {
     }
     Py_DECREF(peer);
 
-    if (verbose) {
-        issuer = _create_tuple_for_X509_NAME(
-            X509_get_issuer_name(certificate));
-        if (issuer == NULL)
-            goto fail0;
-        if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
-            Py_DECREF(issuer);
-            goto fail0;
-        }
+    issuer = _create_tuple_for_X509_NAME(
+        X509_get_issuer_name(certificate));
+    if (issuer == NULL)
+        goto fail0;
+    if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
         Py_DECREF(issuer);
+        goto fail0;
+    }
+    Py_DECREF(issuer);
 
-        version = PyLong_FromLong(X509_get_version(certificate) + 1);
-        if (PyDict_SetItemString(retval, "version", version) < 0) {
-            Py_DECREF(version);
-            goto fail0;
-        }
+    version = PyLong_FromLong(X509_get_version(certificate) + 1);
+    if (PyDict_SetItemString(retval, "version", version) < 0) {
         Py_DECREF(version);
+        goto fail0;
     }
+    Py_DECREF(version);
 
     /* get a memory buffer */
     biobuf = BIO_new(BIO_s_mem());
 
-    if (verbose) {
-
-        (void) BIO_reset(biobuf);
-        serialNumber = X509_get_serialNumber(certificate);
-        /* should not exceed 20 octets, 160 bits, so buf is big enough */
-        i2a_ASN1_INTEGER(biobuf, serialNumber);
-        len = BIO_gets(biobuf, buf, sizeof(buf)-1);
-        if (len < 0) {
-            _setSSLError(NULL, 0, __FILE__, __LINE__);
-            goto fail1;
-        }
-        sn_obj = PyUnicode_FromStringAndSize(buf, len);
-        if (sn_obj == NULL)
-            goto fail1;
-        if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) {
-            Py_DECREF(sn_obj);
-            goto fail1;
-        }
+    (void) BIO_reset(biobuf);
+    serialNumber = X509_get_serialNumber(certificate);
+    /* should not exceed 20 octets, 160 bits, so buf is big enough */
+    i2a_ASN1_INTEGER(biobuf, serialNumber);
+    len = BIO_gets(biobuf, buf, sizeof(buf)-1);
+    if (len < 0) {
+        _setSSLError(NULL, 0, __FILE__, __LINE__);
+        goto fail1;
+    }
+    sn_obj = PyUnicode_FromStringAndSize(buf, len);
+    if (sn_obj == NULL)
+        goto fail1;
+    if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) {
         Py_DECREF(sn_obj);
+        goto fail1;
+    }
+    Py_DECREF(sn_obj);
 
-        (void) BIO_reset(biobuf);
-        notBefore = X509_get_notBefore(certificate);
-        ASN1_TIME_print(biobuf, notBefore);
-        len = BIO_gets(biobuf, buf, sizeof(buf)-1);
-        if (len < 0) {
-            _setSSLError(NULL, 0, __FILE__, __LINE__);
-            goto fail1;
-        }
-        pnotBefore = PyUnicode_FromStringAndSize(buf, len);
-        if (pnotBefore == NULL)
-            goto fail1;
-        if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) {
-            Py_DECREF(pnotBefore);
-            goto fail1;
-        }
+    (void) BIO_reset(biobuf);
+    notBefore = X509_get_notBefore(certificate);
+    ASN1_TIME_print(biobuf, notBefore);
+    len = BIO_gets(biobuf, buf, sizeof(buf)-1);
+    if (len < 0) {
+        _setSSLError(NULL, 0, __FILE__, __LINE__);
+        goto fail1;
+    }
+    pnotBefore = PyUnicode_FromStringAndSize(buf, len);
+    if (pnotBefore == NULL)
+        goto fail1;
+    if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) {
         Py_DECREF(pnotBefore);
+        goto fail1;
     }
+    Py_DECREF(pnotBefore);
 
     (void) BIO_reset(biobuf);
     notAfter = X509_get_notAfter(certificate);
@@ -839,10 +834,9 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) {
     PyObject *filename;
     X509 *x=NULL;
     BIO *cert;
-    int verbose = 1;
 
-    if (!PyArg_ParseTuple(args, "O&|i:test_decode_certificate",
-                          PyUnicode_FSConverter, &filename, &verbose))
+    if (!PyArg_ParseTuple(args, "O&:test_decode_certificate",
+                          PyUnicode_FSConverter, &filename))
         return NULL;
 
     if ((cert=BIO_new(BIO_s_file())) == NULL) {
@@ -864,7 +858,7 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) {
         goto fail0;
     }
 
-    retval = _decode_certificate(x, verbose);
+    retval = _decode_certificate(x);
     X509_free(x);
 
   fail0:
@@ -910,7 +904,7 @@ PySSL_peercert(PySSLSocket *self, PyObject *args)
         if ((verification & SSL_VERIFY_PEER) == 0)
             return PyDict_New();
         else
-            return _decode_certificate (self->peer_cert, 0);
+            return _decode_certificate(self->peer_cert);
     }
 }