1/* 2 Python wrappers for DCERPC/SMB client routines. 3 4 Copyright (C) Tim Potter, 2002 5 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 2 of the License, or 9 (at your option) any later version. 10 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. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "python/py_lsa.h" 22 23PyObject *new_lsa_policy_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 24 POLICY_HND *pol) 25{ 26 lsa_policy_hnd_object *o; 27 28 o = PyObject_New(lsa_policy_hnd_object, &lsa_policy_hnd_type); 29 30 o->cli = cli; 31 o->mem_ctx = mem_ctx; 32 memcpy(&o->pol, pol, sizeof(POLICY_HND)); 33 34 return (PyObject*)o; 35} 36 37/* 38 * Exceptions raised by this module 39 */ 40 41PyObject *lsa_error; /* This indicates a non-RPC related error 42 such as name lookup failure */ 43 44PyObject *lsa_ntstatus; /* This exception is raised when a RPC call 45 returns a status code other than 46 NT_STATUS_OK */ 47 48/* 49 * Open/close lsa handles 50 */ 51 52static PyObject *lsa_open_policy(PyObject *self, PyObject *args, 53 PyObject *kw) 54{ 55 static char *kwlist[] = { "servername", "creds", "access", NULL }; 56 char *server, *errstr; 57 PyObject *creds = NULL, *result = NULL; 58 uint32 desired_access = GENERIC_EXECUTE_ACCESS; 59 struct cli_state *cli = NULL; 60 NTSTATUS ntstatus; 61 TALLOC_CTX *mem_ctx = NULL; 62 POLICY_HND hnd; 63 64 if (!PyArg_ParseTupleAndKeywords( 65 args, kw, "s|Oi", kwlist, &server, &creds, &desired_access)) 66 return NULL; 67 68 if (creds && creds != Py_None && !PyDict_Check(creds)) { 69 PyErr_SetString(PyExc_TypeError, 70 "credentials must be dictionary or None"); 71 return NULL; 72 } 73 74 if (server[0] != '\\' || server[1] != '\\') { 75 PyErr_SetString(PyExc_ValueError, "UNC name required"); 76 return NULL; 77 } 78 79 server += 2; 80 81 if (!(cli = open_pipe_creds(server, creds, PI_LSARPC, &errstr))) { 82 PyErr_SetString(lsa_error, errstr); 83 free(errstr); 84 return NULL; 85 } 86 87 if (!(mem_ctx = talloc_init("lsa_open_policy"))) { 88 PyErr_SetString(lsa_error, "unable to init talloc context\n"); 89 goto done; 90 } 91 92 ntstatus = rpccli_lsa_open_policy( 93 cli->pipe_list, mem_ctx, True, desired_access, &hnd); 94 95 if (!NT_STATUS_IS_OK(ntstatus)) { 96 PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); 97 goto done; 98 } 99 100 result = new_lsa_policy_hnd_object(cli->pipe_list, mem_ctx, &hnd); 101 102done: 103 if (!result) { 104 if (cli) 105 cli_shutdown(cli); 106 107 talloc_destroy(mem_ctx); 108 } 109 110 return result; 111} 112 113static PyObject *lsa_close(PyObject *self, PyObject *args, PyObject *kw) 114{ 115 PyObject *po; 116 lsa_policy_hnd_object *hnd; 117 NTSTATUS result; 118 119 /* Parse parameters */ 120 121 if (!PyArg_ParseTuple(args, "O!", &lsa_policy_hnd_type, &po)) 122 return NULL; 123 124 hnd = (lsa_policy_hnd_object *)po; 125 126 /* Call rpc function */ 127 128 result = rpccli_lsa_close(hnd->cli, hnd->mem_ctx, &hnd->pol); 129 130 /* Cleanup samba stuff */ 131 132 cli_shutdown(hnd->cli); 133 talloc_destroy(hnd->mem_ctx); 134 135 /* Return value */ 136 137 Py_INCREF(Py_None); 138 return Py_None; 139} 140 141static PyObject *lsa_lookup_names(PyObject *self, PyObject *args) 142{ 143 PyObject *py_names, *result = NULL; 144 NTSTATUS ntstatus; 145 lsa_policy_hnd_object *hnd = (lsa_policy_hnd_object *)self; 146 int num_names, i; 147 const char **names; 148 DOM_SID *sids; 149 TALLOC_CTX *mem_ctx = NULL; 150 enum lsa_SidType *name_types; 151 152 if (!PyArg_ParseTuple(args, "O", &py_names)) 153 return NULL; 154 155 if (!PyList_Check(py_names) && !PyString_Check(py_names)) { 156 PyErr_SetString(PyExc_TypeError, "must be list or string"); 157 return NULL; 158 } 159 160 if (!(mem_ctx = talloc_init("lsa_lookup_names"))) { 161 PyErr_SetString(lsa_error, "unable to init talloc context\n"); 162 goto done; 163 } 164 165 if (PyList_Check(py_names)) { 166 167 /* Convert list to char ** array */ 168 169 num_names = PyList_Size(py_names); 170 names = (const char **)_talloc(mem_ctx, num_names * sizeof(char *)); 171 172 for (i = 0; i < num_names; i++) { 173 PyObject *obj = PyList_GetItem(py_names, i); 174 175 names[i] = talloc_strdup(mem_ctx, PyString_AsString(obj)); 176 } 177 178 } else { 179 180 /* Just a single element */ 181 182 num_names = 1; 183 names = (const char **)_talloc(mem_ctx, sizeof(char *)); 184 185 names[0] = PyString_AsString(py_names); 186 } 187 188 ntstatus = rpccli_lsa_lookup_names( 189 hnd->cli, mem_ctx, &hnd->pol, num_names, names, 190 NULL, &sids, &name_types); 191 192 if (!NT_STATUS_IS_OK(ntstatus) && NT_STATUS_V(ntstatus) != 0x107) { 193 PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); 194 goto done; 195 } 196 197 result = PyList_New(num_names); 198 199 for (i = 0; i < num_names; i++) { 200 PyObject *sid_obj, *obj; 201 202 py_from_SID(&sid_obj, &sids[i]); 203 204 obj = Py_BuildValue("(Ni)", sid_obj, name_types[i]); 205 206 PyList_SetItem(result, i, obj); 207 } 208 209 done: 210 talloc_destroy(mem_ctx); 211 212 return result; 213} 214 215static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, 216 PyObject *kw) 217{ 218 PyObject *py_sids, *result = NULL; 219 NTSTATUS ntstatus; 220 int num_sids, i; 221 char **domains, **names; 222 uint32 *types; 223 lsa_policy_hnd_object *hnd = (lsa_policy_hnd_object *)self; 224 TALLOC_CTX *mem_ctx = NULL; 225 DOM_SID *sids; 226 227 if (!PyArg_ParseTuple(args, "O", &py_sids)) 228 return NULL; 229 230 if (!PyList_Check(py_sids) && !PyString_Check(py_sids)) { 231 PyErr_SetString(PyExc_TypeError, "must be list or string"); 232 return NULL; 233 } 234 235 if (!(mem_ctx = talloc_init("lsa_lookup_sids"))) { 236 PyErr_SetString(lsa_error, "unable to init talloc context\n"); 237 goto done; 238 } 239 240 if (PyList_Check(py_sids)) { 241 242 /* Convert dictionary to char ** array */ 243 244 num_sids = PyList_Size(py_sids); 245 sids = (DOM_SID *)_talloc(mem_ctx, num_sids * sizeof(DOM_SID)); 246 247 memset(sids, 0, num_sids * sizeof(DOM_SID)); 248 249 for (i = 0; i < num_sids; i++) { 250 PyObject *obj = PyList_GetItem(py_sids, i); 251 252 if (!string_to_sid(&sids[i], PyString_AsString(obj))) { 253 PyErr_SetString(PyExc_ValueError, "string_to_sid failed"); 254 goto done; 255 } 256 } 257 258 } else { 259 260 /* Just a single element */ 261 262 num_sids = 1; 263 sids = (DOM_SID *)_talloc(mem_ctx, sizeof(DOM_SID)); 264 265 if (!string_to_sid(&sids[0], PyString_AsString(py_sids))) { 266 PyErr_SetString(PyExc_ValueError, "string_to_sid failed"); 267 goto done; 268 } 269 } 270 271 ntstatus = rpccli_lsa_lookup_sids( 272 hnd->cli, mem_ctx, &hnd->pol, num_sids, sids, &domains, 273 &names, &types); 274 275 if (!NT_STATUS_IS_OK(ntstatus)) { 276 PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); 277 goto done; 278 } 279 280 result = PyList_New(num_sids); 281 282 for (i = 0; i < num_sids; i++) { 283 PyObject *obj; 284 285 obj = Py_BuildValue("{sssssi}", "username", names[i], 286 "domain", domains[i], "name_type", 287 types[i]); 288 289 PyList_SetItem(result, i, obj); 290 } 291 292 done: 293 talloc_destroy(mem_ctx); 294 295 return result; 296} 297 298static PyObject *lsa_enum_trust_dom(PyObject *self, PyObject *args) 299{ 300 lsa_policy_hnd_object *hnd = (lsa_policy_hnd_object *)self; 301 NTSTATUS ntstatus; 302 uint32 enum_ctx = 0, num_domains, i; 303 char **domain_names; 304 DOM_SID *domain_sids; 305 PyObject *result; 306 307 if (!PyArg_ParseTuple(args, "")) 308 return NULL; 309 310 ntstatus = rpccli_lsa_enum_trust_dom( 311 hnd->cli, hnd->mem_ctx, &hnd->pol, &enum_ctx, 312 &num_domains, &domain_names, &domain_sids); 313 314 if (!NT_STATUS_IS_OK(ntstatus)) { 315 PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); 316 return NULL; 317 } 318 319 result = PyList_New(num_domains); 320 321 for (i = 0; i < num_domains; i++) { 322 fstring sid_str; 323 324 sid_to_string(sid_str, &domain_sids[i]); 325 PyList_SetItem( 326 result, i, 327 Py_BuildValue("(ss)", domain_names[i], sid_str)); 328 } 329 330 return result; 331} 332 333/* 334 * Method dispatch tables 335 */ 336 337static PyMethodDef lsa_hnd_methods[] = { 338 339 /* SIDs<->names */ 340 341 { "lookup_sids", (PyCFunction)lsa_lookup_sids, 342 METH_VARARGS | METH_KEYWORDS, 343 "Convert sids to names." }, 344 345 { "lookup_names", (PyCFunction)lsa_lookup_names, 346 METH_VARARGS | METH_KEYWORDS, 347 "Convert names to sids." }, 348 349 /* Trusted domains */ 350 351 { "enum_trusted_domains", (PyCFunction)lsa_enum_trust_dom, 352 METH_VARARGS, 353 "Enumerate trusted domains." }, 354 355 { NULL } 356}; 357 358static void py_lsa_policy_hnd_dealloc(PyObject* self) 359{ 360 PyObject_Del(self); 361} 362 363static PyObject *py_lsa_policy_hnd_getattr(PyObject *self, char *attrname) 364{ 365 return Py_FindMethod(lsa_hnd_methods, self, attrname); 366} 367 368PyTypeObject lsa_policy_hnd_type = { 369 PyObject_HEAD_INIT(NULL) 370 0, 371 "LSA Policy Handle", 372 sizeof(lsa_policy_hnd_object), 373 0, 374 py_lsa_policy_hnd_dealloc, /*tp_dealloc*/ 375 0, /*tp_print*/ 376 py_lsa_policy_hnd_getattr, /*tp_getattr*/ 377 0, /*tp_setattr*/ 378 0, /*tp_compare*/ 379 0, /*tp_repr*/ 380 0, /*tp_as_number*/ 381 0, /*tp_as_sequence*/ 382 0, /*tp_as_mapping*/ 383 0, /*tp_hash */ 384}; 385 386static PyMethodDef lsa_methods[] = { 387 388 /* Open/close lsa handles */ 389 390 { "open_policy", (PyCFunction)lsa_open_policy, 391 METH_VARARGS | METH_KEYWORDS, 392 "Open a policy handle" }, 393 394 { "close", (PyCFunction)lsa_close, 395 METH_VARARGS, 396 "Close a policy handle" }, 397 398 /* Other stuff - this should really go into a samba config module 399 but for the moment let's leave it here. */ 400 401 { "setup_logging", (PyCFunction)py_setup_logging, 402 METH_VARARGS | METH_KEYWORDS, 403 "Set up debug logging.\n" 404"\n" 405"Initialises Samba's debug logging system. One argument is expected which\n" 406"is a boolean specifying whether debugging is interactive and sent to stdout\n" 407"or logged to a file.\n" 408"\n" 409"Example:\n" 410"\n" 411">>> lsa.setup_logging(interactive = 1)" }, 412 413 { "get_debuglevel", (PyCFunction)get_debuglevel, 414 METH_VARARGS, 415 "Set the current debug level.\n" 416"\n" 417"Example:\n" 418"\n" 419">>> lsa.get_debuglevel()\n" 420"0" }, 421 422 { "set_debuglevel", (PyCFunction)set_debuglevel, 423 METH_VARARGS, 424 "Get the current debug level.\n" 425"\n" 426"Example:\n" 427"\n" 428">>> lsa.set_debuglevel(10)" }, 429 430 { NULL } 431}; 432 433static struct const_vals { 434 char *name; 435 uint32 value; 436} module_const_vals[] = { 437 { NULL } 438}; 439 440static void const_init(PyObject *dict) 441{ 442 struct const_vals *tmp; 443 PyObject *obj; 444 445 for (tmp = module_const_vals; tmp->name; tmp++) { 446 obj = PyInt_FromLong(tmp->value); 447 PyDict_SetItemString(dict, tmp->name, obj); 448 Py_DECREF(obj); 449 } 450} 451 452/* 453 * Module initialisation 454 */ 455 456void initlsa(void) 457{ 458 PyObject *module, *dict; 459 460 /* Initialise module */ 461 462 module = Py_InitModule("lsa", lsa_methods); 463 dict = PyModule_GetDict(module); 464 465 lsa_error = PyErr_NewException("lsa.error", NULL, NULL); 466 PyDict_SetItemString(dict, "error", lsa_error); 467 468 lsa_ntstatus = PyErr_NewException("lsa.ntstatus", NULL, NULL); 469 PyDict_SetItemString(dict, "ntstatus", lsa_ntstatus); 470 471 /* Initialise policy handle object */ 472 473 lsa_policy_hnd_type.ob_type = &PyType_Type; 474 475 /* Initialise constants */ 476 477 const_init(dict); 478 479 /* Do samba initialisation */ 480 481 py_samba_init(); 482 483 setup_logging("lsa", True); 484 DEBUGLEVEL = 10; 485} 486