pyldb: Add dom_sid.split in favor of less powerful dom_sid_to_rid().
[idra/samba.git] / source4 / scripting / python / pyglue.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
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 "ldb_errors.h"
24 #include "ldb_wrap.h"
25 #include "param/param.h"
26 #include "auth/credentials/credentials.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "lib/ldb-samba/ldif_handlers.h"
29 #include "librpc/ndr/libndr.h"
30 #include "version.h"
31 #include "lib/ldb/pyldb.h"
32 #include "libcli/util/pyerrors.h"
33 #include "libcli/security/security.h"
34 #include "auth/pyauth.h"
35 #include "param/pyparam.h"
36 #include "auth/credentials/pycredentials.h"
37
38 #ifndef Py_RETURN_NONE
39 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
40 #endif
41
42 /* FIXME: These should be in a header file somewhere, once we finish moving
43  * away from SWIG .. */
44 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
45 /*      if (!PyLdb_Check(py_ldb)) { \
46                 PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
47                 return NULL; \
48         } */\
49         ldb = PyLdb_AsLdbContext(py_ldb);
50
51 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
52 {
53         if (ret == LDB_ERR_PYTHON_EXCEPTION)
54                 return; /* Python exception should already be set, just keep that */
55
56         PyErr_SetObject(error, 
57                                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret, 
58                                   ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
59 }
60
61 static PyObject *py_ldb_get_exception(void)
62 {
63         PyObject *mod = PyImport_ImportModule("ldb");
64         if (mod == NULL)
65                 return NULL;
66
67         return PyObject_GetAttrString(mod, "LdbError");
68 }
69
70 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
71 {
72         int len;
73         PyObject *ret;
74         char *retstr;
75         if (!PyArg_ParseTuple(args, "i", &len))
76                 return NULL;
77
78         retstr = generate_random_str(NULL, len);
79         ret = PyString_FromString(retstr);
80         talloc_free(retstr);
81         return ret;
82 }
83
84 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
85 {
86         time_t t;
87         NTTIME nt;
88         if (!PyArg_ParseTuple(args, "I", &t))
89                 return NULL;
90
91         unix_to_nt_time(&nt, t);
92
93         return PyInt_FromLong((uint64_t)nt);
94 }
95
96 static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
97 {
98         unsigned level;
99         if (!PyArg_ParseTuple(args, "I", &level))
100                 return NULL;
101         (DEBUGLEVEL) = level;
102         Py_RETURN_NONE;
103 }
104
105 static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args)
106 {
107         PyObject *py_session_info, *py_ldb;
108         struct auth_session_info *info;
109         struct ldb_context *ldb;
110         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_session_info))
111                 return NULL;
112
113         PyErr_LDB_OR_RAISE(py_ldb, ldb);
114         /*if (!PyAuthSession_Check(py_session_info)) {
115                 PyErr_SetString(PyExc_TypeError, "Expected session info object");
116                 return NULL;
117         }*/
118
119         info = PyAuthSession_AsSession(py_session_info);
120
121         ldb_set_opaque(ldb, "sessionInfo", info);
122
123         Py_RETURN_NONE;
124 }
125
126 static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args)
127 {
128         PyObject *py_creds, *py_ldb;
129         struct cli_credentials *creds;
130         struct ldb_context *ldb;
131         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_creds))
132                 return NULL;
133
134         PyErr_LDB_OR_RAISE(py_ldb, ldb);
135         
136         creds = cli_credentials_from_py_object(py_creds);
137         if (creds == NULL) {
138                 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
139                 return NULL;
140         }
141
142         ldb_set_opaque(ldb, "credentials", creds);
143
144         Py_RETURN_NONE;
145 }
146
147 static PyObject *py_ldb_set_loadparm(PyObject *self, PyObject *args)
148 {
149         PyObject *py_lp_ctx, *py_ldb;
150         struct loadparm_context *lp_ctx;
151         struct ldb_context *ldb;
152         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_lp_ctx))
153                 return NULL;
154
155         PyErr_LDB_OR_RAISE(py_ldb, ldb);
156
157         lp_ctx = lp_from_py_object(py_lp_ctx);
158         if (lp_ctx == NULL) {
159                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
160                 return NULL;
161         }
162
163         ldb_set_opaque(ldb, "loadparm", lp_ctx);
164
165         Py_RETURN_NONE;
166 }
167
168 static PyObject *py_ldb_set_utf8_casefold(PyObject *self, PyObject *args)
169 {
170         PyObject *py_ldb;
171         struct ldb_context *ldb;
172
173         if (!PyArg_ParseTuple(args, "O", &py_ldb))
174                 return NULL;
175
176         PyErr_LDB_OR_RAISE(py_ldb, ldb);
177
178         ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
179
180         Py_RETURN_NONE;
181 }
182
183 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
184
185         PyObject *py_ldb, *py_sid;
186         struct ldb_context *ldb;
187         struct dom_sid *sid;
188         bool ret;
189
190         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
191                 return NULL;
192         
193         PyErr_LDB_OR_RAISE(py_ldb, ldb);
194
195         sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
196
197         ret = samdb_set_domain_sid(ldb, sid);
198         if (!ret) {
199                 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
200                 return NULL;
201         } 
202         Py_RETURN_NONE;
203 }
204
205 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
206
207         PyObject *py_ldb;
208         struct ldb_context *ldb;
209         const struct dom_sid *sid;
210         PyObject *ret;
211         char *retstr;
212
213         if (!PyArg_ParseTuple(args, "O", &py_ldb))
214                 return NULL;
215         
216         PyErr_LDB_OR_RAISE(py_ldb, ldb);
217
218         sid = samdb_domain_sid(ldb);
219         if (!sid) {
220                 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
221                 return NULL;
222         } 
223         retstr = dom_sid_string(NULL, sid);
224         ret = PyString_FromString(retstr);
225         talloc_free(retstr);
226         return ret;
227 }
228
229 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
230 {
231         PyObject *py_ldb;
232         struct ldb_context *ldb;
233         int ret;
234
235         if (!PyArg_ParseTuple(args, "O", &py_ldb))
236                 return NULL;
237
238         PyErr_LDB_OR_RAISE(py_ldb, ldb);
239         ret = ldb_register_samba_handlers(ldb);
240
241         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
242         Py_RETURN_NONE;
243 }
244
245 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
246 {
247         PyObject *py_ldb, *py_guid;
248         bool ret;
249         struct GUID guid;
250         struct ldb_context *ldb;
251         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
252                 return NULL;
253
254         PyErr_LDB_OR_RAISE(py_ldb, ldb);
255         GUID_from_string(PyString_AsString(py_guid), &guid);
256
257         ret = samdb_set_ntds_invocation_id(ldb, &guid);
258         if (!ret) {
259                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
260                 return NULL;
261         }
262         Py_RETURN_NONE;
263 }
264
265 static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
266 {
267         PyObject *py_ldb;
268         int value;
269         int *old_val, *new_val;
270         char *py_opaque_name, *opaque_name_talloc;
271         struct ldb_context *ldb;
272         TALLOC_CTX *tmp_ctx;
273
274         if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
275                 return NULL;
276
277         PyErr_LDB_OR_RAISE(py_ldb, ldb);
278
279         /* see if we have a cached copy */
280         old_val = (int *)ldb_get_opaque(ldb, 
281                                         py_opaque_name);
282
283         if (old_val) {
284                 *old_val = value;
285                 Py_RETURN_NONE;
286         } 
287
288         tmp_ctx = talloc_new(ldb);
289         if (tmp_ctx == NULL) {
290                 goto failed;
291         }
292         
293         new_val = talloc(tmp_ctx, int);
294         if (!new_val) {
295                 goto failed;
296         }
297         
298         opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
299         if (!opaque_name_talloc) {
300                 goto failed;
301         }
302         
303         *new_val = value;
304
305         /* cache the domain_sid in the ldb */
306         if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
307                 goto failed;
308         }
309
310         talloc_steal(ldb, new_val);
311         talloc_steal(ldb, opaque_name_talloc);
312         talloc_free(tmp_ctx);
313
314         Py_RETURN_NONE;
315
316 failed:
317         talloc_free(tmp_ctx);
318         PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n");
319         return NULL;
320 }
321
322 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
323 {
324         PyObject *py_ldb;
325         struct ldb_context *ldb;
326         int ret;
327         if (!PyArg_ParseTuple(args, "O", &py_ldb))
328                 return NULL;
329
330         PyErr_LDB_OR_RAISE(py_ldb, ldb);
331
332         ret = dsdb_set_global_schema(ldb);
333         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
334
335         Py_RETURN_NONE;
336 }
337
338 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
339 {
340         WERROR result;
341         char *pf, *df;
342         PyObject *py_ldb;
343         struct ldb_context *ldb;
344
345         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &pf, &df))
346                 return NULL;
347
348         PyErr_LDB_OR_RAISE(py_ldb, ldb);
349
350         result = dsdb_set_schema_from_ldif(ldb, pf, df);
351         PyErr_WERROR_IS_ERR_RAISE(result);
352
353         Py_RETURN_NONE;
354 }
355
356 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self, PyObject *args)
357 {
358         char *target_str, *mapping;
359         PyObject *py_ldb;
360         struct ldb_context *ldb;
361         PyObject *ret;
362         char *retstr;
363
364         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
365                 return NULL;
366
367         PyErr_LDB_OR_RAISE(py_ldb, ldb);
368
369         retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
370         if (!retstr) {
371                 PyErr_SetString(PyExc_RuntimeError, "dsdb_convert_schema_to_openldap failed");
372                 return NULL;
373         } 
374         ret = PyString_FromString(retstr);
375         talloc_free(retstr);
376         return ret;
377 }
378
379 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
380 {
381         PyObject *py_ldb;
382         struct ldb_context *ldb;
383         WERROR result;
384         struct dsdb_schema *schema;
385
386         if (!PyArg_ParseTuple(args, "O", &py_ldb))
387                 return NULL;
388
389         PyErr_LDB_OR_RAISE(py_ldb, ldb);
390
391         schema = dsdb_get_schema(ldb);
392         if (!schema) {
393                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
394                 return NULL;
395         }
396
397         result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
398         PyErr_WERROR_IS_ERR_RAISE(result);
399
400         Py_RETURN_NONE;
401 }
402
403 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
404 {
405         PyObject *py_ldb;
406         struct ldb_context *ldb;
407         PyObject *py_from_ldb;
408         struct ldb_context *from_ldb;
409         struct dsdb_schema *schema;
410         int ret;
411         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_from_ldb))
412                 return NULL;
413
414         PyErr_LDB_OR_RAISE(py_ldb, ldb);
415
416         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
417
418         schema = dsdb_get_schema(from_ldb);
419         if (!schema) {
420                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
421                 return NULL;
422         }
423
424         ret = dsdb_reference_schema(ldb, schema, true);
425         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
426
427         Py_RETURN_NONE;
428 }
429
430 static PyObject *py_dsdb_make_schema_global(PyObject *self, PyObject *args)
431 {
432         PyObject *py_ldb;
433         struct ldb_context *ldb;
434
435         if (!PyArg_ParseTuple(args, "O", &py_ldb))
436                 return NULL;
437
438         PyErr_LDB_OR_RAISE(py_ldb, ldb);
439
440         dsdb_make_schema_global(ldb);
441
442         Py_RETURN_NONE;
443 }
444
445 static PyMethodDef py_misc_methods[] = {
446         { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
447                 "random_password(len) -> string\n"
448                 "Generate random password with specified length." },
449         { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
450                 "unix2nttime(timestamp) -> nttime" },
451         { "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
452                 "ldb_set_session_info(ldb, session_info)\n"
453                 "Set session info to use when connecting." },
454         { "ldb_set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS,
455                 "ldb_set_credentials(ldb, credentials)\n"
456                 "Set credentials to use when connecting." },
457         { "ldb_set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS,
458                 "ldb_set_loadparm(ldb, session_info)\n"
459                 "Set loadparm context to use when connecting." },
460         { "samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid, METH_VARARGS,
461                 "samdb_set_domain_sid(samdb, sid)\n"
462                 "Set SID of domain to use." },
463         { "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
464                 "samdb_get_domain_sid(samdb)\n"
465                 "Get SID of domain in use." },
466         { "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
467                 "ldb_register_samba_handlers(ldb)\n"
468                 "Register Samba-specific LDB modules and schemas." },
469         { "ldb_set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_VARARGS,
470                 "ldb_set_utf8_casefold(ldb)\n"
471                 "Set the right Samba casefolding function for UTF8 charset." },
472         { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
473                 NULL },
474         { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS,
475                 NULL },
476         { "dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema, METH_VARARGS,
477                 NULL },
478         { "dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
479                 NULL },
480         { "dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
481                 NULL },
482         { "dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
483                 NULL },
484         { "dsdb_convert_schema_to_openldap", (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
485                 NULL },
486         { "dsdb_make_schema_global", (PyCFunction)py_dsdb_make_schema_global, METH_VARARGS,
487                 NULL },
488         { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
489                 "set debug level" },
490         { NULL }
491 };
492
493 void initglue(void)
494 {
495         PyObject *m;
496
497         m = Py_InitModule3("glue", py_misc_methods, 
498                            "Python bindings for miscellaneous Samba functions.");
499         if (m == NULL)
500                 return;
501
502         PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
503
504         /* "userAccountControl" flags */
505         PyModule_AddObject(m, "UF_NORMAL_ACCOUNT", PyInt_FromLong(UF_NORMAL_ACCOUNT));
506         PyModule_AddObject(m, "UF_TEMP_DUPLICATE_ACCOUNT", PyInt_FromLong(UF_TEMP_DUPLICATE_ACCOUNT));
507         PyModule_AddObject(m, "UF_SERVER_TRUST_ACCOUNT", PyInt_FromLong(UF_SERVER_TRUST_ACCOUNT));
508         PyModule_AddObject(m, "UF_WORKSTATION_TRUST_ACCOUNT", PyInt_FromLong(UF_WORKSTATION_TRUST_ACCOUNT));
509         PyModule_AddObject(m, "UF_INTERDOMAIN_TRUST_ACCOUNT", PyInt_FromLong(UF_INTERDOMAIN_TRUST_ACCOUNT));
510         PyModule_AddObject(m, "UF_PASSWD_NOTREQD", PyInt_FromLong(UF_PASSWD_NOTREQD));
511         PyModule_AddObject(m, "UF_ACCOUNTDISABLE", PyInt_FromLong(UF_ACCOUNTDISABLE));
512
513         /* "groupType" flags */
514         PyModule_AddObject(m, "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
515         PyModule_AddObject(m, "GTYPE_SECURITY_GLOBAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_GLOBAL_GROUP));
516         PyModule_AddObject(m, "GTYPE_SECURITY_DOMAIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
517         PyModule_AddObject(m, "GTYPE_SECURITY_UNIVERSAL_GROUP", PyInt_FromLong(GTYPE_SECURITY_UNIVERSAL_GROUP));
518         PyModule_AddObject(m, "GTYPE_DISTRIBUTION_GLOBAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
519         PyModule_AddObject(m, "GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
520         PyModule_AddObject(m, "GTYPE_DISTRIBUTION_UNIVERSAL_GROUP", PyInt_FromLong(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
521
522         /* "sAMAccountType" flags */
523         PyModule_AddObject(m, "ATYPE_NORMAL_ACCOUNT", PyInt_FromLong(ATYPE_NORMAL_ACCOUNT));
524         PyModule_AddObject(m, "ATYPE_WORKSTATION_TRUST", PyInt_FromLong(ATYPE_WORKSTATION_TRUST));
525         PyModule_AddObject(m, "ATYPE_INTERDOMAIN_TRUST", PyInt_FromLong(ATYPE_INTERDOMAIN_TRUST));
526         PyModule_AddObject(m, "ATYPE_SECURITY_GLOBAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_GLOBAL_GROUP));
527         PyModule_AddObject(m, "ATYPE_SECURITY_LOCAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_LOCAL_GROUP));
528         PyModule_AddObject(m, "ATYPE_SECURITY_UNIVERSAL_GROUP", PyInt_FromLong(ATYPE_SECURITY_UNIVERSAL_GROUP));
529         PyModule_AddObject(m, "ATYPE_DISTRIBUTION_GLOBAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_GLOBAL_GROUP));
530         PyModule_AddObject(m, "ATYPE_DISTRIBUTION_LOCAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_LOCAL_GROUP));
531         PyModule_AddObject(m, "ATYPE_DISTRIBUTION_UNIVERSAL_GROUP", PyInt_FromLong(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP));
532
533         /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
534         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2000", PyInt_FromLong(DS_DOMAIN_FUNCTION_2000));
535         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003_MIXED", PyInt_FromLong(DS_DOMAIN_FUNCTION_2003_MIXED));
536         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2003", PyInt_FromLong(DS_DOMAIN_FUNCTION_2003));
537         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008", PyInt_FromLong(DS_DOMAIN_FUNCTION_2008));
538         PyModule_AddObject(m, "DS_DOMAIN_FUNCTION_2008_R2", PyInt_FromLong(DS_DOMAIN_FUNCTION_2008_R2));
539
540         /* "domainControllerFunctionality" flags in the rootDSE */
541         PyModule_AddObject(m, "DS_DC_FUNCTION_2000", PyInt_FromLong(DS_DC_FUNCTION_2000));
542         PyModule_AddObject(m, "DS_DC_FUNCTION_2003", PyInt_FromLong(DS_DC_FUNCTION_2003));
543         PyModule_AddObject(m, "DS_DC_FUNCTION_2008", PyInt_FromLong(DS_DC_FUNCTION_2008));
544         PyModule_AddObject(m, "DS_DC_FUNCTION_2008_R2", PyInt_FromLong(DS_DC_FUNCTION_2008_R2));
545
546         /* "LDAP_SERVER_SD_FLAGS_OID" */
547         PyModule_AddObject(m, "SECINFO_OWNER", PyInt_FromLong(SECINFO_OWNER));
548         PyModule_AddObject(m, "SECINFO_GROUP", PyInt_FromLong(SECINFO_GROUP));
549         PyModule_AddObject(m, "SECINFO_DACL", PyInt_FromLong(SECINFO_DACL));
550         PyModule_AddObject(m, "SECINFO_SACL", PyInt_FromLong(SECINFO_SACL));
551
552         /* one of the most annoying things about python scripts is
553            that they don't die when you hit control-C. This fixes that
554            sillyness. As we do all database operations using
555            transactions, this is also safe. In fact, not dying
556            immediately is unsafe as we could end up treating the
557            control-C exception as a different error and try to modify
558            as database incorrectly 
559         */
560         signal(SIGINT, SIG_DFL);
561 }
562