diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /libcli/smb/py_reparse_symlink.c | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | libcli/smb/py_reparse_symlink.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/libcli/smb/py_reparse_symlink.c b/libcli/smb/py_reparse_symlink.c new file mode 100644 index 0000000..5626e27 --- /dev/null +++ b/libcli/smb/py_reparse_symlink.c @@ -0,0 +1,198 @@ +/* + * Unix SMB/CIFS implementation. + * Copyright (C) Volker Lendecke 2022 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "lib/replace/system/python.h" +#include "replace.h" +#include "python/modules.h" +#include "python/py3compat.h" +#include "libcli/util/pyerrors.h" +#include "reparse.h" +#include "lib/util/iov_buf.h" +#include "smb_constants.h" + +static PyObject *py_reparse_put(PyObject *module, PyObject *args) +{ + char *reparse = NULL; + Py_ssize_t reparse_len; + unsigned long long tag = 0; + unsigned reserved = 0; + uint8_t *buf = NULL; + ssize_t buflen; + PyObject *result = NULL; + struct reparse_data_buffer reparse_buf = {}; + bool ok; + + ok = PyArg_ParseTuple( + args, + "Kk"PYARG_BYTES_LEN":put", + &tag, + &reserved, + &reparse, + &reparse_len); + if (!ok) { + return NULL; + } + + reparse_buf.tag = tag; + reparse_buf.parsed.raw.data = (uint8_t *)reparse; + reparse_buf.parsed.raw.length = reparse_len; + reparse_buf.parsed.raw.reserved = reserved; + + buflen = reparse_data_buffer_marshall(&reparse_buf, NULL, 0); + if (buflen == -1) { + errno = EINVAL; + PyErr_SetFromErrno(PyExc_RuntimeError); + return NULL; + } + buf = talloc_array(NULL, uint8_t, buflen); + if (buf == NULL) { + PyErr_NoMemory(); + return NULL; + } + reparse_data_buffer_marshall(&reparse_buf, buf, buflen); + + result = PyBytes_FromStringAndSize((char *)buf, buflen); + TALLOC_FREE(buf); + return result; +} + +static PyObject *py_reparse_symlink_put(PyObject *module, PyObject *args) +{ + int unparsed = 0; + int flags = 0; + struct reparse_data_buffer reparse = { + .tag = IO_REPARSE_TAG_SYMLINK, + }; + struct symlink_reparse_struct *lnk = &reparse.parsed.lnk; + uint8_t stackbuf[1024]; + uint8_t *buf = stackbuf; + ssize_t buflen = sizeof(stackbuf); + PyObject *result = NULL; + bool ok; + + ok = PyArg_ParseTuple(args, + "ssii:symlink_put", + &lnk->substitute_name, + &lnk->print_name, + &unparsed, + &flags); + if (!ok) { + return NULL; + } + lnk->unparsed_path_length = unparsed; + lnk->flags = flags; + + buflen = reparse_data_buffer_marshall(&reparse, buf, buflen); + + if ((buflen > 0) && ((size_t)buflen > sizeof(stackbuf))) { + buf = malloc(buflen); + buflen = reparse_data_buffer_marshall(&reparse, buf, buflen); + } + + if (buflen == -1) { + PyErr_NoMemory(); + } else { + result = PyBytes_FromStringAndSize((char *)buf, buflen); + } + + if (buf != stackbuf) { + free(buf); + } + + return result; +} + +static PyObject *py_reparse_symlink_get(PyObject *module, PyObject *args) +{ + char *buf = NULL; + Py_ssize_t buflen; + struct reparse_data_buffer *syml = NULL; + struct symlink_reparse_struct *lnk = NULL; + PyObject *result = NULL; + NTSTATUS status; + bool ok; + + ok = PyArg_ParseTuple(args, PYARG_BYTES_LEN ":get", &buf, &buflen); + if (!ok) { + return NULL; + } + + syml = talloc(NULL, struct reparse_data_buffer); + if (syml == NULL) { + PyErr_NoMemory(); + return NULL; + } + + status = reparse_data_buffer_parse(syml, syml, (uint8_t *)buf, buflen); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(syml); + PyErr_SetNTSTATUS(status); + return NULL; + } + + if (syml->tag != IO_REPARSE_TAG_SYMLINK) { + TALLOC_FREE(syml); + PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE); + return NULL; + } + lnk = &syml->parsed.lnk; + + result = Py_BuildValue("ssII", + lnk->substitute_name, + lnk->print_name, + (unsigned)lnk->unparsed_path_length, + (unsigned)lnk->flags); + + TALLOC_FREE(syml); + return result; +} + +static PyMethodDef py_reparse_symlink_methods[] = { + { "put", + PY_DISCARD_FUNC_SIG(PyCFunction, py_reparse_put), + METH_VARARGS, + "Create a reparse point blob"}, + { "symlink_put", + PY_DISCARD_FUNC_SIG(PyCFunction, py_reparse_symlink_put), + METH_VARARGS, + "Create a reparse symlink blob"}, + { "symlink_get", + PY_DISCARD_FUNC_SIG(PyCFunction, py_reparse_symlink_get), + METH_VARARGS, + "Parse a reparse symlink blob"}, + {0}, +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "reparse_symlink", + .m_doc = "[un]marshall reparse symlink blobs", + .m_size = -1, + .m_methods = py_reparse_symlink_methods, +}; + +MODULE_INIT_FUNC(reparse_symlink) +{ + PyObject *m; + + m = PyModule_Create(&moduledef); + if (m == NULL) + return NULL; + + return m; +} |