Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Python interface to DCE/RPC library - utility functions.
5 :
6 : Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
7 : Copyright (C) 2010 Andrew Tridgell <tridge@samba.org>
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "lib/replace/system/python.h"
24 : #include "python/py3compat.h"
25 : #include "includes.h"
26 : #include "python/modules.h"
27 : #include "librpc/rpc/pyrpc_util.h"
28 : #include "librpc/rpc/dcerpc.h"
29 : #include "librpc/rpc/pyrpc.h"
30 : #include "param/pyparam.h"
31 : #include "auth/credentials/pycredentials.h"
32 : #include "lib/events/events.h"
33 : #include "lib/messaging/messaging.h"
34 : #include "lib/messaging/irpc.h"
35 :
36 899066 : bool py_check_dcerpc_type(PyObject *obj, const char *module, const char *type_name)
37 : {
38 80133 : PyObject *mod;
39 80133 : PyTypeObject *type;
40 80133 : bool ret;
41 :
42 899066 : mod = PyImport_ImportModule(module);
43 :
44 899066 : if (mod == NULL) {
45 0 : PyErr_Format(PyExc_RuntimeError, "Unable to import %s to check type %s",
46 : module, type_name);
47 0 : return false;
48 : }
49 :
50 899066 : type = (PyTypeObject *)PyObject_GetAttrString(mod, type_name);
51 705982 : Py_DECREF(mod);
52 899066 : if (type == NULL) {
53 0 : PyErr_Format(PyExc_RuntimeError, "Unable to find type %s in module %s",
54 : module, type_name);
55 0 : return false;
56 : }
57 :
58 899066 : ret = PyObject_TypeCheck(obj, type);
59 705982 : Py_DECREF(type);
60 :
61 899066 : if (!ret)
62 0 : PyErr_Format(PyExc_TypeError, "Expected type %s.%s, got %s",
63 0 : module, type_name, Py_TYPE(obj)->tp_name);
64 :
65 818933 : return ret;
66 : }
67 :
68 : /*
69 : connect to a IRPC pipe from python
70 : */
71 4 : static NTSTATUS pyrpc_irpc_connect(TALLOC_CTX *mem_ctx, const char *irpc_server,
72 : const struct ndr_interface_table *table,
73 : struct tevent_context *event_ctx,
74 : struct loadparm_context *lp_ctx,
75 : struct dcerpc_binding_handle **binding_handle)
76 : {
77 0 : struct imessaging_context *msg;
78 :
79 4 : msg = imessaging_client_init(mem_ctx, lp_ctx, event_ctx);
80 4 : NT_STATUS_HAVE_NO_MEMORY(msg);
81 :
82 4 : *binding_handle = irpc_binding_handle_by_name(mem_ctx, msg, irpc_server, table);
83 4 : if (*binding_handle == NULL) {
84 1 : talloc_free(msg);
85 1 : return NT_STATUS_INVALID_PIPE_STATE;
86 : }
87 :
88 : /*
89 : * Note: this allows nested event loops to happen,
90 : * but as there's no top level event loop it's not that critical.
91 : */
92 3 : dcerpc_binding_handle_set_sync_ev(*binding_handle, event_ctx);
93 :
94 3 : return NT_STATUS_OK;
95 : }
96 :
97 4559 : PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, PyObject *kwargs,
98 : const struct ndr_interface_table *table)
99 : {
100 4 : dcerpc_InterfaceObject *ret;
101 4 : const char *binding_string;
102 4559 : PyObject *py_lp_ctx = Py_None, *py_credentials = Py_None, *py_basis = Py_None;
103 4 : NTSTATUS status;
104 4559 : unsigned int timeout = (unsigned int)-1;
105 4559 : const char *kwnames[] = {
106 : "binding", "lp_ctx", "credentials", "timeout", "basis_connection", NULL
107 : };
108 :
109 4559 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOIO:samr", discard_const_p(char *, kwnames), &binding_string, &py_lp_ctx, &py_credentials, &timeout, &py_basis)) {
110 0 : return NULL;
111 : }
112 :
113 4559 : status = dcerpc_init();
114 4559 : if (!NT_STATUS_IS_OK(status)) {
115 0 : PyErr_SetNTSTATUS(status);
116 0 : return NULL;
117 : }
118 :
119 4559 : ret = PyObject_New(dcerpc_InterfaceObject, type);
120 4559 : if (ret == NULL) {
121 0 : PyErr_NoMemory();
122 0 : return NULL;
123 : }
124 :
125 4559 : ret->pipe = NULL;
126 4559 : ret->binding_handle = NULL;
127 4559 : ret->ev = NULL;
128 4559 : ret->mem_ctx = talloc_new(NULL);
129 4559 : if (ret->mem_ctx == NULL) {
130 0 : PyErr_NoMemory();
131 0 : return NULL;
132 : }
133 :
134 4559 : if (strncmp(binding_string, "irpc:", 5) == 0) {
135 0 : struct loadparm_context *lp_ctx;
136 :
137 4 : ret->ev = s4_event_context_init(ret->mem_ctx);
138 4 : if (ret->ev == NULL) {
139 0 : PyErr_SetString(PyExc_TypeError,
140 : "Unable to initialise event context");
141 0 : Py_DECREF(ret);
142 0 : return NULL;
143 : }
144 :
145 4 : lp_ctx = lpcfg_from_py_object(ret->ev, py_lp_ctx);
146 4 : if (lp_ctx == NULL) {
147 0 : PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
148 0 : Py_DECREF(ret);
149 0 : return NULL;
150 : }
151 :
152 4 : status = pyrpc_irpc_connect(ret->mem_ctx, binding_string+5, table,
153 : ret->ev, lp_ctx, &ret->binding_handle);
154 4 : if (!NT_STATUS_IS_OK(status)) {
155 1 : PyErr_SetNTSTATUS(status);
156 1 : Py_DECREF(ret);
157 1 : return NULL;
158 : }
159 4555 : } else if (py_basis != Py_None) {
160 0 : struct dcerpc_pipe *base_pipe;
161 0 : PyObject *py_base;
162 0 : PyTypeObject *ClientConnection_Type;
163 :
164 3 : py_base = PyImport_ImportModule("samba.dcerpc.base");
165 3 : if (py_base == NULL) {
166 0 : Py_DECREF(ret);
167 0 : return NULL;
168 : }
169 :
170 3 : ClientConnection_Type = (PyTypeObject *)PyObject_GetAttrString(py_base, "ClientConnection");
171 3 : if (ClientConnection_Type == NULL) {
172 0 : PyErr_SetNone(PyExc_TypeError);
173 0 : Py_DECREF(ret);
174 0 : Py_DECREF(py_base);
175 0 : return NULL;
176 : }
177 :
178 3 : if (!PyObject_TypeCheck(py_basis, ClientConnection_Type)) {
179 0 : PyErr_SetString(PyExc_TypeError, "basis_connection must be a DCE/RPC connection");
180 0 : Py_DECREF(ret);
181 0 : Py_DECREF(py_base);
182 0 : Py_DECREF(ClientConnection_Type);
183 0 : return NULL;
184 : }
185 :
186 3 : base_pipe = talloc_reference(ret->mem_ctx,
187 : ((dcerpc_InterfaceObject *)py_basis)->pipe);
188 3 : if (base_pipe == NULL) {
189 0 : PyErr_NoMemory();
190 0 : Py_DECREF(ret);
191 0 : Py_DECREF(py_base);
192 0 : Py_DECREF(ClientConnection_Type);
193 0 : return NULL;
194 : }
195 :
196 3 : ret->ev = talloc_reference(
197 : ret->mem_ctx,
198 : ((dcerpc_InterfaceObject *)py_basis)->ev);
199 3 : if (ret->ev == NULL) {
200 0 : PyErr_NoMemory();
201 0 : Py_DECREF(ret);
202 0 : Py_DECREF(py_base);
203 0 : Py_DECREF(ClientConnection_Type);
204 0 : return NULL;
205 : }
206 :
207 3 : status = dcerpc_secondary_context(base_pipe, &ret->pipe, table);
208 3 : if (!NT_STATUS_IS_OK(status)) {
209 0 : PyErr_SetNTSTATUS(status);
210 0 : Py_DECREF(ret);
211 0 : Py_DECREF(py_base);
212 0 : Py_DECREF(ClientConnection_Type);
213 0 : return NULL;
214 : }
215 :
216 3 : ret->pipe = talloc_steal(ret->mem_ctx, ret->pipe);
217 3 : Py_XDECREF(ClientConnection_Type);
218 3 : Py_XDECREF(py_base);
219 : } else {
220 4 : struct loadparm_context *lp_ctx;
221 4 : struct cli_credentials *credentials;
222 :
223 4552 : ret->ev = s4_event_context_init(ret->mem_ctx);
224 4552 : if (ret->ev == NULL) {
225 0 : PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
226 0 : Py_DECREF(ret);
227 0 : return NULL;
228 : }
229 :
230 4552 : lp_ctx = lpcfg_from_py_object(ret->ev, py_lp_ctx);
231 4552 : if (lp_ctx == NULL) {
232 0 : PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
233 0 : Py_DECREF(ret);
234 0 : return NULL;
235 : }
236 :
237 4552 : credentials = cli_credentials_from_py_object(py_credentials);
238 4552 : if (credentials == NULL) {
239 0 : PyErr_SetString(PyExc_TypeError, "Expected credentials");
240 0 : Py_DECREF(ret);
241 0 : return NULL;
242 : }
243 4552 : status = dcerpc_pipe_connect(ret->mem_ctx, &ret->pipe, binding_string,
244 : table, credentials, ret->ev, lp_ctx);
245 4552 : if (!NT_STATUS_IS_OK(status)) {
246 64 : PyErr_SetNTSTATUS(status);
247 39 : Py_DECREF(ret);
248 64 : return NULL;
249 : }
250 : }
251 :
252 4494 : if (ret->pipe) {
253 4491 : ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
254 4491 : ret->binding_handle = ret->pipe->binding_handle;
255 : }
256 :
257 : /* reset timeout for the handle */
258 4494 : if ((timeout != ((unsigned int)-1)) && (ret->binding_handle != NULL)) {
259 0 : dcerpc_binding_handle_set_timeout(ret->binding_handle, timeout);
260 : }
261 :
262 4490 : return (PyObject *)ret;
263 : }
264 :
265 23384 : static PyObject *py_dcerpc_run_function(dcerpc_InterfaceObject *iface,
266 : const struct PyNdrRpcMethodDef *md,
267 : PyObject *args, PyObject *kwargs)
268 : {
269 10 : TALLOC_CTX *mem_ctx;
270 10 : NTSTATUS status;
271 10 : void *r;
272 23384 : PyObject *result = Py_None;
273 :
274 23384 : if (md->pack_in_data == NULL || md->unpack_out_data == NULL) {
275 0 : PyErr_SetString(PyExc_NotImplementedError, "No marshalling code available yet");
276 0 : return NULL;
277 : }
278 :
279 23384 : mem_ctx = talloc_new(NULL);
280 23384 : if (mem_ctx == NULL) {
281 0 : PyErr_NoMemory();
282 0 : return NULL;
283 : }
284 :
285 23384 : r = talloc_zero_size(mem_ctx, md->table->calls[md->opnum].struct_size);
286 23384 : if (r == NULL) {
287 0 : PyErr_NoMemory();
288 0 : return NULL;
289 : }
290 :
291 23384 : if (!md->pack_in_data(args, kwargs, r)) {
292 0 : talloc_free(mem_ctx);
293 0 : return NULL;
294 : }
295 :
296 23384 : status = md->call(iface->binding_handle, mem_ctx, r);
297 23384 : if (!NT_STATUS_IS_OK(status)) {
298 90 : PyErr_SetDCERPCStatus(iface->pipe, status);
299 90 : talloc_free(mem_ctx);
300 90 : return NULL;
301 : }
302 :
303 23294 : result = md->unpack_out_data(r);
304 :
305 23294 : talloc_free(mem_ctx);
306 23294 : return result;
307 : }
308 :
309 23384 : static PyObject *py_dcerpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)
310 : {
311 23384 : dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self;
312 23384 : const struct PyNdrRpcMethodDef *md = (const struct PyNdrRpcMethodDef *)wrapped;
313 :
314 23384 : return py_dcerpc_run_function(iface, md, args, kwargs);
315 : }
316 :
317 59311 : bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds)
318 : {
319 1614 : int i;
320 1433378 : for (i = 0; mds[i].name; i++) {
321 36195 : PyObject *ret;
322 1374067 : struct wrapperbase *wb = (struct wrapperbase *)calloc(sizeof(struct wrapperbase), 1);
323 :
324 1374067 : if (wb == NULL) {
325 0 : return false;
326 : }
327 1374067 : wb->name = discard_const_p(char, mds[i].name);
328 1374067 : wb->flags = PyWrapperFlag_KEYWORDS;
329 1374067 : wb->wrapper = PY_DISCARD_FUNC_SIG(wrapperfunc,
330 : py_dcerpc_call_wrapper);
331 1374067 : wb->doc = discard_const_p(char, mds[i].doc);
332 :
333 1374067 : ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i]));
334 :
335 1374067 : PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,
336 : (PyObject *)ret);
337 1374067 : Py_CLEAR(ret);
338 : }
339 :
340 57697 : return true;
341 : }
342 :
343 1311 : PyObject *py_dcerpc_syntax_init_helper(PyTypeObject *type, PyObject *args, PyObject *kwargs,
344 : const struct ndr_syntax_id *syntax)
345 : {
346 0 : PyObject *ret;
347 0 : struct ndr_syntax_id *obj;
348 1311 : const char *kwnames[] = { NULL };
349 :
350 1311 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":abstract_syntax", discard_const_p(char *, kwnames))) {
351 0 : return NULL;
352 : }
353 :
354 1311 : ret = pytalloc_new(struct ndr_syntax_id, type);
355 1311 : if (ret == NULL) {
356 0 : return NULL;
357 : }
358 :
359 1311 : obj = pytalloc_get_type(ret, struct ndr_syntax_id);
360 1311 : *obj = *syntax;
361 :
362 1311 : return ret;
363 : }
364 :
365 90 : void PyErr_SetDCERPCStatus(struct dcerpc_pipe *p, NTSTATUS status)
366 : {
367 90 : if (p && NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
368 0 : status = dcerpc_fault_to_nt_status(p->last_fault_code);
369 : }
370 90 : PyErr_SetNTSTATUS(status);
371 90 : }
372 :
373 :
374 : /*
375 : take a NDR structure that has a type in a python module and return
376 : it as a python object
377 :
378 : r is the NDR structure pointer (a C structure)
379 :
380 : r_ctx is the context that is a parent of r. It will be referenced by
381 : the resulting python object
382 :
383 : This MUST only be used by objects that are based on pytalloc_Object
384 : otherwise the pytalloc_reference_ex() will fail.
385 : */
386 41209 : PyObject *py_return_ndr_struct(const char *module_name, const char *type_name,
387 : TALLOC_CTX *r_ctx, void *r)
388 : {
389 616 : PyTypeObject *py_type;
390 616 : PyObject *module;
391 41209 : PyObject *result = NULL;
392 :
393 41209 : if (r == NULL) {
394 2 : Py_RETURN_NONE;
395 : }
396 :
397 41207 : module = PyImport_ImportModule(module_name);
398 41207 : if (module == NULL) {
399 0 : return NULL;
400 : }
401 :
402 41207 : py_type = (PyTypeObject *)PyObject_GetAttrString(module, type_name);
403 41207 : if (py_type == NULL) {
404 0 : Py_DECREF(module);
405 0 : return NULL;
406 : }
407 :
408 41207 : result = pytalloc_reference_ex(py_type, r_ctx, r);
409 41207 : Py_CLEAR(module);
410 41207 : Py_CLEAR(py_type);
411 40591 : return result;
412 : }
413 :
414 214862 : PyObject *PyString_FromStringOrNULL(const char *str)
415 : {
416 214862 : if (str == NULL) {
417 1220 : Py_RETURN_NONE;
418 : }
419 213642 : return PyUnicode_FromString(str);
420 : }
421 :
422 140 : PyObject *PyBytes_FromUtf16StringOrNULL(const unsigned char *str)
423 : {
424 1 : size_t len;
425 :
426 140 : if (str == NULL) {
427 0 : Py_RETURN_NONE;
428 : }
429 :
430 140 : len = utf16_len(str);
431 140 : return PyBytes_FromStringAndSize((const char *)str, len);
432 : }
433 :
434 69 : unsigned char *PyUtf16String_FromBytes(TALLOC_CTX *mem_ctx, PyObject *value)
435 : {
436 69 : char *bytes = NULL;
437 69 : Py_ssize_t len = 0;
438 69 : unsigned char *utf16_string = NULL;
439 1 : int ret;
440 :
441 69 : ret = PyBytes_AsStringAndSize(value, &bytes, &len);
442 69 : if (ret) {
443 0 : return NULL;
444 : }
445 :
446 69 : if (len < 0) {
447 0 : PyErr_SetString(PyExc_ValueError, "bytes length is negative");
448 0 : return NULL;
449 : }
450 69 : if (len & 1) {
451 0 : PyErr_SetString(PyExc_ValueError, "bytes length is odd");
452 0 : return NULL;
453 : }
454 :
455 : /* Ensure that the bytes object contains no embedded null terminator. */
456 69 : if ((size_t)len != utf16_len_n(bytes, len)) {
457 0 : PyErr_SetString(PyExc_ValueError,
458 : "value contains an embedded null terminator");
459 0 : return NULL;
460 : }
461 :
462 69 : utf16_string = talloc_utf16_strlendup(mem_ctx, bytes, len);
463 69 : if (utf16_string == NULL) {
464 0 : PyErr_NoMemory();
465 0 : return NULL;
466 : }
467 :
468 68 : return utf16_string;
469 : }
470 :
471 2529459 : PyObject *pyrpc_import_union(PyTypeObject *type, TALLOC_CTX *mem_ctx, int level,
472 : const void *in, const char *typename)
473 : {
474 2529459 : PyObject *mem_ctx_obj = NULL;
475 2529459 : PyObject *in_obj = NULL;
476 2529459 : PyObject *ret = NULL;
477 :
478 2529459 : mem_ctx_obj = pytalloc_GenericObject_reference(mem_ctx);
479 2529459 : if (mem_ctx_obj == NULL) {
480 0 : return NULL;
481 : }
482 :
483 2529459 : in_obj = pytalloc_GenericObject_reference_ex(mem_ctx, discard_const(in));
484 2529459 : if (in_obj == NULL) {
485 0 : Py_XDECREF(mem_ctx_obj);
486 0 : return NULL;
487 : }
488 :
489 2529459 : ret = PyObject_CallMethod((PyObject *)type,
490 : discard_const_p(char, "__import__"),
491 : discard_const_p(char, "OiO"),
492 : mem_ctx_obj, level, in_obj);
493 2529459 : Py_XDECREF(mem_ctx_obj);
494 2529459 : Py_XDECREF(in_obj);
495 2529459 : if (ret == NULL) {
496 0 : return NULL;
497 : }
498 :
499 2345100 : return ret;
500 : }
501 :
502 46582 : void *pyrpc_export_union(PyTypeObject *type, TALLOC_CTX *mem_ctx, int level,
503 : PyObject *in, const char *typename)
504 : {
505 46582 : PyObject *mem_ctx_obj = NULL;
506 46582 : PyObject *ret_obj = NULL;
507 46582 : void *ret = NULL;
508 :
509 46582 : mem_ctx_obj = pytalloc_GenericObject_reference(mem_ctx);
510 46582 : if (mem_ctx_obj == NULL) {
511 0 : return NULL;
512 : }
513 :
514 46582 : ret_obj = PyObject_CallMethod((PyObject *)type,
515 : discard_const_p(char, "__export__"),
516 : discard_const_p(char, "OiO"),
517 : mem_ctx_obj, level, in);
518 46582 : Py_XDECREF(mem_ctx_obj);
519 46582 : if (ret_obj == NULL) {
520 0 : return NULL;
521 : }
522 :
523 46582 : ret = _pytalloc_get_type(ret_obj, typename);
524 46582 : Py_XDECREF(ret_obj);
525 39392 : return ret;
526 : }
527 :
528 30 : PyObject *py_dcerpc_ndr_pointer_deref(PyTypeObject *type, PyObject *obj)
529 : {
530 30 : if (!PyObject_TypeCheck(obj, type)) {
531 0 : PyErr_Format(PyExc_TypeError,
532 : "Expected type '%s' but got type '%s'",
533 0 : (type)->tp_name, Py_TYPE(obj)->tp_name);
534 0 : return NULL;
535 : }
536 :
537 30 : return PyObject_GetAttrString(obj, discard_const_p(char, "value"));
538 : }
539 :
540 306 : PyObject *py_dcerpc_ndr_pointer_wrap(PyTypeObject *type, PyObject *obj)
541 : {
542 306 : PyObject *args = NULL;
543 306 : PyObject *ret_obj = NULL;
544 :
545 306 : args = PyTuple_New(1);
546 306 : if (args == NULL) {
547 0 : return NULL;
548 : }
549 306 : Py_XINCREF(obj);
550 306 : PyTuple_SetItem(args, 0, obj);
551 :
552 306 : ret_obj = PyObject_Call((PyObject *)type, args, NULL);
553 306 : Py_XDECREF(args);
554 306 : return ret_obj;
555 : }
|