summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-11-09 20:21:19 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-11-09 20:21:19 (GMT)
commitfb0469112f2e027833a1dc7ff4c678417de0111a (patch)
treeac086511b8885cf056a2bdc453087a731f9d82c9
parent859c4ef0a0069a555057f25f02407e89bd2c114b (diff)
downloadcpython-fb0469112f2e027833a1dc7ff4c678417de0111a.zip
cpython-fb0469112f2e027833a1dc7ff4c678417de0111a.tar.gz
cpython-fb0469112f2e027833a1dc7ff4c678417de0111a.tar.bz2
Issue #10022: The dictionary returned by the `getpeercert()` method
of SSL sockets now has additional items such as `issuer` and `notBefore`.
-rw-r--r--Doc/library/ssl.rst12
-rw-r--r--Lib/test/test_ssl.py7
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_ssl.c100
4 files changed, 63 insertions, 59 deletions
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index 57a17bc..39d1cfe 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -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
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index bb9cebf..df9b987 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -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()
diff --git a/Misc/NEWS b/Misc/NEWS
index 519c189..1faf295 100644
--- 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
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 6fa65b2..78ea293 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -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);
}
}