mirror of
https://github.com/python/cpython.git
synced 2025-07-25 20:24:11 +00:00
Issue #18379: SSLSocket.getpeercert() returns CA issuer AIA fields, OCSP
and CRL distribution points.
This commit is contained in:
parent
efff7060f8
commit
bd3a7f90b5
4 changed files with 165 additions and 2 deletions
|
@ -733,6 +733,10 @@ SSL sockets also have the following additional methods and attributes:
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
:exc:`ValueError` is raised when the handshake isn't done.
|
:exc:`ValueError` is raised when the handshake isn't done.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.4
|
||||||
|
The returned dictionary includes additional X509v3 extension items
|
||||||
|
such as ``crlDistributionPoints``, ``caIssuers`` and ``OCSP`` URIs.
|
||||||
|
|
||||||
.. 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
|
||||||
|
|
|
@ -212,6 +212,12 @@ class BasicSocketTests(unittest.TestCase):
|
||||||
(('DNS', 'projects.developer.nokia.com'),
|
(('DNS', 'projects.developer.nokia.com'),
|
||||||
('DNS', 'projects.forum.nokia.com'))
|
('DNS', 'projects.forum.nokia.com'))
|
||||||
)
|
)
|
||||||
|
# extra OCSP and AIA fields
|
||||||
|
self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
|
||||||
|
self.assertEqual(p['caIssuers'],
|
||||||
|
('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
|
||||||
|
self.assertEqual(p['crlDistributionPoints'],
|
||||||
|
('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
|
||||||
|
|
||||||
def test_parse_cert_CVE_2013_4238(self):
|
def test_parse_cert_CVE_2013_4238(self):
|
||||||
p = ssl._ssl._test_decode_cert(NULLBYTECERT)
|
p = ssl._ssl._test_decode_cert(NULLBYTECERT)
|
||||||
|
@ -905,6 +911,7 @@ class ContextTests(unittest.TestCase):
|
||||||
'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
|
'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
|
||||||
'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
|
'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
|
||||||
'serialNumber': '00',
|
'serialNumber': '00',
|
||||||
|
'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
|
||||||
'subject': ((('organizationName', 'Root CA'),),
|
'subject': ((('organizationName', 'Root CA'),),
|
||||||
(('organizationalUnitName', 'http://www.cacert.org'),),
|
(('organizationalUnitName', 'http://www.cacert.org'),),
|
||||||
(('commonName', 'CA Cert Signing Authority'),),
|
(('commonName', 'CA Cert Signing Authority'),),
|
||||||
|
@ -1269,7 +1276,6 @@ class NetworkedTests(unittest.TestCase):
|
||||||
s.close()
|
s.close()
|
||||||
self.assertEqual(len(ctx.get_ca_certs()), 1)
|
self.assertEqual(len(ctx.get_ca_certs()), 1)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import threading
|
import threading
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
@ -59,6 +59,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #18379: SSLSocket.getpeercert() returns CA issuer AIA fields, OCSP
|
||||||
|
and CRL distribution points.
|
||||||
|
|
||||||
- Issue #18138: Implement cadata argument of SSLContext.load_verify_location()
|
- Issue #18138: Implement cadata argument of SSLContext.load_verify_location()
|
||||||
to load CA certificates and CRL from memory. It supports PEM and DER
|
to load CA certificates and CRL from memory. It supports PEM and DER
|
||||||
encoded strings.
|
encoded strings.
|
||||||
|
|
152
Modules/_ssl.c
152
Modules/_ssl.c
|
@ -964,6 +964,120 @@ _get_peer_alt_names (X509 *certificate) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_get_aia_uri(X509 *certificate, int nid) {
|
||||||
|
PyObject *lst = NULL, *ostr = NULL;
|
||||||
|
int i, result;
|
||||||
|
AUTHORITY_INFO_ACCESS *info;
|
||||||
|
|
||||||
|
info = X509_get_ext_d2i(certificate, NID_info_access, NULL, NULL);
|
||||||
|
if ((info == NULL) || (sk_ACCESS_DESCRIPTION_num(info) == 0)) {
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lst = PyList_New(0)) == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
|
||||||
|
ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
|
||||||
|
ASN1_IA5STRING *uri;
|
||||||
|
|
||||||
|
if ((OBJ_obj2nid(ad->method) != nid) ||
|
||||||
|
(ad->location->type != GEN_URI)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uri = ad->location->d.uniformResourceIdentifier;
|
||||||
|
ostr = PyUnicode_FromStringAndSize((char *)uri->data,
|
||||||
|
uri->length);
|
||||||
|
if (ostr == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
result = PyList_Append(lst, ostr);
|
||||||
|
Py_DECREF(ostr);
|
||||||
|
if (result < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AUTHORITY_INFO_ACCESS_free(info);
|
||||||
|
|
||||||
|
/* convert to tuple or None */
|
||||||
|
if (PyList_Size(lst) == 0) {
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return Py_None;
|
||||||
|
} else {
|
||||||
|
PyObject *tup;
|
||||||
|
tup = PyList_AsTuple(lst);
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return tup;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
AUTHORITY_INFO_ACCESS_free(info);
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_get_crl_dp(X509 *certificate) {
|
||||||
|
STACK_OF(DIST_POINT) *dps;
|
||||||
|
int i, j, result;
|
||||||
|
PyObject *lst;
|
||||||
|
|
||||||
|
/* Calls x509v3_cache_extensions and sets up crldp */
|
||||||
|
X509_check_ca(certificate);
|
||||||
|
dps = certificate->crldp;
|
||||||
|
if (dps == NULL) {
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lst = PyList_New(0)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < sk_DIST_POINT_num(dps); i++) {
|
||||||
|
DIST_POINT *dp;
|
||||||
|
STACK_OF(GENERAL_NAME) *gns;
|
||||||
|
|
||||||
|
dp = sk_DIST_POINT_value(dps, i);
|
||||||
|
gns = dp->distpoint->name.fullname;
|
||||||
|
|
||||||
|
for (j=0; j < sk_GENERAL_NAME_num(gns); j++) {
|
||||||
|
GENERAL_NAME *gn;
|
||||||
|
ASN1_IA5STRING *uri;
|
||||||
|
PyObject *ouri;
|
||||||
|
|
||||||
|
gn = sk_GENERAL_NAME_value(gns, j);
|
||||||
|
if (gn->type != GEN_URI) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uri = gn->d.uniformResourceIdentifier;
|
||||||
|
ouri = PyUnicode_FromStringAndSize((char *)uri->data,
|
||||||
|
uri->length);
|
||||||
|
if (ouri == NULL) {
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = PyList_Append(lst, ouri);
|
||||||
|
Py_DECREF(ouri);
|
||||||
|
if (result < 0) {
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* convert to tuple or None */
|
||||||
|
if (PyList_Size(lst) == 0) {
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return Py_None;
|
||||||
|
} else {
|
||||||
|
PyObject *tup;
|
||||||
|
tup = PyList_AsTuple(lst);
|
||||||
|
Py_DECREF(lst);
|
||||||
|
return tup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_decode_certificate(X509 *certificate) {
|
_decode_certificate(X509 *certificate) {
|
||||||
|
|
||||||
|
@ -974,9 +1088,10 @@ _decode_certificate(X509 *certificate) {
|
||||||
PyObject *issuer;
|
PyObject *issuer;
|
||||||
PyObject *version;
|
PyObject *version;
|
||||||
PyObject *sn_obj;
|
PyObject *sn_obj;
|
||||||
|
PyObject *obj;
|
||||||
ASN1_INTEGER *serialNumber;
|
ASN1_INTEGER *serialNumber;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
int len;
|
int len, result;
|
||||||
ASN1_TIME *notBefore, *notAfter;
|
ASN1_TIME *notBefore, *notAfter;
|
||||||
PyObject *pnotBefore, *pnotAfter;
|
PyObject *pnotBefore, *pnotAfter;
|
||||||
|
|
||||||
|
@ -1082,6 +1197,41 @@ _decode_certificate(X509 *certificate) {
|
||||||
Py_DECREF(peer_alt_names);
|
Py_DECREF(peer_alt_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Authority Information Access: OCSP URIs */
|
||||||
|
obj = _get_aia_uri(certificate, NID_ad_OCSP);
|
||||||
|
if (obj == NULL) {
|
||||||
|
goto fail1;
|
||||||
|
} else if (obj != Py_None) {
|
||||||
|
result = PyDict_SetItemString(retval, "OCSP", obj);
|
||||||
|
Py_DECREF(obj);
|
||||||
|
if (result < 0) {
|
||||||
|
goto fail1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = _get_aia_uri(certificate, NID_ad_ca_issuers);
|
||||||
|
if (obj == NULL) {
|
||||||
|
goto fail1;
|
||||||
|
} else if (obj != Py_None) {
|
||||||
|
result = PyDict_SetItemString(retval, "caIssuers", obj);
|
||||||
|
Py_DECREF(obj);
|
||||||
|
if (result < 0) {
|
||||||
|
goto fail1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CDP (CRL distribution points) */
|
||||||
|
obj = _get_crl_dp(certificate);
|
||||||
|
if (obj == NULL) {
|
||||||
|
goto fail1;
|
||||||
|
} else if (obj != Py_None) {
|
||||||
|
result = PyDict_SetItemString(retval, "crlDistributionPoints", obj);
|
||||||
|
Py_DECREF(obj);
|
||||||
|
if (result < 0) {
|
||||||
|
goto fail1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BIO_free(biobuf);
|
BIO_free(biobuf);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue