From 774cc56ed257aed6f744768dd8d35ac4fa5bdb04 Mon Sep 17 00:00:00 2001 From: Joris Vink Date: Sat, 11 Dec 2021 22:37:15 +0100 Subject: [PATCH] Python: Add an req.connection.x509dict This dictionary for now only contains the subject and issuer names from the client certificate (if one was provided) with their X509_NAME components. Eg: { "issuer": { "C": "SE", "O": "kore autogen: x509name-test", "CN": "localhost" }, "subject": { "C": "SE", "O": "kore autogen: x509name-test", "CN": "localhost" } } --- include/kore/python_methods.h | 2 + src/python.c | 93 +++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h index 1160130..72112d0 100644 --- a/include/kore/python_methods.h +++ b/include/kore/python_methods.h @@ -696,11 +696,13 @@ static PyObject *pyconnection_get_fd(struct pyconnection *, void *); static PyObject *pyconnection_get_addr(struct pyconnection *, void *); static PyObject *pyconnection_get_peer_x509(struct pyconnection *, void *); +static PyObject *pyconnection_get_peer_x509dict(struct pyconnection *, void *); static PyGetSetDef pyconnection_getset[] = { GETTER("fd", pyconnection_get_fd), GETTER("addr", pyconnection_get_addr), GETTER("x509", pyconnection_get_peer_x509), + GETTER("x509dict", pyconnection_get_peer_x509dict), GETTER(NULL, NULL), }; diff --git a/src/python.c b/src/python.c index 99e1c59..5a3259d 100644 --- a/src/python.c +++ b/src/python.c @@ -119,6 +119,9 @@ static int pyhttp_iterobj_chunk_sent(struct netbuf *); static int pyhttp_iterobj_next(struct pyhttp_iterobj *); static void pyhttp_iterobj_disconnect(struct connection *); +static int pyconnection_x509_cb(void *, int, int, const char *, + const void *, size_t, int); + #if defined(KORE_USE_PGSQL) static int pykore_pgsql_result(struct pykore_pgsql *); static void pykore_pgsql_callback(struct kore_pgsql *, void *); @@ -2845,6 +2848,96 @@ pyconnection_get_peer_x509(struct pyconnection *pyc, void *closure) return (bytes); } +static PyObject * +pyconnection_get_peer_x509dict(struct pyconnection *pyc, void *closure) +{ + X509_NAME *name; + PyObject *dict, *issuer, *subject, *ret; + + ret = NULL; + issuer = NULL; + subject = NULL; + + if (pyc->c->cert == NULL) { + Py_RETURN_NONE; + } + + if ((dict = PyDict_New()) == NULL) + goto out; + + if ((issuer = PyDict_New()) == NULL) + goto out; + + if (PyDict_SetItemString(dict, "issuer", issuer) == -1) + goto out; + + if ((subject = PyDict_New()) == NULL) + goto out; + + if (PyDict_SetItemString(dict, "subject", subject) == -1) + goto out; + + PyErr_Clear(); + + if ((name = X509_get_issuer_name(pyc->c->cert)) == NULL) { + PyErr_Format(PyExc_RuntimeError, + "X509_get_issuer_name: %s", ssl_errno_s); + goto out; + } + + if (!kore_x509name_foreach(name, 0, issuer, pyconnection_x509_cb)) { + if (PyErr_Occurred() == NULL) { + PyErr_Format(PyExc_RuntimeError, + "failed to add issuer name to dictionary"); + } + goto out; + } + + if ((name = X509_get_subject_name(pyc->c->cert)) == NULL) { + PyErr_Format(PyExc_RuntimeError, + "X509_get_subject_name: %s", ssl_errno_s); + goto out; + } + + if (!kore_x509name_foreach(name, 0, subject, pyconnection_x509_cb)) { + if (PyErr_Occurred() == NULL) { + PyErr_Format(PyExc_RuntimeError, + "failed to add subject name to dictionary"); + } + goto out; + } + + ret = dict; + dict = NULL; + +out: + Py_XDECREF(dict); + Py_XDECREF(issuer); + Py_XDECREF(subject); + + return (ret); +} + +static int +pyconnection_x509_cb(void *udata, int islast, int nid, const char *field, + const void *data, size_t len, int flags) +{ + PyObject *dict, *obj; + + dict = udata; + + if ((obj = PyUnicode_FromStringAndSize(data, len)) == NULL) + return (KORE_RESULT_ERROR); + + if (PyDict_SetItemString(dict, field, obj) == -1) { + Py_DECREF(obj); + return (KORE_RESULT_ERROR); + } + + Py_DECREF(obj); + return (KORE_RESULT_OK); +} + static void pytimer_run(void *arg, u_int64_t now) {