Issue #17134: Finalize interface to Windows' certificate store. Cert and
CRL enumeration are now two functions. enum_certificates() also returns purpose flags as set of OIDs.
This commit is contained in:
parent
d062892542
commit
44109d7de7
|
@ -372,21 +372,45 @@ Certificate handling
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
.. function:: enum_cert_store(store_name, cert_type='certificate')
|
.. function:: enum_certificates(store_name)
|
||||||
|
|
||||||
Retrieve certificates from Windows' system cert store. *store_name* may be
|
Retrieve certificates from Windows' system cert store. *store_name* may be
|
||||||
one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert
|
one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert
|
||||||
stores, too. *cert_type* is either ``certificate`` for X.509 certificates
|
stores, too.
|
||||||
or ``crl`` for X.509 certificate revocation lists.
|
|
||||||
|
|
||||||
The function returns a list of (bytes, encoding_type) tuples. The
|
The function returns a list of (cert_bytes, encoding_type, trust) tuples.
|
||||||
encoding_type flag can be interpreted with :const:`X509_ASN_ENCODING` or
|
The encoding_type specifies the encoding of cert_bytes. It is either
|
||||||
:const:`PKCS_7_ASN_ENCODING`.
|
:const:`x509_asn` for X.509 ASN.1 data or :const:`pkcs_7_asn` for
|
||||||
|
PKCS#7 ASN.1 data. Trust specifies the purpose of the certificate as a set
|
||||||
|
of OIDS or exactly ``True`` if the certificate is trustworthy for all
|
||||||
|
purposes.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
>>> ssl.enum_certificates("CA")
|
||||||
|
[(b'data...', 'x509_asn', {'1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2'}),
|
||||||
|
(b'data...', 'x509_asn', True)]
|
||||||
|
|
||||||
Availability: Windows.
|
Availability: Windows.
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
.. function:: enum_crls(store_name)
|
||||||
|
|
||||||
|
Retrieve CRLs from Windows' system cert store. *store_name* may be
|
||||||
|
one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert
|
||||||
|
stores, too.
|
||||||
|
|
||||||
|
The function returns a list of (cert_bytes, encoding_type, trust) tuples.
|
||||||
|
The encoding_type specifies the encoding of cert_bytes. It is either
|
||||||
|
:const:`x509_asn` for X.509 ASN.1 data or :const:`pkcs_7_asn` for
|
||||||
|
PKCS#7 ASN.1 data.
|
||||||
|
|
||||||
|
Availability: Windows.
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
|
||||||
Constants
|
Constants
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
|
@ -657,15 +681,6 @@ Constants
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
.. data:: X509_ASN_ENCODING
|
|
||||||
PKCS_7_ASN_ENCODING
|
|
||||||
|
|
||||||
Encoding flags for :func:`enum_cert_store`.
|
|
||||||
|
|
||||||
Availability: Windows.
|
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
|
||||||
|
|
||||||
|
|
||||||
SSL Sockets
|
SSL Sockets
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -144,7 +144,7 @@ else:
|
||||||
_PROTOCOL_NAMES[PROTOCOL_TLSv1_2] = "TLSv1.2"
|
_PROTOCOL_NAMES[PROTOCOL_TLSv1_2] = "TLSv1.2"
|
||||||
|
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
from _ssl import enum_cert_store, X509_ASN_ENCODING, PKCS_7_ASN_ENCODING
|
from _ssl import enum_certificates, enum_crls
|
||||||
|
|
||||||
from socket import getnameinfo as _getnameinfo
|
from socket import getnameinfo as _getnameinfo
|
||||||
from socket import socket, AF_INET, SOCK_STREAM, create_connection
|
from socket import socket, AF_INET, SOCK_STREAM, create_connection
|
||||||
|
|
|
@ -528,29 +528,44 @@ class BasicSocketTests(unittest.TestCase):
|
||||||
self.assertEqual(paths.cafile, CERTFILE)
|
self.assertEqual(paths.cafile, CERTFILE)
|
||||||
self.assertEqual(paths.capath, CAPATH)
|
self.assertEqual(paths.capath, CAPATH)
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "win32", "Windows specific")
|
||||||
|
def test_enum_certificates(self):
|
||||||
|
self.assertTrue(ssl.enum_certificates("CA"))
|
||||||
|
self.assertTrue(ssl.enum_certificates("ROOT"))
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, ssl.enum_certificates)
|
||||||
|
self.assertRaises(WindowsError, ssl.enum_certificates, "")
|
||||||
|
|
||||||
|
names = set()
|
||||||
|
ca = ssl.enum_certificates("CA")
|
||||||
|
self.assertIsInstance(ca, list)
|
||||||
|
for element in ca:
|
||||||
|
self.assertIsInstance(element, tuple)
|
||||||
|
self.assertEqual(len(element), 3)
|
||||||
|
cert, enc, trust = element
|
||||||
|
self.assertIsInstance(cert, bytes)
|
||||||
|
self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
|
||||||
|
self.assertIsInstance(trust, (set, bool))
|
||||||
|
if isinstance(trust, set):
|
||||||
|
names.update(trust)
|
||||||
|
|
||||||
|
serverAuth = "1.3.6.1.5.5.7.3.1"
|
||||||
|
self.assertIn(serverAuth, names)
|
||||||
|
|
||||||
@unittest.skipUnless(sys.platform == "win32", "Windows specific")
|
@unittest.skipUnless(sys.platform == "win32", "Windows specific")
|
||||||
def test_enum_cert_store(self):
|
def test_enum_crls(self):
|
||||||
self.assertEqual(ssl.X509_ASN_ENCODING, 1)
|
self.assertTrue(ssl.enum_crls("CA"))
|
||||||
self.assertEqual(ssl.PKCS_7_ASN_ENCODING, 0x00010000)
|
self.assertRaises(TypeError, ssl.enum_crls)
|
||||||
|
self.assertRaises(WindowsError, ssl.enum_crls, "")
|
||||||
|
|
||||||
self.assertEqual(ssl.enum_cert_store("CA"),
|
crls = ssl.enum_crls("CA")
|
||||||
ssl.enum_cert_store("CA", "certificate"))
|
self.assertIsInstance(crls, list)
|
||||||
ssl.enum_cert_store("CA", "crl")
|
for element in crls:
|
||||||
self.assertEqual(ssl.enum_cert_store("ROOT"),
|
self.assertIsInstance(element, tuple)
|
||||||
ssl.enum_cert_store("ROOT", "certificate"))
|
self.assertEqual(len(element), 2)
|
||||||
ssl.enum_cert_store("ROOT", "crl")
|
self.assertIsInstance(element[0], bytes)
|
||||||
|
self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
|
||||||
|
|
||||||
self.assertRaises(TypeError, ssl.enum_cert_store)
|
|
||||||
self.assertRaises(WindowsError, ssl.enum_cert_store, "")
|
|
||||||
self.assertRaises(ValueError, ssl.enum_cert_store, "CA", "wrong")
|
|
||||||
|
|
||||||
ca = ssl.enum_cert_store("CA")
|
|
||||||
self.assertIsInstance(ca, list)
|
|
||||||
self.assertIsInstance(ca[0], tuple)
|
|
||||||
self.assertEqual(len(ca[0]), 2)
|
|
||||||
self.assertIsInstance(ca[0][0], bytes)
|
|
||||||
self.assertIsInstance(ca[0][1], int)
|
|
||||||
|
|
||||||
def test_asn1object(self):
|
def test_asn1object(self):
|
||||||
expected = (129, 'serverAuth', 'TLS Web Server Authentication',
|
expected = (129, 'serverAuth', 'TLS Web Server Authentication',
|
||||||
|
|
|
@ -59,6 +59,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #17134: Finalize interface to Windows' certificate store. Cert and
|
||||||
|
CRL enumeration are now two functions. enum_certificates() also returns
|
||||||
|
purpose flags as set of OIDs.
|
||||||
|
|
||||||
- Issue #19555: Restore sysconfig.get_config_var('SO'), with a
|
- Issue #19555: Restore sysconfig.get_config_var('SO'), with a
|
||||||
DeprecationWarning pointing people at $EXT_SUFFIX.
|
DeprecationWarning pointing people at $EXT_SUFFIX.
|
||||||
|
|
||||||
|
|
316
Modules/_ssl.c
316
Modules/_ssl.c
|
@ -3422,130 +3422,258 @@ PySSL_nid2obj(PyObject *self, PyObject *args)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
PyDoc_STRVAR(PySSL_enum_cert_store_doc,
|
|
||||||
"enum_cert_store(store_name, cert_type='certificate') -> []\n\
|
static PyObject*
|
||||||
|
certEncodingType(DWORD encodingType)
|
||||||
|
{
|
||||||
|
static PyObject *x509_asn = NULL;
|
||||||
|
static PyObject *pkcs_7_asn = NULL;
|
||||||
|
|
||||||
|
if (x509_asn == NULL) {
|
||||||
|
x509_asn = PyUnicode_InternFromString("x509_asn");
|
||||||
|
if (x509_asn == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (pkcs_7_asn == NULL) {
|
||||||
|
pkcs_7_asn = PyUnicode_InternFromString("pkcs_7_asn");
|
||||||
|
if (pkcs_7_asn == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
switch(encodingType) {
|
||||||
|
case X509_ASN_ENCODING:
|
||||||
|
Py_INCREF(x509_asn);
|
||||||
|
return x509_asn;
|
||||||
|
case PKCS_7_ASN_ENCODING:
|
||||||
|
Py_INCREF(pkcs_7_asn);
|
||||||
|
return pkcs_7_asn;
|
||||||
|
default:
|
||||||
|
return PyLong_FromLong(encodingType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags)
|
||||||
|
{
|
||||||
|
CERT_ENHKEY_USAGE *usage;
|
||||||
|
DWORD size, error, i;
|
||||||
|
PyObject *retval;
|
||||||
|
|
||||||
|
if (!CertGetEnhancedKeyUsage(pCertCtx, flags, NULL, &size)) {
|
||||||
|
error = GetLastError();
|
||||||
|
if (error == CRYPT_E_NOT_FOUND) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
return PyErr_SetFromWindowsErr(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
usage = (CERT_ENHKEY_USAGE*)PyMem_Malloc(size);
|
||||||
|
if (usage == NULL) {
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now get the actual enhanced usage property */
|
||||||
|
if (!CertGetEnhancedKeyUsage(pCertCtx, flags, usage, &size)) {
|
||||||
|
PyMem_Free(usage);
|
||||||
|
error = GetLastError();
|
||||||
|
if (error == CRYPT_E_NOT_FOUND) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
return PyErr_SetFromWindowsErr(error);
|
||||||
|
}
|
||||||
|
retval = PySet_New(NULL);
|
||||||
|
if (retval == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
for (i = 0; i < usage->cUsageIdentifier; ++i) {
|
||||||
|
if (usage->rgpszUsageIdentifier[i]) {
|
||||||
|
PyObject *oid;
|
||||||
|
int err;
|
||||||
|
oid = PyUnicode_FromString(usage->rgpszUsageIdentifier[i]);
|
||||||
|
if (oid == NULL) {
|
||||||
|
Py_CLEAR(retval);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
err = PySet_Add(retval, oid);
|
||||||
|
Py_DECREF(oid);
|
||||||
|
if (err == -1) {
|
||||||
|
Py_CLEAR(retval);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
PyMem_Free(usage);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(PySSL_enum_certificates_doc,
|
||||||
|
"enum_certificates(store_name) -> []\n\
|
||||||
\n\
|
\n\
|
||||||
Retrieve certificates from Windows' cert store. store_name may be one of\n\
|
Retrieve certificates from Windows' cert store. store_name may be one of\n\
|
||||||
'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\
|
'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\
|
||||||
cert_type must be either 'certificate' or 'crl'.\n\
|
The function returns a list of (bytes, encoding_type, trust) tuples. The\n\
|
||||||
The function returns a list of (bytes, encoding_type) tuples. The\n\
|
|
||||||
encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\
|
encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\
|
||||||
PKCS_7_ASN_ENCODING.");
|
PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the\n\
|
||||||
|
boolean True.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PySSL_enum_cert_store(PyObject *self, PyObject *args, PyObject *kwds)
|
PySSL_enum_certificates(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
char *kwlist[] = {"store_name", "cert_type", NULL};
|
char *kwlist[] = {"store_name", NULL};
|
||||||
char *store_name;
|
char *store_name;
|
||||||
char *cert_type = "certificate";
|
|
||||||
HCERTSTORE hStore = NULL;
|
HCERTSTORE hStore = NULL;
|
||||||
|
PCCERT_CONTEXT pCertCtx = NULL;
|
||||||
|
PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL;
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
PyObject *tup = NULL, *cert = NULL, *enc = NULL;
|
|
||||||
int ok = 1;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_cert_store",
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_certificates",
|
||||||
kwlist, &store_name, &cert_type)) {
|
kwlist, &store_name)) {
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((strcmp(cert_type, "certificate") != 0) &&
|
|
||||||
(strcmp(cert_type, "crl") != 0)) {
|
|
||||||
return PyErr_Format(PyExc_ValueError,
|
|
||||||
"cert_type must be 'certificate' or 'crl', "
|
|
||||||
"not %.100s", cert_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((result = PyList_New(0)) == NULL) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
result = PyList_New(0);
|
||||||
if ((hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name)) == NULL) {
|
if (result == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
|
||||||
|
if (hStore == NULL) {
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
return PyErr_SetFromWindowsErr(GetLastError());
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(cert_type, "certificate") == 0) {
|
while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) {
|
||||||
PCCERT_CONTEXT pCertCtx = NULL;
|
cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded,
|
||||||
while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) {
|
pCertCtx->cbCertEncoded);
|
||||||
cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded,
|
if (!cert) {
|
||||||
pCertCtx->cbCertEncoded);
|
Py_CLEAR(result);
|
||||||
if (!cert) {
|
break;
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((enc = PyLong_FromLong(pCertCtx->dwCertEncodingType)) == NULL) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((tup = PyTuple_New(2)) == NULL) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
PyTuple_SET_ITEM(tup, 0, cert); cert = NULL;
|
|
||||||
PyTuple_SET_ITEM(tup, 1, enc); enc = NULL;
|
|
||||||
|
|
||||||
if (PyList_Append(result, tup) < 0) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Py_CLEAR(tup);
|
|
||||||
}
|
}
|
||||||
if (pCertCtx) {
|
if ((enc = certEncodingType(pCertCtx->dwCertEncodingType)) == NULL) {
|
||||||
/* loop ended with an error, need to clean up context manually */
|
Py_CLEAR(result);
|
||||||
CertFreeCertificateContext(pCertCtx);
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
keyusage = parseKeyUsage(pCertCtx, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG);
|
||||||
PCCRL_CONTEXT pCrlCtx = NULL;
|
if (keyusage == Py_True) {
|
||||||
while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) {
|
Py_DECREF(keyusage);
|
||||||
cert = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded,
|
keyusage = parseKeyUsage(pCertCtx, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG);
|
||||||
pCrlCtx->cbCrlEncoded);
|
|
||||||
if (!cert) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((enc = PyLong_FromLong(pCrlCtx->dwCertEncodingType)) == NULL) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((tup = PyTuple_New(2)) == NULL) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
PyTuple_SET_ITEM(tup, 0, cert); cert = NULL;
|
|
||||||
PyTuple_SET_ITEM(tup, 1, enc); enc = NULL;
|
|
||||||
|
|
||||||
if (PyList_Append(result, tup) < 0) {
|
|
||||||
ok = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Py_CLEAR(tup);
|
|
||||||
}
|
}
|
||||||
if (pCrlCtx) {
|
if (keyusage == NULL) {
|
||||||
/* loop ended with an error, need to clean up context manually */
|
Py_CLEAR(result);
|
||||||
CertFreeCRLContext(pCrlCtx);
|
break;
|
||||||
}
|
}
|
||||||
|
if ((tup = PyTuple_New(3)) == NULL) {
|
||||||
|
Py_CLEAR(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PyTuple_SET_ITEM(tup, 0, cert);
|
||||||
|
cert = NULL;
|
||||||
|
PyTuple_SET_ITEM(tup, 1, enc);
|
||||||
|
enc = NULL;
|
||||||
|
PyTuple_SET_ITEM(tup, 2, keyusage);
|
||||||
|
keyusage = NULL;
|
||||||
|
if (PyList_Append(result, tup) < 0) {
|
||||||
|
Py_CLEAR(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Py_CLEAR(tup);
|
||||||
|
}
|
||||||
|
if (pCertCtx) {
|
||||||
|
/* loop ended with an error, need to clean up context manually */
|
||||||
|
CertFreeCertificateContext(pCertCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In error cases cert, enc and tup may not be NULL */
|
/* In error cases cert, enc and tup may not be NULL */
|
||||||
Py_XDECREF(cert);
|
Py_XDECREF(cert);
|
||||||
Py_XDECREF(enc);
|
Py_XDECREF(enc);
|
||||||
|
Py_XDECREF(keyusage);
|
||||||
Py_XDECREF(tup);
|
Py_XDECREF(tup);
|
||||||
|
|
||||||
if (!CertCloseStore(hStore, 0)) {
|
if (!CertCloseStore(hStore, 0)) {
|
||||||
/* This error case might shadow another exception.*/
|
/* This error case might shadow another exception.*/
|
||||||
|
Py_XDECREF(result);
|
||||||
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(PySSL_enum_crls_doc,
|
||||||
|
"enum_crls(store_name) -> []\n\
|
||||||
|
\n\
|
||||||
|
Retrieve CRLs from Windows' cert store. store_name may be one of\n\
|
||||||
|
'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\
|
||||||
|
The function returns a list of (bytes, encoding_type) tuples. The\n\
|
||||||
|
encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\
|
||||||
|
PKCS_7_ASN_ENCODING.");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
PySSL_enum_crls(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
char *kwlist[] = {"store_name", NULL};
|
||||||
|
char *store_name;
|
||||||
|
HCERTSTORE hStore = NULL;
|
||||||
|
PCCRL_CONTEXT pCrlCtx = NULL;
|
||||||
|
PyObject *crl = NULL, *enc = NULL, *tup = NULL;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_crls",
|
||||||
|
kwlist, &store_name)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = PyList_New(0);
|
||||||
|
if (result == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
|
||||||
|
if (hStore == NULL) {
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
return PyErr_SetFromWindowsErr(GetLastError());
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
}
|
}
|
||||||
if (ok) {
|
|
||||||
return result;
|
while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) {
|
||||||
} else {
|
crl = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded,
|
||||||
Py_DECREF(result);
|
pCrlCtx->cbCrlEncoded);
|
||||||
return NULL;
|
if (!crl) {
|
||||||
|
Py_CLEAR(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((enc = certEncodingType(pCrlCtx->dwCertEncodingType)) == NULL) {
|
||||||
|
Py_CLEAR(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((tup = PyTuple_New(2)) == NULL) {
|
||||||
|
Py_CLEAR(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PyTuple_SET_ITEM(tup, 0, crl);
|
||||||
|
crl = NULL;
|
||||||
|
PyTuple_SET_ITEM(tup, 1, enc);
|
||||||
|
enc = NULL;
|
||||||
|
|
||||||
|
if (PyList_Append(result, tup) < 0) {
|
||||||
|
Py_CLEAR(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Py_CLEAR(tup);
|
||||||
}
|
}
|
||||||
|
if (pCrlCtx) {
|
||||||
|
/* loop ended with an error, need to clean up context manually */
|
||||||
|
CertFreeCRLContext(pCrlCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In error cases cert, enc and tup may not be NULL */
|
||||||
|
Py_XDECREF(crl);
|
||||||
|
Py_XDECREF(enc);
|
||||||
|
Py_XDECREF(tup);
|
||||||
|
|
||||||
|
if (!CertCloseStore(hStore, 0)) {
|
||||||
|
/* This error case might shadow another exception.*/
|
||||||
|
Py_XDECREF(result);
|
||||||
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
/* List of functions exported by this module. */
|
/* List of functions exported by this module. */
|
||||||
|
|
||||||
|
@ -3567,8 +3695,10 @@ static PyMethodDef PySSL_methods[] = {
|
||||||
{"get_default_verify_paths", (PyCFunction)PySSL_get_default_verify_paths,
|
{"get_default_verify_paths", (PyCFunction)PySSL_get_default_verify_paths,
|
||||||
METH_NOARGS, PySSL_get_default_verify_paths_doc},
|
METH_NOARGS, PySSL_get_default_verify_paths_doc},
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
{"enum_cert_store", (PyCFunction)PySSL_enum_cert_store,
|
{"enum_certificates", (PyCFunction)PySSL_enum_certificates,
|
||||||
METH_VARARGS | METH_KEYWORDS, PySSL_enum_cert_store_doc},
|
METH_VARARGS | METH_KEYWORDS, PySSL_enum_certificates_doc},
|
||||||
|
{"enum_crls", (PyCFunction)PySSL_enum_crls,
|
||||||
|
METH_VARARGS | METH_KEYWORDS, PySSL_enum_crls_doc},
|
||||||
#endif
|
#endif
|
||||||
{"txt2obj", (PyCFunction)PySSL_txt2obj,
|
{"txt2obj", (PyCFunction)PySSL_txt2obj,
|
||||||
METH_VARARGS | METH_KEYWORDS, PySSL_txt2obj_doc},
|
METH_VARARGS | METH_KEYWORDS, PySSL_txt2obj_doc},
|
||||||
|
@ -3811,12 +3941,6 @@ PyInit__ssl(void)
|
||||||
PyModule_AddIntConstant(m, "VERIFY_X509_STRICT",
|
PyModule_AddIntConstant(m, "VERIFY_X509_STRICT",
|
||||||
X509_V_FLAG_X509_STRICT);
|
X509_V_FLAG_X509_STRICT);
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
/* Windows dwCertEncodingType */
|
|
||||||
PyModule_AddIntMacro(m, X509_ASN_ENCODING);
|
|
||||||
PyModule_AddIntMacro(m, PKCS_7_ASN_ENCODING);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Alert Descriptions from ssl.h */
|
/* Alert Descriptions from ssl.h */
|
||||||
/* note RESERVED constants no longer intended for use have been removed */
|
/* note RESERVED constants no longer intended for use have been removed */
|
||||||
/* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */
|
/* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */
|
||||||
|
|
Loading…
Reference in New Issue