kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 774cc56ed257aed6f744768dd8d35ac4fa5bdb04
parent ca4ffa457c0f93d20e70de92b2f64f4e291207aa
Author: Joris Vink <joris@coders.se>
Date:   Sat, 11 Dec 2021 22:37:15 +0100

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"
  }
}

Diffstat:
include/kore/python_methods.h | 2++
src/python.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 0 deletions(-)

diff --git 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 @@ -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) {