diff options
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r-- | Modules/_ssl.c | 109 |
1 files changed, 89 insertions, 20 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 7076fddf8d..fff1a28843 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -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 @@ -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; @@ -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) { @@ -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); } @@ -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; } @@ -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; @@ -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) { @@ -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); } @@ -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()); |