s4-pydsdb: Use local memory context in py_dsdb_get_oid_from_attid()
[kamenim/samba.git] / source4 / dsdb / pydsdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
4    Copyright (C) Matthias Dieter Wallnöfer          2009
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.h>
21 #include "includes.h"
22 #include <ldb.h>
23 #include <pyldb.h>
24 #include "dsdb/samdb/samdb.h"
25 #include "libcli/security/security.h"
26 #include "librpc/ndr/libndr.h"
27 #include "system/kerberos.h"
28 #include "auth/kerberos/kerberos.h"
29 #include "librpc/rpc/pyrpc_util.h"
30 #include "lib/policy/policy.h"
31
32 /* There's no Py_ssize_t in 2.4, apparently */
33 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
34 typedef int Py_ssize_t;
35 typedef inquiry lenfunc;
36 typedef intargfunc ssizeargfunc;
37 #endif
38
39 /* FIXME: These should be in a header file somewhere, once we finish moving
40  * away from SWIG .. */
41 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
42 /*      if (!PyLdb_Check(py_ldb)) { \
43                 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
44                 return NULL; \
45         } */\
46         ldb = PyLdb_AsLdbContext(py_ldb);
47
48 static PyObject *py_ldb_get_exception(void)
49 {
50         PyObject *mod = PyImport_ImportModule("ldb");
51         if (mod == NULL)
52                 return NULL;
53
54         return PyObject_GetAttrString(mod, "LdbError");
55 }
56
57 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
58 {
59         if (ret == LDB_ERR_PYTHON_EXCEPTION)
60                 return; /* Python exception should already be set, just keep that */
61
62         PyErr_SetObject(error, 
63                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
64                         ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
65 }
66
67 static PyObject *py_samdb_server_site_name(PyObject *self, PyObject *args)
68 {
69         PyObject *py_ldb, *result;
70         struct ldb_context *ldb;
71         const char *site;
72         TALLOC_CTX *mem_ctx;
73
74         if (!PyArg_ParseTuple(args, "O", &py_ldb))
75                 return NULL;
76
77         PyErr_LDB_OR_RAISE(py_ldb, ldb);
78
79         mem_ctx = talloc_new(NULL);
80         if (mem_ctx == NULL) {
81                 PyErr_NoMemory();
82                 return NULL;
83         }
84
85         site = samdb_server_site_name(ldb, mem_ctx);
86         if (site == NULL) {
87                 PyErr_SetString(PyExc_RuntimeError, "Failed to find server site");
88                 talloc_free(mem_ctx);
89                 return NULL;
90         }
91
92         result = PyString_FromString(site);
93         talloc_free(mem_ctx);
94         return result;
95 }
96
97 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self,
98                                                                                                         PyObject *args)
99 {
100         char *target_str, *mapping;
101         PyObject *py_ldb;
102         struct ldb_context *ldb;
103         PyObject *ret;
104         char *retstr;
105
106         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
107                 return NULL;
108
109         PyErr_LDB_OR_RAISE(py_ldb, ldb);
110
111         retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
112         if (retstr == NULL) {
113                 PyErr_SetString(PyExc_RuntimeError,
114                                                 "dsdb_convert_schema_to_openldap failed");
115                 return NULL;
116         } 
117
118         ret = PyString_FromString(retstr);
119         talloc_free(retstr);
120         return ret;
121 }
122
123 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
124
125         PyObject *py_ldb, *py_sid;
126         struct ldb_context *ldb;
127         struct dom_sid *sid;
128         bool ret;
129
130         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
131                 return NULL;
132         
133         PyErr_LDB_OR_RAISE(py_ldb, ldb);
134
135         sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
136         if (sid == NULL) {
137                 PyErr_NoMemory();
138                 return NULL;
139         }
140
141         ret = samdb_set_domain_sid(ldb, sid);
142         talloc_free(sid);
143         if (!ret) {
144                 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
145                 return NULL;
146         } 
147         Py_RETURN_NONE;
148 }
149
150 static PyObject *py_samdb_set_ntds_settings_dn(PyLdbObject *self, PyObject *args)
151
152         PyObject *py_ldb, *py_ntds_settings_dn;
153         struct ldb_context *ldb;
154         struct ldb_dn *ntds_settings_dn;
155         TALLOC_CTX *tmp_ctx;
156         bool ret;
157
158         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_ntds_settings_dn))
159                 return NULL;
160
161         PyErr_LDB_OR_RAISE(py_ldb, ldb);
162
163         tmp_ctx = talloc_new(NULL);
164         if (tmp_ctx == NULL) {
165                 PyErr_NoMemory();
166                 return NULL;
167         }
168
169         if (!PyObject_AsDn(tmp_ctx, py_ntds_settings_dn, ldb, &ntds_settings_dn)) {
170                 /* exception thrown by "PyObject_AsDn" */
171                 talloc_free(tmp_ctx);
172                 return NULL;
173         }
174
175         ret = samdb_set_ntds_settings_dn(ldb, ntds_settings_dn);
176         talloc_free(tmp_ctx);
177         if (!ret) {
178                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_settings_dn failed");
179                 return NULL;
180         } 
181         Py_RETURN_NONE;
182 }
183
184 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
185
186         PyObject *py_ldb;
187         struct ldb_context *ldb;
188         const struct dom_sid *sid;
189         PyObject *ret;
190         char *retstr;
191
192         if (!PyArg_ParseTuple(args, "O", &py_ldb))
193                 return NULL;
194
195         PyErr_LDB_OR_RAISE(py_ldb, ldb);
196
197         sid = samdb_domain_sid(ldb);
198         if (!sid) {
199                 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
200                 return NULL;
201         }
202
203         retstr = dom_sid_string(NULL, sid);
204         if (retstr == NULL) {
205                 PyErr_NoMemory();
206                 return NULL;
207         }
208         ret = PyString_FromString(retstr);
209         talloc_free(retstr);
210         return ret;
211 }
212
213 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
214 {
215         PyObject *py_ldb, *result;
216         struct ldb_context *ldb;
217         const struct GUID *guid;
218         char *retstr;
219
220         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
221                 return NULL;
222         }
223
224         PyErr_LDB_OR_RAISE(py_ldb, ldb);
225
226         guid = samdb_ntds_invocation_id(ldb);
227         if (guid == NULL) {
228                 PyErr_SetString(PyExc_RuntimeError,
229                                                 "Failed to find NTDS invocation ID");
230                 return NULL;
231         }
232
233         retstr = GUID_string(NULL, guid);
234         if (retstr == NULL) {
235                 PyErr_NoMemory();
236                 return NULL;
237         }
238         result = PyString_FromString(retstr);
239         talloc_free(retstr);
240         return result;
241 }
242
243 static PyObject *py_dsdb_get_oid_from_attid(PyObject *self, PyObject *args)
244 {
245         PyObject *py_ldb;
246         struct ldb_context *ldb;
247         uint32_t attid;
248         struct dsdb_schema *schema;
249         const char *oid;
250         PyObject *ret;
251         WERROR status;
252         TALLOC_CTX *mem_ctx;
253
254         if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &attid))
255                 return NULL;
256
257         PyErr_LDB_OR_RAISE(py_ldb, ldb);
258
259         mem_ctx = talloc_new(NULL);
260         if (!mem_ctx) {
261                 PyErr_NoMemory();
262                 return NULL;
263         }
264
265         schema = dsdb_get_schema(ldb, mem_ctx);
266         if (!schema) {
267                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb \n");
268                 talloc_free(mem_ctx);
269                 return NULL;
270         }
271         
272         status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid,
273                                                 mem_ctx, &oid);
274         if (!W_ERROR_IS_OK(status)) {
275                 PyErr_SetWERROR(status);
276                 talloc_free(mem_ctx);
277                 return NULL;
278         }
279
280         ret = PyString_FromString(oid);
281
282         talloc_free(mem_ctx);
283
284         return ret;
285 }
286
287
288 static PyObject *py_dsdb_get_attid_from_lDAPDisplayName(PyObject *self, PyObject *args)
289 {
290         PyObject *py_ldb, *is_schema_nc;
291         struct ldb_context *ldb;
292         struct dsdb_schema *schema;
293         const char *ldap_display_name;
294         bool schema_nc = false;
295         const struct dsdb_attribute *a;
296         uint32_t attid;
297
298         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &is_schema_nc))
299                 return NULL;
300
301         PyErr_LDB_OR_RAISE(py_ldb, ldb);
302
303         if (is_schema_nc) {
304                 if (!PyBool_Check(is_schema_nc)) {
305                         PyErr_SetString(PyExc_TypeError, "Expected boolean is_schema_nc");
306                         return NULL;
307                 }
308                 if (is_schema_nc == Py_True) {
309                         schema_nc = true;
310                 }
311         }
312
313         schema = dsdb_get_schema(ldb, NULL);
314
315         if (!schema) {
316                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
317                 return NULL;
318         }
319
320         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
321         if (a == NULL) {
322                 PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name);
323                 return NULL;
324         }
325
326         attid = dsdb_attribute_get_attid(a, schema_nc);
327
328         return PyLong_FromUnsignedLong(attid);
329 }
330
331 /*
332   convert a python string to a DRSUAPI drsuapi_DsReplicaAttribute attribute
333  */
334 static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
335 {
336         PyObject *py_ldb, *el_list, *ret;
337         struct ldb_context *ldb;
338         char *ldap_display_name;
339         const struct dsdb_attribute *a;
340         struct dsdb_schema *schema;
341         struct dsdb_syntax_ctx syntax_ctx;
342         struct ldb_message_element *el;
343         struct drsuapi_DsReplicaAttribute *attr;
344         TALLOC_CTX *tmp_ctx;
345         WERROR werr;
346         Py_ssize_t i;
347
348         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
349                 return NULL;
350         }
351
352         PyErr_LDB_OR_RAISE(py_ldb, ldb);
353
354         if (!PyList_Check(el_list)) {
355                 PyErr_Format(PyExc_TypeError, "ldif_elements must be a list");
356                 return NULL;
357         }
358
359         schema = dsdb_get_schema(ldb, NULL);
360         if (!schema) {
361                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
362                 return NULL;
363         }
364
365         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
366         if (a == NULL) {
367                 PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name);
368                 return NULL;
369         }
370
371         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
372         syntax_ctx.is_schema_nc = false;
373
374         tmp_ctx = talloc_new(ldb);
375         if (tmp_ctx == NULL) {
376                 PyErr_NoMemory();
377                 return NULL;
378         }
379
380         el = talloc_zero(tmp_ctx, struct ldb_message_element);
381         if (el == NULL) {
382                 PyErr_NoMemory();
383                 talloc_free(tmp_ctx);
384                 return NULL;
385         }
386
387         el->name = ldap_display_name;
388         el->num_values = PyList_Size(el_list);
389
390         el->values = talloc_array(el, struct ldb_val, el->num_values);
391         if (el->values == NULL) {
392                 PyErr_NoMemory();
393                 talloc_free(tmp_ctx);
394                 return NULL;
395         }
396
397         for (i = 0; i < el->num_values; i++) {
398                 PyObject *item = PyList_GetItem(el_list, i);
399                 if (!PyString_Check(item)) {
400                         PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
401                         return NULL;
402                 }
403                 el->values[i].data = (uint8_t *)PyString_AsString(item);
404                 el->values[i].length = PyString_Size(item);
405         }
406
407         attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
408         if (attr == NULL) {
409                 PyErr_NoMemory();
410                 talloc_free(tmp_ctx);
411                 return NULL;
412         }
413
414         werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
415         PyErr_WERROR_IS_ERR_RAISE(werr);
416
417         ret = py_return_ndr_struct("samba.dcerpc.drsuapi", "DsReplicaAttribute", attr, attr);
418
419         talloc_free(tmp_ctx);
420
421         return ret;
422 }
423
424 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
425 {
426         PyObject *py_ldb, *py_guid;
427         bool ret;
428         struct GUID guid;
429         struct ldb_context *ldb;
430         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
431                 return NULL;
432
433         PyErr_LDB_OR_RAISE(py_ldb, ldb);
434         GUID_from_string(PyString_AsString(py_guid), &guid);
435
436         ret = samdb_set_ntds_invocation_id(ldb, &guid);
437         if (!ret) {
438                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
439                 return NULL;
440         }
441         Py_RETURN_NONE;
442 }
443
444 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
445 {
446         PyObject *py_ldb, *result;
447         struct ldb_context *ldb;
448         const struct GUID *guid;
449         char *retstr;
450
451         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
452                 return NULL;
453         }
454
455         PyErr_LDB_OR_RAISE(py_ldb, ldb);
456
457         guid = samdb_ntds_objectGUID(ldb);
458         if (guid == NULL) {
459                 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
460                 return NULL;
461         }
462
463         retstr = GUID_string(NULL, guid);
464         if (retstr == NULL) {
465                 PyErr_NoMemory();
466                 return NULL;
467         }
468         result = PyString_FromString(retstr);
469         talloc_free(retstr);
470         return result;
471 }
472
473 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
474 {
475         PyObject *py_ldb;
476         struct ldb_context *ldb;
477         int ret;
478         if (!PyArg_ParseTuple(args, "O", &py_ldb))
479                 return NULL;
480
481         PyErr_LDB_OR_RAISE(py_ldb, ldb);
482
483         ret = dsdb_set_global_schema(ldb);
484         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
485
486         Py_RETURN_NONE;
487 }
488
489 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
490 {
491         PyObject *py_dn, *py_ldb, *result;
492         struct ldb_dn *dn;
493         uint64_t highest_uSN, urgent_uSN;
494         struct ldb_context *ldb;
495         TALLOC_CTX *mem_ctx;
496         int ret;
497
498         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
499                 return NULL;
500         }
501
502         PyErr_LDB_OR_RAISE(py_ldb, ldb);
503
504         mem_ctx = talloc_new(NULL);
505         if (mem_ctx == NULL) {
506            PyErr_NoMemory();
507            return NULL;
508         }
509
510         if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
511            talloc_free(mem_ctx);
512            return NULL;
513         }
514
515         ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
516         if (ret != LDB_SUCCESS) {
517            PyErr_Format(PyExc_RuntimeError,
518                         "Failed to load partition [%s] uSN - %s",
519                         ldb_dn_get_linearized(dn),
520                         ldb_errstring(ldb));
521            talloc_free(mem_ctx);
522            return NULL;
523         }
524
525         talloc_free(mem_ctx);
526
527         result = PyDict_New();
528
529         PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
530         PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
531
532
533         return result;
534 }
535
536 static PyObject *py_dsdb_set_am_rodc(PyObject *self, PyObject *args)
537 {
538         PyObject *py_ldb;
539         bool ret;
540         struct ldb_context *ldb;
541         int py_val;
542
543         if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &py_val))
544                 return NULL;
545
546         PyErr_LDB_OR_RAISE(py_ldb, ldb);
547         ret = samdb_set_am_rodc(ldb, (bool)py_val);
548         if (!ret) {
549                 PyErr_SetString(PyExc_RuntimeError, "set_am_rodc failed");
550                 return NULL;
551         }
552         Py_RETURN_NONE;
553 }
554
555 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
556 {
557         WERROR result;
558         char *pf, *df;
559         PyObject *py_ldb;
560         struct ldb_context *ldb;
561
562         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
563                 return NULL;
564
565         PyErr_LDB_OR_RAISE(py_ldb, ldb);
566
567         result = dsdb_set_schema_from_ldif(ldb, pf, df);
568         PyErr_WERROR_IS_ERR_RAISE(result);
569
570         Py_RETURN_NONE;
571 }
572
573 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
574 {
575         PyObject *py_ldb;
576         struct ldb_context *ldb;
577         PyObject *py_from_ldb;
578         struct ldb_context *from_ldb;
579         struct dsdb_schema *schema;
580         int ret;
581         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
582                 return NULL;
583
584         PyErr_LDB_OR_RAISE(py_ldb, ldb);
585
586         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
587
588         schema = dsdb_get_schema(from_ldb, NULL);
589         if (!schema) {
590                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
591                 return NULL;
592         }
593
594         ret = dsdb_reference_schema(ldb, schema, true);
595         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
596
597         Py_RETURN_NONE;
598 }
599
600 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
601 {
602         PyObject *py_ldb;
603         struct ldb_context *ldb;
604         WERROR result;
605         struct dsdb_schema *schema;
606
607         if (!PyArg_ParseTuple(args, "O", &py_ldb))
608                 return NULL;
609
610         PyErr_LDB_OR_RAISE(py_ldb, ldb);
611
612         schema = dsdb_get_schema(ldb, NULL);
613         if (!schema) {
614                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
615                 return NULL;
616         }
617
618         result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
619         PyErr_WERROR_IS_ERR_RAISE(result);
620
621         Py_RETURN_NONE;
622 }
623
624
625 static PyObject *py_dsdb_get_partitions_dn(PyObject *self, PyObject *args)
626 {
627         struct ldb_context *ldb;
628         struct ldb_dn *dn;
629         PyObject *py_ldb, *ret;
630         PyObject *mod;
631
632         mod = PyImport_ImportModule("ldb");
633
634         if (!PyArg_ParseTuple(args, "O", &py_ldb))
635                 return NULL;
636
637         PyErr_LDB_OR_RAISE(py_ldb, ldb);
638
639         dn = samdb_partitions_dn(ldb, NULL);
640         if (dn == NULL) {
641                 PyErr_NoMemory();
642                 return NULL;
643         }
644         ret = PyLdbDn_FromDn(dn);
645         talloc_free(dn);
646         return ret;
647 }
648
649
650 /*
651   call into samdb_rodc()
652  */
653 static PyObject *py_dsdb_am_rodc(PyObject *self, PyObject *args)
654 {
655         PyObject *py_ldb;
656         struct ldb_context *ldb;
657         int ret;
658         bool am_rodc;
659
660         if (!PyArg_ParseTuple(args, "O", &py_ldb))
661                 return NULL;
662
663         PyErr_LDB_OR_RAISE(py_ldb, ldb);
664
665         ret = samdb_rodc(ldb, &am_rodc);
666         if (ret != LDB_SUCCESS) {
667                 PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
668                 return NULL;
669         }
670
671         return PyBool_FromLong(am_rodc);
672 }
673
674
675 static PyMethodDef py_dsdb_methods[] = {
676         { "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
677                 METH_VARARGS, "Get the server site name as a string"},
678         { "_dsdb_convert_schema_to_openldap",
679                 (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS, 
680                 "dsdb_convert_schema_to_openldap(ldb, target_str, mapping) -> str\n"
681                 "Create an OpenLDAP schema from a schema." },
682         { "_samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid,
683                 METH_VARARGS,
684                 "samdb_set_domain_sid(samdb, sid)\n"
685                 "Set SID of domain to use." },
686         { "_samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid,
687                 METH_VARARGS,
688                 "samdb_get_domain_sid(samdb)\n"
689                 "Get SID of domain in use." },
690         { "_samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id,
691                 METH_VARARGS, "get the NTDS invocation ID GUID as a string"},
692         { "_samdb_set_ntds_settings_dn", (PyCFunction)py_samdb_set_ntds_settings_dn,
693                 METH_VARARGS,
694                 "samdb_set_ntds_settings_dn(samdb, ntds_settings_dn)\n"
695                 "Set NTDS Settings DN for this LDB (allows it to be set before the DB fully exists)." },
696         { "_dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid,
697                 METH_VARARGS, NULL },
698         { "_dsdb_get_attid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_attid_from_lDAPDisplayName,
699                 METH_VARARGS, NULL },
700         { "_dsdb_set_ntds_invocation_id",
701                 (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
702                 NULL },
703         { "_samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID,
704                 METH_VARARGS, "get the NTDS objectGUID as a string"},
705         { "_dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema,
706                 METH_VARARGS, NULL },
707         { "_dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn,
708                 METH_VARARGS,
709                 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
710         { "_dsdb_set_am_rodc",
711                 (PyCFunction)py_dsdb_set_am_rodc, METH_VARARGS,
712                 NULL },
713         { "_am_rodc",
714                 (PyCFunction)py_dsdb_am_rodc, METH_VARARGS,
715                 NULL },
716         { "_dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
717                 NULL },
718         { "_dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
719                 NULL },
720         { "_dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
721                 NULL },
722         { "_dsdb_get_partitions_dn", (PyCFunction)py_dsdb_get_partitions_dn, METH_VARARGS, NULL },
723         { "_dsdb_DsReplicaAttribute", (PyCFunction)py_dsdb_DsReplicaAttribute, METH_VARARGS, NULL },
724         { NULL }
725 };
726
727 void initdsdb(void)
728 {
729         PyObject *m;
730
731         m = Py_InitModule3("dsdb", py_dsdb_methods, 
732                            "Python bindings for the directory service databases.");
733         if (m == NULL)
734                 return;
735
736 #define ADD_DSDB_FLAG(val)  PyModule_AddObject(m, #val, PyInt_FromLong(val))
737
738         /* "userAccountControl" flags */
739         ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
740         ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
741         ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
742         ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
743         ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
744         ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
745         ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
746
747         ADD_DSDB_FLAG(UF_SCRIPT);
748         ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
749         ADD_DSDB_FLAG(UF_00000004);
750         ADD_DSDB_FLAG(UF_HOMEDIR_REQUIRED);
751         ADD_DSDB_FLAG(UF_LOCKOUT);
752         ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
753         ADD_DSDB_FLAG(UF_PASSWD_CANT_CHANGE);
754         ADD_DSDB_FLAG(UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED);
755         ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
756         ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
757         ADD_DSDB_FLAG(UF_00000400);
758         ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
759         ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
760         ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
761         ADD_DSDB_FLAG(UF_00004000);
762         ADD_DSDB_FLAG(UF_00008000);
763         ADD_DSDB_FLAG(UF_DONT_EXPIRE_PASSWD);
764         ADD_DSDB_FLAG(UF_MNS_LOGON_ACCOUNT);
765         ADD_DSDB_FLAG(UF_SMARTCARD_REQUIRED);
766         ADD_DSDB_FLAG(UF_TRUSTED_FOR_DELEGATION);
767         ADD_DSDB_FLAG(UF_NOT_DELEGATED);
768         ADD_DSDB_FLAG(UF_USE_DES_KEY_ONLY);
769         ADD_DSDB_FLAG(UF_DONT_REQUIRE_PREAUTH);
770         ADD_DSDB_FLAG(UF_PASSWORD_EXPIRED);
771         ADD_DSDB_FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION);
772         ADD_DSDB_FLAG(UF_NO_AUTH_DATA_REQUIRED);
773         ADD_DSDB_FLAG(UF_PARTIAL_SECRETS_ACCOUNT);
774
775         /* groupType flags */
776         ADD_DSDB_FLAG(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP);
777         ADD_DSDB_FLAG(GTYPE_SECURITY_GLOBAL_GROUP);
778         ADD_DSDB_FLAG(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
779         ADD_DSDB_FLAG(GTYPE_SECURITY_UNIVERSAL_GROUP);
780         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_GLOBAL_GROUP);
781         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP);
782         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP);
783
784         /* "sAMAccountType" flags */
785         ADD_DSDB_FLAG(ATYPE_NORMAL_ACCOUNT);
786         ADD_DSDB_FLAG(ATYPE_WORKSTATION_TRUST);
787         ADD_DSDB_FLAG(ATYPE_INTERDOMAIN_TRUST);
788         ADD_DSDB_FLAG(ATYPE_SECURITY_GLOBAL_GROUP);
789         ADD_DSDB_FLAG(ATYPE_SECURITY_LOCAL_GROUP);
790         ADD_DSDB_FLAG(ATYPE_SECURITY_UNIVERSAL_GROUP);
791         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_GLOBAL_GROUP);
792         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_LOCAL_GROUP);
793         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP);
794
795         /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
796         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2000);
797         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003_MIXED);
798         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003);
799         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008);
800         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008_R2);
801
802         /* "systemFlags" */
803         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NC);
804         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_DOMAIN);
805         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NOT_GC_REPLICATED);
806         ADD_DSDB_FLAG(SYSTEM_FLAG_SCHEMA_BASE_OBJECT);
807         ADD_DSDB_FLAG(SYSTEM_FLAG_ATTR_IS_RDN);
808         ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
809         ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE);
810         ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME);
811         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
812         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_MOVE);
813         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
814         ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_DELETE);
815
816         /* Kerberos encryption type constants */
817         ADD_DSDB_FLAG(ENC_ALL_TYPES);
818         ADD_DSDB_FLAG(ENC_CRC32);
819         ADD_DSDB_FLAG(ENC_RSA_MD5);
820         ADD_DSDB_FLAG(ENC_RC4_HMAC_MD5);
821         ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES128);
822         ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES256);
823
824         ADD_DSDB_FLAG(SEARCH_FLAG_ATTINDEX);
825         ADD_DSDB_FLAG(SEARCH_FLAG_PDNTATTINDEX);
826         ADD_DSDB_FLAG(SEARCH_FLAG_ANR);
827         ADD_DSDB_FLAG(SEARCH_FLAG_PRESERVEONDELETE);
828         ADD_DSDB_FLAG(SEARCH_FLAG_COPY);
829         ADD_DSDB_FLAG(SEARCH_FLAG_TUPLEINDEX);
830         ADD_DSDB_FLAG(SEARCH_FLAG_SUBTREEATTRINDEX);
831         ADD_DSDB_FLAG(SEARCH_FLAG_CONFIDENTIAL);
832         ADD_DSDB_FLAG(SEARCH_FLAG_NEVERVALUEAUDIT);
833         ADD_DSDB_FLAG(SEARCH_FLAG_RODC_ATTRIBUTE);
834
835         ADD_DSDB_FLAG(DS_FLAG_ATTR_NOT_REPLICATED);
836         ADD_DSDB_FLAG(DS_FLAG_ATTR_REQ_PARTIAL_SET_MEMBER);
837         ADD_DSDB_FLAG(DS_FLAG_ATTR_IS_CONSTRUCTED);
838
839         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_IS_GC);
840         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL);
841         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL);
842         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE);
843         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_SPN_REGISTRATION);
844
845         ADD_DSDB_FLAG(NTDSCONN_KCC_GC_TOPOLOGY);
846         ADD_DSDB_FLAG(NTDSCONN_KCC_RING_TOPOLOGY);
847         ADD_DSDB_FLAG(NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY);
848         ADD_DSDB_FLAG(NTDSCONN_KCC_STALE_SERVERS_TOPOLOGY);
849         ADD_DSDB_FLAG(NTDSCONN_KCC_OSCILLATING_CONNECTION_TOPOLOGY);
850         ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_GC_TOPOLOGY);
851         ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_TOPOLOGY);
852         ADD_DSDB_FLAG(NTDSCONN_KCC_SERVER_FAILOVER_TOPOLOGY);
853         ADD_DSDB_FLAG(NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY);
854         ADD_DSDB_FLAG(NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY);
855
856         /* GPO policy flags */
857         ADD_DSDB_FLAG(GPLINK_OPT_DISABLE);
858         ADD_DSDB_FLAG(GPLINK_OPT_ENFORCE);
859         ADD_DSDB_FLAG(GPO_FLAG_USER_DISABLE);
860         ADD_DSDB_FLAG(GPO_FLAG_MACHINE_DISABLE);
861         ADD_DSDB_FLAG(GPO_INHERIT);
862         ADD_DSDB_FLAG(GPO_BLOCK_INHERITANCE);
863 }