diff options
Diffstat (limited to 'source4/librpc/rpc/pyrpc_util.c')
-rw-r--r-- | source4/librpc/rpc/pyrpc_util.c | 183 |
1 files changed, 182 insertions, 1 deletions
diff --git a/source4/librpc/rpc/pyrpc_util.c b/source4/librpc/rpc/pyrpc_util.c index e1d3450336..2af868c0c2 100644 --- a/source4/librpc/rpc/pyrpc_util.c +++ b/source4/librpc/rpc/pyrpc_util.c @@ -23,6 +23,11 @@ #include <Python.h> #include "includes.h" #include "librpc/rpc/pyrpc_util.h" +#include "librpc/rpc/dcerpc.h" +#include "librpc/rpc/pyrpc.h" +#include "param/pyparam.h" +#include "auth/credentials/pycredentials.h" +#include "lib/events/events.h" #ifndef Py_TYPE /* Py_TYPE is only available on Python > 2.6 */ #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) @@ -31,7 +36,7 @@ bool py_check_dcerpc_type(PyObject *obj, const char *module, const char *typename) { PyObject *mod; - PyTypeObject *type; + PyTypeObject *type; bool ret; mod = PyImport_ImportModule(module); @@ -59,3 +64,179 @@ bool py_check_dcerpc_type(PyObject *obj, const char *module, const char *typenam return ret; } + +PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, PyObject *kwargs, const struct ndr_interface_table *table) +{ + dcerpc_InterfaceObject *ret; + const char *binding_string; + struct cli_credentials *credentials; + struct loadparm_context *lp_ctx = NULL; + PyObject *py_lp_ctx = Py_None, *py_credentials = Py_None, *py_basis = Py_None; + TALLOC_CTX *mem_ctx = NULL; + struct tevent_context *event_ctx; + NTSTATUS status; + + const char *kwnames[] = { + "binding", "lp_ctx", "credentials", "basis_connection", NULL + }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO:samr", discard_const_p(char *, kwnames), &binding_string, &py_lp_ctx, &py_credentials, &py_basis)) { + return NULL; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); + if (lp_ctx == NULL) { + PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); + talloc_free(mem_ctx); + return NULL; + } + + status = dcerpc_init(lp_ctx); + if (!NT_STATUS_IS_OK(status)) { + PyErr_SetNTSTATUS(status); + talloc_free(mem_ctx); + return NULL; + } + credentials = cli_credentials_from_py_object(py_credentials); + if (credentials == NULL) { + PyErr_SetString(PyExc_TypeError, "Expected credentials"); + talloc_free(mem_ctx); + return NULL; + } + ret = PyObject_New(dcerpc_InterfaceObject, type); + ret->mem_ctx = mem_ctx; + + event_ctx = s4_event_context_init(ret->mem_ctx); + + if (py_basis != Py_None) { + struct dcerpc_pipe *base_pipe; + PyObject *py_base; + PyTypeObject *ClientConnection_Type; + + py_base = PyImport_ImportModule("samba.dcerpc.base"); + if (py_base == NULL) { + talloc_free(mem_ctx); + return NULL; + } + + ClientConnection_Type = (PyTypeObject *)PyObject_GetAttrString(py_base, "ClientConnection"); + if (ClientConnection_Type == NULL) { + PyErr_SetNone(PyExc_TypeError); + talloc_free(mem_ctx); + return NULL; + } + + if (!PyObject_TypeCheck(py_basis, ClientConnection_Type)) { + PyErr_SetString(PyExc_TypeError, "basis_connection must be a DCE/RPC connection"); + talloc_free(mem_ctx); + return NULL; + } + + base_pipe = talloc_reference(mem_ctx, ((dcerpc_InterfaceObject *)py_basis)->pipe); + + status = dcerpc_secondary_context(base_pipe, &ret->pipe, table); + + ret->pipe = talloc_steal(ret->mem_ctx, ret->pipe); + } else { + status = dcerpc_pipe_connect(event_ctx, &ret->pipe, binding_string, + table, credentials, event_ctx, lp_ctx); + } + if (NT_STATUS_IS_ERR(status)) { + PyErr_SetNTSTATUS(status); + talloc_free(mem_ctx); + return NULL; + } + + ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC; + ret->binding_handle = ret->pipe->binding_handle; + return (PyObject *)ret; +} + +static PyObject *py_dcerpc_run_function(dcerpc_InterfaceObject *iface, + const struct PyNdrRpcMethodDef *md, + PyObject *args, PyObject *kwargs) +{ + TALLOC_CTX *mem_ctx; + NTSTATUS status; + void *r; + PyObject *result = Py_None; + + if (md->pack_in_data == NULL || md->unpack_out_data == NULL) { + PyErr_SetString(PyExc_NotImplementedError, "No marshalling code available yet"); + return NULL; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + r = talloc_zero_size(mem_ctx, md->table->calls[md->opnum].struct_size); + if (r == NULL) { + PyErr_NoMemory(); + return NULL; + } + + if (!md->pack_in_data(args, kwargs, r)) { + talloc_free(mem_ctx); + return NULL; + } + + status = md->call(iface->binding_handle, mem_ctx, r); + if (!NT_STATUS_IS_OK(status)) { + PyErr_SetDCERPCStatus(iface->pipe, status); + talloc_free(mem_ctx); + return NULL; + } + + result = md->unpack_out_data(r); + + talloc_free(mem_ctx); + return result; +} + +static PyObject *py_dcerpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs) +{ + dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self; + const struct PyNdrRpcMethodDef *md = (const struct PyNdrRpcMethodDef *)wrapped; + + return py_dcerpc_run_function(iface, md, args, kwargs); +} + +bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds) +{ + int i; + for (i = 0; mds[i].name; i++) { + PyObject *ret; + struct wrapperbase *wb = (struct wrapperbase *)calloc(sizeof(struct wrapperbase), 1); + + wb->name = discard_const_p(char, mds[i].name); + wb->flags = PyWrapperFlag_KEYWORDS; + wb->wrapper = (wrapperfunc)py_dcerpc_call_wrapper; + wb->doc = discard_const_p(char, mds[i].doc); + + ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i])); + + PyDict_SetItemString(ifacetype->tp_dict, mds[i].name, + (PyObject *)ret); + } + + return true; +} + +void PyErr_SetDCERPCStatus(struct dcerpc_pipe *p, NTSTATUS status) +{ + if (p && NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { + status = dcerpc_fault_to_nt_status(p->last_fault_code); + } + PyErr_SetNTSTATUS(status); +} + + |