@@ -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