summaryrefslogtreecommitdiff
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r--Modules/_ssl.c109
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());