[3.7] bpo-35941: Fix ssl certificate enumeration for windows (GH-12486) by miss-islington · Pull Request #12609 · python/cpython

Expand Up @@ -5401,6 +5401,68 @@ parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags) return retval; }
static HCERTSTORE ssl_collect_certificates(const char *store_name) { /* this function collects the system certificate stores listed in * system_stores into a collection certificate store for being * enumerated. The store must be readable to be added to the * store collection. */
HCERTSTORE hCollectionStore = NULL, hSystemStore = NULL; static DWORD system_stores[] = { CERT_SYSTEM_STORE_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, CERT_SYSTEM_STORE_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, CERT_SYSTEM_STORE_SERVICES, CERT_SYSTEM_STORE_USERS}; size_t i, storesAdded; BOOL result;
hCollectionStore = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, (HCRYPTPROV)NULL, 0, NULL); if (!hCollectionStore) { return NULL; } storesAdded = 0; for (i = 0; i < sizeof(system_stores) / sizeof(DWORD); i++) { hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL, CERT_STORE_READONLY_FLAG | system_stores[i], store_name); if (hSystemStore) { result = CertAddStoreToCollection(hCollectionStore, hSystemStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); if (result) { ++storesAdded; } } } if (storesAdded == 0) { CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_FORCE_FLAG); return NULL; }
return hCollectionStore; }
/* code from Objects/listobject.c */
static int list_contains(PyListObject *a, PyObject *el) { Py_ssize_t i; int cmp;
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i), Py_EQ); return cmp; }
/*[clinic input] _ssl.enum_certificates store_name: str Expand All @@ -5418,7 +5480,7 @@ static PyObject * _ssl_enum_certificates_impl(PyObject *module, const char *store_name) /*[clinic end generated code: output=5134dc8bb3a3c893 input=915f60d70461ea4e]*/ { HCERTSTORE hStore = NULL; HCERTSTORE hCollectionStore = NULL; PCCERT_CONTEXT pCertCtx = NULL; PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; Expand All @@ -5427,15 +5489,13 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name) if (result == NULL) { return NULL; } hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL, CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, store_name); if (hStore == NULL) { hCollectionStore = ssl_collect_certificates(store_name); if (hCollectionStore == NULL) { Py_DECREF(result); return PyErr_SetFromWindowsErr(GetLastError()); }
while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) { while (pCertCtx = CertEnumCertificatesInStore(hCollectionStore, pCertCtx)) { cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded); if (!cert) { Expand Down Expand Up @@ -5465,9 +5525,11 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name) enc = NULL; PyTuple_SET_ITEM(tup, 2, keyusage); keyusage = NULL; if (PyList_Append(result, tup) < 0) { Py_CLEAR(result); break; if (!list_contains((PyListObject*)result, tup)) { if (PyList_Append(result, tup) < 0) { Py_CLEAR(result); break; } } Py_CLEAR(tup); } Expand All @@ -5482,11 +5544,15 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name) Py_XDECREF(keyusage); Py_XDECREF(tup);
if (!CertCloseStore(hStore, 0)) { /* CERT_CLOSE_STORE_FORCE_FLAG forces freeing of memory for all contexts associated with the store, in this case our collection store and the associated system stores. */ if (!CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_FORCE_FLAG)) { /* This error case might shadow another exception.*/ Py_XDECREF(result); return PyErr_SetFromWindowsErr(GetLastError()); }
return result; }
Expand All @@ -5506,7 +5572,7 @@ static PyObject * _ssl_enum_crls_impl(PyObject *module, const char *store_name) /*[clinic end generated code: output=bce467f60ccd03b6 input=a1f1d7629f1c5d3d]*/ { HCERTSTORE hStore = NULL; HCERTSTORE hCollectionStore = NULL; PCCRL_CONTEXT pCrlCtx = NULL; PyObject *crl = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; Expand All @@ -5515,15 +5581,13 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name) if (result == NULL) { return NULL; } hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL, CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, store_name); if (hStore == NULL) { hCollectionStore = ssl_collect_certificates(store_name); if (hCollectionStore == NULL) { Py_DECREF(result); return PyErr_SetFromWindowsErr(GetLastError()); }
while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) { while (pCrlCtx = CertEnumCRLsInStore(hCollectionStore, pCrlCtx)) { crl = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded, pCrlCtx->cbCrlEncoded); if (!crl) { Expand All @@ -5543,9 +5607,11 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name) PyTuple_SET_ITEM(tup, 1, enc); enc = NULL;
if (PyList_Append(result, tup) < 0) { Py_CLEAR(result); break; if (!list_contains((PyListObject*)result, tup)) { if (PyList_Append(result, tup) < 0) { Py_CLEAR(result); break; } } Py_CLEAR(tup); } Expand All @@ -5559,7 +5625,10 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name) Py_XDECREF(enc); Py_XDECREF(tup);
if (!CertCloseStore(hStore, 0)) { /* CERT_CLOSE_STORE_FORCE_FLAG forces freeing of memory for all contexts associated with the store, in this case our collection store and the associated system stores. */ if (!CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_FORCE_FLAG)) { /* This error case might shadow another exception.*/ Py_XDECREF(result); return PyErr_SetFromWindowsErr(GetLastError()); Expand Down