Changeset 745 for trunk/server/source4/librpc/rpc/pyrpc.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/librpc/rpc/pyrpc.c
r414 r745 3 3 Samba utility functions 4 4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 5 5 6 6 This program is free software; you can redistribute it and/or modify 7 7 it under the terms of the GNU General Public License as published by 8 8 the Free Software Foundation; either version 3 of the License, or 9 9 (at your option) any later version. 10 10 11 11 This program is distributed in the hope that it will be useful, 12 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 14 GNU General Public License for more details. 15 15 16 16 You should have received a copy of the GNU General Public License 17 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 18 */ 19 19 20 #include <Python.h> 20 21 #include "includes.h" 21 #include <Python.h>22 22 #include <structmember.h> 23 23 #include "librpc/rpc/pyrpc.h" 24 #include "librpc/rpc/dcerpc.h"25 24 #include "lib/events/events.h" 26 25 #include "param/pyparam.h" 26 #include "librpc/rpc/dcerpc.h" 27 #include "librpc/rpc/pyrpc_util.h" 27 28 #include "auth/credentials/pycredentials.h" 28 29 29 #ifndef Py_RETURN_NONE 30 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None 31 #endif 32 33 static PyObject *py_dcerpc_run_function(dcerpc_InterfaceObject *iface, 34 const struct PyNdrRpcMethodDef *md, 35 PyObject *args, PyObject *kwargs) 36 { 37 TALLOC_CTX *mem_ctx; 38 NTSTATUS status; 39 void *r; 40 PyObject *result = Py_None; 41 42 if (md->pack_in_data == NULL || md->unpack_out_data == NULL) { 43 PyErr_SetString(PyExc_NotImplementedError, "No marshalling code available yet"); 44 return NULL; 45 } 46 47 mem_ctx = talloc_new(NULL); 48 if (mem_ctx == NULL) { 49 PyErr_NoMemory(); 50 return NULL; 51 } 52 53 r = talloc_zero_size(mem_ctx, md->table->calls[md->opnum].struct_size); 54 if (r == NULL) { 55 PyErr_NoMemory(); 56 return NULL; 57 } 58 59 if (!md->pack_in_data(args, kwargs, r)) { 60 talloc_free(mem_ctx); 61 return NULL; 62 } 63 64 status = md->call(iface->pipe, mem_ctx, r); 65 if (NT_STATUS_IS_ERR(status)) { 66 PyErr_SetDCERPCStatus(iface->pipe, status); 67 talloc_free(mem_ctx); 68 return NULL; 69 } 70 71 result = md->unpack_out_data(r); 72 73 talloc_free(mem_ctx); 74 return result; 75 } 76 77 static PyObject *py_dcerpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs) 78 { 79 dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self; 80 const struct PyNdrRpcMethodDef *md = (const struct PyNdrRpcMethodDef *)wrapped; 81 82 return py_dcerpc_run_function(iface, md, args, kwargs); 83 } 84 85 86 bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds) 87 { 88 int i; 89 for (i = 0; mds[i].name; i++) { 90 PyObject *ret; 91 struct wrapperbase *wb = (struct wrapperbase *)calloc(sizeof(struct wrapperbase), 1); 92 93 wb->name = discard_const_p(char, mds[i].name); 94 wb->flags = PyWrapperFlag_KEYWORDS; 95 wb->wrapper = (wrapperfunc)py_dcerpc_call_wrapper; 96 wb->doc = discard_const_p(char, mds[i].doc); 97 98 ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i])); 99 100 PyDict_SetItemString(ifacetype->tp_dict, mds[i].name, 101 (PyObject *)ret); 102 } 103 104 return true; 105 } 30 void initbase(void); 31 32 staticforward PyTypeObject dcerpc_InterfaceType; 106 33 107 34 static bool PyString_AsGUID(PyObject *object, struct GUID *uuid) … … 147 74 PyErr_SetString(PyExc_TypeError, "Expected UUID or syntax id tuple"); 148 75 return false; 149 } 76 } 150 77 151 78 static PyObject *py_iface_server_name(PyObject *obj, void *closure) … … 153 80 const char *server_name; 154 81 dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)obj; 155 82 156 83 server_name = dcerpc_server_name(iface->pipe); 157 84 if (server_name == NULL) … … 207 134 { NULL } 208 135 }; 209 210 void PyErr_SetDCERPCStatus(struct dcerpc_pipe *p, NTSTATUS status)211 {212 if (p != NULL && NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {213 const char *errstr = dcerpc_errstr(NULL, p->last_fault_code);214 PyErr_SetObject(PyExc_RuntimeError,215 Py_BuildValue("(i,s)", p->last_fault_code,216 errstr));217 } else {218 PyErr_SetNTSTATUS(status);219 }220 }221 136 222 137 static PyObject *py_iface_request(PyObject *self, PyObject *args, PyObject *kwargs) … … 232 147 struct GUID object_guid; 233 148 TALLOC_CTX *mem_ctx = talloc_new(NULL); 149 uint32_t out_flags = 0; 234 150 const char *kwnames[] = { "opnum", "data", "object", NULL }; 235 151 236 152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "is#|O:request", 237 153 discard_const_p(char *, kwnames), &opnum, &in_data, &in_length, &object)) { 154 talloc_free(mem_ctx); 238 155 return NULL; 239 156 } … … 245 162 246 163 if (object != NULL && !PyString_AsGUID(object, &object_guid)) { 247 return NULL; 248 } 249 250 status = dcerpc_request(iface->pipe, object?&object_guid:NULL, 251 opnum, mem_ctx, &data_in, &data_out); 252 253 if (NT_STATUS_IS_ERR(status)) { 164 talloc_free(mem_ctx); 165 return NULL; 166 } 167 168 status = dcerpc_binding_handle_raw_call(iface->binding_handle, 169 object?&object_guid:NULL, 170 opnum, 171 0, /* in_flags */ 172 data_in.data, 173 data_in.length, 174 mem_ctx, 175 &data_out.data, 176 &data_out.length, 177 &out_flags); 178 if (!NT_STATUS_IS_OK(status)) { 254 179 PyErr_SetDCERPCStatus(iface->pipe, status); 255 180 talloc_free(mem_ctx); … … 291 216 &transfer_syntax); 292 217 293 if ( NT_STATUS_IS_ERR(status)) {218 if (!NT_STATUS_IS_OK(status)) { 294 219 PyErr_SetDCERPCStatus(iface->pipe, status); 295 220 return NULL; … … 299 224 } 300 225 301 PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, PyObject *kwargs, const struct ndr_interface_table *table) 226 static PyMethodDef dcerpc_interface_methods[] = { 227 { "request", (PyCFunction)py_iface_request, METH_VARARGS|METH_KEYWORDS, "S.request(opnum, data, object=None) -> data\nMake a raw request" }, 228 { "alter_context", (PyCFunction)py_iface_alter_context, METH_VARARGS|METH_KEYWORDS, "S.alter_context(syntax)\nChange to a different interface" }, 229 { NULL, NULL, 0, NULL }, 230 }; 231 232 static void dcerpc_interface_dealloc(PyObject* self) 233 { 234 dcerpc_InterfaceObject *interface = (dcerpc_InterfaceObject *)self; 235 talloc_free(interface->mem_ctx); 236 self->ob_type->tp_free(self); 237 } 238 239 static PyObject *dcerpc_interface_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 302 240 { 303 241 dcerpc_InterfaceObject *ret; … … 305 243 struct cli_credentials *credentials; 306 244 struct loadparm_context *lp_ctx = NULL; 307 PyObject *py_lp_ctx = Py_None, *py_credentials = Py_None , *py_basis = Py_None;308 TALLOC_CTX *mem_ctx = NULL;245 PyObject *py_lp_ctx = Py_None, *py_credentials = Py_None; 246 TALLOC_CTX *mem_ctx; 309 247 struct tevent_context *event_ctx; 310 248 NTSTATUS status; 311 249 250 PyObject *syntax, *py_basis = Py_None; 312 251 const char *kwnames[] = { 313 "binding", " lp_ctx", "credentials", "basis_connection", NULL252 "binding", "syntax", "lp_ctx", "credentials", "basis_connection", NULL 314 253 }; 315 316 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO:samr", discard_const_p(char *, kwnames), &binding_string, &py_lp_ctx, &py_credentials, &py_basis)) { 317 return NULL; 318 } 319 320 lp_ctx = lp_from_py_object(py_lp_ctx); 254 struct ndr_interface_table *table; 255 256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OOO:connect", discard_const_p(char *, kwnames), &binding_string, &syntax, &py_lp_ctx, &py_credentials, &py_basis)) { 257 return NULL; 258 } 259 260 mem_ctx = talloc_new(NULL); 261 if (mem_ctx == NULL) { 262 PyErr_NoMemory(); 263 return NULL; 264 } 265 266 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); 321 267 if (lp_ctx == NULL) { 322 268 PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); 323 return NULL; 324 } 325 326 status = dcerpc_init(lp_ctx); 327 if (!NT_STATUS_IS_OK(status)) { 328 PyErr_SetNTSTATUS(status); 329 return NULL; 330 } 269 talloc_free(mem_ctx); 270 return NULL; 271 } 272 331 273 credentials = cli_credentials_from_py_object(py_credentials); 332 274 if (credentials == NULL) { 333 275 PyErr_SetString(PyExc_TypeError, "Expected credentials"); 276 talloc_free(mem_ctx); 334 277 return NULL; 335 278 } 336 279 ret = PyObject_New(dcerpc_InterfaceObject, type); 337 338 event_ctx = event_context_init(mem_ctx); 280 ret->mem_ctx = mem_ctx; 281 282 event_ctx = s4_event_context_init(ret->mem_ctx); 283 284 /* Create a dummy interface table struct. TODO: In the future, we should 285 * rather just allow connecting without requiring an interface table. 286 */ 287 288 table = talloc_zero(ret->mem_ctx, struct ndr_interface_table); 289 290 if (table == NULL) { 291 PyErr_SetString(PyExc_MemoryError, "Allocating interface table"); 292 talloc_free(mem_ctx); 293 return NULL; 294 } 295 296 if (!ndr_syntax_from_py_object(syntax, &table->syntax_id)) { 297 talloc_free(mem_ctx); 298 return NULL; 299 } 300 301 ret->pipe = NULL; 302 ret->binding_handle = NULL; 339 303 340 304 if (py_basis != Py_None) { … … 347 311 } 348 312 349 base_pipe = ((dcerpc_InterfaceObject *)py_basis)->pipe; 313 base_pipe = talloc_reference(ret->mem_ctx, 314 ((dcerpc_InterfaceObject *)py_basis)->pipe); 350 315 351 316 status = dcerpc_secondary_context(base_pipe, &ret->pipe, table); 317 318 ret->pipe = talloc_steal(ret->mem_ctx, ret->pipe); 352 319 } else { 353 status = dcerpc_pipe_connect( NULL, &ret->pipe, binding_string,354 355 } 356 if (NT_STATUS_IS_ERR(status)) { 357 PyErr_SetNTSTATUS(status);358 talloc_free(mem_ctx);359 return NULL;360 }361 320 status = dcerpc_pipe_connect(ret->mem_ctx, &ret->pipe, binding_string, 321 table, credentials, event_ctx, lp_ctx); 322 } 323 324 if (!NT_STATUS_IS_OK(status)) { 325 PyErr_SetDCERPCStatus(ret->pipe, status); 326 talloc_free(ret->mem_ctx); 327 return NULL; 328 } 362 329 ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC; 330 ret->binding_handle = ret->pipe->binding_handle; 363 331 return (PyObject *)ret; 364 332 } 365 333 366 static PyMethodDef dcerpc_interface_methods[] = { 367 { "request", (PyCFunction)py_iface_request, METH_VARARGS|METH_KEYWORDS, "S.request(opnum, data, object=None) -> data\nMake a raw request" }, 368 { "alter_context", (PyCFunction)py_iface_alter_context, METH_VARARGS|METH_KEYWORDS, "S.alter_context(syntax)\nChange to a different interface" }, 369 { NULL, NULL, 0, NULL }, 370 }; 371 372 373 static void dcerpc_interface_dealloc(PyObject* self) 374 { 375 dcerpc_InterfaceObject *interface = (dcerpc_InterfaceObject *)self; 376 talloc_free(interface->pipe); 377 PyObject_Del(self); 378 } 379 380 static PyObject *dcerpc_interface_new(PyTypeObject *self, PyObject *args, PyObject *kwargs) 381 { 382 dcerpc_InterfaceObject *ret; 383 const char *binding_string; 384 struct cli_credentials *credentials; 385 struct loadparm_context *lp_ctx = NULL; 386 PyObject *py_lp_ctx = Py_None, *py_credentials = Py_None; 387 TALLOC_CTX *mem_ctx = NULL; 388 struct tevent_context *event_ctx; 389 NTSTATUS status; 390 391 PyObject *syntax, *py_basis = Py_None; 392 const char *kwnames[] = { 393 "binding", "syntax", "lp_ctx", "credentials", "basis_connection", NULL 394 }; 395 struct ndr_interface_table *table; 396 397 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OOO:connect", discard_const_p(char *, kwnames), &binding_string, &syntax, &py_lp_ctx, &py_credentials, &py_basis)) { 398 return NULL; 399 } 400 401 lp_ctx = lp_from_py_object(py_lp_ctx); 402 if (lp_ctx == NULL) { 403 PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); 404 return NULL; 405 } 406 407 credentials = cli_credentials_from_py_object(py_credentials); 408 if (credentials == NULL) { 409 PyErr_SetString(PyExc_TypeError, "Expected credentials"); 410 return NULL; 411 } 412 ret = PyObject_New(dcerpc_InterfaceObject, &dcerpc_InterfaceType); 413 414 event_ctx = s4_event_context_init(mem_ctx); 415 416 /* Create a dummy interface table struct. TODO: In the future, we should rather just allow 417 * connecting without requiring an interface table. 418 */ 419 420 table = talloc_zero(mem_ctx, struct ndr_interface_table); 421 422 if (table == NULL) { 423 PyErr_SetString(PyExc_MemoryError, "Allocating interface table"); 424 return NULL; 425 } 426 427 if (!ndr_syntax_from_py_object(syntax, &table->syntax_id)) { 428 return NULL; 429 } 430 431 ret->pipe = NULL; 432 433 if (py_basis != Py_None) { 434 struct dcerpc_pipe *base_pipe; 435 436 if (!PyObject_TypeCheck(py_basis, &dcerpc_InterfaceType)) { 437 PyErr_SetString(PyExc_ValueError, "basis_connection must be a DCE/RPC connection"); 438 talloc_free(mem_ctx); 439 return NULL; 440 } 441 442 base_pipe = ((dcerpc_InterfaceObject *)py_basis)->pipe; 443 444 status = dcerpc_secondary_context(base_pipe, &ret->pipe, 445 table); 446 ret->pipe = talloc_steal(NULL, ret->pipe); 447 } else { 448 status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, 449 table, credentials, event_ctx, lp_ctx); 450 } 451 452 if (NT_STATUS_IS_ERR(status)) { 453 PyErr_SetDCERPCStatus(ret->pipe, status); 454 talloc_free(mem_ctx); 455 return NULL; 456 } 457 ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC; 458 return (PyObject *)ret; 459 } 460 461 PyTypeObject dcerpc_InterfaceType = { 334 static PyTypeObject dcerpc_InterfaceType = { 462 335 PyObject_HEAD_INIT(NULL) 0, 463 336 .tp_name = "dcerpc.ClientConnection",
Note:
See TracChangeset
for help on using the changeset viewer.