2 Python interface to cli_mdssvc
4 Copyright (C) Ralph Boehme 2019
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "lib/replace/system/python.h"
23 #include "python/py3compat.h"
24 #include "python/modules.h"
25 #include "lib/util/talloc_stack.h"
26 #include "lib/util/tevent_ntstatus.h"
27 #include "librpc/rpc/rpc_common.h"
28 #include "librpc/rpc/pyrpc_util.h"
29 #include "rpc_client/cli_mdssvc.h"
30 #include "rpc_client/cli_mdssvc_private.h"
32 static PyObject
*search_get_results(PyObject
*self
,
36 TALLOC_CTX
*frame
= talloc_stackframe();
37 const char * const kwnames
[] = {"pipe", NULL
};
38 PyObject
*pypipe
= NULL
;
39 PyObject
*result
= NULL
;
40 dcerpc_InterfaceObject
*pipe
= NULL
;
41 struct tevent_req
*req
= NULL
;
42 struct mdscli_search_ctx
*search
= NULL
;
43 uint64_t *cnids
= NULL
;
50 if (!PyArg_ParseTupleAndKeywords(args
,
53 discard_const_p(char *, kwnames
),
55 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
59 ok
= py_check_dcerpc_type(pypipe
,
66 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
68 search
= pytalloc_get_type(self
, struct mdscli_search_ctx
);
74 * We must use the async send/recv versions in order to pass the correct
75 * tevent context, here and any other place we call mdscli_*
76 * functions. Using the sync version we would be polling a temporary
77 * event context, but unfortunately the s4 Python RPC bindings dispatch
80 * dcerpc_bh_raw_call_send()
81 * -> dcerpc_request_send()
82 * -> dcerpc_schedule_io_trigger()
83 * -> dcerpc_send_request()
84 * -> tstream_writev_queue_send()
86 * on an hardcoded event context allocated via
88 * py_dcerpc_interface_init_helper()
89 * -> dcerpc_pipe_connect()
92 req
= mdscli_get_results_send(frame
,
100 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
101 PyErr_SetNTSTATUS(status
);
105 status
= mdscli_get_results_recv(req
, frame
, &cnids
);
107 if (NT_STATUS_EQUAL(status
, NT_STATUS_PENDING
)) {
111 if (!NT_STATUS_IS_OK(status
) &&
112 !NT_STATUS_EQUAL(status
, NT_STATUS_NO_MORE_MATCHES
))
114 PyErr_SetNTSTATUS(status
);
118 result
= Py_BuildValue("[]");
120 ncnids
= talloc_array_length(cnids
);
121 for (i
= 0; i
< ncnids
; i
++) {
123 PyObject
*pypath
= NULL
;
125 req
= mdscli_get_path_send(frame
,
136 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
137 PyErr_SetNTSTATUS(status
);
143 status
= mdscli_get_path_recv(req
, frame
, &path
);
145 PyErr_NTSTATUS_NOT_OK_RAISE(status
);
147 pypath
= PyUnicode_FromString(path
);
148 if (pypath
== NULL
) {
155 ret
= PyList_Append(result
, pypath
);
158 PyErr_SetString(PyExc_RuntimeError
,
159 "list append failed");
171 static PyObject
*search_close(PyObject
*self
,
175 TALLOC_CTX
*frame
= talloc_stackframe();
176 const char * const kwnames
[] = {"pipe", NULL
};
177 PyObject
*pypipe
= NULL
;
178 dcerpc_InterfaceObject
*pipe
= NULL
;
179 struct tevent_req
*req
= NULL
;
180 struct mdscli_search_ctx
*search
= NULL
;
184 if (!PyArg_ParseTupleAndKeywords(args
,
187 discard_const_p(char *, kwnames
),
189 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
193 ok
= py_check_dcerpc_type(pypipe
,
200 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
202 search
= pytalloc_get_type(self
, struct mdscli_search_ctx
);
203 if (search
== NULL
) {
207 req
= mdscli_close_search_send(frame
,
215 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
216 PyErr_SetNTSTATUS(status
);
220 status
= mdscli_close_search_recv(req
);
221 if (!NT_STATUS_IS_OK(status
) &&
222 !NT_STATUS_EQUAL(status
, NT_STATUS_NO_MORE_MATCHES
))
224 PyErr_SetNTSTATUS(status
);
238 static PyMethodDef search_methods
[] = {
240 .ml_name
= "get_results",
241 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, search_get_results
),
242 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
247 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, search_close
),
248 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
254 static PyObject
*search_new(PyTypeObject
*type
,
258 TALLOC_CTX
*frame
= talloc_stackframe();
259 struct mdscli_search_ctx
*search
= NULL
;
260 PyObject
*self
= NULL
;
262 search
= talloc_zero(frame
, struct mdscli_search_ctx
);
263 if (search
== NULL
) {
269 self
= pytalloc_steal(type
, search
);
274 static PyTypeObject search_type
= {
275 .tp_name
= "mdscli.ctx.search",
276 .tp_new
= search_new
,
277 .tp_flags
= Py_TPFLAGS_DEFAULT
,
278 .tp_doc
= "search([....]) -> mdssvc client search context\n",
279 .tp_methods
= search_methods
,
282 static PyObject
*conn_sharepath(PyObject
*self
,
285 TALLOC_CTX
*frame
= talloc_stackframe();
286 struct mdscli_ctx
*ctx
= NULL
;
287 char *sharepath
= NULL
;
288 PyObject
*result
= NULL
;
290 ctx
= pytalloc_get_type(self
, struct mdscli_ctx
);
295 sharepath
= mdscli_get_basepath(frame
, ctx
);
296 if (sharepath
== NULL
) {
301 result
= PyUnicode_FromString(sharepath
);
308 static PyObject
*conn_search(PyObject
*self
,
312 TALLOC_CTX
*frame
= talloc_stackframe();
313 PyObject
*pypipe
= NULL
;
314 dcerpc_InterfaceObject
*pipe
= NULL
;
315 struct mdscli_ctx
*ctx
= NULL
;
316 PyObject
*result
= NULL
;
318 char *basepath
= NULL
;
319 struct tevent_req
*req
= NULL
;
320 struct mdscli_search_ctx
*search
= NULL
;
321 const char * const kwnames
[] = {
322 "pipe", "query", "basepath", NULL
327 if (!PyArg_ParseTupleAndKeywords(args
,
330 discard_const_p(char *, kwnames
),
334 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
338 ok
= py_check_dcerpc_type(pypipe
,
345 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
347 ctx
= pytalloc_get_type(self
, struct mdscli_ctx
);
352 req
= mdscli_search_send(frame
,
363 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
364 PyErr_SetNTSTATUS(status
);
368 status
= mdscli_search_recv(req
, frame
, &search
);
369 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
371 result
= pytalloc_steal(&search_type
, search
);
378 static PyObject
*conn_disconnect(PyObject
*self
,
382 TALLOC_CTX
*frame
= talloc_stackframe();
383 PyObject
*pypipe
= NULL
;
384 dcerpc_InterfaceObject
*pipe
= NULL
;
385 struct mdscli_ctx
*ctx
= NULL
;
386 struct tevent_req
*req
= NULL
;
387 const char * const kwnames
[] = {"pipe", NULL
};
391 if (!PyArg_ParseTupleAndKeywords(args
,
394 discard_const_p(char *, kwnames
),
396 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
400 ok
= py_check_dcerpc_type(pypipe
,
407 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
409 ctx
= pytalloc_get_type(self
, struct mdscli_ctx
);
414 req
= mdscli_disconnect_send(frame
, pipe
->ev
, ctx
);
420 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
421 PyErr_SetNTSTATUS(status
);
425 status
= mdscli_disconnect_recv(req
);
426 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
437 static PyMethodDef conn_methods
[] = {
439 .ml_name
= "sharepath",
440 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, conn_sharepath
),
441 .ml_flags
= METH_NOARGS
,
442 .ml_doc
= "mdscli.conn.sharepath(...) -> get share basepath",
446 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, conn_search
),
447 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
448 .ml_doc
= "mdscli.conn.search(...) -> run mdssvc query",
451 .ml_name
= "disconnect",
452 .ml_meth
= PY_DISCARD_FUNC_SIG(PyCFunction
, conn_disconnect
),
453 .ml_flags
= METH_VARARGS
|METH_KEYWORDS
,
454 .ml_doc
= "mdscli.conn.disconnect(...) -> disconnect",
459 static PyObject
*conn_new(PyTypeObject
*type
,
463 TALLOC_CTX
*frame
= talloc_stackframe();
464 const char * const kwnames
[] = { "pipe", "share", "mountpoint", NULL
};
465 PyObject
*pypipe
= NULL
;
466 dcerpc_InterfaceObject
*pipe
= NULL
;
467 struct tevent_req
*req
= NULL
;
469 char *mountpoint
= NULL
;
470 struct mdscli_ctx
*ctx
= NULL
;
471 PyObject
*self
= NULL
;
475 if (!PyArg_ParseTupleAndKeywords(args
,
478 discard_const_p(char *, kwnames
),
482 PyErr_SetString(PyExc_RuntimeError
, "Failed to parse args");
486 ok
= py_check_dcerpc_type(pypipe
,
493 pipe
= (dcerpc_InterfaceObject
*)pypipe
;
495 req
= mdscli_connect_send(frame
,
497 pipe
->binding_handle
,
505 if (!tevent_req_poll_ntstatus(req
, pipe
->ev
, &status
)) {
506 PyErr_SetNTSTATUS(status
);
510 status
= mdscli_connect_recv(req
, frame
, &ctx
);
511 PyErr_NTSTATUS_IS_ERR_RAISE(status
);
513 self
= pytalloc_steal(type
, ctx
);
520 static PyTypeObject conn_type
= {
521 .tp_name
= "mdscli.conn",
523 .tp_flags
= Py_TPFLAGS_DEFAULT
,
524 .tp_doc
= "conn([....]) -> mdssvc connection\n",
525 .tp_methods
= conn_methods
,
528 static PyMethodDef mdscli_methods
[] = {
532 static struct PyModuleDef moduledef
= {
533 PyModuleDef_HEAD_INIT
,
535 .m_doc
= "RPC mdssvc client",
537 .m_methods
= mdscli_methods
,
540 MODULE_INIT_FUNC(mdscli
)
542 TALLOC_CTX
*frame
= talloc_stackframe();
546 ret
= pytalloc_BaseObject_PyType_Ready(&conn_type
);
552 ret
= pytalloc_BaseObject_PyType_Ready(&search_type
);
558 m
= PyModule_Create(&moduledef
);
564 Py_INCREF(&conn_type
);
565 PyModule_AddObject(m
, "conn", (PyObject
*)&conn_type
);
567 Py_INCREF(&search_type
);
568 PyModule_AddObject(m
, "search", (PyObject
*)&search_type
);