diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -897,6 +897,94 @@ } static PyObject * +_get_ocsp(X509 *certificate) { + STACK_OF(OPENSSL_STRING) *str; + PyObject *retval = NULL, *ostr = NULL; + int i, len; + + str = X509_get1_ocsp(certificate); + if (str == NULL) { + /* No NID_info_access with NID_ad_OCSP */ + Py_RETURN_NONE; + } + len = sk_OPENSSL_STRING_num(str); + if ((retval = PyTuple_New(len)) == NULL) { + goto fail; + } + for (i=0; i < len; i++) { + ostr = PyUnicode_FromString(sk_OPENSSL_STRING_value(str, i)); + if (ostr == NULL) { + goto fail; + } + PyTuple_SET_ITEM(retval, i, ostr); + } + return retval; + + fail: + X509_email_free(str); /* sic! */ + Py_XDECREF(retval); + return NULL; +} + +static PyObject * +_get_crl_dp(X509 *certificate) { + STACK_OF(DIST_POINT) *dps; + int i, j; + PyObject *lst; + + /* Calls x509v3_cache_extensions and sets up crldp */ + X509_check_ca(certificate); + dps = certificate->crldp; + if (dps == NULL) { + Py_RETURN_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; + char *uri; + PyObject *ouri; + + gn = sk_GENERAL_NAME_value(gns, j); + if (gn->type != GEN_URI) { + continue; + } + uri = (char *)gn->d.uniformResourceIdentifier->data; + if ((ouri = PyUnicode_FromString(uri)) == NULL) { + Py_DECREF(lst); + return NULL; + } + if (PyList_Append(lst, ouri) < 0) { + Py_DECREF(ouri); + Py_DECREF(lst); + return NULL; + } + Py_DECREF(ouri); + } + } + /* convert to tuple or None */ + if (PyList_Size(lst) == 0) { + Py_DECREF(lst); + Py_RETURN_NONE; + } else { + PyObject *tup; + tup = PyList_AsTuple(lst); + Py_DECREF(lst); + return tup; + } +} + +static PyObject * _decode_certificate(X509 *certificate) { PyObject *retval = NULL; @@ -906,6 +994,8 @@ PyObject *issuer; PyObject *version; PyObject *sn_obj; + PyObject *ocsp; + PyObject *crldp; ASN1_INTEGER *serialNumber; char buf[2048]; int len; @@ -1012,6 +1102,31 @@ Py_DECREF(peer_alt_names); } + /* OCSP URIs */ + ocsp = _get_ocsp(certificate); + if (ocsp == NULL) { + goto fail1; + } else if (ocsp != Py_None) { + if (PyDict_SetItemString(retval, "OCSP", ocsp) < 0) { + Py_DECREF(ocsp); + goto fail1; + } + Py_DECREF(ocsp); + } + + /* CRL distribution points */ + crldp = _get_crl_dp(certificate); + if (crldp == NULL) { + goto fail1; + } else if (crldp != Py_None) { + if (PyDict_SetItemString(retval, "crlDistributionPoints", + crldp) < 0) { + Py_DECREF(crldp); + goto fail1; + } + Py_DECREF(crldp); + } + BIO_free(biobuf); return retval;