Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Copyright (C) Volker Lendecke 2022
4 : *
5 : * This program is free software; you can redistribute it and/or modify
6 : * it under the terms of the GNU General Public License as published by
7 : * the Free Software Foundation; either version 3 of the License, or
8 : * (at your option) any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : */
18 :
19 : #include "lib/replace/system/python.h"
20 : #include "replace.h"
21 : #include "python/modules.h"
22 : #include "python/py3compat.h"
23 : #include "libcli/util/pyerrors.h"
24 : #include "reparse.h"
25 : #include "lib/util/iov_buf.h"
26 : #include "smb_constants.h"
27 :
28 0 : static PyObject *py_reparse_put(PyObject *module, PyObject *args)
29 : {
30 0 : char *reparse = NULL;
31 : Py_ssize_t reparse_len;
32 0 : unsigned long long tag = 0;
33 0 : unsigned reserved = 0;
34 0 : uint8_t *buf = NULL;
35 : ssize_t buflen;
36 0 : PyObject *result = NULL;
37 0 : struct reparse_data_buffer reparse_buf = {};
38 : bool ok;
39 :
40 0 : ok = PyArg_ParseTuple(
41 : args,
42 : "Kk"PYARG_BYTES_LEN":put",
43 : &tag,
44 : &reserved,
45 : &reparse,
46 : &reparse_len);
47 0 : if (!ok) {
48 0 : return NULL;
49 : }
50 :
51 0 : reparse_buf.tag = tag;
52 0 : reparse_buf.parsed.raw.data = (uint8_t *)reparse;
53 0 : reparse_buf.parsed.raw.length = reparse_len;
54 0 : reparse_buf.parsed.raw.reserved = reserved;
55 :
56 0 : buflen = reparse_data_buffer_marshall(&reparse_buf, NULL, 0);
57 0 : if (buflen == -1) {
58 0 : errno = EINVAL;
59 0 : PyErr_SetFromErrno(PyExc_RuntimeError);
60 0 : return NULL;
61 : }
62 0 : buf = talloc_array(NULL, uint8_t, buflen);
63 0 : if (buf == NULL) {
64 0 : PyErr_NoMemory();
65 0 : return NULL;
66 : }
67 0 : reparse_data_buffer_marshall(&reparse_buf, buf, buflen);
68 :
69 0 : result = PyBytes_FromStringAndSize((char *)buf, buflen);
70 0 : TALLOC_FREE(buf);
71 0 : return result;
72 : }
73 :
74 0 : static PyObject *py_reparse_symlink_put(PyObject *module, PyObject *args)
75 : {
76 0 : int unparsed = 0;
77 0 : int flags = 0;
78 0 : struct reparse_data_buffer reparse = {
79 : .tag = IO_REPARSE_TAG_SYMLINK,
80 : };
81 0 : struct symlink_reparse_struct *lnk = &reparse.parsed.lnk;
82 : uint8_t stackbuf[1024];
83 0 : uint8_t *buf = stackbuf;
84 0 : ssize_t buflen = sizeof(stackbuf);
85 0 : PyObject *result = NULL;
86 : bool ok;
87 :
88 0 : ok = PyArg_ParseTuple(args,
89 : "ssii:symlink_put",
90 : &lnk->substitute_name,
91 : &lnk->print_name,
92 : &unparsed,
93 : &flags);
94 0 : if (!ok) {
95 0 : return NULL;
96 : }
97 0 : lnk->unparsed_path_length = unparsed;
98 0 : lnk->flags = flags;
99 :
100 0 : buflen = reparse_data_buffer_marshall(&reparse, buf, buflen);
101 :
102 0 : if ((buflen > 0) && ((size_t)buflen > sizeof(stackbuf))) {
103 0 : buf = malloc(buflen);
104 0 : buflen = reparse_data_buffer_marshall(&reparse, buf, buflen);
105 : }
106 :
107 0 : if (buflen == -1) {
108 0 : PyErr_NoMemory();
109 : } else {
110 0 : result = PyBytes_FromStringAndSize((char *)buf, buflen);
111 : }
112 :
113 0 : if (buf != stackbuf) {
114 0 : free(buf);
115 : }
116 :
117 0 : return result;
118 : }
119 :
120 2 : static PyObject *py_reparse_symlink_get(PyObject *module, PyObject *args)
121 : {
122 2 : char *buf = NULL;
123 : Py_ssize_t buflen;
124 2 : struct reparse_data_buffer *syml = NULL;
125 2 : struct symlink_reparse_struct *lnk = NULL;
126 2 : PyObject *result = NULL;
127 : NTSTATUS status;
128 : bool ok;
129 :
130 2 : ok = PyArg_ParseTuple(args, PYARG_BYTES_LEN ":get", &buf, &buflen);
131 2 : if (!ok) {
132 0 : return NULL;
133 : }
134 :
135 2 : syml = talloc(NULL, struct reparse_data_buffer);
136 2 : if (syml == NULL) {
137 0 : PyErr_NoMemory();
138 0 : return NULL;
139 : }
140 :
141 2 : status = reparse_data_buffer_parse(syml, syml, (uint8_t *)buf, buflen);
142 2 : if (!NT_STATUS_IS_OK(status)) {
143 0 : TALLOC_FREE(syml);
144 0 : PyErr_SetNTSTATUS(status);
145 0 : return NULL;
146 : }
147 :
148 2 : if (syml->tag != IO_REPARSE_TAG_SYMLINK) {
149 0 : TALLOC_FREE(syml);
150 0 : PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE);
151 0 : return NULL;
152 : }
153 2 : lnk = &syml->parsed.lnk;
154 :
155 2 : result = Py_BuildValue("ssII",
156 : lnk->substitute_name,
157 : lnk->print_name,
158 2 : (unsigned)lnk->unparsed_path_length,
159 2 : (unsigned)lnk->flags);
160 :
161 2 : TALLOC_FREE(syml);
162 2 : return result;
163 : }
164 :
165 : static PyMethodDef py_reparse_symlink_methods[] = {
166 : { "put",
167 : PY_DISCARD_FUNC_SIG(PyCFunction, py_reparse_put),
168 : METH_VARARGS,
169 : "Create a reparse point blob"},
170 : { "symlink_put",
171 : PY_DISCARD_FUNC_SIG(PyCFunction, py_reparse_symlink_put),
172 : METH_VARARGS,
173 : "Create a reparse symlink blob"},
174 : { "symlink_get",
175 : PY_DISCARD_FUNC_SIG(PyCFunction, py_reparse_symlink_get),
176 : METH_VARARGS,
177 : "Parse a reparse symlink blob"},
178 : {0},
179 : };
180 :
181 : static struct PyModuleDef moduledef = {
182 : PyModuleDef_HEAD_INIT,
183 : .m_name = "reparse_symlink",
184 : .m_doc = "[un]marshall reparse symlink blobs",
185 : .m_size = -1,
186 : .m_methods = py_reparse_symlink_methods,
187 : };
188 :
189 2 : MODULE_INIT_FUNC(reparse_symlink)
190 : {
191 : PyObject *m;
192 :
193 2 : m = PyModule_Create(&moduledef);
194 2 : if (m == NULL)
195 0 : return NULL;
196 :
197 2 : return m;
198 : }
|