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