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_samr.h" 22 23/* 24 * Exceptions raised by this module 25 */ 26 27PyObject *samr_error; /* This indicates a non-RPC related error 28 such as name lookup failure */ 29 30PyObject *samr_ntstatus; /* This exception is raised when a RPC call 31 returns a status code other than 32 NT_STATUS_OK */ 33 34/* SAMR group handle object */ 35 36static void py_samr_group_hnd_dealloc(PyObject* self) 37{ 38 PyObject_Del(self); 39} 40 41static PyMethodDef samr_group_methods[] = { 42 { NULL } 43}; 44 45static PyObject *py_samr_group_hnd_getattr(PyObject *self, char *attrname) 46{ 47 return Py_FindMethod(samr_group_methods, self, attrname); 48} 49 50PyTypeObject samr_group_hnd_type = { 51 PyObject_HEAD_INIT(NULL) 52 0, 53 "SAMR Group Handle", 54 sizeof(samr_group_hnd_object), 55 0, 56 py_samr_group_hnd_dealloc, /*tp_dealloc*/ 57 0, /*tp_print*/ 58 py_samr_group_hnd_getattr, /*tp_getattr*/ 59 0, /*tp_setattr*/ 60 0, /*tp_compare*/ 61 0, /*tp_repr*/ 62 0, /*tp_as_number*/ 63 0, /*tp_as_sequence*/ 64 0, /*tp_as_mapping*/ 65 0, /*tp_hash */ 66}; 67 68PyObject *new_samr_group_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx, 69 POLICY_HND *pol) 70{ 71 samr_group_hnd_object *o; 72 73 o = PyObject_New(samr_group_hnd_object, &samr_group_hnd_type); 74 75 o->cli = cli; 76 o->mem_ctx = mem_ctx; 77 memcpy(&o->group_pol, pol, sizeof(POLICY_HND)); 78 79 return (PyObject*)o; 80} 81 82/* Alias handle object */ 83 84static void py_samr_alias_hnd_dealloc(PyObject* self) 85{ 86 PyObject_Del(self); 87} 88 89static PyMethodDef samr_alias_methods[] = { 90 { NULL } 91}; 92 93static PyObject *py_samr_alias_hnd_getattr(PyObject *self, char *attrname) 94{ 95 return Py_FindMethod(samr_alias_methods, self, attrname); 96} 97 98PyTypeObject samr_alias_hnd_type = { 99 PyObject_HEAD_INIT(NULL) 100 0, 101 "SAMR Alias Handle", 102 sizeof(samr_alias_hnd_object), 103 0, 104 py_samr_alias_hnd_dealloc, /*tp_dealloc*/ 105 0, /*tp_print*/ 106 py_samr_alias_hnd_getattr, /*tp_getattr*/ 107 0, /*tp_setattr*/ 108 0, /*tp_compare*/ 109 0, /*tp_repr*/ 110 0, /*tp_as_number*/ 111 0, /*tp_as_sequence*/ 112 0, /*tp_as_mapping*/ 113 0, /*tp_hash */ 114}; 115 116PyObject *new_samr_alias_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx, 117 POLICY_HND *pol) 118{ 119 samr_alias_hnd_object *o; 120 121 o = PyObject_New(samr_alias_hnd_object, &samr_alias_hnd_type); 122 123 o->cli = cli; 124 o->mem_ctx = mem_ctx; 125 memcpy(&o->alias_pol, pol, sizeof(POLICY_HND)); 126 127 return (PyObject*)o; 128} 129 130/* SAMR user handle object */ 131 132static void py_samr_user_hnd_dealloc(PyObject* self) 133{ 134 PyObject_Del(self); 135} 136 137static PyObject *samr_set_user_info2(PyObject *self, PyObject *args, 138 PyObject *kw) 139{ 140 samr_user_hnd_object *user_hnd = (samr_user_hnd_object *)self; 141 static char *kwlist[] = { "dict", NULL }; 142 PyObject *info, *result = NULL; 143 SAM_USERINFO_CTR ctr; 144 TALLOC_CTX *mem_ctx; 145 uchar sess_key[16]; 146 NTSTATUS ntstatus; 147 int level; 148 union { 149 SAM_USER_INFO_16 id16; 150 SAM_USER_INFO_21 id21; 151 } pinfo; 152 153 if (!PyArg_ParseTupleAndKeywords( 154 args, kw, "O!", kwlist, &PyDict_Type, &info)) 155 return NULL; 156 157 if (!get_level_value(info, &level)) { 158 PyErr_SetString(samr_error, "invalid info level"); 159 return NULL; 160 } 161 162 ZERO_STRUCT(ctr); 163 164 ctr.switch_value = level; 165 166 switch(level) { 167 case 16: 168 ctr.info.id16 = &pinfo.id16; 169 170 if (!py_to_SAM_USER_INFO_16(ctr.info.id16, info)) { 171 PyErr_SetString( 172 samr_error, "error converting user info"); 173 goto done; 174 } 175 176 break; 177 case 21: 178 ctr.info.id21 = &pinfo.id21; 179 180 if (!py_to_SAM_USER_INFO_21(ctr.info.id21, info)) { 181 PyErr_SetString( 182 samr_error, "error converting user info"); 183 goto done; 184 } 185 186 break; 187 default: 188 PyErr_SetString(samr_error, "unsupported info level"); 189 goto done; 190 } 191 192 /* Call RPC function */ 193 194 if (!(mem_ctx = talloc_init("samr_set_user_info2"))) { 195 PyErr_SetString( 196 samr_error, "unable to init talloc context\n"); 197 goto done; 198 } 199 200 ntstatus = rpccli_samr_set_userinfo2( 201 user_hnd->cli, mem_ctx, &user_hnd->user_pol, level, 202 sess_key, &ctr); 203 204 talloc_destroy(mem_ctx); 205 206 if (!NT_STATUS_IS_OK(ntstatus)) { 207 PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); 208 goto done; 209 } 210 211 Py_INCREF(Py_None); 212 result = Py_None; 213 214done: 215 return result; 216} 217 218static PyObject *samr_delete_dom_user(PyObject *self, PyObject *args, 219 PyObject *kw) 220{ 221 samr_user_hnd_object *user_hnd = (samr_user_hnd_object *)self; 222 static char *kwlist[] = { NULL }; 223 NTSTATUS ntstatus; 224 TALLOC_CTX *mem_ctx; 225 PyObject *result = NULL; 226 227 if (!PyArg_ParseTupleAndKeywords( 228 args, kw, "", kwlist)) 229 return NULL; 230 231 if (!(mem_ctx = talloc_init("samr_delete_dom_user"))) { 232 PyErr_SetString(samr_error, "unable to init talloc context"); 233 return NULL; 234 } 235 236 ntstatus = rpccli_samr_delete_dom_user( 237 user_hnd->cli, mem_ctx, &user_hnd->user_pol); 238 239 if (!NT_STATUS_IS_OK(ntstatus)) { 240 PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); 241 goto done; 242 } 243 244 Py_INCREF(Py_None); 245 result = Py_None; 246 247done: 248 talloc_destroy(mem_ctx); 249 250 return result; 251} 252 253static PyMethodDef samr_user_methods[] = { 254 { "delete_domain_user", (PyCFunction)samr_delete_dom_user, 255 METH_VARARGS | METH_KEYWORDS, 256 "Delete domain user." }, 257 { "set_user_info2", (PyCFunction)samr_set_user_info2, 258 METH_VARARGS | METH_KEYWORDS, 259 "Set user info 2" }, 260 { NULL } 261}; 262 263static PyObject *py_samr_user_hnd_getattr(PyObject *self, char *attrname) 264{ 265 return Py_FindMethod(samr_user_methods, self, attrname); 266} 267 268PyTypeObject samr_user_hnd_type = { 269 PyObject_HEAD_INIT(NULL) 270 0, 271 "SAMR User Handle", 272 sizeof(samr_user_hnd_object), 273 0, 274 py_samr_user_hnd_dealloc, /*tp_dealloc*/ 275 0, /*tp_print*/ 276 py_samr_user_hnd_getattr, /*tp_getattr*/ 277 0, /*tp_setattr*/ 278 0, /*tp_compare*/ 279 0, /*tp_repr*/ 280 0, /*tp_as_number*/ 281 0, /*tp_as_sequence*/ 282 0, /*tp_as_mapping*/ 283 0, /*tp_hash */ 284}; 285 286PyObject *new_samr_user_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 287 POLICY_HND *pol) 288{ 289 samr_user_hnd_object *o; 290 291 o = PyObject_New(samr_user_hnd_object, &samr_user_hnd_type); 292 293 o->cli = cli; 294 o->mem_ctx = mem_ctx; 295 memcpy(&o->user_pol, pol, sizeof(POLICY_HND)); 296 297 return (PyObject*)o; 298} 299 300/* SAMR connect handle object */ 301 302static void py_samr_connect_hnd_dealloc(PyObject* self) 303{ 304 PyObject_Del(self); 305} 306 307PyObject *new_samr_domain_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 308 POLICY_HND *pol) 309{ 310 samr_domain_hnd_object *o; 311 312 o = PyObject_New(samr_domain_hnd_object, &samr_domain_hnd_type); 313 314 o->cli = cli; 315 o->mem_ctx = mem_ctx; 316 memcpy(&o->domain_pol, pol, sizeof(POLICY_HND)); 317 318 return (PyObject*)o; 319} 320 321static PyObject *samr_open_domain(PyObject *self, PyObject *args, PyObject *kw) 322{ 323 samr_connect_hnd_object *connect_hnd = (samr_connect_hnd_object *)self; 324 static char *kwlist[] = { "sid", "access", NULL }; 325 uint32 desired_access = MAXIMUM_ALLOWED_ACCESS; 326 char *sid_str; 327 DOM_SID sid; 328 TALLOC_CTX *mem_ctx = NULL; 329 POLICY_HND domain_pol; 330 NTSTATUS ntstatus; 331 PyObject *result = NULL; 332 333 if (!PyArg_ParseTupleAndKeywords( 334 args, kw, "s|i", kwlist, &sid_str, &desired_access)) 335 return NULL; 336 337 if (!string_to_sid(&sid, sid_str)) { 338 PyErr_SetString(PyExc_TypeError, "string is not a sid"); 339 return NULL; 340 } 341 342 if (!(mem_ctx = talloc_init("samr_open_domain"))) { 343 PyErr_SetString(samr_error, "unable to init talloc context"); 344 return NULL; 345 } 346 347 ntstatus = rpccli_samr_open_domain( 348 connect_hnd->cli, mem_ctx, &connect_hnd->connect_pol, 349 desired_access, &sid, &domain_pol); 350 351 if (!NT_STATUS_IS_OK(ntstatus)) { 352 PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); 353 goto done; 354 } 355 356 result = new_samr_domain_hnd_object( 357 connect_hnd->cli, mem_ctx, &domain_pol); 358 359done: 360 if (!result) { 361 if (mem_ctx) 362 talloc_destroy(mem_ctx); 363 } 364 365 return result; 366} 367 368static PyMethodDef samr_connect_methods[] = { 369 { "open_domain", (PyCFunction)samr_open_domain, 370 METH_VARARGS | METH_KEYWORDS, 371 "Open a handle on a domain" }, 372 373 { NULL } 374}; 375 376static PyObject *py_samr_connect_hnd_getattr(PyObject *self, char *attrname) 377{ 378 return Py_FindMethod(samr_connect_methods, self, attrname); 379} 380 381PyTypeObject samr_connect_hnd_type = { 382 PyObject_HEAD_INIT(NULL) 383 0, 384 "SAMR Connect Handle", 385 sizeof(samr_connect_hnd_object), 386 0, 387 py_samr_connect_hnd_dealloc, /*tp_dealloc*/ 388 0, /*tp_print*/ 389 py_samr_connect_hnd_getattr, /*tp_getattr*/ 390 0, /*tp_setattr*/ 391 0, /*tp_compare*/ 392 0, /*tp_repr*/ 393 0, /*tp_as_number*/ 394 0, /*tp_as_sequence*/ 395 0, /*tp_as_mapping*/ 396 0, /*tp_hash */ 397}; 398 399PyObject *new_samr_connect_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 400 POLICY_HND *pol) 401{ 402 samr_connect_hnd_object *o; 403 404 o = PyObject_New(samr_connect_hnd_object, &samr_connect_hnd_type); 405 406 o->cli = cli; 407 o->mem_ctx = mem_ctx; 408 memcpy(&o->connect_pol, pol, sizeof(POLICY_HND)); 409 410 return (PyObject*)o; 411} 412 413/* SAMR domain handle object */ 414 415static void py_samr_domain_hnd_dealloc(PyObject* self) 416{ 417 PyObject_Del(self); 418} 419 420static PyObject *samr_enum_dom_groups(PyObject *self, PyObject *args, 421 PyObject *kw) 422{ 423 samr_domain_hnd_object *domain_hnd = (samr_domain_hnd_object *)self; 424 static char *kwlist[] = { NULL }; 425 TALLOC_CTX *mem_ctx; 426/* uint32 desired_access = MAXIMUM_ALLOWED_ACCESS; */ 427 uint32 start_idx, size, num_dom_groups; 428 struct acct_info *dom_groups; 429 NTSTATUS result; 430 PyObject *py_result = NULL; 431 432 if (!PyArg_ParseTupleAndKeywords(args, kw, "", kwlist)) 433 return NULL; 434 435 if (!(mem_ctx = talloc_init("samr_enum_dom_groups"))) { 436 PyErr_SetString(samr_error, "unable to init talloc context"); 437 return NULL; 438 } 439 440 start_idx = 0; 441 size = 0xffff; 442 443 do { 444 result = rpccli_samr_enum_dom_groups( 445 domain_hnd->cli, mem_ctx, &domain_hnd->domain_pol, 446 &start_idx, size, &dom_groups, &num_dom_groups); 447 448 if (NT_STATUS_IS_OK(result) || 449 NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) { 450 py_from_acct_info(&py_result, dom_groups, 451 num_dom_groups); 452 } 453 454 } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)); 455 456 return py_result; 457} 458 459static PyObject *samr_create_dom_user(PyObject *self, PyObject *args, 460 PyObject *kw) 461{ 462 samr_domain_hnd_object *domain_hnd = (samr_domain_hnd_object *)self; 463 static char *kwlist[] = { "account_name", "acb_info", NULL }; 464 char *account_name; 465 NTSTATUS ntstatus; 466 uint32 unknown = 0xe005000b; /* Access mask? */ 467 uint32 user_rid; 468 PyObject *result = NULL; 469 TALLOC_CTX *mem_ctx; 470 uint32 acb_info = ACB_NORMAL; 471 POLICY_HND user_pol; 472 473 if (!PyArg_ParseTupleAndKeywords( 474 args, kw, "s|i", kwlist, &account_name, &acb_info)) 475 return NULL; 476 477 if (!(mem_ctx = talloc_init("samr_create_dom_user"))) { 478 PyErr_SetString(samr_error, "unable to init talloc context"); 479 return NULL; 480 } 481 482 ntstatus = rpccli_samr_create_dom_user( 483 domain_hnd->cli, mem_ctx, &domain_hnd->domain_pol, 484 account_name, acb_info, unknown, &user_pol, &user_rid); 485 486 if (!NT_STATUS_IS_OK(ntstatus)) { 487 PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); 488 talloc_destroy(mem_ctx); 489 goto done; 490 } 491 492 result = new_samr_user_hnd_object( 493 domain_hnd->cli, mem_ctx, &user_pol); 494 495done: 496 497 return result; 498} 499 500static PyMethodDef samr_domain_methods[] = { 501 { "enum_domain_groups", (PyCFunction)samr_enum_dom_groups, 502 METH_VARARGS | METH_KEYWORDS, "Enumerate domain groups" }, 503 { "create_domain_user", (PyCFunction)samr_create_dom_user, 504 METH_VARARGS | METH_KEYWORDS, "Create domain user" }, 505 { NULL } 506}; 507 508static PyObject *py_samr_domain_hnd_getattr(PyObject *self, char *attrname) 509{ 510 return Py_FindMethod(samr_domain_methods, self, attrname); 511} 512 513PyTypeObject samr_domain_hnd_type = { 514 PyObject_HEAD_INIT(NULL) 515 0, 516 "SAMR Domain Handle", 517 sizeof(samr_domain_hnd_object), 518 0, 519 py_samr_domain_hnd_dealloc, /*tp_dealloc*/ 520 0, /*tp_print*/ 521 py_samr_domain_hnd_getattr, /*tp_getattr*/ 522 0, /*tp_setattr*/ 523 0, /*tp_compare*/ 524 0, /*tp_repr*/ 525 0, /*tp_as_number*/ 526 0, /*tp_as_sequence*/ 527 0, /*tp_as_mapping*/ 528 0, /*tp_hash */ 529}; 530 531static PyObject *samr_connect(PyObject *self, PyObject *args, PyObject *kw) 532{ 533 static char *kwlist[] = { "server", "creds", "access", NULL }; 534 uint32 desired_access = MAXIMUM_ALLOWED_ACCESS; 535 char *server, *errstr; 536 struct cli_state *cli = NULL; 537 POLICY_HND hnd; 538 TALLOC_CTX *mem_ctx = NULL; 539 PyObject *result = NULL, *creds = NULL; 540 NTSTATUS ntstatus; 541 542 if (!PyArg_ParseTupleAndKeywords( 543 args, kw, "s|Oi", kwlist, &server, &creds, 544 &desired_access)) 545 return NULL; 546 547 if (server[0] != '\\' || server[1] != '\\') { 548 PyErr_SetString(PyExc_ValueError, "UNC name required"); 549 return NULL; 550 } 551 552 server += 2; 553 554 if (creds && creds != Py_None && !PyDict_Check(creds)) { 555 PyErr_SetString(PyExc_TypeError, 556 "credentials must be dictionary or None"); 557 return NULL; 558 } 559 560 if (!(cli = open_pipe_creds(server, creds, PI_SAMR, &errstr))) { 561 PyErr_SetString(samr_error, errstr); 562 free(errstr); 563 return NULL; 564 } 565 566 if (!(mem_ctx = talloc_init("samr_connect"))) { 567 PyErr_SetString(samr_ntstatus, 568 "unable to init talloc context\n"); 569 goto done; 570 } 571 572 ntstatus = rpccli_samr_connect(cli->pipe_list, mem_ctx, desired_access, &hnd); 573 574 if (!NT_STATUS_IS_OK(ntstatus)) { 575 cli_shutdown(cli); 576 PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); 577 goto done; 578 } 579 580 result = new_samr_connect_hnd_object(cli->pipe_list, mem_ctx, &hnd); 581 582done: 583 if (!result) { 584 if (cli) 585 cli_shutdown(cli); 586 587 if (mem_ctx) 588 talloc_destroy(mem_ctx); 589 } 590 591 return result; 592} 593 594/* 595 * Module initialisation 596 */ 597 598static PyMethodDef samr_methods[] = { 599 600 /* Open/close samr connect handles */ 601 602 { "connect", (PyCFunction)samr_connect, 603 METH_VARARGS | METH_KEYWORDS, 604 "Open a connect handle" }, 605 606 { NULL } 607}; 608 609static struct const_vals { 610 char *name; 611 uint32 value; 612} module_const_vals[] = { 613 614 /* Account control bits */ 615 616 { "ACB_DISABLED", 0x0001 }, 617 { "ACB_HOMDIRREQ", 0x0002 }, 618 { "ACB_PWNOTREQ", 0x0004 }, 619 { "ACB_TEMPDUP", 0x0008 }, 620 { "ACB_NORMAL", 0x0010 }, 621 { "ACB_MNS", 0x0020 }, 622 { "ACB_DOMTRUST", 0x0040 }, 623 { "ACB_WSTRUST", 0x0080 }, 624 { "ACB_SVRTRUST", 0x0100 }, 625 { "ACB_PWNOEXP", 0x0200 }, 626 { "ACB_AUTOLOCK", 0x0400 }, 627 628 { NULL } 629}; 630 631static void const_init(PyObject *dict) 632{ 633 struct const_vals *tmp; 634 PyObject *obj; 635 636 for (tmp = module_const_vals; tmp->name; tmp++) { 637 obj = PyInt_FromLong(tmp->value); 638 PyDict_SetItemString(dict, tmp->name, obj); 639 Py_DECREF(obj); 640 } 641} 642 643void initsamr(void) 644{ 645 PyObject *module, *dict; 646 647 /* Initialise module */ 648 649 module = Py_InitModule("samr", samr_methods); 650 dict = PyModule_GetDict(module); 651 652 samr_error = PyErr_NewException("samr.error", NULL, NULL); 653 PyDict_SetItemString(dict, "error", samr_error); 654 655 samr_ntstatus = PyErr_NewException("samr.ntstatus", NULL, NULL); 656 PyDict_SetItemString(dict, "ntstatus", samr_ntstatus); 657 658 /* Initialise policy handle object */ 659 660 samr_connect_hnd_type.ob_type = &PyType_Type; 661 samr_domain_hnd_type.ob_type = &PyType_Type; 662 samr_user_hnd_type.ob_type = &PyType_Type; 663 samr_group_hnd_type.ob_type = &PyType_Type; 664 samr_alias_hnd_type.ob_type = &PyType_Type; 665 666 /* Initialise constants */ 667 668 const_init(dict); 669 670 /* Do samba initialisation */ 671 672 py_samba_init(); 673 674 setup_logging("samr", True); 675 DEBUGLEVEL = 10; 676} 677