Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d93fbbf

Browse files
kctherookiezooba
authored andcommitted
bpo-35941: Fix ssl certificate enumeration for windows (GH-12486)
Add a function to collect certificates from several certificate stores into one certificate collection store that is then enumerated. This ensures we load as many certificates as we can access.
1 parent 45a5fdb commit d93fbbf

2 files changed

Lines changed: 92 additions & 20 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
enum_certificates function of the ssl module now returns certificates from all available certificate stores inside windows in a query instead of returning only certificates from the system wide certificate store.
2+
This includes certificates from these certificate stores: local machine, local machine enterprise, local machine group policy, current user, current user group policy, services, users.
3+
ssl.enum_crls() function is changed in the same way to return all certificate revocation lists inside the windows certificate revocation list stores.

Modules/_ssl.c

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5400,6 +5400,68 @@ parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags)
54005400
return retval;
54015401
}
54025402

5403+
static HCERTSTORE
5404+
ssl_collect_certificates(const char *store_name)
5405+
{
5406+
/* this function collects the system certificate stores listed in
5407+
* system_stores into a collection certificate store for being
5408+
* enumerated. The store must be readable to be added to the
5409+
* store collection.
5410+
*/
5411+
5412+
HCERTSTORE hCollectionStore = NULL, hSystemStore = NULL;
5413+
static DWORD system_stores[] = {
5414+
CERT_SYSTEM_STORE_LOCAL_MACHINE,
5415+
CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
5416+
CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
5417+
CERT_SYSTEM_STORE_CURRENT_USER,
5418+
CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
5419+
CERT_SYSTEM_STORE_SERVICES,
5420+
CERT_SYSTEM_STORE_USERS};
5421+
size_t i, storesAdded;
5422+
BOOL result;
5423+
5424+
hCollectionStore = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0,
5425+
(HCRYPTPROV)NULL, 0, NULL);
5426+
if (!hCollectionStore) {
5427+
return NULL;
5428+
}
5429+
storesAdded = 0;
5430+
for (i = 0; i < sizeof(system_stores) / sizeof(DWORD); i++) {
5431+
hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0,
5432+
(HCRYPTPROV)NULL,
5433+
CERT_STORE_READONLY_FLAG |
5434+
system_stores[i], store_name);
5435+
if (hSystemStore) {
5436+
result = CertAddStoreToCollection(hCollectionStore, hSystemStore,
5437+
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
5438+
if (result) {
5439+
++storesAdded;
5440+
}
5441+
}
5442+
}
5443+
if (storesAdded == 0) {
5444+
CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_FORCE_FLAG);
5445+
return NULL;
5446+
}
5447+
5448+
return hCollectionStore;
5449+
}
5450+
5451+
/* code from Objects/listobject.c */
5452+
5453+
static int
5454+
list_contains(PyListObject *a, PyObject *el)
5455+
{
5456+
Py_ssize_t i;
5457+
int cmp;
5458+
5459+
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
5460+
cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
5461+
Py_EQ);
5462+
return cmp;
5463+
}
5464+
54035465
/*[clinic input]
54045466
_ssl.enum_certificates
54055467
store_name: str
@@ -5417,7 +5479,7 @@ static PyObject *
54175479
_ssl_enum_certificates_impl(PyObject *module, const char *store_name)
54185480
/*[clinic end generated code: output=5134dc8bb3a3c893 input=915f60d70461ea4e]*/
54195481
{
5420-
HCERTSTORE hStore = NULL;
5482+
HCERTSTORE hCollectionStore = NULL;
54215483
PCCERT_CONTEXT pCertCtx = NULL;
54225484
PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL;
54235485
PyObject *result = NULL;
@@ -5426,15 +5488,13 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name)
54265488
if (result == NULL) {
54275489
return NULL;
54285490
}
5429-
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL,
5430-
CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
5431-
store_name);
5432-
if (hStore == NULL) {
5491+
hCollectionStore = ssl_collect_certificates(store_name);
5492+
if (hCollectionStore == NULL) {
54335493
Py_DECREF(result);
54345494
return PyErr_SetFromWindowsErr(GetLastError());
54355495
}
54365496

5437-
while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) {
5497+
while (pCertCtx = CertEnumCertificatesInStore(hCollectionStore, pCertCtx)) {
54385498
cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded,
54395499
pCertCtx->cbCertEncoded);
54405500
if (!cert) {
@@ -5464,9 +5524,11 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name)
54645524
enc = NULL;
54655525
PyTuple_SET_ITEM(tup, 2, keyusage);
54665526
keyusage = NULL;
5467-
if (PyList_Append(result, tup) < 0) {
5468-
Py_CLEAR(result);
5469-
break;
5527+
if (!list_contains((PyListObject*)result, tup)) {
5528+
if (PyList_Append(result, tup) < 0) {
5529+
Py_CLEAR(result);
5530+
break;
5531+
}
54705532
}
54715533
Py_CLEAR(tup);
54725534
}
@@ -5481,11 +5543,15 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name)
54815543
Py_XDECREF(keyusage);
54825544
Py_XDECREF(tup);
54835545

