summaryrefslogtreecommitdiffstats
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
authorChristian Heimes <christian@cheimes.de>2013-06-09 17:03:31 (GMT)
committerChristian Heimes <christian@cheimes.de>2013-06-09 17:03:31 (GMT)
commit46bebee25f8cdbec6bbee04fdf9681edf0155c5b (patch)
tree1efc519de6a189022c18f84d46c234fa48bf55ff /Modules/_ssl.c
parent142ec2c0149995c8d2299eaf6eccec9c69d6110b (diff)
downloadcpython-46bebee25f8cdbec6bbee04fdf9681edf0155c5b.zip
cpython-46bebee25f8cdbec6bbee04fdf9681edf0155c5b.tar.gz
cpython-46bebee25f8cdbec6bbee04fdf9681edf0155c5b.tar.bz2
Issue #17134: Add ssl.enum_cert_store() as interface to Windows' cert store.
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r--Modules/_ssl.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 999dd09..5959f18 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -2801,7 +2801,129 @@ get_default_verify_paths(PyObject *self)
return NULL;
}
+#ifdef _MSC_VER
+PyDoc_STRVAR(PySSL_enum_cert_store_doc,
+"enum_cert_store(store_name, cert_type='certificate') -> []\n\
+\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\
+cert_type must be either 'certificate' or 'crl'.\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_cert_store(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ char *kwlist[] = {"store_name", "cert_type", NULL};
+ char *store_name;
+ char *cert_type = "certificate";
+ HCERTSTORE hStore = NULL;
+ PyObject *result = NULL;
+ PyObject *tup = NULL, *cert = NULL, *enc = NULL;
+ int ok = 1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_cert_store",
+ kwlist, &store_name, &cert_type)) {
+ 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;
+ }
+
+ if ((hStore = CertOpenSystemStore(NULL, store_name)) == NULL) {
+ Py_DECREF(result);
+ return PyErr_SetFromWindowsErr(GetLastError());
+ }
+ if (strcmp(cert_type, "certificate") == 0) {
+ PCCERT_CONTEXT pCertCtx = NULL;
+ while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) {
+ cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded,
+ pCertCtx->cbCertEncoded);
+ if (!cert) {
+ 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) {
+ /* loop ended with an error, need to clean up context manually */
+ CertFreeCertificateContext(pCertCtx);
+ }
+ } else {
+ PCCRL_CONTEXT pCrlCtx = NULL;
+ while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) {
+ cert = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded,
+ 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) {
+ /* 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(cert);
+ Py_XDECREF(enc);
+ Py_XDECREF(tup);
+
+ if (!CertCloseStore(hStore, 0)) {
+ /* This error case might shadow another exception.*/
+ Py_DECREF(result);
+ return PyErr_SetFromWindowsErr(GetLastError());
+ }
+ if (ok) {
+ return result;
+ } else {
+ Py_DECREF(result);
+ return NULL;
+ }
+}
+#endif
/* List of functions exported by this module. */
@@ -2822,6 +2944,10 @@ static PyMethodDef PySSL_methods[] = {
#endif
{"get_default_verify_paths", (PyCFunction)get_default_verify_paths,
METH_NOARGS, PySSL_get_default_verify_paths_doc},
+#ifdef _MSC_VER
+ {"enum_cert_store", (PyCFunction)PySSL_enum_cert_store,
+ METH_VARARGS | METH_KEYWORDS, PySSL_enum_cert_store_doc},
+#endif
{NULL, NULL} /* Sentinel */
};
@@ -3034,6 +3160,12 @@ PyInit__ssl(void)
PyModule_AddIntConstant(m, "CERT_REQUIRED",
PY_SSL_CERT_REQUIRED);
+#ifdef _MSC_VER
+ /* Windows dwCertEncodingType */
+ PyModule_AddIntMacro(m, X509_ASN_ENCODING);
+ PyModule_AddIntMacro(m, PKCS_7_ASN_ENCODING);
+#endif
+
/* Alert Descriptions from ssl.h */
/* note RESERVED constants no longer intended for use have been removed */
/* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */