From: Joseph Sutton Date: Mon, 19 Jul 2021 22:48:41 +0000 (+1200) Subject: pygensec: Don't modify Python bytes objects X-Git-Tag: ldb-2.5.0~965 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6818d204897d0b7946dcfbedf79cd53fb9b3f159;p=thirdparty%2Fsamba.git pygensec: Don't modify Python bytes objects gensec_update() and gensec_unwrap() can both modify their input buffers (for example, during the inplace RRC operation on GSSAPI tokens). However, buffers obtained from Python bytes objects must not be modified in any way. Create a copy of the input buffer so the original isn't modified. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Andreas Schneider --- diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 9adc477a15c..e33c78462e2 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -1168,6 +1168,10 @@ static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, } } + /* + * FIXME: input_message_buffer is marked const, but gss_unwrap() may + * modify it (see calls to rrc_rotate() in _gssapi_unwrap_cfx()). + */ maj_stat = gss_unwrap(&min_stat, gensec_gssapi_state->gssapi_context, &input_token, diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index f1f845a4663..dd63fa58348 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -468,6 +468,9 @@ static PyObject *py_gensec_update(PyObject *self, PyObject *args) PyObject *py_bytes, *result, *py_in; struct gensec_security *security = pytalloc_get_type(self, struct gensec_security); PyObject *finished_processing; + char *data = NULL; + Py_ssize_t len; + int err; if (!PyArg_ParseTuple(args, "O", &py_in)) return NULL; @@ -477,14 +480,21 @@ static PyObject *py_gensec_update(PyObject *self, PyObject *args) return PyErr_NoMemory(); } - if (!PyBytes_Check(py_in)) { + err = PyBytes_AsStringAndSize(py_in, &data, &len); + if (err) { talloc_free(mem_ctx); - PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } - in.data = (uint8_t *)PyBytes_AsString(py_in); - in.length = PyBytes_Size(py_in); + /* + * Make a copy of the input buffer, as gensec_update may modify its + * input argument. + */ + in = data_blob_talloc(mem_ctx, data, len); + if (!in.data) { + talloc_free(mem_ctx); + return PyErr_NoMemory(); + } status = gensec_update(security, mem_ctx, in, &out); @@ -556,6 +566,9 @@ static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args) DATA_BLOB in, out; PyObject *ret, *py_in; struct gensec_security *security = pytalloc_get_type(self, struct gensec_security); + char *data = NULL; + Py_ssize_t len; + int err; if (!PyArg_ParseTuple(args, "O", &py_in)) return NULL; @@ -565,14 +578,21 @@ static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args) return PyErr_NoMemory(); } - if (!PyBytes_Check(py_in)) { + err = PyBytes_AsStringAndSize(py_in, &data, &len); + if (err) { talloc_free(mem_ctx); - PyErr_Format(PyExc_TypeError, "bytes expected"); return NULL; } - in.data = (uint8_t *)PyBytes_AsString(py_in); - in.length = PyBytes_Size(py_in); + /* + * Make a copy of the input buffer, as gensec_unwrap may modify its + * input argument. + */ + in = data_blob_talloc(mem_ctx, data, len); + if (!in.data) { + talloc_free(mem_ctx); + return PyErr_NoMemory(); + } status = gensec_unwrap(security, mem_ctx, &in, &out);