Initial import
[samba] / source / python / py_samr.c
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
27 PyObject *samr_error;           /* This indicates a non-RPC related error
28                                    such as name lookup failure */
29
30 PyObject *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
36 static void py_samr_group_hnd_dealloc(PyObject* self)
37 {
38         PyObject_Del(self);
39 }
40
41 static PyMethodDef samr_group_methods[] = {
42         { NULL }
43 };
44
45 static PyObject *py_samr_group_hnd_getattr(PyObject *self, char *attrname)
46 {
47         return Py_FindMethod(samr_group_methods, self, attrname);
48 }
49
50 PyTypeObject 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
68 PyObject *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
84 static void py_samr_alias_hnd_dealloc(PyObject* self)
85 {
86         PyObject_Del(self);
87 }
88
89 static PyMethodDef samr_alias_methods[] = {
90         { NULL }
91 };
92
93 static PyObject *py_samr_alias_hnd_getattr(PyObject *self, char *attrname)
94 {
95         return Py_FindMethod(samr_alias_methods, self, attrname);
96 }
97
98 PyTypeObject 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
116 PyObject *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
132 static void py_samr_user_hnd_dealloc(PyObject* self)
133 {
134         PyObject_Del(self);
135 }
136
137 static 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         
214 done:
215         return result;
216 }
217
218 static 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
247 done:
248         talloc_destroy(mem_ctx);
249
250         return result;
251 }
252
253 static 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
263 static PyObject *py_samr_user_hnd_getattr(PyObject *self, char *attrname)
264 {
265         return Py_FindMethod(samr_user_methods, self, attrname);
266 }
267
268 PyTypeObject 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
286 PyObject *new_samr_user_hnd_object(struct cli_state *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
302 static void py_samr_connect_hnd_dealloc(PyObject* self)
303 {
304         PyObject_Del(self);
305 }
306
307 PyObject *new_samr_domain_hnd_object(struct cli_state *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
321 static 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
359 done:
360         if (!result) {
361                 if (mem_ctx)
362                         talloc_destroy(mem_ctx);
363         }
364
365         return result;
366 }
367
368 static 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
376 static PyObject *py_samr_connect_hnd_getattr(PyObject *self, char *attrname)
377 {
378         return Py_FindMethod(samr_connect_methods, self, attrname);
379 }
380
381 PyTypeObject 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
399 PyObject *new_samr_connect_hnd_object(struct cli_state *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
415 static void py_samr_domain_hnd_dealloc(PyObject* self)
416 {
417         PyObject_Del(self);
418 }
419
420 static 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
459 static 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         uint16 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
495 done:
496
497         return result;
498 }
499
500 static 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
508 static PyObject *py_samr_domain_hnd_getattr(PyObject *self, char *attrname)
509 {
510         return Py_FindMethod(samr_domain_methods, self, attrname);
511 }
512
513 PyTypeObject 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
531 static 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, 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, mem_ctx, &hnd);
581
582 done:
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
598 static 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
609 static 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
631 static 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
643 void 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 }