5484-
if (!CertCloseStore(hStore, 0)) {
5546+
/* CERT_CLOSE_STORE_FORCE_FLAG forces freeing of memory for all contexts
5547+
associated with the store, in this case our collection store and the
5548+
associated system stores. */
5549+
if (!CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_FORCE_FLAG)) {
54855550
/* This error case might shadow another exception.*/
54865551
Py_XDECREF(result);
54875552
return PyErr_SetFromWindowsErr(GetLastError());
54885553
}
5554+
54895555
return result;
54905556
}
54915557

@@ -5505,7 +5571,7 @@ static PyObject *
55055571
_ssl_enum_crls_impl(PyObject *module, const char *store_name)
55065572
/*[clinic end generated code: output=bce467f60ccd03b6 input=a1f1d7629f1c5d3d]*/
55075573
{
5508-
HCERTSTORE hStore = NULL;
5574+
HCERTSTORE hCollectionStore = NULL;
55095575
PCCRL_CONTEXT pCrlCtx = NULL;
55105576
PyObject *crl = NULL, *enc = NULL, *tup = NULL;
55115577
PyObject *result = NULL;
@@ -5514,15 +5580,13 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name)
55145580
if (result == NULL) {
55155581
return NULL;
55165582
}
5517-
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL,
5518-
CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
5519-
store_name);
5520-
if (hStore == NULL) {
5583+
hCollectionStore = ssl_collect_certificates(store_name);
5584+
if (hCollectionStore == NULL) {
55215585
Py_DECREF(result);
55225586
return PyErr_SetFromWindowsErr(GetLastError());
55235587
}
55245588

5525-
while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) {
5589+
while (pCrlCtx = CertEnumCRLsInStore(hCollectionStore, pCrlCtx)) {
55265590
crl = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded,
55275591
pCrlCtx->cbCrlEncoded);
55285592
if (!crl) {
@@ -5542,9 +5606,11 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name)
55425606
PyTuple_SET_ITEM(tup, 1, enc);
55435607
enc = NULL;
55445608

5545-
if (PyList_Append(result, tup) < 0) {
5546-
Py_CLEAR(result);
5547-
break;
5609+
if (!list_contains((PyListObject*)result, tup)) {
5610+
if (PyList_Append(result, tup) < 0) {
5611+
Py_CLEAR(result);
5612+
break;
5613+
}
55485614
}
55495615
Py_CLEAR(tup);
55505616
}
@@ -5558,7 +5624,10 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name)
55585624
Py_XDECREF(enc);
55595625
Py_XDECREF(tup);
55605626

5561-
if (!CertCloseStore(hStore, 0)) {
5627+
/* CERT_CLOSE_STORE_FORCE_FLAG forces freeing of memory for all contexts
5628+
associated with the store, in this case our collection store and the
5629+
associated system stores. */
5630+
if (!CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_FORCE_FLAG)) {
55625631
/* This error case might shadow another exception.*/
55635632
Py_XDECREF(result);
55645633
return PyErr_SetFromWindowsErr(GetLastError());

0 commit comments

Comments
 (0)