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 "python/py3compat.h"
22 #include "includes.h"
23 #include <ldb.h>
24 #include <pyldb.h>
25 #include "dsdb/samdb/samdb.h"
26 #include "libcli/security/security.h"
27 #include "librpc/ndr/libndr.h"
28 #include "system/kerberos.h"
29 #include "auth/kerberos/kerberos.h"
30 #include "librpc/rpc/pyrpc_util.h"
31 #include "lib/policy/policy.h"
32 #include "param/pyparam.h"
33 #include "lib/util/dlinklist.h"
34 #include "dsdb/kcc/garbage_collect_tombstones.h"
35 #include "dsdb/kcc/scavenge_dns_records.h"
36 
37 
38 /* FIXME: These should be in a header file somewhere */
39 #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
40 	if (!py_check_dcerpc_type(py_ldb, "ldb", "Ldb")) { \
41 		PyErr_SetString(PyExc_TypeError, "Ldb connection object required"); \
42 		return NULL; \
43 	} \
44 	ldb = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
45 
46 #define PyErr_LDB_DN_OR_RAISE(py_ldb_dn, dn) \
47 	if (!py_check_dcerpc_type(py_ldb_dn, "ldb", "Dn")) { \
48 		PyErr_SetString(PyExc_TypeError, "ldb Dn object required"); \
49 		return NULL; \
50 	} \
51 	dn = pyldb_Dn_AS_DN(py_ldb_dn);
52 
53 static PyObject *py_ldb_get_exception(void)
54 {
55 	PyObject *mod = PyImport_ImportModule("ldb");
56 	PyObject *result = NULL;
57 	if (mod == NULL)
58 		return NULL;
59 
60 	result = PyObject_GetAttrString(mod, "LdbError");
61 	Py_CLEAR(mod);
62 	return result;
63 }
64 
65 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
66 {
67 	if (ret == LDB_ERR_PYTHON_EXCEPTION)
68 		return; /* Python exception should already be set, just keep that */
69 
70 	PyErr_SetObject(error,
71 			Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
72 			ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
73 }
74 
75 static PyObject *py_samdb_server_site_name(PyObject *self, PyObject *args)
76 {
77 	PyObject *py_ldb, *result;
78 	struct ldb_context *ldb;
79 	const char *site;
80 	TALLOC_CTX *mem_ctx;
81 
82 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
83 		return NULL;
84 
85 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
86 
87 	mem_ctx = talloc_new(NULL);
88 	if (mem_ctx == NULL) {
89 		PyErr_NoMemory();
90 		return NULL;
91 	}
92 
93 	site = samdb_server_site_name(ldb, mem_ctx);
94 	if (site == NULL) {
95 		PyErr_SetString(PyExc_RuntimeError, "Failed to find server site");
96 		talloc_free(mem_ctx);
97 		return NULL;
98 	}
99 
100 	result = PyUnicode_FromString(site);
101 	talloc_free(mem_ctx);
102 	return result;
103 }
104 
105 static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self,
106 						    PyObject *args)
107 {
108 	char *target_str, *mapping;
109 	PyObject *py_ldb;
110 	struct ldb_context *ldb;
111 	PyObject *ret;
112 	char *retstr;
113 
114 	if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
115 		return NULL;
116 
117 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
118 
119 	retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
120 	if (retstr == NULL) {
121 		PyErr_SetString(PyExc_RuntimeError,
122 						"dsdb_convert_schema_to_openldap failed");
123 		return NULL;
124 	}
125 
126 	ret = PyUnicode_FromString(retstr);
127 	talloc_free(retstr);
128 	return ret;
129 }
130 
131 static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
132 {
133 	PyObject *py_ldb, *py_sid;
134 	struct ldb_context *ldb;
135 	struct dom_sid *sid;
136 	bool ret;
137 	const char *sid_str = NULL;
138 
139 	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
140 		return NULL;
141 
142 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
143 
144 	sid_str = PyUnicode_AsUTF8(py_sid);
145 	if (sid_str == NULL) {
146 		PyErr_NoMemory();
147 		return NULL;
148 	}
149 
150 	sid = dom_sid_parse_talloc(NULL, sid_str);
151 	if (sid == NULL) {
152 		PyErr_NoMemory();
153 		return NULL;
154 	}
155 
156 	ret = samdb_set_domain_sid(ldb, sid);
157 	talloc_free(sid);
158 	if (!ret) {
159 		PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
160 		return NULL;
161 	}
162 	Py_RETURN_NONE;
163 }
164 
165 static PyObject *py_samdb_set_ntds_settings_dn(PyLdbObject *self, PyObject *args)
166 {
167 	PyObject *py_ldb, *py_ntds_settings_dn;
168 	struct ldb_context *ldb;
169 	struct ldb_dn *ntds_settings_dn;
170 	TALLOC_CTX *tmp_ctx;
171 	bool ret;
172 
173 	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_ntds_settings_dn))
174 		return NULL;
175 
176 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
177 
178 	tmp_ctx = talloc_new(NULL);
179 	if (tmp_ctx == NULL) {
180 		PyErr_NoMemory();
181 		return NULL;
182 	}
183 
184 	if (!pyldb_Object_AsDn(tmp_ctx, py_ntds_settings_dn, ldb, &ntds_settings_dn)) {
185 		/* exception thrown by "pyldb_Object_AsDn" */
186 		talloc_free(tmp_ctx);
187 		return NULL;
188 	}
189 
190 	ret = samdb_set_ntds_settings_dn(ldb, ntds_settings_dn);
191 	talloc_free(tmp_ctx);
192 	if (!ret) {
193 		PyErr_SetString(PyExc_RuntimeError, "set_ntds_settings_dn failed");
194 		return NULL;
195 	}
196 	Py_RETURN_NONE;
197 }
198 
199 static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
200 {
201 	PyObject *py_ldb;
202 	struct ldb_context *ldb;
203 	const struct dom_sid *sid;
204 	struct dom_sid_buf buf;
205 	PyObject *ret;
206 
207 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
208 		return NULL;
209 
210 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
211 
212 	sid = samdb_domain_sid(ldb);
213 	if (!sid) {
214 		PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
215 		return NULL;
216 	}
217 
218 	ret = PyUnicode_FromString(dom_sid_str_buf(sid, &buf));
219 	return ret;
220 }
221 
222 static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
223 {
224 	PyObject *py_ldb, *result;
225 	struct ldb_context *ldb;
226 	const struct GUID *guid;
227 	char *retstr;
228 
229 	if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
230 		return NULL;
231 	}
232 
233 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
234 
235 	guid = samdb_ntds_invocation_id(ldb);
236 	if (guid == NULL) {
237 		PyErr_SetString(PyExc_RuntimeError,
238 						"Failed to find NTDS invocation ID");
239 		return NULL;
240 	}
241 
242 	retstr = GUID_string(NULL, guid);
243 	if (retstr == NULL) {
244 		PyErr_NoMemory();
245 		return NULL;
246 	}
247 	result = PyUnicode_FromString(retstr);
248 	talloc_free(retstr);
249 	return result;
250 }
251 
252 static PyObject *py_dsdb_get_oid_from_attid(PyObject *self, PyObject *args)
253 {
254 	PyObject *py_ldb;
255 	struct ldb_context *ldb;
256 	uint32_t attid;
257 	struct dsdb_schema *schema;
258 	const char *oid;
259 	PyObject *ret;
260 	WERROR status;
261 	TALLOC_CTX *mem_ctx;
262 
263 	if (!PyArg_ParseTuple(args, "OI", &py_ldb, &attid))
264 		return NULL;
265 
266 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
267 
268 	mem_ctx = talloc_new(NULL);
269 	if (!mem_ctx) {
270 		PyErr_NoMemory();
271 		return NULL;
272 	}
273 
274 	schema = dsdb_get_schema(ldb, mem_ctx);
275 	if (!schema) {
276 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb \n");
277 		talloc_free(mem_ctx);
278 		return NULL;
279 	}
280 
281 	status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid,
282 	                                        mem_ctx, &oid);
283 	if (!W_ERROR_IS_OK(status)) {
284 		PyErr_SetWERROR(status);
285 		talloc_free(mem_ctx);
286 		return NULL;
287 	}
288 
289 	ret = PyUnicode_FromString(oid);
290 
291 	talloc_free(mem_ctx);
292 
293 	return ret;
294 }
295 
296 
297 static PyObject *py_dsdb_get_attid_from_lDAPDisplayName(PyObject *self, PyObject *args)
298 {
299 	PyObject *py_ldb, *is_schema_nc;
300 	struct ldb_context *ldb;
301 	struct dsdb_schema *schema;
302 	const char *ldap_display_name;
303 	bool schema_nc = false;
304 	const struct dsdb_attribute *a;
305 	uint32_t attid;
306 
307 	if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &is_schema_nc))
308 		return NULL;
309 
310 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
311 
312 	if (is_schema_nc) {
313 		if (!PyBool_Check(is_schema_nc)) {
314 			PyErr_SetString(PyExc_TypeError, "Expected boolean is_schema_nc");
315 			return NULL;
316 		}
317 		if (is_schema_nc == Py_True) {
318 			schema_nc = true;
319 		}
320 	}
321 
322 	schema = dsdb_get_schema(ldb, NULL);
323 
324 	if (!schema) {
325 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
326 		return NULL;
327 	}
328 
329 	a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
330 	if (a == NULL) {
331 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
332 		return NULL;
333 	}
334 
335 	attid = dsdb_attribute_get_attid(a, schema_nc);
336 
337 	return PyLong_FromUnsignedLong(attid);
338 }
339 
340 /*
341   return the systemFlags as int from the attribute name
342  */
343 static PyObject *py_dsdb_get_systemFlags_from_lDAPDisplayName(PyObject *self, PyObject *args)
344 {
345 	PyObject *py_ldb;
346 	struct ldb_context *ldb;
347 	struct dsdb_schema *schema;
348 	const char *ldap_display_name;
349 	const struct dsdb_attribute *attribute;
350 
351 	if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
352 		return NULL;
353 
354 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
355 
356 	schema = dsdb_get_schema(ldb, NULL);
357 
358 	if (!schema) {
359 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
360 		return NULL;
361 	}
362 
363 	attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
364 	if (attribute == NULL) {
365 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
366 		return NULL;
367 	}
368 
369 	return PyInt_FromLong(attribute->systemFlags);
370 }
371 
372 /*
373   return the linkID from the attribute name
374  */
375 static PyObject *py_dsdb_get_linkId_from_lDAPDisplayName(PyObject *self, PyObject *args)
376 {
377 	PyObject *py_ldb;
378 	struct ldb_context *ldb;
379 	struct dsdb_schema *schema;
380 	const char *ldap_display_name;
381 	const struct dsdb_attribute *attribute;
382 
383 	if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
384 		return NULL;
385 
386 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
387 
388 	schema = dsdb_get_schema(ldb, NULL);
389 
390 	if (!schema) {
391 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
392 		return NULL;
393 	}
394 
395 	attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
396 	if (attribute == NULL) {
397 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
398 		return NULL;
399 	}
400 
401 	return PyInt_FromLong(attribute->linkID);
402 }
403 
404 /*
405   return the backlink attribute name (if any) for an attribute
406  */
407 static PyObject *py_dsdb_get_backlink_from_lDAPDisplayName(PyObject *self, PyObject *args)
408 {
409 	PyObject *py_ldb;
410 	struct ldb_context *ldb;
411 	struct dsdb_schema *schema;
412 	const char *ldap_display_name;
413 	const struct dsdb_attribute *attribute, *target_attr;
414 
415 	if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
416 		return NULL;
417 
418 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
419 
420 	schema = dsdb_get_schema(ldb, NULL);
421 
422 	if (!schema) {
423 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
424 		return NULL;
425 	}
426 
427 	attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
428 	if (attribute == NULL) {
429 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
430 		return NULL;
431 	}
432 
433 	if (attribute->linkID == 0) {
434 		Py_RETURN_NONE;
435 	}
436 
437 	target_attr = dsdb_attribute_by_linkID(schema, attribute->linkID ^ 1);
438 	if (target_attr == NULL) {
439 		/* when we add pseudo-backlinks we'll need to handle
440 		   them here */
441 		Py_RETURN_NONE;
442 	}
443 
444 	return PyUnicode_FromString(target_attr->lDAPDisplayName);
445 }
446 
447 
448 static PyObject *py_dsdb_get_lDAPDisplayName_by_attid(PyObject *self, PyObject *args)
449 {
450 	PyObject *py_ldb;
451 	struct ldb_context *ldb;
452 	struct dsdb_schema *schema;
453 	const struct dsdb_attribute *a;
454 	uint32_t attid;
455 
456 	if (!PyArg_ParseTuple(args, "OI", &py_ldb, &attid))
457 		return NULL;
458 
459 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
460 
461 	schema = dsdb_get_schema(ldb, NULL);
462 
463 	if (!schema) {
464 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
465 		return NULL;
466 	}
467 
468 	a = dsdb_attribute_by_attributeID_id(schema, attid);
469 	if (a == NULL) {
470 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '0x%08x'", attid);
471 		return NULL;
472 	}
473 
474 	return PyUnicode_FromString(a->lDAPDisplayName);
475 }
476 
477 
478 /*
479   return the attribute syntax oid as a string from the attribute name
480  */
481 static PyObject *py_dsdb_get_syntax_oid_from_lDAPDisplayName(PyObject *self, PyObject *args)
482 {
483 	PyObject *py_ldb;
484 	struct ldb_context *ldb;
485 	struct dsdb_schema *schema;
486 	const char *ldap_display_name;
487 	const struct dsdb_attribute *attribute;
488 
489 	if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
490 		return NULL;
491 
492 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
493 
494 	schema = dsdb_get_schema(ldb, NULL);
495 
496 	if (!schema) {
497 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
498 		return NULL;
499 	}
500 
501 	attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
502 	if (attribute == NULL) {
503 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
504 		return NULL;
505 	}
506 
507 	return PyUnicode_FromString(attribute->syntax->ldap_oid);
508 }
509 
510 /*
511   convert a python string to a DRSUAPI drsuapi_DsReplicaAttribute attribute
512  */
513 static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
514 {
515 	PyObject *py_ldb, *el_list, *ret;
516 	struct ldb_context *ldb;
517 	char *ldap_display_name;
518 	const struct dsdb_attribute *a;
519 	struct dsdb_schema *schema;
520 	struct dsdb_syntax_ctx syntax_ctx;
521 	struct ldb_message_element *el;
522 	struct drsuapi_DsReplicaAttribute *attr;
523 	TALLOC_CTX *tmp_ctx;
524 	WERROR werr;
525 	Py_ssize_t i;
526 
527 	if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
528 		return NULL;
529 	}
530 
531 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
532 
533 	schema = dsdb_get_schema(ldb, NULL);
534 	if (!schema) {
535 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
536 		return NULL;
537 	}
538 
539 	a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
540 	if (a == NULL) {
541 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
542 		return NULL;
543 	}
544 
545 	dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
546 	syntax_ctx.is_schema_nc = false;
547 
548 	tmp_ctx = talloc_new(ldb);
549 	if (tmp_ctx == NULL) {
550 		PyErr_NoMemory();
551 		return NULL;
552 	}
553 
554 	/* If we were not given an LdbMessageElement */
555 	if (!PyList_Check(el_list)) {
556 		if (!py_check_dcerpc_type(el_list, "ldb", "MessageElement")) {
557 			PyErr_SetString(py_ldb_get_exception(),
558 					"list of strings or ldb MessageElement object required");
559 			return NULL;
560 		}
561 		/*
562 		 * NOTE:
563 		 * el may not be a valid talloc context, it
564 		 * could be part of an array
565 		 */
566 		el = pyldb_MessageElement_AsMessageElement(el_list);
567 	} else {
568 		el = talloc_zero(tmp_ctx, struct ldb_message_element);
569 		if (el == NULL) {
570 			PyErr_NoMemory();
571 			talloc_free(tmp_ctx);
572 			return NULL;
573 		}
574 
575 		el->name = ldap_display_name;
576 		el->num_values = PyList_Size(el_list);
577 
578 		el->values = talloc_array(el, struct ldb_val, el->num_values);
579 		if (el->values == NULL) {
580 			PyErr_NoMemory();
581 			talloc_free(tmp_ctx);
582 			return NULL;
583 		}
584 
585 		for (i = 0; i < el->num_values; i++) {
586 			PyObject *item = PyList_GetItem(el_list, i);
587 			if (!(PyBytes_Check(item))) {
588 				PyErr_Format(PyExc_TypeError,
589 					     "ldif_element type should be "
590 					     PY_DESC_PY3_BYTES
591 					     );
592 				talloc_free(tmp_ctx);
593 				return NULL;
594 			}
595 			el->values[i].data =
596 				(uint8_t *)PyBytes_AsString(item);
597 			el->values[i].length = PyBytes_Size(item);
598 		}
599 	}
600 
601 	attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
602 	if (attr == NULL) {
603 		PyErr_NoMemory();
604 		talloc_free(tmp_ctx);
605 		return NULL;
606 	}
607 
608 	werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
609 	PyErr_WERROR_NOT_OK_RAISE(werr);
610 
611 	ret = py_return_ndr_struct("samba.dcerpc.drsuapi", "DsReplicaAttribute", attr, attr);
612 
613 	talloc_free(tmp_ctx);
614 
615 	return ret;
616 }
617 
618 
619 /*
620   normalise a ldb attribute list
621  */
622 static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
623 {
624 	PyObject *py_ldb, *el_list, *py_ret;
625 	struct ldb_context *ldb;
626 	char *ldap_display_name;
627 	const struct dsdb_attribute *a;
628 	struct dsdb_schema *schema;
629 	struct dsdb_syntax_ctx syntax_ctx;
630 	struct ldb_message_element *el, *new_el;
631 	struct drsuapi_DsReplicaAttribute *attr;
632 	PyLdbMessageElementObject *ret;
633 	TALLOC_CTX *tmp_ctx;
634 	WERROR werr;
635 	Py_ssize_t i;
636 	PyTypeObject *py_type = NULL;
637 	PyObject *module = NULL;
638 
639 	if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
640 		return NULL;
641 	}
642 
643 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
644 
645 	schema = dsdb_get_schema(ldb, NULL);
646 	if (!schema) {
647 		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
648 		return NULL;
649 	}
650 
651 	a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
652 	if (a == NULL) {
653 		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
654 		return NULL;
655 	}
656 
657 	dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
658 	syntax_ctx.is_schema_nc = false;
659 
660 	tmp_ctx = talloc_new(ldb);
661 	if (tmp_ctx == NULL) {
662 		PyErr_NoMemory();
663 		return NULL;
664 	}
665 
666 	if (!PyList_Check(el_list)) {
667 		if (!py_check_dcerpc_type(el_list, "ldb", "MessageElement")) {
668 			PyErr_SetString(py_ldb_get_exception(),
669 					"list of strings or ldb MessageElement object required");
670 			return NULL;
671 		}
672 		/*
673 		 * NOTE:
674 		 * el may not be a valid talloc context, it
675 		 * could be part of an array
676 		 */
677 		el = pyldb_MessageElement_AsMessageElement(el_list);
678 	} else {
679 		el = talloc_zero(tmp_ctx, struct ldb_message_element);
680 		if (el == NULL) {
681 			PyErr_NoMemory();
682 			talloc_free(tmp_ctx);
683 			return NULL;
684 		}
685 
686 		el->name = ldap_display_name;
687 		el->num_values = PyList_Size(el_list);
688 
689 		el->values = talloc_array(el, struct ldb_val, el->num_values);
690 		if (el->values == NULL) {
691 			PyErr_NoMemory();
692 			talloc_free(tmp_ctx);
693 			return NULL;
694 		}
695 
696 		for (i = 0; i < el->num_values; i++) {
697 			PyObject *item = PyList_GetItem(el_list, i);
698 			if (!PyBytes_Check(item)) {
699 				PyErr_Format(PyExc_TypeError,
700 					     "ldif_element type should be "
701 					     PY_DESC_PY3_BYTES
702 					     );
703 				talloc_free(tmp_ctx);
704 				return NULL;
705 			}
706 			el->values[i].data = (uint8_t *)PyBytes_AsString(item);
707 			el->values[i].length = PyBytes_Size(item);
708 		}
709 	}
710 
711 	new_el = talloc_zero(tmp_ctx, struct ldb_message_element);
712 	if (new_el == NULL) {
713 		PyErr_NoMemory();
714 		talloc_free(tmp_ctx);
715 		return NULL;
716 	}
717 
718 	/* Normalise "objectClass" attribute if needed */
719 	if (ldb_attr_cmp(a->lDAPDisplayName, "objectClass") == 0) {
720 		int iret;
721 		iret = dsdb_sort_objectClass_attr(ldb, schema, el, new_el, new_el);
722 		if (iret != LDB_SUCCESS) {
723 			PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
724 			talloc_free(tmp_ctx);
725 			return NULL;
726 		}
727 	}
728 
729 	/* first run ldb_to_drsuapi, then convert back again. This has
730 	 * the effect of normalising the attributes
731 	 */
732 
733 	attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
734 	if (attr == NULL) {
735 		PyErr_NoMemory();
736 		talloc_free(tmp_ctx);
737 		return NULL;
738 	}
739 
740 	werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
741 	PyErr_WERROR_NOT_OK_RAISE(werr);
742 
743 	/* now convert back again */
744 	werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, new_el, new_el);
745 	PyErr_WERROR_NOT_OK_RAISE(werr);
746 
747 	module = PyImport_ImportModule("ldb");
748 	if (module == NULL) {
749 		return NULL;
750 	}
751 
752 	py_type = (PyTypeObject *)PyObject_GetAttrString(module, "MessageElement");
753 	if (py_type == NULL) {
754 		Py_DECREF(module);
755 		return NULL;
756 	}
757 
758 	Py_CLEAR(module);
759 
760 	py_ret = py_type->tp_alloc(py_type, 0);
761 	Py_CLEAR(py_type);
762 	if (py_ret == NULL) {
763 		PyErr_NoMemory();
764 		return NULL;
765 	}
766 	ret = (PyLdbMessageElementObject *)py_ret;
767 
768 	ret->mem_ctx = talloc_new(NULL);
769 	if (talloc_reference(ret->mem_ctx, new_el) == NULL) {
770 		Py_CLEAR(py_ret);
771 		PyErr_NoMemory();
772 		return NULL;
773 	}
774 	ret->el = new_el;
775 
776 	talloc_free(tmp_ctx);
777 
778 	return py_ret;
779 }
780 
781 
782 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
783 {
784 	PyObject *py_ldb, *py_guid;
785 	bool ret;
786 	struct GUID guid;
787 	struct ldb_context *ldb;
788 	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
789 		return NULL;
790 
791 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
792 	GUID_from_string(PyUnicode_AsUTF8(py_guid), &guid);
793 
794 	if (GUID_all_zero(&guid)) {
795 		PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id rejected due to all-zero invocation ID");
796 		return NULL;
797 	}
798 
799 	ret = samdb_set_ntds_invocation_id(ldb, &guid);
800 	if (!ret) {
801 		PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
802 		return NULL;
803 	}
804 	Py_RETURN_NONE;
805 }
806 
807 static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
808 {
809 	PyObject *py_ldb, *result;
810 	struct ldb_context *ldb;
811 	const struct GUID *guid;
812 	char *retstr;
813 
814 	if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
815 		return NULL;
816 	}
817 
818 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
819 
820 	guid = samdb_ntds_objectGUID(ldb);
821 	if (guid == NULL) {
822 		PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
823 		return NULL;
824 	}
825 
826 	retstr = GUID_string(NULL, guid);
827 	if (retstr == NULL) {
828 		PyErr_NoMemory();
829 		return NULL;
830 	}
831 	result = PyUnicode_FromString(retstr);
832 	talloc_free(retstr);
833 	return result;
834 }
835 
836 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
837 {
838 	PyObject *py_ldb;
839 	struct ldb_context *ldb;
840 	int ret;
841 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
842 		return NULL;
843 
844 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
845 
846 	ret = dsdb_set_global_schema(ldb);
847 	PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
848 
849 	Py_RETURN_NONE;
850 }
851 
852 static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
853 {
854 	PyObject *py_dn, *py_ldb, *result;
855 	struct ldb_dn *dn;
856 	uint64_t highest_uSN, urgent_uSN;
857 	struct ldb_context *ldb;
858 	TALLOC_CTX *mem_ctx;
859 	int ret;
860 
861 	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
862 		return NULL;
863 	}
864 
865 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
866 
867 	mem_ctx = talloc_new(NULL);
868 	if (mem_ctx == NULL) {
869 		PyErr_NoMemory();
870 		return NULL;
871 	}
872 
873 	if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb, &dn)) {
874 		talloc_free(mem_ctx);
875 		return NULL;
876 	}
877 
878 	ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
879 	if (ret != LDB_SUCCESS) {
880 	   PyErr_Format(PyExc_RuntimeError,
881 			"Failed to load partition [%s] uSN - %s",
882 			ldb_dn_get_linearized(dn),
883 			ldb_errstring(ldb));
884 	   talloc_free(mem_ctx);
885 	   return NULL;
886 	}
887 
888 	talloc_free(mem_ctx);
889 
890 	result = Py_BuildValue(
891 			"{s:l, s:l}",
892 			"uSNHighest", (uint64_t)highest_uSN,
893 			"uSNUrgent", (uint64_t)urgent_uSN);
894 
895 	return result;
896 }
897 
898 static PyObject *py_dsdb_set_am_rodc(PyObject *self, PyObject *args)
899 {
900 	PyObject *py_ldb;
901 	bool ret;
902 	struct ldb_context *ldb;
903 	int py_val;
904 
905 	if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &py_val))
906 		return NULL;
907 
908 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
909 	ret = samdb_set_am_rodc(ldb, (bool)py_val);
910 	if (!ret) {
911 		PyErr_SetString(PyExc_RuntimeError, "set_am_rodc failed");
912 		return NULL;
913 	}
914 	Py_RETURN_NONE;
915 }
916 
917 static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
918 {
919 	WERROR result;
920 	char *pf, *df, *dn;
921 	PyObject *py_ldb;
922 	struct ldb_context *ldb;
923 
924 	if (!PyArg_ParseTuple(args, "Osss", &py_ldb, &pf, &df, &dn))
925 		return NULL;
926 
927 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
928 
929 	result = dsdb_set_schema_from_ldif(ldb, pf, df, dn);
930 	PyErr_WERROR_NOT_OK_RAISE(result);
931 
932 	Py_RETURN_NONE;
933 }
934 
935 static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
936 {
937 	PyObject *py_ldb;
938 	struct ldb_context *ldb;
939 	PyObject *py_from_ldb;
940 	struct ldb_context *from_ldb;
941 	struct dsdb_schema *schema;
942 	int ret;
943 	char write_indices_and_attributes = SCHEMA_WRITE;
944 	if (!PyArg_ParseTuple(args, "OO|b",
945 			      &py_ldb, &py_from_ldb, &write_indices_and_attributes))
946 		return NULL;
947 
948 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
949 
950 	PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
951 
952 	schema = dsdb_get_schema(from_ldb, NULL);
953 	if (!schema) {
954 		PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
955 		return NULL;
956 	}
957 
958 	ret = dsdb_reference_schema(ldb, schema, write_indices_and_attributes);
959 	PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
960 
961 	Py_RETURN_NONE;
962 }
963 
964 static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
965 {
966 	PyObject *py_ldb;
967 	struct ldb_context *ldb;
968 	WERROR result;
969 	struct dsdb_schema *schema;
970 
971 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
972 		return NULL;
973 
974 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
975 
976 	schema = dsdb_get_schema(ldb, NULL);
977 	if (!schema) {
978 		PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
979 		return NULL;
980 	}
981 
982 	result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
983 	PyErr_WERROR_NOT_OK_RAISE(result);
984 
985 	Py_RETURN_NONE;
986 }
987 
988 
989 static PyObject *py_dsdb_get_partitions_dn(PyObject *self, PyObject *args)
990 {
991 	struct ldb_context *ldb;
992 	struct ldb_dn *dn;
993 	PyObject *py_ldb, *ret;
994 
995 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
996 		return NULL;
997 
998 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
999 
1000 	dn = samdb_partitions_dn(ldb, NULL);
1001 	if (dn == NULL) {
1002 		PyErr_NoMemory();
1003 		return NULL;
1004 	}
1005 	ret = pyldb_Dn_FromDn(dn);
1006 	talloc_free(dn);
1007 	return ret;
1008 }
1009 
1010 
1011 static PyObject *py_dsdb_get_nc_root(PyObject *self, PyObject *args)
1012 {
1013 	struct ldb_context *ldb;
1014 	struct ldb_dn *dn, *nc_root;
1015 	PyObject *py_ldb, *py_ldb_dn, *py_nc_root;
1016 	int ret;
1017 
1018 	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_ldb_dn))
1019 		return NULL;
1020 
1021 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1022 	PyErr_LDB_DN_OR_RAISE(py_ldb_dn, dn);
1023 
1024 	ret = dsdb_find_nc_root(ldb, ldb, dn, &nc_root);
1025 	PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
1026 
1027 	py_nc_root = pyldb_Dn_FromDn(nc_root);
1028 	talloc_unlink(ldb, nc_root);
1029 	return py_nc_root;
1030 }
1031 
1032 static PyObject *py_dsdb_get_wellknown_dn(PyObject *self, PyObject *args)
1033 {
1034 	struct ldb_context *ldb;
1035 	struct ldb_dn *nc_dn, *wk_dn;
1036 	char *wkguid;
1037 	PyObject *py_ldb, *py_nc_dn, *py_wk_dn;
1038 	int ret;
1039 
1040 	if (!PyArg_ParseTuple(args, "OOs", &py_ldb, &py_nc_dn, &wkguid))
1041 		return NULL;
1042 
1043 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1044 	PyErr_LDB_DN_OR_RAISE(py_nc_dn, nc_dn);
1045 
1046 	ret = dsdb_wellknown_dn(ldb, ldb, nc_dn, wkguid, &wk_dn);
1047 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1048 		PyErr_Format(PyExc_KeyError, "Failed to find well known DN for GUID %s", wkguid);
1049 		return NULL;
1050 	}
1051 
1052 	PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
1053 
1054 	py_wk_dn = pyldb_Dn_FromDn(wk_dn);
1055 	talloc_unlink(ldb, wk_dn);
1056 	return py_wk_dn;
1057 }
1058 
1059 
1060 /*
1061   call into samdb_rodc()
1062  */
1063 static PyObject *py_dsdb_am_rodc(PyObject *self, PyObject *args)
1064 {
1065 	PyObject *py_ldb;
1066 	struct ldb_context *ldb;
1067 	int ret;
1068 	bool am_rodc;
1069 
1070 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
1071 		return NULL;
1072 
1073 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1074 
1075 	ret = samdb_rodc(ldb, &am_rodc);
1076 	if (ret != LDB_SUCCESS) {
1077 		PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
1078 		return NULL;
1079 	}
1080 
1081 	return PyBool_FromLong(am_rodc);
1082 }
1083 
1084 /*
1085   call into samdb_is_pdc()
1086  */
1087 static PyObject *py_dsdb_am_pdc(PyObject *self, PyObject *args)
1088 {
1089 	PyObject *py_ldb;
1090 	struct ldb_context *ldb;
1091 	bool am_pdc;
1092 
1093 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
1094 		return NULL;
1095 
1096 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1097 
1098 	am_pdc = samdb_is_pdc(ldb);
1099 	return PyBool_FromLong(am_pdc);
1100 }
1101 
1102 /*
1103   call DSDB_EXTENDED_CREATE_OWN_RID_SET to get a new RID set for this server
1104  */
1105 static PyObject *py_dsdb_create_own_rid_set(PyObject *self, PyObject *args)
1106 {
1107 	PyObject *py_ldb;
1108 	struct ldb_context *ldb;
1109 	int ret;
1110 	struct ldb_result *ext_res;
1111 
1112 	if (!PyArg_ParseTuple(args, "O", &py_ldb))
1113 		return NULL;
1114 
1115 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1116 
1117 	/*
1118 	 * Run DSDB_EXTENDED_CREATE_OWN_RID_SET to get a RID set
1119 	 */
1120 
1121 	ret = ldb_extended(ldb, DSDB_EXTENDED_CREATE_OWN_RID_SET, NULL, &ext_res);
1122 
1123 	PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
1124 
1125 	TALLOC_FREE(ext_res);
1126 
1127 	Py_RETURN_NONE;
1128 }
1129 
1130 /*
1131   call DSDB_EXTENDED_ALLOCATE_RID to get a new RID set for this server
1132  */
1133 static PyObject *py_dsdb_allocate_rid(PyObject *self, PyObject *args)
1134 {
1135 	PyObject *py_ldb;
1136 	struct ldb_context *ldb;
1137 	int ret;
1138 	uint32_t rid;
1139 	struct ldb_result *ext_res = NULL;
1140 	struct dsdb_extended_allocate_rid *rid_return = NULL;
1141 	if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
1142 		return NULL;
1143 	}
1144 
1145 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1146 
1147 	rid_return = talloc_zero(ldb, struct dsdb_extended_allocate_rid);
1148 	if (rid_return == NULL) {
1149 		return PyErr_NoMemory();
1150 	}
1151 
1152 	/*
1153 	 * Run DSDB_EXTENDED_ALLOCATE_RID to get a new RID
1154 	 */
1155 
1156 	ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID, rid_return, &ext_res);
1157 	if (ret != LDB_SUCCESS) {
1158 		TALLOC_FREE(rid_return);
1159 		TALLOC_FREE(ext_res);
1160 		PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
1161 	}
1162 
1163 	rid = rid_return->rid;
1164 	TALLOC_FREE(rid_return);
1165 	TALLOC_FREE(ext_res);
1166 
1167 	return PyInt_FromLong(rid);
1168 }
1169 
1170 static PyObject *py_dns_delete_tombstones(PyObject *self, PyObject *args)
1171 {
1172 	PyObject *py_ldb;
1173 	NTSTATUS status;
1174 	struct ldb_context *ldb = NULL;
1175 	TALLOC_CTX *mem_ctx = NULL;
1176 	char *error_string = NULL;
1177 
1178 	if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
1179 		return NULL;
1180 	}
1181 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1182 
1183 	mem_ctx = talloc_new(ldb);
1184 	if (mem_ctx == NULL) {
1185 		return PyErr_NoMemory();
1186 	}
1187 
1188 	status = dns_delete_tombstones(mem_ctx, ldb, &error_string);
1189 
1190 	if (!NT_STATUS_IS_OK(status)) {
1191 		if (error_string) {
1192 			PyErr_Format(PyExc_RuntimeError, "%s", error_string);
1193 		} else {
1194 			PyErr_SetNTSTATUS(status);
1195 		}
1196 		TALLOC_FREE(mem_ctx);
1197 		return NULL;
1198 	}
1199 
1200 	TALLOC_FREE(mem_ctx);
1201 	Py_RETURN_NONE;
1202 }
1203 
1204 static PyObject *py_scavenge_dns_records(PyObject *self, PyObject *args)
1205 {
1206 	PyObject *py_ldb;
1207 	NTSTATUS status;
1208 	struct ldb_context *ldb = NULL;
1209 	TALLOC_CTX *mem_ctx = NULL;
1210 	char *error_string = NULL;
1211 
1212 	if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
1213 		return NULL;
1214 	}
1215 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1216 
1217 	mem_ctx = talloc_new(ldb);
1218 	if (mem_ctx == NULL) {
1219 		return PyErr_NoMemory();
1220 	}
1221 
1222 	status = dns_tombstone_records(mem_ctx, ldb, &error_string);
1223 
1224 	if (!NT_STATUS_IS_OK(status)) {
1225 		if (error_string) {
1226 			PyErr_Format(PyExc_RuntimeError, "%s", error_string);
1227 		} else {
1228 			PyErr_SetNTSTATUS(status);
1229 		}
1230 		TALLOC_FREE(mem_ctx);
1231 		return NULL;
1232 	}
1233 
1234 	TALLOC_FREE(mem_ctx);
1235 	Py_RETURN_NONE;
1236 }
1237 
1238 static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *args)
1239 {
1240 	PyObject *py_ldb, *py_list_dn;
1241 	struct ldb_context *ldb = NULL;
1242         Py_ssize_t i;
1243         Py_ssize_t length;
1244 	long long _current_time, _tombstone_lifetime = LLONG_MAX;
1245 	uint32_t tombstone_lifetime32;
1246 	struct dsdb_ldb_dn_list_node *part = NULL;
1247 	time_t current_time, tombstone_lifetime;
1248 	TALLOC_CTX *mem_ctx = NULL;
1249 	NTSTATUS status;
1250 	unsigned int num_objects_removed = 0;
1251 	unsigned int num_links_removed = 0;
1252 	char *error_string = NULL;
1253 
1254 	if (!PyArg_ParseTuple(args, "OOL|L", &py_ldb,
1255 			      &py_list_dn, &_current_time, &_tombstone_lifetime)) {
1256 		return NULL;
1257 	}
1258 
1259 
1260 	PyErr_LDB_OR_RAISE(py_ldb, ldb);
1261 
1262 	mem_ctx = talloc_new(ldb);
1263 	if (mem_ctx == NULL) {
1264 		return PyErr_NoMemory();
1265 	}
1266 
1267 	current_time = _current_time;
1268 
1269 	if (_tombstone_lifetime == LLONG_MAX) {
1270 		int ret = dsdb_tombstone_lifetime(ldb, &tombstone_lifetime32);
1271 		if (ret != LDB_SUCCESS) {
1272 			PyErr_Format(PyExc_RuntimeError,
1273 				     "Failed to get tombstone lifetime: %s",
1274 				     ldb_errstring(ldb));
1275 			TALLOC_FREE(mem_ctx);
1276 			return NULL;
1277 		}
1278 		tombstone_lifetime = tombstone_lifetime32;
1279 	} else {
1280 		tombstone_lifetime = _tombstone_lifetime;
1281 	}
1282 
1283 	if (!PyList_Check(py_list_dn)) {
1284 		PyErr_SetString(PyExc_TypeError, "A list of DNs were expected");
1285 		TALLOC_FREE(mem_ctx);
1286 		return NULL;
1287 	}
1288 
1289 	length = PyList_GET_SIZE(py_list_dn);
1290 
1291 	for (i = 0; i < length; i++) {
1292 		const char *part_str = PyUnicode_AsUTF8(PyList_GetItem(py_list_dn, i));
1293 		struct ldb_dn *p;
1294 		struct dsdb_ldb_dn_list_node *node;
1295 
1296 		if (part_str == NULL) {
1297 			TALLOC_FREE(mem_ctx);
1298 			return PyErr_NoMemory();
1299 		}
1300 
1301 		p = ldb_dn_new(mem_ctx, ldb, part_str);
1302 		if (p == NULL) {
1303 			PyErr_Format(PyExc_RuntimeError, "Failed to parse DN %s", part_str);
1304 			TALLOC_FREE(mem_ctx);
1305 			return NULL;
1306 		}
1307 		node = talloc_zero(mem_ctx, struct dsdb_ldb_dn_list_node);
1308 		node->dn = p;
1309 
1310 		DLIST_ADD_END(part, node);
1311 	}
1312 
1313 	status = dsdb_garbage_collect_tombstones(mem_ctx, ldb,
1314 						 part, current_time,
1315 						 tombstone_lifetime,
1316 						 &num_objects_removed,
1317 						 &num_links_removed,
1318 						 &error_string);
1319 
1320 	if (!NT_STATUS_IS_OK(status)) {
1321 		if (error_string) {
1322 			PyErr_Format(PyExc_RuntimeError, "%s", error_string);
1323 		} else {
1324 			PyErr_SetNTSTATUS(status);
1325 		}
1326 		TALLOC_FREE(mem_ctx);
1327 		return NULL;
1328 	}
1329 
1330 	TALLOC_FREE(mem_ctx);
1331 
1332 	return Py_BuildValue("(II)", num_objects_removed,
1333 			    num_links_removed);
1334 }
1335 
1336 static PyObject *py_dsdb_load_udv_v2(PyObject *self, PyObject *args)
1337 {
1338 	uint32_t count;
1339 	int ret, i;
1340 	bool ok;
1341 	PyObject *py_ldb = NULL, *py_dn = NULL, *pylist = NULL;
1342 	struct ldb_context *samdb = NULL;
1343 	struct ldb_dn *dn = NULL;
1344 	struct drsuapi_DsReplicaCursor2 *cursors = NULL;
1345 	TALLOC_CTX *tmp_ctx = NULL;
1346 
1347 	if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
1348 		return NULL;
1349 	}
1350 
1351 	PyErr_LDB_OR_RAISE(py_ldb, samdb);
1352 
1353 	tmp_ctx = talloc_new(samdb);
1354 	if (tmp_ctx == NULL) {
1355 		return PyErr_NoMemory();
1356 	}
1357 
1358 	ok = pyldb_Object_AsDn(tmp_ctx, py_dn, samdb, &dn);
1359 	if (!ok) {
1360 		TALLOC_FREE(tmp_ctx);
1361 		return NULL;
1362 	}
1363 
1364 	ret = dsdb_load_udv_v2(samdb, dn, tmp_ctx, &cursors, &count);
1365 	if (ret != LDB_SUCCESS) {
1366 		TALLOC_FREE(tmp_ctx);
1367 		PyErr_SetString(PyExc_RuntimeError,
1368 				"Failed to load udv from ldb");
1369 		return NULL;
1370 	}
1371 
1372 	pylist = PyList_New(count);
1373 	if (pylist == NULL) {
1374 		TALLOC_FREE(tmp_ctx);
1375 		return PyErr_NoMemory();
1376 	}
1377 
1378 	for (i = 0; i < count; i++) {
1379 		PyObject *py_cursor;
1380 		struct drsuapi_DsReplicaCursor2 *cursor;
1381 		cursor = talloc(tmp_ctx, struct drsuapi_DsReplicaCursor2);
1382 		if (cursor == NULL) {
1383 			TALLOC_FREE(tmp_ctx);
1384 			return PyErr_NoMemory();
1385 		}
1386 		*cursor = cursors[i];
1387 
1388 		py_cursor = py_return_ndr_struct("samba.dcerpc.drsuapi",
1389 						 "DsReplicaCursor2",
1390 						 cursor, cursor);
1391 		if (py_cursor == NULL) {
1392 			TALLOC_FREE(tmp_ctx);
1393 			return PyErr_NoMemory();
1394 		}
1395 
1396 		PyList_SetItem(pylist, i, py_cursor);
1397 	}
1398 
1399 	TALLOC_FREE(tmp_ctx);
1400 	return pylist;
1401 }
1402 
1403 static PyMethodDef py_dsdb_methods[] = {
1404 	{ "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
1405 		METH_VARARGS, "Get the server site name as a string"},
1406 	{ "_dsdb_convert_schema_to_openldap",
1407 		(PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
1408 		"dsdb_convert_schema_to_openldap(ldb, target_str, mapping) -> str\n"
1409 		"Create an OpenLDAP schema from a schema." },
1410 	{ "_samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid,
1411 		METH_VARARGS,
1412 		"samdb_set_domain_sid(samdb, sid)\n"
1413 		"Set SID of domain to use." },
1414 	{ "_samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid,
1415 		METH_VARARGS,
1416 		"samdb_get_domain_sid(samdb)\n"
1417 		"Get SID of domain in use." },
1418 	{ "_samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id,
1419 		METH_VARARGS, "get the NTDS invocation ID GUID as a string"},
1420 	{ "_samdb_set_ntds_settings_dn", (PyCFunction)py_samdb_set_ntds_settings_dn,
1421 		METH_VARARGS,
1422 		"samdb_set_ntds_settings_dn(samdb, ntds_settings_dn)\n"
1423 		"Set NTDS Settings DN for this LDB (allows it to be set before the DB fully exists)." },
1424 	{ "_dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid,
1425 		METH_VARARGS, NULL },
1426 	{ "_dsdb_get_attid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_attid_from_lDAPDisplayName,
1427 		METH_VARARGS, NULL },
1428 	{ "_dsdb_get_syntax_oid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_syntax_oid_from_lDAPDisplayName,
1429 		METH_VARARGS, NULL },
1430 	{ "_dsdb_get_systemFlags_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_systemFlags_from_lDAPDisplayName,
1431 		METH_VARARGS, NULL },
1432 	{ "_dsdb_get_linkId_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_linkId_from_lDAPDisplayName,
1433 		METH_VARARGS, NULL },
1434 	{ "_dsdb_get_lDAPDisplayName_by_attid", (PyCFunction)py_dsdb_get_lDAPDisplayName_by_attid,
1435 		METH_VARARGS, NULL },
1436 	{ "_dsdb_get_backlink_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_backlink_from_lDAPDisplayName,
1437 		METH_VARARGS, NULL },
1438 	{ "_dsdb_set_ntds_invocation_id",
1439 		(PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
1440 		NULL },
1441 	{ "_samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID,
1442 		METH_VARARGS, "get the NTDS objectGUID as a string"},
1443 	{ "_dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema,
1444 		METH_VARARGS, NULL },
1445 	{ "_dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn,
1446 		METH_VARARGS,
1447 		"get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
1448 	{ "_dsdb_set_am_rodc",
1449 		(PyCFunction)py_dsdb_set_am_rodc, METH_VARARGS,
1450 		NULL },
1451 	{ "_am_rodc",
1452 		(PyCFunction)py_dsdb_am_rodc, METH_VARARGS,
1453 		NULL },
1454 	{ "_am_pdc",
1455 		(PyCFunction)py_dsdb_am_pdc, METH_VARARGS,
1456 		NULL },
1457 	{ "_dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
1458 		NULL },
1459 	{ "_dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
1460 		NULL },
1461 	{ "_dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
1462 		NULL },
1463 	{ "_dsdb_get_partitions_dn", (PyCFunction)py_dsdb_get_partitions_dn, METH_VARARGS, NULL },
1464 	{ "_dsdb_get_nc_root", (PyCFunction)py_dsdb_get_nc_root, METH_VARARGS, NULL },
1465 	{ "_dsdb_get_wellknown_dn", (PyCFunction)py_dsdb_get_wellknown_dn, METH_VARARGS, NULL },
1466 	{ "_dsdb_DsReplicaAttribute", (PyCFunction)py_dsdb_DsReplicaAttribute, METH_VARARGS, NULL },
1467 	{ "_dsdb_normalise_attributes", (PyCFunction)py_dsdb_normalise_attributes, METH_VARARGS, NULL },
1468 	{ "_dsdb_garbage_collect_tombstones", (PyCFunction)py_dsdb_garbage_collect_tombstones, METH_VARARGS,
1469 		"_dsdb_kcc_check_deleted(samdb, [dn], current_time, tombstone_lifetime)"
1470 		" -> (num_objects_expunged, num_links_expunged)" },
1471 	{ "_scavenge_dns_records", (PyCFunction)py_scavenge_dns_records,
1472 		METH_VARARGS, NULL},
1473 	{ "_dns_delete_tombstones", (PyCFunction)py_dns_delete_tombstones,
1474 		METH_VARARGS, NULL},
1475 	{ "_dsdb_create_own_rid_set", (PyCFunction)py_dsdb_create_own_rid_set, METH_VARARGS,
1476 		"_dsdb_create_own_rid_set(samdb)"
1477 		" -> None" },
1478 	{ "_dsdb_allocate_rid", (PyCFunction)py_dsdb_allocate_rid, METH_VARARGS,
1479 		"_dsdb_allocate_rid(samdb)"
1480 		" -> RID" },
1481 	{ "_dsdb_load_udv_v2", (PyCFunction)py_dsdb_load_udv_v2, METH_VARARGS, NULL },
1482 	{ NULL }
1483 };
1484 
1485 static struct PyModuleDef moduledef = {
1486     PyModuleDef_HEAD_INIT,
1487     .m_name = "dsdb",
1488     .m_doc = "Python bindings for the directory service databases.",
1489     .m_size = -1,
1490     .m_methods = py_dsdb_methods,
1491 };
1492 
1493 MODULE_INIT_FUNC(dsdb)
1494 {
1495 	PyObject *m;
1496 
1497 	m = PyModule_Create(&moduledef);
1498 
1499 	if (m == NULL)
1500 		return NULL;
1501 
1502 #define ADD_DSDB_FLAG(val)  PyModule_AddObject(m, #val, PyInt_FromLong(val))
1503 
1504 	/* "userAccountControl" flags */
1505 	ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
1506 	ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
1507 	ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
1508 	ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
1509 	ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
1510 	ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
1511 	ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
1512 
1513 	ADD_DSDB_FLAG(UF_SCRIPT);
1514 	ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
1515 	ADD_DSDB_FLAG(UF_00000004);
1516 	ADD_DSDB_FLAG(UF_HOMEDIR_REQUIRED);
1517 	ADD_DSDB_FLAG(UF_LOCKOUT);
1518 	ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
1519 	ADD_DSDB_FLAG(UF_PASSWD_CANT_CHANGE);
1520 	ADD_DSDB_FLAG(UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED);
1521 	ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
1522 	ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
1523 	ADD_DSDB_FLAG(UF_00000400);
1524 	ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
1525 	ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
1526 	ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
1527 	ADD_DSDB_FLAG(UF_00004000);
1528 	ADD_DSDB_FLAG(UF_00008000);
1529 	ADD_DSDB_FLAG(UF_DONT_EXPIRE_PASSWD);
1530 	ADD_DSDB_FLAG(UF_MNS_LOGON_ACCOUNT);
1531 	ADD_DSDB_FLAG(UF_SMARTCARD_REQUIRED);
1532 	ADD_DSDB_FLAG(UF_TRUSTED_FOR_DELEGATION);
1533 	ADD_DSDB_FLAG(UF_NOT_DELEGATED);
1534 	ADD_DSDB_FLAG(UF_USE_DES_KEY_ONLY);
1535 	ADD_DSDB_FLAG(UF_DONT_REQUIRE_PREAUTH);
1536 	ADD_DSDB_FLAG(UF_PASSWORD_EXPIRED);
1537 	ADD_DSDB_FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION);
1538 	ADD_DSDB_FLAG(UF_NO_AUTH_DATA_REQUIRED);
1539 	ADD_DSDB_FLAG(UF_PARTIAL_SECRETS_ACCOUNT);
1540 	ADD_DSDB_FLAG(UF_USE_AES_KEYS);
1541 
1542 	/* groupType flags */
1543 	ADD_DSDB_FLAG(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP);
1544 	ADD_DSDB_FLAG(GTYPE_SECURITY_GLOBAL_GROUP);
1545 	ADD_DSDB_FLAG(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1546 	ADD_DSDB_FLAG(GTYPE_SECURITY_UNIVERSAL_GROUP);
1547 	ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_GLOBAL_GROUP);
1548 	ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP);
1549 	ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP);
1550 
1551 	/* "sAMAccountType" flags */
1552 	ADD_DSDB_FLAG(ATYPE_NORMAL_ACCOUNT);
1553 	ADD_DSDB_FLAG(ATYPE_WORKSTATION_TRUST);
1554 	ADD_DSDB_FLAG(ATYPE_INTERDOMAIN_TRUST);
1555 	ADD_DSDB_FLAG(ATYPE_SECURITY_GLOBAL_GROUP);
1556 	ADD_DSDB_FLAG(ATYPE_SECURITY_LOCAL_GROUP);
1557 	ADD_DSDB_FLAG(ATYPE_SECURITY_UNIVERSAL_GROUP);
1558 	ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_GLOBAL_GROUP);
1559 	ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_LOCAL_GROUP);
1560 	ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP);
1561 
1562 	/* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
1563 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2000);
1564 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003_MIXED);
1565 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003);
1566 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008);
1567 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008_R2);
1568 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2012);
1569 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2012_R2);
1570 	ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2016);
1571 
1572         /* nc replica flags */
1573 	ADD_DSDB_FLAG(INSTANCE_TYPE_IS_NC_HEAD);
1574 	ADD_DSDB_FLAG(INSTANCE_TYPE_UNINSTANT);
1575 	ADD_DSDB_FLAG(INSTANCE_TYPE_WRITE);
1576 	ADD_DSDB_FLAG(INSTANCE_TYPE_NC_ABOVE);
1577 	ADD_DSDB_FLAG(INSTANCE_TYPE_NC_COMING);
1578 	ADD_DSDB_FLAG(INSTANCE_TYPE_NC_GOING);
1579 
1580 	/* "systemFlags" */
1581 	ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NC);
1582 	ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_DOMAIN);
1583 	ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NOT_GC_REPLICATED);
1584 	ADD_DSDB_FLAG(SYSTEM_FLAG_SCHEMA_BASE_OBJECT);
1585 	ADD_DSDB_FLAG(SYSTEM_FLAG_ATTR_IS_RDN);
1586 	ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
1587 	ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE);
1588 	ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME);
1589 	ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
1590 	ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_MOVE);
1591 	ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
1592 	ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_DELETE);
1593 
1594 	/* Kerberos encryption type constants */
1595 	ADD_DSDB_FLAG(ENC_ALL_TYPES);
1596 	ADD_DSDB_FLAG(ENC_CRC32);
1597 	ADD_DSDB_FLAG(ENC_RSA_MD5);
1598 	ADD_DSDB_FLAG(ENC_RC4_HMAC_MD5);
1599 	ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES128);
1600 	ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES256);
1601 
1602 	ADD_DSDB_FLAG(SEARCH_FLAG_ATTINDEX);
1603 	ADD_DSDB_FLAG(SEARCH_FLAG_PDNTATTINDEX);
1604 	ADD_DSDB_FLAG(SEARCH_FLAG_ANR);
1605 	ADD_DSDB_FLAG(SEARCH_FLAG_PRESERVEONDELETE);
1606 	ADD_DSDB_FLAG(SEARCH_FLAG_COPY);
1607 	ADD_DSDB_FLAG(SEARCH_FLAG_TUPLEINDEX);
1608 	ADD_DSDB_FLAG(SEARCH_FLAG_SUBTREEATTRINDEX);
1609 	ADD_DSDB_FLAG(SEARCH_FLAG_CONFIDENTIAL);
1610 	ADD_DSDB_FLAG(SEARCH_FLAG_NEVERVALUEAUDIT);
1611 	ADD_DSDB_FLAG(SEARCH_FLAG_RODC_ATTRIBUTE);
1612 
1613 	ADD_DSDB_FLAG(DS_FLAG_ATTR_NOT_REPLICATED);
1614 	ADD_DSDB_FLAG(DS_FLAG_ATTR_REQ_PARTIAL_SET_MEMBER);
1615 	ADD_DSDB_FLAG(DS_FLAG_ATTR_IS_CONSTRUCTED);
1616 
1617 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_AUTO_TOPOLOGY_DISABLED);
1618 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_TOPL_CLEANUP_DISABLED);
1619 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_TOPL_MIN_HOPS_DISABLED);
1620 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_TOPL_DETECT_STALE_DISABLED);
1621 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_INTER_SITE_AUTO_TOPOLOGY_DISABLED);
1622 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_GROUP_CACHING_ENABLED);
1623 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_FORCE_KCC_WHISTLER_BEHAVIOR);
1624 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_RAND_BH_SELECTION_DISABLED);
1625 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_SCHEDULE_HASHING_ENABLED);
1626 	ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_REDUNDANT_SERVER_TOPOLOGY_ENABLED);
1627 
1628 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_IS_GC);
1629 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL);
1630 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL);
1631 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE);
1632 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_SPN_REGISTRATION);
1633 
1634 	ADD_DSDB_FLAG(NTDSCONN_KCC_GC_TOPOLOGY);
1635 	ADD_DSDB_FLAG(NTDSCONN_KCC_RING_TOPOLOGY);
1636 	ADD_DSDB_FLAG(NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY);
1637 	ADD_DSDB_FLAG(NTDSCONN_KCC_STALE_SERVERS_TOPOLOGY);
1638 	ADD_DSDB_FLAG(NTDSCONN_KCC_OSCILLATING_CONNECTION_TOPOLOGY);
1639 	ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_GC_TOPOLOGY);
1640 	ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_TOPOLOGY);
1641 	ADD_DSDB_FLAG(NTDSCONN_KCC_SERVER_FAILOVER_TOPOLOGY);
1642 	ADD_DSDB_FLAG(NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY);
1643 	ADD_DSDB_FLAG(NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY);
1644 
1645         ADD_DSDB_FLAG(NTDSCONN_OPT_IS_GENERATED);
1646         ADD_DSDB_FLAG(NTDSCONN_OPT_TWOWAY_SYNC);
1647         ADD_DSDB_FLAG(NTDSCONN_OPT_OVERRIDE_NOTIFY_DEFAULT);
1648         ADD_DSDB_FLAG(NTDSCONN_OPT_USE_NOTIFY);
1649         ADD_DSDB_FLAG(NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION);
1650         ADD_DSDB_FLAG(NTDSCONN_OPT_USER_OWNED_SCHEDULE);
1651         ADD_DSDB_FLAG(NTDSCONN_OPT_RODC_TOPOLOGY);
1652 
1653         /* Site Link Object options */
1654         ADD_DSDB_FLAG(NTDSSITELINK_OPT_USE_NOTIFY);
1655         ADD_DSDB_FLAG(NTDSSITELINK_OPT_TWOWAY_SYNC);
1656         ADD_DSDB_FLAG(NTDSSITELINK_OPT_DISABLE_COMPRESSION);
1657 
1658 	/* GPO policy flags */
1659 	ADD_DSDB_FLAG(GPLINK_OPT_DISABLE);
1660 	ADD_DSDB_FLAG(GPLINK_OPT_ENFORCE);
1661 	ADD_DSDB_FLAG(GPO_FLAG_USER_DISABLE);
1662 	ADD_DSDB_FLAG(GPO_FLAG_MACHINE_DISABLE);
1663 	ADD_DSDB_FLAG(GPO_INHERIT);
1664 	ADD_DSDB_FLAG(GPO_BLOCK_INHERITANCE);
1665 
1666 #define ADD_DSDB_STRING(val)  PyModule_AddObject(m, #val, PyUnicode_FromString(val))
1667 
1668 	ADD_DSDB_STRING(DSDB_SYNTAX_BINARY_DN);
1669 	ADD_DSDB_STRING(DSDB_SYNTAX_STRING_DN);
1670 	ADD_DSDB_STRING(DSDB_SYNTAX_OR_NAME);
1671 	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
1672 	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
1673 	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
1674 	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
1675 	ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
1676 	ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
1677 	ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
1678 	ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
1679 	ADD_DSDB_STRING(DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
1680 	ADD_DSDB_STRING(DSDB_CONTROL_INVALID_NOT_IMPLEMENTED);
1681 
1682 	ADD_DSDB_STRING(DS_GUID_COMPUTERS_CONTAINER);
1683 	ADD_DSDB_STRING(DS_GUID_DELETED_OBJECTS_CONTAINER);
1684 	ADD_DSDB_STRING(DS_GUID_DOMAIN_CONTROLLERS_CONTAINER);
1685 	ADD_DSDB_STRING(DS_GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER);
1686 	ADD_DSDB_STRING(DS_GUID_INFRASTRUCTURE_CONTAINER);
1687 	ADD_DSDB_STRING(DS_GUID_LOSTANDFOUND_CONTAINER);
1688 	ADD_DSDB_STRING(DS_GUID_MICROSOFT_PROGRAM_DATA_CONTAINER);
1689 	ADD_DSDB_STRING(DS_GUID_NTDS_QUOTAS_CONTAINER);
1690 	ADD_DSDB_STRING(DS_GUID_PROGRAM_DATA_CONTAINER);
1691 	ADD_DSDB_STRING(DS_GUID_SYSTEMS_CONTAINER);
1692 	ADD_DSDB_STRING(DS_GUID_USERS_CONTAINER);
1693 
1694 	return m;
1695 }
1696