af035042e641ddbbb8e6a5099c60af99d65429e6
[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
253         if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &attid))
254                 return NULL;
255
256         PyErr_LDB_OR_RAISE(py_ldb, ldb);
257
258         schema = dsdb_get_schema(ldb, NULL);
259
260         if (!schema) {
261                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb \n");
262                 return NULL;
263         }
264         
265         status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid,
266                                                 NULL, &oid);
267         PyErr_WERROR_IS_ERR_RAISE(status);
268
269         ret = PyString_FromString(oid);
270         talloc_free(discard_const_p(char, oid));
271
272         return ret;
273 }
274
275
276 static PyObject *py_dsdb_get_attid_from_lDAPDisplayName(PyObject *self, PyObject *args)
277 {
278         PyObject *py_ldb, *is_schema_nc;
279         struct ldb_context *ldb;
280         struct dsdb_schema *schema;
281         const char *ldap_display_name;
282         bool schema_nc = false;
283         const struct dsdb_attribute *a;
284         uint32_t attid;
285
286         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &is_schema_nc))
287                 return NULL;
288
289         PyErr_LDB_OR_RAISE(py_ldb, ldb);
290
291         if (is_schema_nc) {
292                 if (!PyBool_Check(is_schema_nc)) {
293                         PyErr_SetString(PyExc_TypeError, "Expected boolean is_schema_nc");
294                         return NULL;
295                 }
296                 if (is_schema_nc == Py_True) {
297                         schema_nc = true;
298                 }
299         }
300
301         schema = dsdb_get_schema(ldb, NULL);
302
303         if (!schema) {
304                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
305                 return NULL;
306         }
307
308         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
309         if (a == NULL) {
310                 PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name);
311                 return NULL;
312         }
313
314         attid = dsdb_attribute_get_attid(a, schema_nc);
315
316         return PyLong_FromUnsignedLong(attid);
317 }
318
319 /*
320   convert a python string to a DRSUAPI drsuapi_DsReplicaAttribute attribute
321  */
322 static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
323 {
324         PyObject *py_ldb, *el_list, *ret;
325         struct ldb_context *ldb;
326         char *ldap_display_name;
327         const struct dsdb_attribute *a;
328         struct dsdb_schema *schema;
329         struct dsdb_syntax_ctx syntax_ctx;
330         struct ldb_message_element *el;
331         struct drsuapi_DsReplicaAttribute *attr;
332         TALLOC_CTX *tmp_ctx;
333         WERROR werr;
334         Py_ssize_t i;
335
336         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
337                 return NULL;
338         }
339
340         PyErr_LDB_OR_RAISE(py_ldb, ldb);
341
342         if (!PyList_Check(el_list)) {
343                 PyErr_Format(PyExc_TypeError, "ldif_elements must be a list");
344                 return NULL;
345         }
346
347         schema = dsdb_get_schema(ldb, NULL);
348         if (!schema) {
349                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
350                 return NULL;
351         }
352
353         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
354         if (a == NULL) {
355                 PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name);
356                 return NULL;
357         }
358
359         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
360         syntax_ctx.is_schema_nc = false;
361
362         tmp_ctx = talloc_new(ldb);
363         if (tmp_ctx == NULL) {
364                 PyErr_NoMemory();
365                 return NULL;
366         }
367
368         el = talloc_zero(tmp_ctx, struct ldb_message_element);
369         if (el == NULL) {
370                 PyErr_NoMemory();
371                 talloc_free(tmp_ctx);
372                 return NULL;
373         }
374
375         el->name = ldap_display_name;
376         el->num_values = PyList_Size(el_list);
377
378         el->values = talloc_array(el, struct ldb_val, el->num_values);
379         if (el->values == NULL) {
380                 PyErr_NoMemory();
381                 talloc_free(tmp_ctx);
382                 return NULL;
383         }
384
385         for (i = 0; i < el->num_values; i++) {
386                 PyObject *item = PyList_GetItem(el_list, i);
387                 if (!PyString_Check(item)) {
388                         PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
389                         return NULL;
390                 }
391                 el->values[i].data = (uint8_t *)PyString_AsString(item);
392                 el->values[i].length = PyString_Size(item);
393         }
394
395         attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
396         if (attr == NULL) {
397                 PyErr_NoMemory();
398                 talloc_free(tmp_ctx);
399                 return NULL;
400         }
401
402         werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
403         PyErr_WERROR_IS_ERR_RAISE(werr);
404
405         ret = py_return_ndr_struct("samba.dcerpc.drsuapi", "DsReplicaAttribute", attr, attr);
406
407         talloc_free(tmp_ctx);
408
409         return ret;
410 }
411
412 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
413 {
414         PyObject *py_ldb, *py_guid;
415         bool ret;
416         struct GUID guid;
417         struct ldb_context *ldb;
418         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
419                 return NULL;
420
421         PyErr_LDB_OR_RAISE(py_ldb, ldb);
422         GUID_from_string(PyString_AsString(py_guid), &guid);
423
424         ret = samdb_set_ntds_invocation_id(ldb, &guid);
425         if (!ret) {
426                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
427                 return NULL;
428         }
429         Py_RETURN_NONE;
430 }
431
432 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
433 {
434         PyObject *py_ldb, *result;
435         struct ldb_context *ldb;
436         const struct GUID *guid;
437         char *retstr;
438
439         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
440                 return NULL;
441         }
442
443         PyErr_LDB_OR_RAISE(py_ldb, ldb);
444
445         guid = samdb_ntds_objectGUID(ldb);
446         if (guid == NULL) {
447                 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
448                 return NULL;
449         }
450
451         retstr = GUID_string(NULL, guid);
452         if (retstr == NULL) {
453                 PyErr_NoMemory();
454                 return NULL;
455         }
456         result = PyString_FromString(retstr);
457         talloc_free(retstr);
458         return result;
459 }
460
461 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
462 {
463         PyObject *py_ldb;
464         struct ldb_context *ldb;
465         int ret;
466         if (!PyArg_ParseTuple(args, "O", &py_ldb))
467                 return NULL;
468
469         PyErr_LDB_OR_RAISE(py_ldb, ldb);
470
471         ret = dsdb_set_global_schema(ldb);
472         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
473
474         Py_RETURN_NONE;
475 }
476
477 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
478 {
479         PyObject *py_dn, *py_ldb, *result;
480         struct ldb_dn *dn;
481         uint64_t highest_uSN, urgent_uSN;
482         struct ldb_context *ldb;
483         TALLOC_CTX *mem_ctx;
484         int ret;
485
486         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
487                 return NULL;
488         }
489
490         PyErr_LDB_OR_RAISE(py_ldb, ldb);
491
492         mem_ctx = talloc_new(NULL);
493         if (mem_ctx == NULL) {
494            PyErr_NoMemory();
495            return NULL;
496         }
497
498         if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
499            talloc_free(mem_ctx);
500            return NULL;
501         }
502
503         ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
504         if (ret != LDB_SUCCESS) {
505            PyErr_Format(PyExc_RuntimeError,
506                         "Failed to load partition [%s] uSN - %s",
507                         ldb_dn_get_linearized(dn),
508                         ldb_errstring(ldb));
509            talloc_free(mem_ctx);
510            return NULL;
511         }
512
513         talloc_free(mem_ctx);
514
515         result = PyDict_New();
516
517         PyDict_SetItemString(result, "uSNHighest", PyInt_FromLong((uint64_t)highest_uSN));
518         PyDict_SetItemString(result, "uSNUrgent", PyInt_FromLong((uint64_t)urgent_uSN));
519
520
521         return result;
522 }
523
524 static PyObject *py_dsdb_set_am_rodc(PyObject *self, PyObject *args)
525 {
526         PyObject *py_ldb;
527         bool ret;
528         struct ldb_context *ldb;
529         int py_val;
530
531         if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &py_val))
532                 return NULL;
533
534         PyErr_LDB_OR_RAISE(py_ldb, ldb);
535         ret = samdb_set_am_rodc(ldb, (bool)py_val);
536         if (!ret) {
537                 PyErr_SetString(PyExc_RuntimeError, "set_am_rodc failed");
538                 return NULL;
539         }
540         Py_RETURN_NONE;
541 }
542
543 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
544 {
545         WERROR result;
546         char *pf, *df;
547         PyObject *py_ldb;
548         struct ldb_context *ldb;
549
550         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
551                 return NULL;
552
553         PyErr_LDB_OR_RAISE(py_ldb, ldb);
554
555         result = dsdb_set_schema_from_ldif(ldb, pf, df);
556         PyErr_WERROR_IS_ERR_RAISE(result);
557
558         Py_RETURN_NONE;
559 }
560
561 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
562 {
563         PyObject *py_ldb;
564         struct ldb_context *ldb;
565         PyObject *py_from_ldb;
566         struct ldb_context *from_ldb;
567         struct dsdb_schema *schema;
568         int ret;
569         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
570                 return NULL;
571
572         PyErr_LDB_OR_RAISE(py_ldb, ldb);
573
574         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
575
576         schema = dsdb_get_schema(from_ldb, NULL);
577         if (!schema) {
578                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
579                 return NULL;
580         }
581
582         ret = dsdb_reference_schema(ldb, schema, true);
583         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
584
585         Py_RETURN_NONE;
586 }
587
588 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
589 {
590         PyObject *py_ldb;
591         struct ldb_context *ldb;
592         WERROR result;
593         struct dsdb_schema *schema;
594
595         if (!PyArg_ParseTuple(args, "O", &py_ldb))
596                 return NULL;
597
598         PyErr_LDB_OR_RAISE(py_ldb, ldb);
599
600         schema = dsdb_get_schema(ldb, NULL);
601         if (!schema) {
602                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
603                 return NULL;
604         }
605
606         result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
607         PyErr_WERROR_IS_ERR_RAISE(result);
608
609         Py_RETURN_NONE;
610 }
611
612
613 static PyObject *py_dsdb_get_partitions_dn(PyObject *self, PyObject *args)
614 {
615         struct ldb_context *ldb;
616         struct ldb_dn *dn;
617         PyObject *py_ldb, *ret;
618         PyObject *mod;
619
620         mod = PyImport_ImportModule("ldb");
621
622         if (!PyArg_ParseTuple(args, "O", &py_ldb))
623                 return NULL;
624
625         PyErr_LDB_OR_RAISE(py_ldb, ldb);
626
627         dn = samdb_partitions_dn(ldb, NULL);
628         if (dn == NULL) {
629                 PyErr_NoMemory();
630                 return NULL;
631         }
632         ret = PyLdbDn_FromDn(dn);
633         talloc_free(dn);
634         return ret;
635 }
636
637
638 /*
639   call into samdb_rodc()
640  */
641 static PyObject *py_dsdb_am_rodc(PyObject *self, PyObject *args)
642 {
643         PyObject *py_ldb;
644         struct ldb_context *ldb;
645         int ret;
646         bool am_rodc;
647
648         if (!PyArg_ParseTuple(args, "O", &py_ldb))
649                 return NULL;
650
651         PyErr_LDB_OR_RAISE(py_ldb, ldb);
652
653         ret = samdb_rodc(ldb, &am_rodc);
654         if (ret != LDB_SUCCESS) {
655                 PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
656                 return NULL;
657         }
658
659         return PyBool_FromLong(am_rodc);
660 }
661
662
663 static PyMethodDef py_dsdb_methods[] = {
664         { "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
665                 METH_VARARGS, "Get the server site name as a string"},
666         { "_dsdb_convert_schema_to_openldap",
667                 (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS, 
668                 "dsdb_convert_schema_to_openldap(ldb, target_str, mapping) -> str\n"
669                 "Create an OpenLDAP schema from a schema." },
670         { "_samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid,
671                 METH_VARARGS,
672                 "samdb_set_domain_sid(samdb, sid)\n"
673                 "Set SID of domain to use." },
674         { "_samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid,
675                 METH_VARARGS,
676                 "samdb_get_domain_sid(samdb)\n"
677                 "Get SID of domain in use." },
678         { "_samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id,
679                 METH_VARARGS, "get the NTDS invocation ID GUID as a string"},
680         { "_samdb_set_ntds_settings_dn", (PyCFunction)py_samdb_set_ntds_settings_dn,
681                 METH_VARARGS,
682                 "samdb_set_ntds_settings_dn(samdb, ntds_settings_dn)\n"
683                 "Set NTDS Settings DN for this LDB (allows it to be set before the DB fully exists)." },
684         { "_dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid,
685                 METH_VARARGS, NULL },
686         { "_dsdb_get_attid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_attid_from_lDAPDisplayName,
687                 METH_VARARGS, NULL },
688         { "_dsdb_set_ntds_invocation_id",
689                 (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
690                 NULL },
691         { "_samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID,
692                 METH_VARARGS, "get the NTDS objectGUID as a string"},
693         { "_dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema,
694                 METH_VARARGS, NULL },
695         { "_dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn,
696                 METH_VARARGS,
697                 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
698         { "_dsdb_set_am_rodc",
699                 (PyCFunction)py_dsdb_set_am_rodc, METH_VARARGS,
700                 NULL },
701         { "_am_rodc",
702                 (PyCFunction)py_dsdb_am_rodc, METH_VARARGS,
703                 NULL },
704         { "_dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
705                 NULL },
706         { "_dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
707                 NULL },
708         { "_dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
709                 NULL },
710         { "_dsdb_get_partitions_dn", (PyCFunction)py_dsdb_get_partitions_dn, METH_VARARGS, NULL },
711         { "_dsdb_DsReplicaAttribute", (PyCFunction)py_dsdb_DsReplicaAttribute, METH_VARARGS, NULL },
712         { NULL }
713 };
714
715 void initdsdb(void)
716 {
717         PyObject *m;
718
719         m = Py_InitModule3("dsdb", py_dsdb_methods, 
720                            "Python bindings for the directory service databases.");
721         if (m == NULL)
722                 return;
723
724 #define ADD_DSDB_FLAG(val)  PyModule_AddObject(m, #val, PyInt_FromLong(val))
725
726         /* "userAccountControl" flags */
727         ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
728         ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
729         ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
730         ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
731         ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
732         ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
733         ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
734
735         ADD_DSDB_FLAG(UF_SCRIPT);
736         ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
737         ADD_DSDB_FLAG(UF_00000004);
738         ADD_DSDB_FLAG(UF_HOMEDIR_REQUIRED);
739         ADD_DSDB_FLAG(UF_LOCKOUT);
740         ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
741         ADD_DSDB_FLAG(UF_PASSWD_CANT_CHANGE);
742         ADD_DSDB_FLAG(UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED);
743         ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
744         ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
745         ADD_DSDB_FLAG(UF_00000400);
746         ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
747         ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
748         ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
749         ADD_DSDB_FLAG(UF_00004000);
750         ADD_DSDB_FLAG(UF_00008000);
751         ADD_DSDB_FLAG(UF_DONT_EXPIRE_PASSWD);
752         ADD_DSDB_FLAG(UF_MNS_LOGON_ACCOUNT);
753         ADD_DSDB_FLAG(UF_SMARTCARD_REQUIRED);
754         ADD_DSDB_FLAG(UF_TRUSTED_FOR_DELEGATION);
755         ADD_DSDB_FLAG(UF_NOT_DELEGATED);
756         ADD_DSDB_FLAG(UF_USE_DES_KEY_ONLY);
757         ADD_DSDB_FLAG(UF_DONT_REQUIRE_PREAUTH);
758         ADD_DSDB_FLAG(UF_PASSWORD_EXPIRED);
759         ADD_DSDB_FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION);
760         ADD_DSDB_FLAG(UF_NO_AUTH_DATA_REQUIRED);
761         ADD_DSDB_FLAG(UF_PARTIAL_SECRETS_ACCOUNT);
762
763         /* groupType flags */
764         ADD_DSDB_FLAG(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP);
765         ADD_DSDB_FLAG(GTYPE_SECURITY_GLOBAL_GROUP);
766         ADD_DSDB_FLAG(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
767         ADD_DSDB_FLAG(GTYPE_SECURITY_UNIVERSAL_GROUP);
768         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_GLOBAL_GROUP);
769         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP);
770         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP);
771
772         /* "sAMAccountType" flags */
773         ADD_DSDB_FLAG(ATYPE_NORMAL_ACCOUNT);
774         ADD_DSDB_FLAG(ATYPE_WORKSTATION_TRUST);
775         ADD_DSDB_FLAG(ATYPE_INTERDOMAIN_TRUST);
776         ADD_DSDB_FLAG(ATYPE_SECURITY_GLOBAL_GROUP);
777         ADD_DSDB_FLAG(ATYPE_SECURITY_LOCAL_GROUP);
778         ADD_DSDB_FLAG(ATYPE_SECURITY_UNIVERSAL_GROUP);
779         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_GLOBAL_GROUP);
780         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_LOCAL_GROUP);
781         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP);
782
783         /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
784         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2000);
785         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003_MIXED);
786         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003);
787         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008);
788         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008_R2);
789
790         /* "systemFlags" */
791         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NC);
792         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_DOMAIN);
793         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NOT_GC_REPLICATED);
794         ADD_DSDB_FLAG(SYSTEM_FLAG_SCHEMA_BASE_OBJECT);
795         ADD_DSDB_FLAG(SYSTEM_FLAG_ATTR_IS_RDN);
796         ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
797         ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE);
798         ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME);
799         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
800         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_MOVE);
801         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
802         ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_DELETE);
803
804         /* Kerberos encryption type constants */
805         ADD_DSDB_FLAG(ENC_ALL_TYPES);
806         ADD_DSDB_FLAG(ENC_CRC32);
807         ADD_DSDB_FLAG(ENC_RSA_MD5);
808         ADD_DSDB_FLAG(ENC_RC4_HMAC_MD5);
809         ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES128);
810         ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES256);
811
812         ADD_DSDB_FLAG(SEARCH_FLAG_ATTINDEX);
813         ADD_DSDB_FLAG(SEARCH_FLAG_PDNTATTINDEX);
814         ADD_DSDB_FLAG(SEARCH_FLAG_ANR);
815         ADD_DSDB_FLAG(SEARCH_FLAG_PRESERVEONDELETE);
816         ADD_DSDB_FLAG(SEARCH_FLAG_COPY);
817         ADD_DSDB_FLAG(SEARCH_FLAG_TUPLEINDEX);
818         ADD_DSDB_FLAG(SEARCH_FLAG_SUBTREEATTRINDEX);
819         ADD_DSDB_FLAG(SEARCH_FLAG_CONFIDENTIAL);
820         ADD_DSDB_FLAG(SEARCH_FLAG_NEVERVALUEAUDIT);
821         ADD_DSDB_FLAG(SEARCH_FLAG_RODC_ATTRIBUTE);
822
823         ADD_DSDB_FLAG(DS_FLAG_ATTR_NOT_REPLICATED);
824         ADD_DSDB_FLAG(DS_FLAG_ATTR_REQ_PARTIAL_SET_MEMBER);
825         ADD_DSDB_FLAG(DS_FLAG_ATTR_IS_CONSTRUCTED);
826
827         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_IS_GC);
828         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL);
829         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL);
830         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE);
831         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_SPN_REGISTRATION);
832
833         ADD_DSDB_FLAG(NTDSCONN_KCC_GC_TOPOLOGY);
834         ADD_DSDB_FLAG(NTDSCONN_KCC_RING_TOPOLOGY);
835         ADD_DSDB_FLAG(NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY);
836         ADD_DSDB_FLAG(NTDSCONN_KCC_STALE_SERVERS_TOPOLOGY);
837         ADD_DSDB_FLAG(NTDSCONN_KCC_OSCILLATING_CONNECTION_TOPOLOGY);
838         ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_GC_TOPOLOGY);
839         ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_TOPOLOGY);
840         ADD_DSDB_FLAG(NTDSCONN_KCC_SERVER_FAILOVER_TOPOLOGY);
841         ADD_DSDB_FLAG(NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY);
842         ADD_DSDB_FLAG(NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY);
843
844         /* GPO policy flags */
845         ADD_DSDB_FLAG(GPLINK_OPT_DISABLE);
846         ADD_DSDB_FLAG(GPLINK_OPT_ENFORCE);
847         ADD_DSDB_FLAG(GPO_FLAG_USER_DISABLE);
848         ADD_DSDB_FLAG(GPO_FLAG_MACHINE_DISABLE);
849         ADD_DSDB_FLAG(GPO_INHERIT);
850         ADD_DSDB_FLAG(GPO_BLOCK_INHERITANCE);
851 }