mirror of
https://github.com/python/cpython.git
synced 2025-08-31 22:18:28 +00:00
Issue #10022: The dictionary returned by the getpeercert()
method
of SSL sockets now has additional items such as `issuer` and `notBefore`.
This commit is contained in:
parent
859c4ef0a0
commit
fb0469112f
4 changed files with 68 additions and 64 deletions
|
@ -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
|
certificate was not validated, the dict is empty. If the certificate was
|
||||||
validated, it returns a dict with the keys ``subject`` (the principal for
|
validated, it returns a dict with the keys ``subject`` (the principal for
|
||||||
which the certificate was issued), and ``notAfter`` (the time after which the
|
which the certificate was issued), and ``notAfter`` (the time after which the
|
||||||
certificate should not be trusted). The certificate was already validated,
|
certificate should not be trusted). If a certificate contains an instance
|
||||||
so the ``notBefore`` and ``issuer`` fields are not returned. If a
|
of the *Subject Alternative Name* extension (see :rfc:`3280`), there will
|
||||||
certificate contains an instance of the *Subject Alternative Name* extension
|
also be a ``subjectAltName`` key in the dictionary.
|
||||||
(see :rfc:`3280`), there will also be a ``subjectAltName`` key in the
|
|
||||||
dictionary.
|
|
||||||
|
|
||||||
The "subject" field is a tuple containing the sequence of relative
|
The "subject" field is a tuple containing the sequence of relative
|
||||||
distinguished names (RDNs) given in the certificate's data structure for the
|
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
|
been validated, but if :const:`CERT_NONE` was used to establish the
|
||||||
connection, the certificate, if present, will not have been validated.
|
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()
|
.. method:: SSLSocket.cipher()
|
||||||
|
|
||||||
Returns a three-value tuple containing the name of the cipher being used, the
|
Returns a three-value tuple containing the name of the cipher being used, the
|
||||||
|
|
|
@ -109,7 +109,7 @@ class BasicSocketTests(unittest.TestCase):
|
||||||
# note that this uses an 'unofficial' function in _ssl.c,
|
# note that this uses an 'unofficial' function in _ssl.c,
|
||||||
# provided solely for this test, to exercise the certificate
|
# provided solely for this test, to exercise the certificate
|
||||||
# parsing code
|
# parsing code
|
||||||
p = ssl._ssl._test_decode_cert(CERTFILE, False)
|
p = ssl._ssl._test_decode_cert(CERTFILE)
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
sys.stdout.write("\n" + pprint.pformat(p) + "\n")
|
sys.stdout.write("\n" + pprint.pformat(p) + "\n")
|
||||||
|
|
||||||
|
@ -1059,6 +1059,11 @@ else:
|
||||||
self.fail(
|
self.fail(
|
||||||
"Missing or invalid 'organizationName' field in certificate subject; "
|
"Missing or invalid 'organizationName' field in certificate subject; "
|
||||||
"should be 'Python Software Foundation'.")
|
"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()
|
s.close()
|
||||||
finally:
|
finally:
|
||||||
server.stop()
|
server.stop()
|
||||||
|
|
|
@ -60,6 +60,9 @@ Core and Builtins
|
||||||
Library
|
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.
|
- ``usenetrc`` is now false by default for NNTP objects.
|
||||||
|
|
||||||
- Issue #1926: Add support for NNTP over SSL on port 563, as well as
|
- Issue #1926: Add support for NNTP over SSL on port 563, as well as
|
||||||
|
|
110
Modules/_ssl.c
110
Modules/_ssl.c
|
@ -700,7 +700,7 @@ _get_peer_alt_names (X509 *certificate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_decode_certificate (X509 *certificate, int verbose) {
|
_decode_certificate(X509 *certificate) {
|
||||||
|
|
||||||
PyObject *retval = NULL;
|
PyObject *retval = NULL;
|
||||||
BIO *biobuf = NULL;
|
BIO *biobuf = NULL;
|
||||||
|
@ -729,65 +729,60 @@ _decode_certificate (X509 *certificate, int verbose) {
|
||||||
}
|
}
|
||||||
Py_DECREF(peer);
|
Py_DECREF(peer);
|
||||||
|
|
||||||
if (verbose) {
|
issuer = _create_tuple_for_X509_NAME(
|
||||||
issuer = _create_tuple_for_X509_NAME(
|
X509_get_issuer_name(certificate));
|
||||||
X509_get_issuer_name(certificate));
|
if (issuer == NULL)
|
||||||
if (issuer == NULL)
|
goto fail0;
|
||||||
goto fail0;
|
if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
|
||||||
if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
|
|
||||||
Py_DECREF(issuer);
|
|
||||||
goto fail0;
|
|
||||||
}
|
|
||||||
Py_DECREF(issuer);
|
Py_DECREF(issuer);
|
||||||
|
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);
|
|
||||||
}
|
}
|
||||||
|
Py_DECREF(issuer);
|
||||||
|
|
||||||
|
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 */
|
/* get a memory buffer */
|
||||||
biobuf = BIO_new(BIO_s_mem());
|
biobuf = BIO_new(BIO_s_mem());
|
||||||
|
|
||||||
if (verbose) {
|
(void) BIO_reset(biobuf);
|
||||||
|
serialNumber = X509_get_serialNumber(certificate);
|
||||||
(void) BIO_reset(biobuf);
|
/* should not exceed 20 octets, 160 bits, so buf is big enough */
|
||||||
serialNumber = X509_get_serialNumber(certificate);
|
i2a_ASN1_INTEGER(biobuf, serialNumber);
|
||||||
/* should not exceed 20 octets, 160 bits, so buf is big enough */
|
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
|
||||||
i2a_ASN1_INTEGER(biobuf, serialNumber);
|
if (len < 0) {
|
||||||
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
|
_setSSLError(NULL, 0, __FILE__, __LINE__);
|
||||||
if (len < 0) {
|
goto fail1;
|
||||||
_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;
|
|
||||||
}
|
|
||||||
Py_DECREF(pnotBefore);
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
Py_DECREF(pnotBefore);
|
||||||
|
|
||||||
(void) BIO_reset(biobuf);
|
(void) BIO_reset(biobuf);
|
||||||
notAfter = X509_get_notAfter(certificate);
|
notAfter = X509_get_notAfter(certificate);
|
||||||
|
@ -839,10 +834,9 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) {
|
||||||
PyObject *filename;
|
PyObject *filename;
|
||||||
X509 *x=NULL;
|
X509 *x=NULL;
|
||||||
BIO *cert;
|
BIO *cert;
|
||||||
int verbose = 1;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&|i:test_decode_certificate",
|
if (!PyArg_ParseTuple(args, "O&:test_decode_certificate",
|
||||||
PyUnicode_FSConverter, &filename, &verbose))
|
PyUnicode_FSConverter, &filename))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((cert=BIO_new(BIO_s_file())) == NULL) {
|
if ((cert=BIO_new(BIO_s_file())) == NULL) {
|
||||||
|
@ -864,7 +858,7 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) {
|
||||||
goto fail0;
|
goto fail0;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = _decode_certificate(x, verbose);
|
retval = _decode_certificate(x);
|
||||||
X509_free(x);
|
X509_free(x);
|
||||||
|
|
||||||
fail0:
|
fail0:
|
||||||
|
@ -910,7 +904,7 @@ PySSL_peercert(PySSLSocket *self, PyObject *args)
|
||||||
if ((verification & SSL_VERIFY_PEER) == 0)
|
if ((verification & SSL_VERIFY_PEER) == 0)
|
||||||
return PyDict_New();
|
return PyDict_New();
|
||||||
else
|
else
|
||||||
return _decode_certificate (self->peer_cert, 0);
|
return _decode_certificate(self->peer_cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue