1 /*
2    Unix SMB/CIFS implementation.
3 
4    Python interface to ldb.
5 
6    Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
7    Copyright (C) 2006 Simo Sorce <idra@samba.org>
8    Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
9    Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
10    Copyright (C) 2009-2011 Andrew Tridgell
11    Copyright (C) 2009-2011 Andrew Bartlett
12 
13     ** NOTE! The following LGPL license applies to the ldb
14     ** library. This does NOT imply that all of Samba is released
15     ** under the LGPL
16 
17    This library is free software; you can redistribute it and/or
18    modify it under the terms of the GNU Lesser General Public
19    License as published by the Free Software Foundation; either
20    version 3 of the License, or (at your option) any later version.
21 
22    This library is distributed in the hope that it will be useful,
23    but WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25    Lesser General Public License for more details.
26 
27    You should have received a copy of the GNU Lesser General Public
28    License along with this library; if not, see <http://www.gnu.org/licenses/>.
29 */
30 
31 #include <Python.h>
32 #include "ldb_private.h"
33 #include "ldb_handlers.h"
34 #include "pyldb.h"
35 #include "dlinklist.h"
36 
37 /* discard signature of 'func' in favour of 'target_sig' */
38 #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
39 
40 struct py_ldb_search_iterator_reply;
41 
42 typedef struct {
43 	PyObject_HEAD
44 	TALLOC_CTX *mem_ctx;
45 	PyLdbObject *ldb;
46 	struct {
47 		struct ldb_request *req;
48 		struct py_ldb_search_iterator_reply *next;
49 		struct py_ldb_search_iterator_reply *result;
50 		PyObject *exception;
51 	} state;
52 } PyLdbSearchIteratorObject;
53 
54 struct py_ldb_search_iterator_reply {
55 	struct py_ldb_search_iterator_reply *prev, *next;
56 	PyLdbSearchIteratorObject *py_iter;
57 	PyObject *obj;
58 };
59 
60 void initldb(void);
61 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
62 static PyObject *PyExc_LdbError;
63 
64 static PyTypeObject PyLdbControl;
65 static PyTypeObject PyLdbResult;
66 static PyTypeObject PyLdbSearchIterator;
67 static PyTypeObject PyLdbMessage;
68 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
69 static PyTypeObject PyLdbModule;
70 static PyTypeObject PyLdbDn;
71 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
72 static PyTypeObject PyLdb;
73 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
74 static PyTypeObject PyLdbMessageElement;
75 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
76 
77 static PyTypeObject PyLdbTree;
78 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
79 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
80 static struct ldb_message_element *PyObject_AsMessageElement(
81 						      TALLOC_CTX *mem_ctx,
82 						      PyObject *set_obj,
83 						      unsigned int flags,
84 						      const char *attr_name);
85 static PyTypeObject PyLdbBytesType;
86 
87 #if PY_MAJOR_VERSION >= 3
88 #define PyInt_FromLong PyLong_FromLong
89 
90 #define PYARG_STR_UNI "es"
91 
PyLdbBytes_FromStringAndSize(const char * msg,int size)92 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
93 {
94 	PyObject* result = NULL;
95 	PyObject* args = NULL;
96 	args = Py_BuildValue("(y#)", msg, size);
97 	result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
98 	Py_DECREF(args);
99 	return result;
100 }
101 #else
102 #define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize
103 
104 #define PYARG_STR_UNI "et"
105 
106 #endif
107 
richcmp(int cmp_val,int op)108 static PyObject *richcmp(int cmp_val, int op)
109 {
110 	int ret;
111 	switch (op) {
112 		case Py_LT: ret = cmp_val < 0;  break;
113 		case Py_LE: ret = cmp_val <= 0; break;
114 		case Py_EQ: ret = cmp_val == 0; break;
115 		case Py_NE: ret = cmp_val != 0; break;
116 		case Py_GT: ret = cmp_val > 0;  break;
117 		case Py_GE: ret = cmp_val >= 0; break;
118 		default:
119 			Py_INCREF(Py_NotImplemented);
120 			return Py_NotImplemented;
121 	}
122 	return PyBool_FromLong(ret);
123 }
124 
125 
py_ldb_control_str(PyLdbControlObject * self)126 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
127 {
128 	if (self->data != NULL) {
129 		char* control = ldb_control_to_string(self->mem_ctx, self->data);
130 		if (control == NULL) {
131 			PyErr_NoMemory();
132 			return NULL;
133 		}
134 		return PyUnicode_FromString(control);
135 	} else {
136 		return PyUnicode_FromString("ldb control");
137 	}
138 }
139 
py_ldb_control_dealloc(PyLdbControlObject * self)140 static void py_ldb_control_dealloc(PyLdbControlObject *self)
141 {
142 	if (self->mem_ctx != NULL) {
143 		talloc_free(self->mem_ctx);
144 	}
145 	self->data = NULL;
146 	Py_TYPE(self)->tp_free(self);
147 }
148 
149 /* Create a text (rather than bytes) interface for a LDB result object */
wrap_text(const char * type,PyObject * wrapped)150 static PyObject *wrap_text(const char *type, PyObject *wrapped)
151 {
152 	PyObject *mod, *cls, *constructor, *inst;
153 	mod = PyImport_ImportModule("_ldb_text");
154 	if (mod == NULL)
155 		return NULL;
156 	cls = PyObject_GetAttrString(mod, type);
157 	Py_DECREF(mod);
158 	if (cls == NULL) {
159 		Py_DECREF(mod);
160 		return NULL;
161 	}
162 	constructor = PyObject_GetAttrString(cls, "_wrap");
163 	Py_DECREF(cls);
164 	if (constructor == NULL) {
165 		return NULL;
166 	}
167 	inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
168 	Py_DECREF(constructor);
169 	return inst;
170 }
171 
py_ldb_control_get_oid(PyLdbControlObject * self,PyObject * Py_UNUSED (ignored))172 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self,
173 		PyObject *Py_UNUSED(ignored))
174 {
175 	return PyUnicode_FromString(self->data->oid);
176 }
177 
py_ldb_control_get_critical(PyLdbControlObject * self,PyObject * Py_UNUSED (ignored))178 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self,
179 		PyObject *Py_UNUSED(ignored))
180 {
181 	return PyBool_FromLong(self->data->critical);
182 }
183 
py_ldb_control_set_critical(PyLdbControlObject * self,PyObject * value,void * closure)184 static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
185 {
186 	if (PyObject_IsTrue(value)) {
187 		self->data->critical = true;
188 	} else {
189 		self->data->critical = false;
190 	}
191 	return 0;
192 }
193 
py_ldb_control_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)194 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
195 {
196 	char *data = NULL;
197 	const char * const kwnames[] = { "ldb", "data", NULL };
198 	struct ldb_control *parsed_controls;
199 	PyLdbControlObject *ret;
200 	PyObject *py_ldb;
201 	TALLOC_CTX *mem_ctx;
202 	struct ldb_context *ldb_ctx;
203 
204 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
205 					 discard_const_p(char *, kwnames),
206 					 &PyLdb, &py_ldb, &data))
207 		return NULL;
208 
209 	mem_ctx = talloc_new(NULL);
210 	if (mem_ctx == NULL) {
211 		PyErr_NoMemory();
212 		return NULL;
213 	}
214 
215 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
216 	parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
217 
218 	if (!parsed_controls) {
219 		talloc_free(mem_ctx);
220 		PyErr_SetString(PyExc_ValueError, "unable to parse control string");
221 		return NULL;
222 	}
223 
224 	ret = PyObject_New(PyLdbControlObject, type);
225 	if (ret == NULL) {
226 		PyErr_NoMemory();
227 		talloc_free(mem_ctx);
228 		return NULL;
229 	}
230 
231 	ret->mem_ctx = mem_ctx;
232 
233 	ret->data = talloc_move(mem_ctx, &parsed_controls);
234 	if (ret->data == NULL) {
235 		Py_DECREF(ret);
236 		PyErr_NoMemory();
237 		talloc_free(mem_ctx);
238 		return NULL;
239 	}
240 
241 	return (PyObject *)ret;
242 }
243 
244 static PyGetSetDef py_ldb_control_getset[] = {
245 	{
246 		.name = discard_const_p(char, "oid"),
247 		.get  = (getter)py_ldb_control_get_oid,
248 	},
249 	{
250 		.name = discard_const_p(char, "critical"),
251 		.get  = (getter)py_ldb_control_get_critical,
252 		.set  = (setter)py_ldb_control_set_critical,
253 	},
254 	{ .name = NULL },
255 };
256 
257 static PyTypeObject PyLdbControl = {
258 	.tp_name = "ldb.control",
259 	.tp_dealloc = (destructor)py_ldb_control_dealloc,
260 	.tp_getattro = PyObject_GenericGetAttr,
261 	.tp_basicsize = sizeof(PyLdbControlObject),
262 	.tp_getset = py_ldb_control_getset,
263 	.tp_doc = "LDB control.",
264 	.tp_str = (reprfunc)py_ldb_control_str,
265 	.tp_new = py_ldb_control_new,
266 	.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
267 };
268 
PyErr_SetLdbError(PyObject * error,int ret,struct ldb_context * ldb_ctx)269 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
270 {
271 	if (ret == LDB_ERR_PYTHON_EXCEPTION)
272 		return; /* Python exception should already be set, just keep that */
273 
274 	PyErr_SetObject(error,
275 			Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
276 				      ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
277 }
py_ldb_bytes_str(PyBytesObject * self)278 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
279 {
280 	char *msg = NULL;
281 	Py_ssize_t size;
282 	int result = 0;
283 	if (!PyBytes_Check(self)) {
284 		PyErr_Format(PyExc_TypeError,"Unexpected type");
285 		return NULL;
286 	}
287 	result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
288 	if (result != 0) {
289 		PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
290 		return NULL;
291 	}
292 	return PyUnicode_FromStringAndSize(msg, size);
293 }
294 
295 static PyTypeObject PyLdbBytesType = {
296 	PyVarObject_HEAD_INIT(NULL, 0)
297 	.tp_name = "ldb.bytes",
298 	.tp_doc = "str/bytes (with custom str)",
299         .tp_str = (reprfunc)py_ldb_bytes_str,
300 	.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
301 };
302 
PyObject_FromLdbValue(const struct ldb_val * val)303 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
304 {
305 	return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
306 }
307 
PyStr_FromLdbValue(const struct ldb_val * val)308 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
309 {
310 	return PyUnicode_FromStringAndSize((const char *)val->data, val->length);
311 }
312 
313 /**
314  * Create a Python object from a ldb_result.
315  *
316  * @param result LDB result to convert
317  * @return Python object with converted result (a list object)
318  */
PyLdbControl_FromControl(struct ldb_control * control)319 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
320 {
321 	TALLOC_CTX *ctl_ctx = talloc_new(NULL);
322 	PyLdbControlObject *ctrl;
323 	if (ctl_ctx == NULL) {
324 		PyErr_NoMemory();
325 		return NULL;
326 	}
327 
328 	ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
329 	if (ctrl == NULL) {
330 		talloc_free(ctl_ctx);
331 		PyErr_NoMemory();
332 		return NULL;
333 	}
334 	ctrl->mem_ctx = ctl_ctx;
335 	ctrl->data = talloc_steal(ctrl->mem_ctx, control);
336 	if (ctrl->data == NULL) {
337 		Py_DECREF(ctrl);
338 		PyErr_NoMemory();
339 		return NULL;
340 	}
341 	return (PyObject*) ctrl;
342 }
343 
344 /**
345  * Create a Python object from a ldb_result.
346  *
347  * @param result LDB result to convert
348  * @return Python object with converted result (a list object)
349  */
PyLdbResult_FromResult(struct ldb_result * result)350 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
351 {
352 	PyLdbResultObject *ret;
353 	PyObject *list, *controls, *referals;
354 	Py_ssize_t i;
355 
356 	if (result == NULL) {
357 		Py_RETURN_NONE;
358 	}
359 
360 	ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
361 	if (ret == NULL) {
362 		PyErr_NoMemory();
363 		return NULL;
364 	}
365 
366 	list = PyList_New(result->count);
367 	if (list == NULL) {
368 		PyErr_NoMemory();
369 		Py_DECREF(ret);
370 		return NULL;
371 	}
372 
373 	for (i = 0; i < result->count; i++) {
374 		PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
375 	}
376 
377 	ret->mem_ctx = talloc_new(NULL);
378 	if (ret->mem_ctx == NULL) {
379 		Py_DECREF(list);
380 		Py_DECREF(ret);
381 		PyErr_NoMemory();
382 		return NULL;
383 	}
384 
385 	ret->msgs = list;
386 
387 	if (result->controls) {
388 		i = 0;
389 		while (result->controls[i]) {
390 			i++;
391 		}
392 		controls = PyList_New(i);
393 		if (controls == NULL) {
394 			Py_DECREF(ret);
395 			PyErr_NoMemory();
396 			return NULL;
397 		}
398 		for (i=0; result->controls[i]; i++) {
399 			PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
400 			if (ctrl == NULL) {
401 				Py_DECREF(ret);
402 				Py_DECREF(controls);
403 				PyErr_NoMemory();
404 				return NULL;
405 			}
406 			PyList_SetItem(controls, i, ctrl);
407 		}
408 	} else {
409 		/*
410 		 * No controls so we keep an empty list
411 		 */
412 		controls = PyList_New(0);
413 		if (controls == NULL) {
414 			Py_DECREF(ret);
415 			PyErr_NoMemory();
416 			return NULL;
417 		}
418 	}
419 
420 	ret->controls = controls;
421 
422 	i = 0;
423 
424 	while (result->refs && result->refs[i]) {
425 		i++;
426 	}
427 
428 	referals = PyList_New(i);
429 	if (referals == NULL) {
430 		Py_DECREF(ret);
431 		PyErr_NoMemory();
432 		return NULL;
433 	}
434 
435 	for (i = 0;result->refs && result->refs[i]; i++) {
436 		PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i]));
437 	}
438 	ret->referals = referals;
439 	return (PyObject *)ret;
440 }
441 
442 /**
443  * Create a LDB Result from a Python object.
444  * If conversion fails, NULL will be returned and a Python exception set.
445  *
446  * Note: the result object only includes the messages at the moment; extended
447  * result, controls and referrals are ignored.
448  *
449  * @param mem_ctx Memory context in which to allocate the LDB Result
450  * @param obj Python object to convert
451  * @return a ldb_result, or NULL if the conversion failed
452  */
PyLdbResult_AsResult(TALLOC_CTX * mem_ctx,PyObject * obj)453 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
454 					       PyObject *obj)
455 {
456 	struct ldb_result *res;
457 	Py_ssize_t i;
458 
459 	if (obj == Py_None)
460 		return NULL;
461 
462 	res = talloc_zero(mem_ctx, struct ldb_result);
463 	res->count = PyList_Size(obj);
464 	res->msgs = talloc_array(res, struct ldb_message *, res->count);
465 	for (i = 0; i < res->count; i++) {
466 		PyObject *item = PyList_GetItem(obj, i);
467 		res->msgs[i] = pyldb_Message_AsMessage(item);
468 	}
469 	return res;
470 }
471 
py_ldb_dn_validate(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))472 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self,
473 		PyObject *Py_UNUSED(ignored))
474 {
475 	return PyBool_FromLong(ldb_dn_validate(self->dn));
476 }
477 
py_ldb_dn_is_valid(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))478 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self,
479 		PyObject *Py_UNUSED(ignored))
480 {
481 	return PyBool_FromLong(ldb_dn_is_valid(self->dn));
482 }
483 
py_ldb_dn_is_special(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))484 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self,
485 		PyObject *Py_UNUSED(ignored))
486 {
487 	return PyBool_FromLong(ldb_dn_is_special(self->dn));
488 }
489 
py_ldb_dn_is_null(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))490 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self,
491 		PyObject *Py_UNUSED(ignored))
492 {
493 	return PyBool_FromLong(ldb_dn_is_null(self->dn));
494 }
495 
py_ldb_dn_get_casefold(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))496 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self,
497 		PyObject *Py_UNUSED(ignored))
498 {
499 	return PyUnicode_FromString(ldb_dn_get_casefold(self->dn));
500 }
501 
py_ldb_dn_get_linearized(PyLdbDnObject * self)502 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
503 {
504 	return PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
505 }
506 
py_ldb_dn_canonical_str(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))507 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self,
508 		PyObject *Py_UNUSED(ignored))
509 {
510 	return PyUnicode_FromString(ldb_dn_canonical_string(self->dn, self->dn));
511 }
512 
py_ldb_dn_canonical_ex_str(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))513 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self,
514 		PyObject *Py_UNUSED(ignored))
515 {
516 	return PyUnicode_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
517 }
518 
py_ldb_dn_extended_str(PyLdbDnObject * self,PyObject * args,PyObject * kwargs)519 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
520 {
521 	const char * const kwnames[] = { "mode", NULL };
522 	int mode = 1;
523 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
524 					 discard_const_p(char *, kwnames),
525 					 &mode))
526 		return NULL;
527 	return PyUnicode_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
528 }
529 
py_ldb_dn_get_extended_component(PyLdbDnObject * self,PyObject * args)530 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
531 {
532 	char *name;
533 	const struct ldb_val *val;
534 
535 	if (!PyArg_ParseTuple(args, "s", &name))
536 		return NULL;
537 	val = ldb_dn_get_extended_component(self->dn, name);
538 	if (val == NULL) {
539 		Py_RETURN_NONE;
540 	}
541 
542 	return PyBytes_FromStringAndSize((const char *)val->data, val->length);
543 }
544 
py_ldb_dn_set_extended_component(PyLdbDnObject * self,PyObject * args)545 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
546 {
547 	char *name;
548 	int err;
549 	uint8_t *value = NULL;
550 	Py_ssize_t size = 0;
551 
552 	if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
553 		return NULL;
554 
555 	if (value == NULL) {
556 		err = ldb_dn_set_extended_component(self->dn, name, NULL);
557 	} else {
558 		struct ldb_val val;
559 		val.data = (uint8_t *)value;
560 		val.length = size;
561 		err = ldb_dn_set_extended_component(self->dn, name, &val);
562 	}
563 
564 	if (err != LDB_SUCCESS) {
565 		PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
566 		return NULL;
567 	}
568 
569 	Py_RETURN_NONE;
570 }
571 
py_ldb_dn_repr(PyLdbDnObject * self)572 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
573 {
574 	PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
575 	PyObject *repr, *result;
576 	if (str == NULL)
577 		return NULL;
578 	repr = PyObject_Repr(str);
579 	if (repr == NULL) {
580 		Py_DECREF(str);
581 		return NULL;
582 	}
583 	result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr));
584 	Py_DECREF(str);
585 	Py_DECREF(repr);
586 	return result;
587 }
588 
py_ldb_dn_check_special(PyLdbDnObject * self,PyObject * args)589 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
590 {
591 	char *name;
592 
593 	if (!PyArg_ParseTuple(args, "s", &name))
594 		return NULL;
595 
596 	return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
597 }
598 
py_ldb_dn_richcmp(PyObject * dn1,PyObject * dn2,int op)599 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
600 {
601 	int ret;
602 	if (!pyldb_Dn_Check(dn2)) {
603 		Py_INCREF(Py_NotImplemented);
604 		return Py_NotImplemented;
605 	}
606 	ret = ldb_dn_compare(pyldb_Dn_AS_DN(dn1), pyldb_Dn_AS_DN(dn2));
607 	return richcmp(ret, op);
608 }
609 
py_ldb_dn_get_parent(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))610 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self,
611 		PyObject *Py_UNUSED(ignored))
612 {
613 	struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self);
614 	struct ldb_dn *parent;
615 	PyLdbDnObject *py_ret;
616 	TALLOC_CTX *mem_ctx = talloc_new(NULL);
617 
618 	parent = ldb_dn_get_parent(mem_ctx, dn);
619 	if (parent == NULL) {
620 		talloc_free(mem_ctx);
621 		Py_RETURN_NONE;
622 	}
623 
624 	py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
625 	if (py_ret == NULL) {
626 		PyErr_NoMemory();
627 		talloc_free(mem_ctx);
628 		return NULL;
629 	}
630 	py_ret->mem_ctx = mem_ctx;
631 	py_ret->dn = parent;
632 	return (PyObject *)py_ret;
633 }
634 
py_ldb_dn_add_child(PyLdbDnObject * self,PyObject * args)635 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
636 {
637 	PyObject *py_other;
638 	struct ldb_dn *dn, *other;
639 	if (!PyArg_ParseTuple(args, "O", &py_other))
640 		return NULL;
641 
642 	dn = pyldb_Dn_AS_DN((PyObject *)self);
643 
644 	if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
645 		return NULL;
646 
647 	return PyBool_FromLong(ldb_dn_add_child(dn, other));
648 }
649 
py_ldb_dn_add_base(PyLdbDnObject * self,PyObject * args)650 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
651 {
652 	PyObject *py_other;
653 	struct ldb_dn *other, *dn;
654 	if (!PyArg_ParseTuple(args, "O", &py_other))
655 		return NULL;
656 
657 	dn = pyldb_Dn_AS_DN((PyObject *)self);
658 
659 	if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
660 		return NULL;
661 
662 	return PyBool_FromLong(ldb_dn_add_base(dn, other));
663 }
664 
py_ldb_dn_remove_base_components(PyLdbDnObject * self,PyObject * args)665 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
666 {
667 	struct ldb_dn *dn;
668 	int i;
669 	if (!PyArg_ParseTuple(args, "i", &i))
670 		return NULL;
671 
672 	dn = pyldb_Dn_AS_DN((PyObject *)self);
673 
674 	return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
675 }
676 
py_ldb_dn_is_child_of(PyLdbDnObject * self,PyObject * args)677 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
678 {
679 	PyObject *py_base;
680 	struct ldb_dn *dn, *base;
681 	if (!PyArg_ParseTuple(args, "O", &py_base))
682 		return NULL;
683 
684 	dn = pyldb_Dn_AS_DN((PyObject *)self);
685 
686 	if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
687 		return NULL;
688 
689 	return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
690 }
691 
py_ldb_dn_get_component_name(PyLdbDnObject * self,PyObject * args)692 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
693 {
694 	struct ldb_dn *dn;
695 	const char *name;
696 	unsigned int num = 0;
697 
698 	if (!PyArg_ParseTuple(args, "I", &num))
699 		return NULL;
700 
701 	dn = pyldb_Dn_AS_DN((PyObject *)self);
702 
703 	name = ldb_dn_get_component_name(dn, num);
704 	if (name == NULL) {
705 		Py_RETURN_NONE;
706 	}
707 
708 	return PyUnicode_FromString(name);
709 }
710 
py_ldb_dn_get_component_value(PyLdbDnObject * self,PyObject * args)711 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
712 {
713 	struct ldb_dn *dn;
714 	const struct ldb_val *val;
715 	unsigned int num = 0;
716 
717 	if (!PyArg_ParseTuple(args, "I", &num))
718 		return NULL;
719 
720 	dn = pyldb_Dn_AS_DN((PyObject *)self);
721 
722 	val = ldb_dn_get_component_val(dn, num);
723 	if (val == NULL) {
724 		Py_RETURN_NONE;
725 	}
726 
727 	return PyStr_FromLdbValue(val);
728 }
729 
py_ldb_dn_set_component(PyLdbDnObject * self,PyObject * args)730 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
731 {
732 	unsigned int num = 0;
733 	char *name = NULL, *value = NULL;
734 	struct ldb_val val = { NULL, };
735 	int err;
736 	Py_ssize_t size = 0;
737 
738 	if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
739 		return NULL;
740 
741 	val.data = (unsigned char*) value;
742 	val.length = size;
743 
744 	err = ldb_dn_set_component(self->dn, num, name, val);
745 	if (err != LDB_SUCCESS) {
746 		PyErr_SetString(PyExc_TypeError, "Failed to set component");
747 		return NULL;
748 	}
749 
750 	Py_RETURN_NONE;
751 }
752 
py_ldb_dn_get_rdn_name(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))753 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self,
754 		PyObject *Py_UNUSED(ignored))
755 {
756 	struct ldb_dn *dn;
757 	const char *name;
758 
759 	dn = pyldb_Dn_AS_DN((PyObject *)self);
760 
761 	name = ldb_dn_get_rdn_name(dn);
762 	if (name == NULL) {
763 		Py_RETURN_NONE;
764 	}
765 
766 	return PyUnicode_FromString(name);
767 }
768 
py_ldb_dn_get_rdn_value(PyLdbDnObject * self,PyObject * Py_UNUSED (ignored))769 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self,
770 		PyObject *Py_UNUSED(ignored))
771 {
772 	struct ldb_dn *dn;
773 	const struct ldb_val *val;
774 
775 	dn = pyldb_Dn_AS_DN((PyObject *)self);
776 
777 	val = ldb_dn_get_rdn_val(dn);
778 	if (val == NULL) {
779 		Py_RETURN_NONE;
780 	}
781 
782 	return PyStr_FromLdbValue(val);
783 }
784 
785 static PyMethodDef py_ldb_dn_methods[] = {
786 	{ "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
787 		"S.validate() -> bool\n"
788 		"Validate DN is correct." },
789 	{ "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
790 		"S.is_valid() -> bool\n" },
791 	{ "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
792 		"S.is_special() -> bool\n"
793 		"Check whether this is a special LDB DN." },
794 	{ "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
795 		"Check whether this is a null DN." },
796 	{ "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
797 		NULL },
798 	{ "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction,
799 						py_ldb_dn_get_linearized),
800 		METH_NOARGS,
801 		NULL },
802 	{ "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
803 		"S.canonical_str() -> string\n"
804 		"Canonical version of this DN (like a posix path)." },
805 	{ "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
806 		"S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
807 	{ "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
808 		"S.canonical_ex_str() -> string\n"
809 		"Canonical version of this DN (like a posix path, with terminating newline)." },
810 	{ "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction,
811 					      py_ldb_dn_extended_str),
812 		METH_VARARGS | METH_KEYWORDS,
813 		"S.extended_str(mode=1) -> string\n"
814 		"Extended version of this DN" },
815 	{ "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
816    		"S.parent() -> dn\n"
817 		"Get the parent for this DN." },
818 	{ "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
819 		"S.add_child(dn) -> None\n"
820 		"Add a child DN to this DN." },
821 	{ "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
822 		"S.add_base(dn) -> None\n"
823 		"Add a base DN to this DN." },
824 	{ "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
825 		"S.remove_base_components(int) -> bool\n"
826 		"Remove a number of DN components from the base of this DN." },
827 	{ "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
828 		"S.check_special(name) -> bool\n\n"
829 		"Check if name is a special DN name"},
830 	{ "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
831 		"S.get_extended_component(name) -> string\n\n"
832 		"returns a DN extended component as a binary string"},
833 	{ "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
834 		"S.set_extended_component(name, value) -> None\n\n"
835 		"set a DN extended component as a binary string"},
836 	{ "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
837 		"S.get_component_name(num) -> string\n"
838 		"get the attribute name of the specified component" },
839 	{ "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
840 		"S.get_component_value(num) -> string\n"
841 		"get the attribute value of the specified component as a binary string" },
842 	{ "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
843 		"S.get_component_value(num, name, value) -> None\n"
844 		"set the attribute name and value of the specified component" },
845 	{ "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
846 		"S.get_rdn_name() -> string\n"
847 		"get the RDN attribute name" },
848 	{ "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
849 		"S.get_rdn_value() -> string\n"
850 		"get the RDN attribute value as a binary string" },
851 	{ NULL }
852 };
853 
py_ldb_dn_len(PyLdbDnObject * self)854 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
855 {
856 	return ldb_dn_get_comp_num(pyldb_Dn_AS_DN((PyObject *)self));
857 }
858 
859 /*
860   copy a DN as a python object
861  */
py_ldb_dn_copy(struct ldb_dn * dn)862 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
863 {
864 	PyLdbDnObject *py_ret;
865 
866 	py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
867 	if (py_ret == NULL) {
868 		PyErr_NoMemory();
869 		return NULL;
870 	}
871 	py_ret->mem_ctx = talloc_new(NULL);
872 	py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
873 	return (PyObject *)py_ret;
874 }
875 
py_ldb_dn_concat(PyLdbDnObject * self,PyObject * py_other)876 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
877 {
878 	struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self),
879 				  *other;
880 	PyLdbDnObject *py_ret;
881 
882 	if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
883 		return NULL;
884 
885 	py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
886 	if (py_ret == NULL) {
887 		PyErr_NoMemory();
888 		return NULL;
889 	}
890 	py_ret->mem_ctx = talloc_new(NULL);
891 	py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
892 	ldb_dn_add_base(py_ret->dn, other);
893 	return (PyObject *)py_ret;
894 }
895 
896 static PySequenceMethods py_ldb_dn_seq = {
897 	.sq_length = (lenfunc)py_ldb_dn_len,
898 	.sq_concat = (binaryfunc)py_ldb_dn_concat,
899 };
900 
py_ldb_dn_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)901 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
902 {
903 	struct ldb_dn *ret = NULL;
904 	char *str = NULL;
905 	PyObject *py_ldb = NULL;
906 	struct ldb_context *ldb_ctx = NULL;
907 	TALLOC_CTX *mem_ctx = NULL;
908 	PyLdbDnObject *py_ret = NULL;
909 	const char * const kwnames[] = { "ldb", "dn", NULL };
910 
911 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI,
912 					 discard_const_p(char *, kwnames),
913 					 &py_ldb, "utf8", &str))
914 		goto out;
915 
916 	if (!PyLdb_Check(py_ldb)) {
917 		PyErr_SetString(PyExc_TypeError, "Expected Ldb");
918 		goto out;
919 	}
920 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
921 
922 	mem_ctx = talloc_new(NULL);
923 	if (mem_ctx == NULL) {
924 		PyErr_NoMemory();
925 		goto out;
926 	}
927 
928 	ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
929 	if (!ldb_dn_validate(ret)) {
930 		talloc_free(mem_ctx);
931 		PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
932 		goto out;
933 	}
934 
935 	py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
936 	if (py_ret == NULL) {
937 		talloc_free(mem_ctx);
938 		PyErr_NoMemory();
939 		goto out;
940 	}
941 	py_ret->mem_ctx = mem_ctx;
942 	py_ret->dn = ret;
943 out:
944 	if (str != NULL) {
945 		PyMem_Free(discard_const_p(char, str));
946 	}
947 	return (PyObject *)py_ret;
948 }
949 
py_ldb_dn_dealloc(PyLdbDnObject * self)950 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
951 {
952 	talloc_free(self->mem_ctx);
953 	PyObject_Del(self);
954 }
955 
956 static PyTypeObject PyLdbDn = {
957 	.tp_name = "ldb.Dn",
958 	.tp_methods = py_ldb_dn_methods,
959 	.tp_str = (reprfunc)py_ldb_dn_get_linearized,
960 	.tp_repr = (reprfunc)py_ldb_dn_repr,
961 	.tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
962 	.tp_as_sequence = &py_ldb_dn_seq,
963 	.tp_doc = "A LDB distinguished name.",
964 	.tp_new = py_ldb_dn_new,
965 	.tp_dealloc = (destructor)py_ldb_dn_dealloc,
966 	.tp_basicsize = sizeof(PyLdbDnObject),
967 	.tp_flags = Py_TPFLAGS_DEFAULT,
968 };
969 
970 /* Debug */
971 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
py_ldb_debug(void * context,enum ldb_debug_level level,const char * fmt,va_list ap)972 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
973 {
974 	PyObject *fn = (PyObject *)context;
975 	PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap));
976 }
977 
978 static PyObject *py_ldb_debug_func;
979 
py_ldb_set_debug(PyObject * self,PyObject * args)980 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
981 {
982 	PyObject *cb;
983 	struct ldb_context *ldb_ctx;
984 
985 	if (!PyArg_ParseTuple(args, "O", &cb))
986 		return NULL;
987 
988 	if (py_ldb_debug_func != NULL) {
989 		Py_DECREF(py_ldb_debug_func);
990 	}
991 
992 	Py_INCREF(cb);
993 	/* FIXME: DECREF cb when exiting program */
994 	py_ldb_debug_func = cb;
995 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
996 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
997 		ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
998 		ldb_ctx);
999 
1000 	Py_RETURN_NONE;
1001 }
1002 
py_ldb_set_create_perms(PyTypeObject * self,PyObject * args)1003 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
1004 {
1005 	unsigned int perms;
1006 	if (!PyArg_ParseTuple(args, "I", &perms))
1007 		return NULL;
1008 
1009 	ldb_set_create_perms(pyldb_Ldb_AS_LDBCONTEXT(self), perms);
1010 
1011 	Py_RETURN_NONE;
1012 }
1013 
py_ldb_set_modules_dir(PyTypeObject * self,PyObject * args)1014 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1015 {
1016 	char *modules_dir;
1017 	if (!PyArg_ParseTuple(args, "s", &modules_dir))
1018 		return NULL;
1019 
1020 	ldb_set_modules_dir(pyldb_Ldb_AS_LDBCONTEXT(self), modules_dir);
1021 
1022 	Py_RETURN_NONE;
1023 }
1024 
py_ldb_transaction_start(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1025 static PyObject *py_ldb_transaction_start(PyLdbObject *self,
1026 		PyObject *Py_UNUSED(ignored))
1027 {
1028 	struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1029 	int ldb_err;
1030 	ldb_err = ldb_transaction_start(ldb_ctx);
1031 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1032 	Py_RETURN_NONE;
1033 }
1034 
py_ldb_transaction_commit(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1035 static PyObject *py_ldb_transaction_commit(PyLdbObject *self,
1036 		PyObject *Py_UNUSED(ignored))
1037 {
1038 	struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1039 	int ldb_err;
1040 	ldb_err = ldb_transaction_commit(ldb_ctx);
1041 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1042 	Py_RETURN_NONE;
1043 }
1044 
py_ldb_transaction_prepare_commit(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1045 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self,
1046 		PyObject *Py_UNUSED(ignored))
1047 {
1048 	struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1049 	int ldb_err;
1050 	ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1051 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1052 	Py_RETURN_NONE;
1053 }
1054 
py_ldb_transaction_cancel(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1055 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self,
1056 		PyObject *Py_UNUSED(ignored))
1057 {
1058 	struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1059 	int ldb_err;
1060 	ldb_err = ldb_transaction_cancel(ldb_ctx);
1061 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1062 	Py_RETURN_NONE;
1063 }
1064 
py_ldb_setup_wellknown_attributes(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1065 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self,
1066 		PyObject *Py_UNUSED(ignored))
1067 {
1068 	struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1069 	int ldb_err;
1070 	ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1071 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1072 	Py_RETURN_NONE;
1073 }
1074 
py_ldb_repr(PyLdbObject * self)1075 static PyObject *py_ldb_repr(PyLdbObject *self)
1076 {
1077 	return PyUnicode_FromString("<ldb connection>");
1078 }
1079 
py_ldb_get_root_basedn(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1080 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
1081 		PyObject *Py_UNUSED(ignored))
1082 {
1083 	struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1084 	if (dn == NULL)
1085 		Py_RETURN_NONE;
1086 	return py_ldb_dn_copy(dn);
1087 }
1088 
1089 
py_ldb_get_schema_basedn(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1090 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
1091 		PyObject *Py_UNUSED(ignored))
1092 {
1093 	struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1094 	if (dn == NULL)
1095 		Py_RETURN_NONE;
1096 	return py_ldb_dn_copy(dn);
1097 }
1098 
py_ldb_get_config_basedn(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1099 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
1100 		PyObject *Py_UNUSED(ignored))
1101 {
1102 	struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1103 	if (dn == NULL)
1104 		Py_RETURN_NONE;
1105 	return py_ldb_dn_copy(dn);
1106 }
1107 
py_ldb_get_default_basedn(PyLdbObject * self,PyObject * Py_UNUSED (ignored))1108 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
1109 		PyObject *Py_UNUSED(ignored))
1110 {
1111 	struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1112 	if (dn == NULL)
1113 		Py_RETURN_NONE;
1114 	return py_ldb_dn_copy(dn);
1115 }
1116 
PyList_AsStrList(TALLOC_CTX * mem_ctx,PyObject * list,const char * paramname)1117 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1118                     const char *paramname)
1119 {
1120 	const char **ret;
1121 	Py_ssize_t i;
1122 	if (!PyList_Check(list)) {
1123 		PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1124 		return NULL;
1125 	}
1126 	ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1127 	if (ret == NULL) {
1128 		PyErr_NoMemory();
1129 		return NULL;
1130 	}
1131 
1132 	for (i = 0; i < PyList_Size(list); i++) {
1133 		const char *str = NULL;
1134 		Py_ssize_t size;
1135 		PyObject *item = PyList_GetItem(list, i);
1136 		if (!PyUnicode_Check(item)) {
1137 			PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1138 			talloc_free(ret);
1139 			return NULL;
1140 		}
1141 		str = PyUnicode_AsUTF8AndSize(item, &size);
1142 		if (str == NULL) {
1143 			talloc_free(ret);
1144 			return NULL;
1145 		}
1146 		ret[i] = talloc_strndup(ret, str, size);
1147 	}
1148 	ret[i] = NULL;
1149 	return ret;
1150 }
1151 
py_ldb_init(PyLdbObject * self,PyObject * args,PyObject * kwargs)1152 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1153 {
1154 	const char * const kwnames[] = { "url", "flags", "options", NULL };
1155 	char *url = NULL;
1156 	PyObject *py_options = Py_None;
1157 	const char **options;
1158 	unsigned int flags = 0;
1159 	int ret;
1160 	struct ldb_context *ldb;
1161 
1162 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1163 					 discard_const_p(char *, kwnames),
1164 					 &url, &flags, &py_options))
1165 		return -1;
1166 
1167 	ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1168 
1169 	if (py_options == Py_None) {
1170 		options = NULL;
1171 	} else {
1172 		options = PyList_AsStrList(ldb, py_options, "options");
1173 		if (options == NULL)
1174 			return -1;
1175 	}
1176 
1177 	if (url != NULL) {
1178 		ret = ldb_connect(ldb, url, flags, options);
1179 		if (ret != LDB_SUCCESS) {
1180 			PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1181 			return -1;
1182 		}
1183 	} else {
1184 		ldb_set_flags(ldb, flags);
1185 	}
1186 
1187 	talloc_free(options);
1188 	return 0;
1189 }
1190 
py_ldb_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)1191 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1192 {
1193 	PyLdbObject *ret;
1194 	struct ldb_context *ldb;
1195 	ret = (PyLdbObject *)type->tp_alloc(type, 0);
1196 	if (ret == NULL) {
1197 		PyErr_NoMemory();
1198 		return NULL;
1199 	}
1200 	ret->mem_ctx = talloc_new(NULL);
1201 	ldb = ldb_init(ret->mem_ctx, NULL);
1202 
1203 	if (ldb == NULL) {
1204 		PyErr_NoMemory();
1205 		return NULL;
1206 	}
1207 
1208 	ret->ldb_ctx = ldb;
1209 	return (PyObject *)ret;
1210 }
1211 
py_ldb_connect(PyLdbObject * self,PyObject * args,PyObject * kwargs)1212 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1213 {
1214 	char *url = NULL;
1215 	unsigned int flags = 0;
1216 	PyObject *py_options = Py_None;
1217 	int ret;
1218 	const char **options;
1219 	const char * const kwnames[] = { "url", "flags", "options", NULL };
1220 	struct ldb_context *ldb_ctx;
1221 
1222 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1223 					 discard_const_p(char *, kwnames),
1224 					 &url, &flags, &py_options))
1225 		return NULL;
1226 
1227 	if (py_options == Py_None) {
1228 		options = NULL;
1229 	} else {
1230 		options = PyList_AsStrList(NULL, py_options, "options");
1231 		if (options == NULL)
1232 			return NULL;
1233 	}
1234 
1235 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1236 	ret = ldb_connect(ldb_ctx, url, flags, options);
1237 	talloc_free(options);
1238 
1239 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1240 
1241 	Py_RETURN_NONE;
1242 }
1243 
py_ldb_modify(PyLdbObject * self,PyObject * args,PyObject * kwargs)1244 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1245 {
1246 	PyObject *py_msg;
1247 	PyObject *py_controls = Py_None;
1248 	struct ldb_context *ldb_ctx;
1249 	struct ldb_request *req;
1250 	struct ldb_control **parsed_controls;
1251 	struct ldb_message *msg;
1252 	int ret;
1253 	TALLOC_CTX *mem_ctx;
1254 	bool validate=true;
1255 	const char * const kwnames[] = { "message", "controls", "validate", NULL };
1256 
1257 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1258 					 discard_const_p(char *, kwnames),
1259 					 &py_msg, &py_controls, &validate))
1260 		return NULL;
1261 
1262 	mem_ctx = talloc_new(NULL);
1263 	if (mem_ctx == NULL) {
1264 		PyErr_NoMemory();
1265 		return NULL;
1266 	}
1267 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1268 
1269 	if (py_controls == Py_None) {
1270 		parsed_controls = NULL;
1271 	} else {
1272 		const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1273 		if (controls == NULL) {
1274 			talloc_free(mem_ctx);
1275 			return NULL;
1276 		}
1277 		parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1278 		talloc_free(controls);
1279 	}
1280 
1281 	if (!PyLdbMessage_Check(py_msg)) {
1282 		PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1283 		talloc_free(mem_ctx);
1284 		return NULL;
1285 	}
1286 	msg = pyldb_Message_AsMessage(py_msg);
1287 
1288 	if (validate) {
1289 		ret = ldb_msg_sanity_check(ldb_ctx, msg);
1290 		if (ret != LDB_SUCCESS) {
1291 			PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1292 			talloc_free(mem_ctx);
1293 			return NULL;
1294 		}
1295 	}
1296 
1297 	ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1298 				NULL, ldb_op_default_callback, NULL);
1299 	if (ret != LDB_SUCCESS) {
1300 		PyErr_SetString(PyExc_TypeError, "failed to build request");
1301 		talloc_free(mem_ctx);
1302 		return NULL;
1303 	}
1304 
1305 	/* do request and autostart a transaction */
1306 	/* Then let's LDB handle the message error in case of pb as they are meaningful */
1307 
1308 	ret = ldb_transaction_start(ldb_ctx);
1309 	if (ret != LDB_SUCCESS) {
1310 		talloc_free(mem_ctx);
1311 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1312 		return NULL;
1313 	}
1314 
1315 	ret = ldb_request(ldb_ctx, req);
1316 	if (ret == LDB_SUCCESS) {
1317 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1318 	}
1319 
1320 	if (ret == LDB_SUCCESS) {
1321 		ret = ldb_transaction_commit(ldb_ctx);
1322 	} else {
1323 		ldb_transaction_cancel(ldb_ctx);
1324 	}
1325 
1326 	talloc_free(mem_ctx);
1327 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1328 
1329 	Py_RETURN_NONE;
1330 }
1331 
1332 
1333 /**
1334  * Obtain a ldb message from a Python Dictionary object.
1335  *
1336  * @param mem_ctx Memory context
1337  * @param py_obj Python Dictionary object
1338  * @param ldb_ctx LDB context
1339  * @param mod_flags Flags to be set on every message element
1340  * @return ldb_message on success or NULL on failure
1341  */
PyDict_AsMessage(TALLOC_CTX * mem_ctx,PyObject * py_obj,struct ldb_context * ldb_ctx,unsigned int mod_flags)1342 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1343 					    PyObject *py_obj,
1344 					    struct ldb_context *ldb_ctx,
1345 					    unsigned int mod_flags)
1346 {
1347 	struct ldb_message *msg;
1348 	unsigned int msg_pos = 0;
1349 	Py_ssize_t dict_pos = 0;
1350 	PyObject *key, *value;
1351 	struct ldb_message_element *msg_el;
1352 	PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1353 
1354 	msg = ldb_msg_new(mem_ctx);
1355 	if (msg == NULL) {
1356 		PyErr_NoMemory();
1357 		return NULL;
1358 	}
1359 	msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1360 
1361 	if (dn_value) {
1362 		if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1363 			PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1364 			return NULL;
1365 		}
1366 		if (msg->dn == NULL) {
1367 			PyErr_SetString(PyExc_TypeError, "dn set but not found");
1368 			return NULL;
1369 		}
1370 	} else {
1371 		PyErr_SetString(PyExc_TypeError, "no dn set");
1372 		return NULL;
1373 	}
1374 
1375 	while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1376 		const char *key_str = PyUnicode_AsUTF8(key);
1377 		if (ldb_attr_cmp(key_str, "dn") != 0) {
1378 			msg_el = PyObject_AsMessageElement(msg->elements, value,
1379 							   mod_flags, key_str);
1380 			if (msg_el == NULL) {
1381 				PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1382 				return NULL;
1383 			}
1384 			memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1385 			msg_pos++;
1386 		}
1387 	}
1388 
1389 	msg->num_elements = msg_pos;
1390 
1391 	return msg;
1392 }
1393 
py_ldb_add(PyLdbObject * self,PyObject * args,PyObject * kwargs)1394 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1395 {
1396 	PyObject *py_obj;
1397 	int ret;
1398 	struct ldb_context *ldb_ctx;
1399 	struct ldb_request *req;
1400 	struct ldb_message *msg = NULL;
1401 	PyObject *py_controls = Py_None;
1402 	TALLOC_CTX *mem_ctx;
1403 	struct ldb_control **parsed_controls;
1404 	const char * const kwnames[] = { "message", "controls", NULL };
1405 
1406 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1407 					 discard_const_p(char *, kwnames),
1408 					 &py_obj, &py_controls))
1409 		return NULL;
1410 
1411 	mem_ctx = talloc_new(NULL);
1412 	if (mem_ctx == NULL) {
1413 		PyErr_NoMemory();
1414 		return NULL;
1415 	}
1416 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1417 
1418 	if (py_controls == Py_None) {
1419 		parsed_controls = NULL;
1420 	} else {
1421 		const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1422 		if (controls == NULL) {
1423 			talloc_free(mem_ctx);
1424 			return NULL;
1425 		}
1426 		parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1427 		talloc_free(controls);
1428 	}
1429 
1430 	if (PyLdbMessage_Check(py_obj)) {
1431 		msg = pyldb_Message_AsMessage(py_obj);
1432 	} else if (PyDict_Check(py_obj)) {
1433 		msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1434 	} else {
1435 		PyErr_SetString(PyExc_TypeError,
1436 				"Dictionary or LdbMessage object expected!");
1437 	}
1438 
1439 	if (!msg) {
1440 		/* we should have a PyErr already set */
1441 		talloc_free(mem_ctx);
1442 		return NULL;
1443 	}
1444 
1445 	ret = ldb_msg_sanity_check(ldb_ctx, msg);
1446 	if (ret != LDB_SUCCESS) {
1447 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1448 		talloc_free(mem_ctx);
1449 		return NULL;
1450 	}
1451 
1452 	ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1453 				NULL, ldb_op_default_callback, NULL);
1454 	if (ret != LDB_SUCCESS) {
1455 		PyErr_SetString(PyExc_TypeError, "failed to build request");
1456 		talloc_free(mem_ctx);
1457 		return NULL;
1458 	}
1459 
1460         /* do request and autostart a transaction */
1461 	/* Then let's LDB handle the message error in case of pb as they are meaningful */
1462 
1463 	ret = ldb_transaction_start(ldb_ctx);
1464 	if (ret != LDB_SUCCESS) {
1465 		talloc_free(mem_ctx);
1466 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1467 		return NULL;
1468 	}
1469 
1470 	ret = ldb_request(ldb_ctx, req);
1471 	if (ret == LDB_SUCCESS) {
1472 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1473 	}
1474 
1475 	if (ret == LDB_SUCCESS) {
1476 		ret = ldb_transaction_commit(ldb_ctx);
1477 	} else {
1478 		ldb_transaction_cancel(ldb_ctx);
1479 	}
1480 
1481 	talloc_free(mem_ctx);
1482 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1483 
1484 	Py_RETURN_NONE;
1485 }
1486 
py_ldb_delete(PyLdbObject * self,PyObject * args,PyObject * kwargs)1487 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1488 {
1489 	PyObject *py_dn;
1490 	struct ldb_dn *dn;
1491 	int ret;
1492 	struct ldb_context *ldb_ctx;
1493 	struct ldb_request *req;
1494 	PyObject *py_controls = Py_None;
1495 	TALLOC_CTX *mem_ctx;
1496 	struct ldb_control **parsed_controls;
1497 	const char * const kwnames[] = { "dn", "controls", NULL };
1498 
1499 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1500 					 discard_const_p(char *, kwnames),
1501 					 &py_dn, &py_controls))
1502 		return NULL;
1503 
1504 	mem_ctx = talloc_new(NULL);
1505 	if (mem_ctx == NULL) {
1506 		PyErr_NoMemory();
1507 		return NULL;
1508 	}
1509 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1510 
1511 	if (py_controls == Py_None) {
1512 		parsed_controls = NULL;
1513 	} else {
1514 		const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1515 		if (controls == NULL) {
1516 			talloc_free(mem_ctx);
1517 			return NULL;
1518 		}
1519 		parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1520 		talloc_free(controls);
1521 	}
1522 
1523 	if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1524 		talloc_free(mem_ctx);
1525 		return NULL;
1526 	}
1527 
1528 	ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1529 				NULL, ldb_op_default_callback, NULL);
1530 	if (ret != LDB_SUCCESS) {
1531 		PyErr_SetString(PyExc_TypeError, "failed to build request");
1532 		talloc_free(mem_ctx);
1533 		return NULL;
1534 	}
1535 
1536 	/* do request and autostart a transaction */
1537 	/* Then let's LDB handle the message error in case of pb as they are meaningful */
1538 
1539 	ret = ldb_transaction_start(ldb_ctx);
1540 	if (ret != LDB_SUCCESS) {
1541 		talloc_free(mem_ctx);
1542 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1543 		return NULL;
1544 	}
1545 
1546 	ret = ldb_request(ldb_ctx, req);
1547 	if (ret == LDB_SUCCESS) {
1548 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1549 	}
1550 
1551 	if (ret == LDB_SUCCESS) {
1552 		ret = ldb_transaction_commit(ldb_ctx);
1553 	} else {
1554 		ldb_transaction_cancel(ldb_ctx);
1555 	}
1556 
1557 	talloc_free(mem_ctx);
1558 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1559 
1560 	Py_RETURN_NONE;
1561 }
1562 
py_ldb_rename(PyLdbObject * self,PyObject * args,PyObject * kwargs)1563 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1564 {
1565 	PyObject *py_dn1, *py_dn2;
1566 	struct ldb_dn *dn1, *dn2;
1567 	int ret;
1568 	TALLOC_CTX *mem_ctx;
1569 	PyObject *py_controls = Py_None;
1570 	struct ldb_control **parsed_controls;
1571 	struct ldb_context *ldb_ctx;
1572 	struct ldb_request *req;
1573 	const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1574 
1575 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1576 
1577 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1578 					 discard_const_p(char *, kwnames),
1579 					 &py_dn1, &py_dn2, &py_controls))
1580 		return NULL;
1581 
1582 
1583 	mem_ctx = talloc_new(NULL);
1584 	if (mem_ctx == NULL) {
1585 		PyErr_NoMemory();
1586 		return NULL;
1587 	}
1588 
1589 	if (py_controls == Py_None) {
1590 		parsed_controls = NULL;
1591 	} else {
1592 		const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1593 		if (controls == NULL) {
1594 			talloc_free(mem_ctx);
1595 			return NULL;
1596 		}
1597 		parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1598 		talloc_free(controls);
1599 	}
1600 
1601 
1602 	if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1603 		talloc_free(mem_ctx);
1604 		return NULL;
1605 	}
1606 
1607 	if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1608 		talloc_free(mem_ctx);
1609 		return NULL;
1610 	}
1611 
1612 	ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1613 				NULL, ldb_op_default_callback, NULL);
1614 	if (ret != LDB_SUCCESS) {
1615 		PyErr_SetString(PyExc_TypeError, "failed to build request");
1616 		talloc_free(mem_ctx);
1617 		return NULL;
1618 	}
1619 
1620 	/* do request and autostart a transaction */
1621 	/* Then let's LDB handle the message error in case of pb as they are meaningful */
1622 
1623 	ret = ldb_transaction_start(ldb_ctx);
1624 	if (ret != LDB_SUCCESS) {
1625 		talloc_free(mem_ctx);
1626 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1627 		return NULL;
1628 	}
1629 
1630 	ret = ldb_request(ldb_ctx, req);
1631 	if (ret == LDB_SUCCESS) {
1632 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1633 	}
1634 
1635 	if (ret == LDB_SUCCESS) {
1636 		ret = ldb_transaction_commit(ldb_ctx);
1637 	} else {
1638 		ldb_transaction_cancel(ldb_ctx);
1639 	}
1640 
1641 	talloc_free(mem_ctx);
1642 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1643 
1644 	Py_RETURN_NONE;
1645 }
1646 
py_ldb_schema_attribute_remove(PyLdbObject * self,PyObject * args)1647 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1648 {
1649 	char *name;
1650 	if (!PyArg_ParseTuple(args, "s", &name))
1651 		return NULL;
1652 
1653 	ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
1654 
1655 	Py_RETURN_NONE;
1656 }
1657 
py_ldb_schema_attribute_add(PyLdbObject * self,PyObject * args)1658 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1659 {
1660 	char *attribute, *syntax;
1661 	unsigned int flags;
1662 	int ret;
1663 	struct ldb_context *ldb_ctx;
1664 
1665 	if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1666 		return NULL;
1667 
1668 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1669 	ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1670 
1671 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1672 
1673 	Py_RETURN_NONE;
1674 }
1675 
ldb_ldif_to_pyobject(struct ldb_ldif * ldif)1676 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1677 {
1678 	if (ldif == NULL) {
1679 		Py_RETURN_NONE;
1680 	} else {
1681 	/* We don't want this attached to the 'ldb' any more */
1682 		PyObject *obj = PyLdbMessage_FromMessage(ldif->msg);
1683 		PyObject *result =
1684 			Py_BuildValue(discard_const_p(char, "(iO)"),
1685 				      ldif->changetype,
1686 				      obj);
1687 		Py_CLEAR(obj);
1688 		return result;
1689 	}
1690 }
1691 
1692 
py_ldb_write_ldif(PyLdbObject * self,PyObject * args)1693 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1694 {
1695 	int changetype;
1696 	PyObject *py_msg;
1697 	struct ldb_ldif ldif;
1698 	PyObject *ret;
1699 	char *string;
1700 	TALLOC_CTX *mem_ctx;
1701 
1702 	if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1703 		return NULL;
1704 
1705 	if (!PyLdbMessage_Check(py_msg)) {
1706 		PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1707 		return NULL;
1708 	}
1709 
1710 	ldif.msg = pyldb_Message_AsMessage(py_msg);
1711 	ldif.changetype = changetype;
1712 
1713 	mem_ctx = talloc_new(NULL);
1714 
1715 	string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
1716 	if (!string) {
1717 		PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1718 		return NULL;
1719 	}
1720 
1721 	ret = PyUnicode_FromString(string);
1722 
1723 	talloc_free(mem_ctx);
1724 
1725 	return ret;
1726 }
1727 
py_ldb_parse_ldif(PyLdbObject * self,PyObject * args)1728 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1729 {
1730 	PyObject *list, *ret;
1731 	struct ldb_ldif *ldif;
1732 	const char *s;
1733 	struct ldb_dn *last_dn = NULL;
1734 
1735 	TALLOC_CTX *mem_ctx;
1736 
1737 	if (!PyArg_ParseTuple(args, "s", &s))
1738 		return NULL;
1739 
1740 	mem_ctx = talloc_new(NULL);
1741 	if (!mem_ctx) {
1742 		Py_RETURN_NONE;
1743 	}
1744 
1745 	list = PyList_New(0);
1746 	while (s && *s != '\0') {
1747 		ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1748 		talloc_steal(mem_ctx, ldif);
1749 		if (ldif) {
1750 			int res = 0;
1751 			PyObject *py_ldif = ldb_ldif_to_pyobject(ldif);
1752 			if (py_ldif == NULL) {
1753 				Py_CLEAR(list);
1754 				PyErr_BadArgument();
1755 				talloc_free(mem_ctx);
1756 				return NULL;
1757 			}
1758 			res = PyList_Append(list, py_ldif);
1759 			Py_CLEAR(py_ldif);
1760 			if (res == -1) {
1761 				Py_CLEAR(list);
1762 				talloc_free(mem_ctx);
1763 				return NULL;
1764 			}
1765 			last_dn = ldif->msg->dn;
1766 		} else {
1767 			const char *last_dn_str = NULL;
1768 			const char *err_string = NULL;
1769 			if (last_dn == NULL) {
1770 				PyErr_SetString(PyExc_ValueError,
1771 						"unable to parse LDIF "
1772 						"string at first chunk");
1773 				Py_CLEAR(list);
1774 				talloc_free(mem_ctx);
1775 				return NULL;
1776 			}
1777 
1778 			last_dn_str
1779 				= ldb_dn_get_linearized(last_dn);
1780 
1781 			err_string
1782 				= talloc_asprintf(mem_ctx,
1783 						  "unable to parse ldif "
1784 						  "string AFTER %s",
1785 						  last_dn_str);
1786 
1787 			PyErr_SetString(PyExc_ValueError,
1788 					err_string);
1789 			talloc_free(mem_ctx);
1790 			Py_CLEAR(list);
1791 			return NULL;
1792 		}
1793 	}
1794 	talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1795 	ret = PyObject_GetIter(list);
1796 	Py_DECREF(list);
1797 	return ret;
1798 }
1799 
py_ldb_msg_diff(PyLdbObject * self,PyObject * args)1800 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1801 {
1802 	int ldb_ret;
1803 	PyObject *py_msg_old;
1804 	PyObject *py_msg_new;
1805 	struct ldb_message *diff;
1806 	struct ldb_context *ldb;
1807 	PyObject *py_ret;
1808 
1809 	if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1810 		return NULL;
1811 
1812 	if (!PyLdbMessage_Check(py_msg_old)) {
1813 		PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1814 		return NULL;
1815 	}
1816 
1817 	if (!PyLdbMessage_Check(py_msg_new)) {
1818 		PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1819 		return NULL;
1820 	}
1821 
1822 	ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1823 	ldb_ret = ldb_msg_difference(ldb, ldb,
1824 	                             pyldb_Message_AsMessage(py_msg_old),
1825 	                             pyldb_Message_AsMessage(py_msg_new),
1826 	                             &diff);
1827 	if (ldb_ret != LDB_SUCCESS) {
1828 		PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1829 		return NULL;
1830 	}
1831 
1832 	py_ret = PyLdbMessage_FromMessage(diff);
1833 
1834 	talloc_unlink(ldb, diff);
1835 
1836 	return py_ret;
1837 }
1838 
py_ldb_schema_format_value(PyLdbObject * self,PyObject * args)1839 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1840 {
1841 	const struct ldb_schema_attribute *a;
1842 	struct ldb_val old_val;
1843 	struct ldb_val new_val;
1844 	TALLOC_CTX *mem_ctx;
1845 	PyObject *ret;
1846 	char *element_name;
1847 	PyObject *val;
1848 	Py_ssize_t size;
1849 	int result;
1850 
1851 	if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1852 		return NULL;
1853 
1854 	result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1855 	old_val.length = size;
1856 
1857 	if (result != 0) {
1858 		PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1859 		return NULL;
1860 	}
1861 
1862 	a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
1863 
1864 	if (a == NULL) {
1865 		Py_RETURN_NONE;
1866 	}
1867 
1868 	mem_ctx = talloc_new(NULL);
1869 	if (mem_ctx == NULL) {
1870 		PyErr_NoMemory();
1871 		return NULL;
1872 	}
1873 
1874 	if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
1875 		talloc_free(mem_ctx);
1876 		Py_RETURN_NONE;
1877 	}
1878 
1879 	ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1880 
1881 	talloc_free(mem_ctx);
1882 
1883 	return ret;
1884 }
1885 
py_ldb_search(PyLdbObject * self,PyObject * args,PyObject * kwargs)1886 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1887 {
1888 	PyObject *py_base = Py_None;
1889 	int scope = LDB_SCOPE_DEFAULT;
1890 	char *expr = NULL;
1891 	PyObject *py_attrs = Py_None;
1892 	PyObject *py_controls = Py_None;
1893 	const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1894 	int ret;
1895 	struct ldb_result *res;
1896 	struct ldb_request *req;
1897 	const char **attrs;
1898 	struct ldb_context *ldb_ctx;
1899 	struct ldb_control **parsed_controls;
1900 	struct ldb_dn *base;
1901 	PyObject *py_ret;
1902 	TALLOC_CTX *mem_ctx;
1903 
1904 	/* type "int" rather than "enum" for "scope" is intentional */
1905 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1906 					 discard_const_p(char *, kwnames),
1907 					 &py_base, &scope, &expr, &py_attrs, &py_controls))
1908 		return NULL;
1909 
1910 
1911 	mem_ctx = talloc_new(NULL);
1912 	if (mem_ctx == NULL) {
1913 		PyErr_NoMemory();
1914 		return NULL;
1915 	}
1916 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1917 
1918 	if (py_attrs == Py_None) {
1919 		attrs = NULL;
1920 	} else {
1921 		attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1922 		if (attrs == NULL) {
1923 			talloc_free(mem_ctx);
1924 			return NULL;
1925 		}
1926 	}
1927 
1928 	if (py_base == Py_None) {
1929 		base = ldb_get_default_basedn(ldb_ctx);
1930 	} else {
1931 		if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1932 			talloc_free(mem_ctx);
1933 			return NULL;
1934 		}
1935 	}
1936 
1937 	if (py_controls == Py_None) {
1938 		parsed_controls = NULL;
1939 	} else {
1940 		const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1941 		if (controls == NULL) {
1942 			talloc_free(mem_ctx);
1943 			return NULL;
1944 		}
1945 		parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1946 		talloc_free(controls);
1947 	}
1948 
1949 	res = talloc_zero(mem_ctx, struct ldb_result);
1950 	if (res == NULL) {
1951 		PyErr_NoMemory();
1952 		talloc_free(mem_ctx);
1953 		return NULL;
1954 	}
1955 
1956 	ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1957 				   base,
1958 				   scope,
1959 				   expr,
1960 				   attrs,
1961 				   parsed_controls,
1962 				   res,
1963 				   ldb_search_default_callback,
1964 				   NULL);
1965 
1966 	if (ret != LDB_SUCCESS) {
1967 		talloc_free(mem_ctx);
1968 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1969 		return NULL;
1970 	}
1971 
1972 	talloc_steal(req, attrs);
1973 
1974 	ret = ldb_request(ldb_ctx, req);
1975 
1976 	if (ret == LDB_SUCCESS) {
1977 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1978 	}
1979 
1980 	if (ret != LDB_SUCCESS) {
1981 		talloc_free(mem_ctx);
1982 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1983 		return NULL;
1984 	}
1985 
1986 	py_ret = PyLdbResult_FromResult(res);
1987 
1988 	talloc_free(mem_ctx);
1989 
1990 	return py_ret;
1991 }
1992 
py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply * reply)1993 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1994 {
1995 	if (reply->py_iter != NULL) {
1996 		DLIST_REMOVE(reply->py_iter->state.next, reply);
1997 		if (reply->py_iter->state.result == reply) {
1998 			reply->py_iter->state.result = NULL;
1999 		}
2000 		reply->py_iter = NULL;
2001 	}
2002 
2003 	if (reply->obj != NULL) {
2004 		Py_DECREF(reply->obj);
2005 		reply->obj = NULL;
2006 	}
2007 
2008 	return 0;
2009 }
2010 
py_ldb_search_iterator_callback(struct ldb_request * req,struct ldb_reply * ares)2011 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2012 					   struct ldb_reply *ares)
2013 {
2014 	PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2015 	struct ldb_result result = { .msgs = NULL };
2016 	struct py_ldb_search_iterator_reply *reply = NULL;
2017 
2018 	if (ares == NULL) {
2019 		return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2020 	}
2021 
2022 	if (ares->error != LDB_SUCCESS) {
2023 		int ret = ares->error;
2024 		TALLOC_FREE(ares);
2025 		return ldb_request_done(req, ret);
2026 	}
2027 
2028 	reply = talloc_zero(py_iter->mem_ctx,
2029 			    struct py_ldb_search_iterator_reply);
2030 	if (reply == NULL) {
2031 		TALLOC_FREE(ares);
2032 		return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2033 	}
2034 	reply->py_iter = py_iter;
2035 	talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2036 
2037 	switch (ares->type) {
2038 	case LDB_REPLY_ENTRY:
2039 		reply->obj = PyLdbMessage_FromMessage(ares->message);
2040 		if (reply->obj == NULL) {
2041 			TALLOC_FREE(ares);
2042 			return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2043 		}
2044 		DLIST_ADD_END(py_iter->state.next, reply);
2045 		TALLOC_FREE(ares);
2046 		return LDB_SUCCESS;
2047 
2048 	case LDB_REPLY_REFERRAL:
2049 		reply->obj = PyUnicode_FromString(ares->referral);
2050 		if (reply->obj == NULL) {
2051 			TALLOC_FREE(ares);
2052 			return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2053 		}
2054 		DLIST_ADD_END(py_iter->state.next, reply);
2055 		TALLOC_FREE(ares);
2056 		return LDB_SUCCESS;
2057 
2058 	case LDB_REPLY_DONE:
2059 		result = (struct ldb_result) { .controls = ares->controls };
2060 		reply->obj = PyLdbResult_FromResult(&result);
2061 		if (reply->obj == NULL) {
2062 			TALLOC_FREE(ares);
2063 			return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2064 		}
2065 		py_iter->state.result = reply;
2066 		TALLOC_FREE(ares);
2067 		return ldb_request_done(req, LDB_SUCCESS);
2068 	}
2069 
2070 	TALLOC_FREE(ares);
2071 	return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2072 }
2073 
py_ldb_search_iterator(PyLdbObject * self,PyObject * args,PyObject * kwargs)2074 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2075 {
2076 	PyObject *py_base = Py_None;
2077 	int scope = LDB_SCOPE_DEFAULT;
2078 	int timeout = 0;
2079 	char *expr = NULL;
2080 	PyObject *py_attrs = Py_None;
2081 	PyObject *py_controls = Py_None;
2082 	const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2083 	int ret;
2084 	const char **attrs;
2085 	struct ldb_context *ldb_ctx;
2086 	struct ldb_control **parsed_controls;
2087 	struct ldb_dn *base;
2088 	PyLdbSearchIteratorObject *py_iter;
2089 
2090 	/* type "int" rather than "enum" for "scope" is intentional */
2091 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2092 					 discard_const_p(char *, kwnames),
2093 					 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2094 		return NULL;
2095 
2096 	py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2097 	if (py_iter == NULL) {
2098 		PyErr_NoMemory();
2099 		return NULL;
2100 	}
2101 	py_iter->ldb = self;
2102 	Py_INCREF(self);
2103 	ZERO_STRUCT(py_iter->state);
2104 	py_iter->mem_ctx = talloc_new(NULL);
2105 	if (py_iter->mem_ctx == NULL) {
2106 		Py_DECREF(py_iter);
2107 		PyErr_NoMemory();
2108 		return NULL;
2109 	}
2110 
2111 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2112 
2113 	if (py_attrs == Py_None) {
2114 		attrs = NULL;
2115 	} else {
2116 		attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2117 		if (attrs == NULL) {
2118 			Py_DECREF(py_iter);
2119 			PyErr_NoMemory();
2120 			return NULL;
2121 		}
2122 	}
2123 
2124 	if (py_base == Py_None) {
2125 		base = ldb_get_default_basedn(ldb_ctx);
2126 	} else {
2127 		if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2128 			Py_DECREF(py_iter);
2129 			PyErr_NoMemory();
2130 			return NULL;
2131 		}
2132 	}
2133 
2134 	if (py_controls == Py_None) {
2135 		parsed_controls = NULL;
2136 	} else {
2137 		const char **controls = NULL;
2138 
2139 		controls = PyList_AsStrList(py_iter->mem_ctx,
2140 					    py_controls, "controls");
2141 		if (controls == NULL) {
2142 			Py_DECREF(py_iter);
2143 			PyErr_NoMemory();
2144 			return NULL;
2145 		}
2146 
2147 		parsed_controls = ldb_parse_control_strings(ldb_ctx,
2148 							    py_iter->mem_ctx,
2149 							    controls);
2150 		if (controls[0] != NULL && parsed_controls == NULL) {
2151 			Py_DECREF(py_iter);
2152 			PyErr_NoMemory();
2153 			return NULL;
2154 		}
2155 		talloc_free(controls);
2156 	}
2157 
2158 	ret = ldb_build_search_req(&py_iter->state.req,
2159 				   ldb_ctx,
2160 				   py_iter->mem_ctx,
2161 				   base,
2162 				   scope,
2163 				   expr,
2164 				   attrs,
2165 				   parsed_controls,
2166 				   py_iter,
2167 				   py_ldb_search_iterator_callback,
2168 				   NULL);
2169 	if (ret != LDB_SUCCESS) {
2170 		Py_DECREF(py_iter);
2171 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2172 		return NULL;
2173 	}
2174 
2175 	ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2176 
2177 	ret = ldb_request(ldb_ctx, py_iter->state.req);
2178 	if (ret != LDB_SUCCESS) {
2179 		Py_DECREF(py_iter);
2180 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2181 		return NULL;
2182 	}
2183 
2184 	return (PyObject *)py_iter;
2185 }
2186 
py_ldb_get_opaque(PyLdbObject * self,PyObject * args)2187 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2188 {
2189 	char *name;
2190 	void *data;
2191 
2192 	if (!PyArg_ParseTuple(args, "s", &name))
2193 		return NULL;
2194 
2195 	data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2196 
2197 	if (data == NULL)
2198 		Py_RETURN_NONE;
2199 
2200 	/* FIXME: More interpretation */
2201 
2202 	Py_RETURN_TRUE;
2203 }
2204 
py_ldb_set_opaque(PyLdbObject * self,PyObject * args)2205 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2206 {
2207 	char *name;
2208 	PyObject *data;
2209 
2210 	if (!PyArg_ParseTuple(args, "sO", &name, &data))
2211 		return NULL;
2212 
2213 	/* FIXME: More interpretation */
2214 
2215 	ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, data);
2216 
2217 	Py_RETURN_NONE;
2218 }
2219 
py_ldb_modules(PyLdbObject * self,PyObject * Py_UNUSED (ignored))2220 static PyObject *py_ldb_modules(PyLdbObject *self,
2221 		PyObject *Py_UNUSED(ignored))
2222 {
2223 	struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2224 	PyObject *ret = PyList_New(0);
2225 	struct ldb_module *mod;
2226 
2227 	if (ret == NULL) {
2228 		return PyErr_NoMemory();
2229 	}
2230 	for (mod = ldb->modules; mod; mod = mod->next) {
2231 		PyObject *item = PyLdbModule_FromModule(mod);
2232 		int res = 0;
2233 		if (item == NULL) {
2234 			PyErr_SetString(PyExc_RuntimeError,
2235 				"Failed to load LdbModule");
2236 			Py_CLEAR(ret);
2237 			return NULL;
2238 		}
2239 		res = PyList_Append(ret, item);
2240 		Py_CLEAR(item);
2241 		if (res == -1) {
2242 			Py_CLEAR(ret);
2243 			return NULL;
2244 		}
2245 	}
2246 
2247 	return ret;
2248 }
2249 
py_ldb_sequence_number(PyLdbObject * self,PyObject * args)2250 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2251 {
2252 	struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2253 	int type, ret;
2254 	uint64_t value;
2255 
2256 	if (!PyArg_ParseTuple(args, "i", &type))
2257 		return NULL;
2258 
2259 	/* FIXME: More interpretation */
2260 
2261 	ret = ldb_sequence_number(ldb, type, &value);
2262 
2263 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2264 
2265 	return PyLong_FromLongLong(value);
2266 }
2267 
2268 
2269 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2270 	.name             = "TEST",
2271 	.read_fn          = ldb_handler_copy,
2272 	.write_clear_fn   = ldb_handler_copy,
2273 	.write_hex_fn     = ldb_handler_copy,
2274 };
2275 
py_ldb_register_test_extensions(PyLdbObject * self,PyObject * Py_UNUSED (ignored))2276 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2277 		PyObject *Py_UNUSED(ignored))
2278 {
2279 	struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2280 	int ret;
2281 
2282 	ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2283 
2284 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2285 
2286 	Py_RETURN_NONE;
2287 }
2288 
2289 
2290 static PyMethodDef py_ldb_methods[] = {
2291 	{ "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2292 		"S.set_debug(callback) -> None\n"
2293 		"Set callback for LDB debug messages.\n"
2294 		"The callback should accept a debug level and debug text." },
2295 	{ "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2296 		"S.set_create_perms(mode) -> None\n"
2297 		"Set mode to use when creating new LDB files." },
2298 	{ "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2299 		"S.set_modules_dir(path) -> None\n"
2300 		"Set path LDB should search for modules" },
2301 	{ "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2302 		"S.transaction_start() -> None\n"
2303 		"Start a new transaction." },
2304 	{ "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2305 		"S.transaction_prepare_commit() -> None\n"
2306 		"prepare to commit a new transaction (2-stage commit)." },
2307 	{ "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2308 		"S.transaction_commit() -> None\n"
2309 		"commit a new transaction." },
2310 	{ "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2311 		"S.transaction_cancel() -> None\n"
2312 		"cancel a new transaction." },
2313 	{ "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2314 		NULL },
2315 	{ "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2316 		NULL },
2317 	{ "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2318 		NULL },
2319 	{ "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2320 		NULL },
2321 	{ "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2322 		NULL },
2323 	{ "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2324 		METH_VARARGS|METH_KEYWORDS,
2325 		"S.connect(url, flags=0, options=None) -> None\n"
2326 		"Connect to a LDB URL." },
2327 	{ "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2328 		METH_VARARGS|METH_KEYWORDS,
2329 		"S.modify(message, controls=None, validate=False) -> None\n"
2330 		"Modify an entry." },
2331 	{ "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2332 		METH_VARARGS|METH_KEYWORDS,
2333 		"S.add(message, controls=None) -> None\n"
2334 		"Add an entry." },
2335 	{ "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2336 		METH_VARARGS|METH_KEYWORDS,
2337 		"S.delete(dn, controls=None) -> None\n"
2338 		"Remove an entry." },
2339 	{ "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2340 		METH_VARARGS|METH_KEYWORDS,
2341 		"S.rename(old_dn, new_dn, controls=None) -> None\n"
2342 		"Rename an entry." },
2343 	{ "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2344 		METH_VARARGS|METH_KEYWORDS,
2345 		"S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2346 		"Search in a database.\n"
2347 		"\n"
2348 		":param base: Optional base DN to search\n"
2349 		":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2350 		":param expression: Optional search expression\n"
2351 		":param attrs: Attributes to return (defaults to all)\n"
2352 		":param controls: Optional list of controls\n"
2353 		":return: ldb.Result object\n"
2354 	},
2355 	{ "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2356 						 py_ldb_search_iterator),
2357 		METH_VARARGS|METH_KEYWORDS,
2358 		"S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2359 		"Search in a database.\n"
2360 		"\n"
2361 		":param base: Optional base DN to search\n"
2362 		":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2363 		":param expression: Optional search expression\n"
2364 		":param attrs: Attributes to return (defaults to all)\n"
2365 		":param controls: Optional list of controls\n"
2366 		":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2367 		":return: ldb.SearchIterator object that provides results when they arrive\n"
2368 	},
2369 	{ "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2370 		NULL },
2371 	{ "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2372 		NULL },
2373 	{ "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2374 		NULL },
2375 	{ "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2376 		"S.parse_ldif(ldif) -> iter(messages)\n"
2377 		"Parse a string formatted using LDIF." },
2378 	{ "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2379 		"S.write_ldif(message, changetype) -> ldif\n"
2380 		"Print the message as a string formatted using LDIF." },
2381 	{ "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2382 		"S.msg_diff(Message) -> Message\n"
2383 		"Return an LDB Message of the difference between two Message objects." },
2384 	{ "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2385 		"S.get_opaque(name) -> value\n"
2386 		"Get an opaque value set on this LDB connection. \n"
2387 		":note: The returned value may not be useful in Python."
2388 	},
2389 	{ "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2390 		"S.set_opaque(name, value) -> None\n"
2391 		"Set an opaque value on this LDB connection. \n"
2392 		":note: Passing incorrect values may cause crashes." },
2393 	{ "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2394 		"S.modules() -> list\n"
2395 		"Return the list of modules on this LDB connection " },
2396 	{ "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2397 		"S.sequence_number(type) -> value\n"
2398 		"Return the value of the sequence according to the requested type" },
2399 	{ "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2400 		"S._register_test_extensions() -> None\n"
2401 		"Register internal extensions used in testing" },
2402 	{ NULL },
2403 };
2404 
PyLdbModule_FromModule(struct ldb_module * mod)2405 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2406 {
2407 	PyLdbModuleObject *ret;
2408 
2409 	ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2410 	if (ret == NULL) {
2411 		PyErr_NoMemory();
2412 		return NULL;
2413 	}
2414 	ret->mem_ctx = talloc_new(NULL);
2415 	ret->mod = talloc_reference(ret->mem_ctx, mod);
2416 	return (PyObject *)ret;
2417 }
2418 
py_ldb_get_firstmodule(PyLdbObject * self,void * closure)2419 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2420 {
2421 	struct ldb_module *mod = pyldb_Ldb_AS_LDBCONTEXT(self)->modules;
2422 	if (mod == NULL) {
2423 		Py_RETURN_NONE;
2424 	}
2425 	return PyLdbModule_FromModule(mod);
2426 }
2427 
2428 static PyGetSetDef py_ldb_getset[] = {
2429 	{
2430 		.name = discard_const_p(char, "firstmodule"),
2431 		.get  = (getter)py_ldb_get_firstmodule,
2432 	},
2433 	{ .name = NULL },
2434 };
2435 
py_ldb_contains(PyLdbObject * self,PyObject * obj)2436 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2437 {
2438 	struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2439 	struct ldb_dn *dn;
2440 	struct ldb_result *result;
2441 	unsigned int count;
2442 	int ret;
2443 
2444 	if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2445 		return -1;
2446 	}
2447 
2448 	ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2449 			 NULL);
2450 	if (ret != LDB_SUCCESS) {
2451 		PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2452 		return -1;
2453 	}
2454 
2455 	count = result->count;
2456 
2457 	talloc_free(result);
2458 
2459 	if (count > 1) {
2460 		PyErr_Format(PyExc_RuntimeError,
2461 			     "Searching for [%s] dn gave %u results!",
2462 			     ldb_dn_get_linearized(dn),
2463 			     count);
2464 		return -1;
2465 	}
2466 
2467 	return count;
2468 }
2469 
2470 static PySequenceMethods py_ldb_seq = {
2471 	.sq_contains = (objobjproc)py_ldb_contains,
2472 };
2473 
PyLdb_FromLdbContext(struct ldb_context * ldb_ctx)2474 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2475 {
2476 	PyLdbObject *ret;
2477 
2478 	ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2479 	if (ret == NULL) {
2480 		PyErr_NoMemory();
2481 		return NULL;
2482 	}
2483 	ret->mem_ctx = talloc_new(NULL);
2484 	ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2485 	return (PyObject *)ret;
2486 }
2487 
py_ldb_dealloc(PyLdbObject * self)2488 static void py_ldb_dealloc(PyLdbObject *self)
2489 {
2490 	talloc_free(self->mem_ctx);
2491 	Py_TYPE(self)->tp_free(self);
2492 }
2493 
2494 static PyTypeObject PyLdb = {
2495 	.tp_name = "ldb.Ldb",
2496 	.tp_methods = py_ldb_methods,
2497 	.tp_repr = (reprfunc)py_ldb_repr,
2498 	.tp_new = py_ldb_new,
2499 	.tp_init = (initproc)py_ldb_init,
2500 	.tp_dealloc = (destructor)py_ldb_dealloc,
2501 	.tp_getset = py_ldb_getset,
2502 	.tp_getattro = PyObject_GenericGetAttr,
2503 	.tp_basicsize = sizeof(PyLdbObject),
2504 	.tp_doc = "Connection to a LDB database.",
2505 	.tp_as_sequence = &py_ldb_seq,
2506 	.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2507 };
2508 
py_ldb_result_dealloc(PyLdbResultObject * self)2509 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2510 {
2511 	talloc_free(self->mem_ctx);
2512 	Py_DECREF(self->msgs);
2513 	Py_DECREF(self->referals);
2514 	Py_DECREF(self->controls);
2515 	Py_TYPE(self)->tp_free(self);
2516 }
2517 
py_ldb_result_get_msgs(PyLdbResultObject * self,void * closure)2518 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2519 {
2520 	Py_INCREF(self->msgs);
2521 	return self->msgs;
2522 }
2523 
py_ldb_result_get_controls(PyLdbResultObject * self,void * closure)2524 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2525 {
2526 	Py_INCREF(self->controls);
2527 	return self->controls;
2528 }
2529 
py_ldb_result_get_referals(PyLdbResultObject * self,void * closure)2530 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2531 {
2532 	Py_INCREF(self->referals);
2533 	return self->referals;
2534 }
2535 
py_ldb_result_get_count(PyLdbResultObject * self,void * closure)2536 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2537 {
2538 	Py_ssize_t size;
2539 	if (self->msgs == NULL) {
2540 		PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2541 		return NULL;
2542 	}
2543 	size = PyList_Size(self->msgs);
2544 	return PyInt_FromLong(size);
2545 }
2546 
2547 static PyGetSetDef py_ldb_result_getset[] = {
2548 	{
2549 		.name = discard_const_p(char, "controls"),
2550 		.get  = (getter)py_ldb_result_get_controls,
2551 	},
2552 	{
2553 		.name = discard_const_p(char, "msgs"),
2554 		.get  = (getter)py_ldb_result_get_msgs,
2555 	},
2556 	{
2557 		.name = discard_const_p(char, "referals"),
2558 		.get  = (getter)py_ldb_result_get_referals,
2559 	},
2560 	{
2561 		.name = discard_const_p(char, "count"),
2562 		.get  = (getter)py_ldb_result_get_count,
2563 	},
2564 	{ .name = NULL },
2565 };
2566 
py_ldb_result_iter(PyLdbResultObject * self)2567 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2568 {
2569 	return PyObject_GetIter(self->msgs);
2570 }
2571 
py_ldb_result_len(PyLdbResultObject * self)2572 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2573 {
2574 	return PySequence_Size(self->msgs);
2575 }
2576 
py_ldb_result_find(PyLdbResultObject * self,Py_ssize_t idx)2577 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2578 {
2579 	return PySequence_GetItem(self->msgs, idx);
2580 }
2581 
2582 static PySequenceMethods py_ldb_result_seq = {
2583 	.sq_length = (lenfunc)py_ldb_result_len,
2584 	.sq_item = (ssizeargfunc)py_ldb_result_find,
2585 };
2586 
py_ldb_result_repr(PyLdbObject * self)2587 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2588 {
2589 	return PyUnicode_FromString("<ldb result>");
2590 }
2591 
2592 
2593 static PyTypeObject PyLdbResult = {
2594 	.tp_name = "ldb.Result",
2595 	.tp_repr = (reprfunc)py_ldb_result_repr,
2596 	.tp_dealloc = (destructor)py_ldb_result_dealloc,
2597 	.tp_iter = (getiterfunc)py_ldb_result_iter,
2598 	.tp_getset = py_ldb_result_getset,
2599 	.tp_getattro = PyObject_GenericGetAttr,
2600 	.tp_basicsize = sizeof(PyLdbResultObject),
2601 	.tp_as_sequence = &py_ldb_result_seq,
2602 	.tp_doc = "LDB result.",
2603 	.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2604 };
2605 
py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject * self)2606 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2607 {
2608 	Py_XDECREF(self->state.exception);
2609 	TALLOC_FREE(self->mem_ctx);
2610 	ZERO_STRUCT(self->state);
2611 	Py_DECREF(self->ldb);
2612 	Py_TYPE(self)->tp_free(self);
2613 }
2614 
py_ldb_search_iterator_next(PyLdbSearchIteratorObject * self)2615 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2616 {
2617 	PyObject *py_ret = NULL;
2618 
2619 	if (self->state.req == NULL) {
2620 		PyErr_SetString(PyExc_RuntimeError,
2621 				"ldb.SearchIterator request already finished");
2622 		return NULL;
2623 	}
2624 
2625 	/*
2626 	 * TODO: do we want a non-blocking mode?
2627 	 * In future we may add an optional 'nonblocking'
2628 	 * argument to search_iterator().
2629 	 *
2630 	 * For now we keep it simple and wait for at
2631 	 * least one reply.
2632 	 */
2633 
2634 	while (self->state.next == NULL) {
2635 		int ret;
2636 
2637 		if (self->state.result != NULL) {
2638 			/*
2639 			 * We (already) got a final result from the server.
2640 			 *
2641 			 * We stop the iteration and let
2642 			 * py_ldb_search_iterator_result() will deliver
2643 			 * the result details.
2644 			 */
2645 			TALLOC_FREE(self->state.req);
2646 			PyErr_SetNone(PyExc_StopIteration);
2647 			return NULL;
2648 		}
2649 
2650 		ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2651 		if (ret != LDB_SUCCESS) {
2652 			struct ldb_context *ldb_ctx;
2653 			TALLOC_FREE(self->state.req);
2654 			ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
2655 			/*
2656 			 * We stop the iteration and let
2657 			 * py_ldb_search_iterator_result() will deliver
2658 			 * the exception.
2659 			 */
2660 			self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2661 						ret, ldb_errstring(ldb_ctx));
2662 			PyErr_SetNone(PyExc_StopIteration);
2663 			return NULL;
2664 		}
2665 	}
2666 
2667 	py_ret = self->state.next->obj;
2668 	self->state.next->obj = NULL;
2669 	/* no TALLOC_FREE() as self->state.next is a list */
2670 	talloc_free(self->state.next);
2671 	return py_ret;
2672 }
2673 
py_ldb_search_iterator_result(PyLdbSearchIteratorObject * self,PyObject * Py_UNUSED (ignored))2674 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
2675 		PyObject *Py_UNUSED(ignored))
2676 {
2677 	PyObject *py_ret = NULL;
2678 
2679 	if (self->state.req != NULL) {
2680 		PyErr_SetString(PyExc_RuntimeError,
2681 				"ldb.SearchIterator request running");
2682 		return NULL;
2683 	}
2684 
2685 	if (self->state.next != NULL) {
2686 		PyErr_SetString(PyExc_RuntimeError,
2687 				"ldb.SearchIterator not fully consumed.");
2688 		return NULL;
2689 	}
2690 
2691 	if (self->state.exception != NULL) {
2692 		PyErr_SetObject(PyExc_LdbError, self->state.exception);
2693 		self->state.exception = NULL;
2694 		return NULL;
2695 	}
2696 
2697 	if (self->state.result == NULL) {
2698 		PyErr_SetString(PyExc_RuntimeError,
2699 				"ldb.SearchIterator result already consumed");
2700 		return NULL;
2701 	}
2702 
2703 	py_ret = self->state.result->obj;
2704 	self->state.result->obj = NULL;
2705 	TALLOC_FREE(self->state.result);
2706 	return py_ret;
2707 }
2708 
py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject * self,PyObject * Py_UNUSED (ignored))2709 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
2710 		PyObject *Py_UNUSED(ignored))
2711 {
2712 	if (self->state.req == NULL) {
2713 		PyErr_SetString(PyExc_RuntimeError,
2714 				"ldb.SearchIterator request already finished");
2715 		return NULL;
2716 	}
2717 
2718 	Py_XDECREF(self->state.exception);
2719 	TALLOC_FREE(self->mem_ctx);
2720 	ZERO_STRUCT(self->state);
2721 	Py_RETURN_NONE;
2722 }
2723 
2724 static PyMethodDef py_ldb_search_iterator_methods[] = {
2725 	{ "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2726 		"S.result() -> ldb.Result (without msgs and referrals)\n" },
2727 	{ "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2728 		"S.abandon()\n" },
2729 	{ NULL }
2730 };
2731 
py_ldb_search_iterator_repr(PyLdbSearchIteratorObject * self)2732 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2733 {
2734 	return PyUnicode_FromString("<ldb search iterator>");
2735 }
2736 
2737 static PyTypeObject PyLdbSearchIterator = {
2738 	.tp_name = "ldb.SearchIterator",
2739 	.tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2740 	.tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2741 	.tp_iter = PyObject_SelfIter,
2742 	.tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2743 	.tp_methods = py_ldb_search_iterator_methods,
2744 	.tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2745 	.tp_doc = "LDB search_iterator.",
2746 	.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2747 };
2748 
py_ldb_module_repr(PyLdbModuleObject * self)2749 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2750 {
2751 	return PyUnicode_FromFormat("<ldb module '%s'>",
2752 		pyldb_Module_AsModule(self)->ops->name);
2753 }
2754 
py_ldb_module_str(PyLdbModuleObject * self)2755 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2756 {
2757 	return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name);
2758 }
2759 
py_ldb_module_start_transaction(PyLdbModuleObject * self,PyObject * Py_UNUSED (ignored))2760 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self,
2761 		PyObject *Py_UNUSED(ignored))
2762 {
2763 	pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2764 	Py_RETURN_NONE;
2765 }
2766 
py_ldb_module_end_transaction(PyLdbModuleObject * self,PyObject * Py_UNUSED (ignored))2767 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self,
2768 		PyObject *Py_UNUSED(ignored))
2769 {
2770 	pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2771 	Py_RETURN_NONE;
2772 }
2773 
py_ldb_module_del_transaction(PyLdbModuleObject * self,PyObject * Py_UNUSED (ignored))2774 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self,
2775 		PyObject *Py_UNUSED(ignored))
2776 {
2777 	pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2778 	Py_RETURN_NONE;
2779 }
2780 
py_ldb_module_search(PyLdbModuleObject * self,PyObject * args,PyObject * kwargs)2781 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2782 {
2783 	PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2784 	int ret, scope;
2785 	struct ldb_request *req;
2786 	const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2787 	struct ldb_module *mod;
2788 	const char * const*attrs;
2789 
2790 	/* type "int" rather than "enum" for "scope" is intentional */
2791 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2792 					 discard_const_p(char *, kwnames),
2793 					 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2794 		return NULL;
2795 
2796 	mod = self->mod;
2797 
2798 	if (py_attrs == Py_None) {
2799 		attrs = NULL;
2800 	} else {
2801 		attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2802 		if (attrs == NULL)
2803 			return NULL;
2804 	}
2805 
2806 	ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AS_DN(py_base),
2807 			     scope, NULL /* expr */, attrs,
2808 			     NULL /* controls */, NULL, NULL, NULL);
2809 
2810 	talloc_steal(req, attrs);
2811 
2812 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2813 
2814 	req->op.search.res = NULL;
2815 
2816 	ret = mod->ops->search(mod, req);
2817 
2818 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2819 
2820 	py_ret = PyLdbResult_FromResult(req->op.search.res);
2821 
2822 	talloc_free(req);
2823 
2824 	return py_ret;
2825 }
2826 
2827 
py_ldb_module_add(PyLdbModuleObject * self,PyObject * args)2828 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2829 {
2830 	struct ldb_request *req;
2831 	PyObject *py_message;
2832 	int ret;
2833 	struct ldb_module *mod;
2834 
2835 	if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2836 		return NULL;
2837 
2838 	req = talloc_zero(NULL, struct ldb_request);
2839 	req->operation = LDB_ADD;
2840 	req->op.add.message = pyldb_Message_AsMessage(py_message);
2841 
2842 	mod = pyldb_Module_AsModule(self);
2843 	ret = mod->ops->add(mod, req);
2844 
2845 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2846 
2847 	Py_RETURN_NONE;
2848 }
2849 
py_ldb_module_modify(PyLdbModuleObject * self,PyObject * args)2850 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2851 {
2852 	int ret;
2853 	struct ldb_request *req;
2854 	PyObject *py_message;
2855 	struct ldb_module *mod;
2856 
2857 	if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2858 		return NULL;
2859 
2860 	req = talloc_zero(NULL, struct ldb_request);
2861 	req->operation = LDB_MODIFY;
2862 	req->op.mod.message = pyldb_Message_AsMessage(py_message);
2863 
2864 	mod = pyldb_Module_AsModule(self);
2865 	ret = mod->ops->modify(mod, req);
2866 
2867 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2868 
2869 	Py_RETURN_NONE;
2870 }
2871 
py_ldb_module_delete(PyLdbModuleObject * self,PyObject * args)2872 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2873 {
2874 	int ret;
2875 	struct ldb_request *req;
2876 	PyObject *py_dn;
2877 
2878 	if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2879 		return NULL;
2880 
2881 	req = talloc_zero(NULL, struct ldb_request);
2882 	req->operation = LDB_DELETE;
2883 	req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
2884 
2885 	ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2886 
2887 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2888 
2889 	Py_RETURN_NONE;
2890 }
2891 
py_ldb_module_rename(PyLdbModuleObject * self,PyObject * args)2892 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2893 {
2894 	int ret;
2895 	struct ldb_request *req;
2896 	PyObject *py_dn1, *py_dn2;
2897 
2898 	if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2899 		return NULL;
2900 
2901 	req = talloc_zero(NULL, struct ldb_request);
2902 
2903 	req->operation = LDB_RENAME;
2904 	req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
2905 	req->op.rename.newdn = pyldb_Dn_AS_DN(py_dn2);
2906 
2907 	ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2908 
2909 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2910 
2911 	Py_RETURN_NONE;
2912 }
2913 
2914 static PyMethodDef py_ldb_module_methods[] = {
2915 	{ "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search),
2916 		METH_VARARGS|METH_KEYWORDS, NULL },
2917 	{ "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2918 	{ "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2919 	{ "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2920 	{ "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2921 	{ "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2922 	{ "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2923 	{ "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2924 	{ NULL },
2925 };
2926 
py_ldb_module_dealloc(PyLdbModuleObject * self)2927 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2928 {
2929 	talloc_free(self->mem_ctx);
2930 	PyObject_Del(self);
2931 }
2932 
2933 static PyTypeObject PyLdbModule = {
2934 	.tp_name = "ldb.LdbModule",
2935 	.tp_methods = py_ldb_module_methods,
2936 	.tp_repr = (reprfunc)py_ldb_module_repr,
2937 	.tp_str = (reprfunc)py_ldb_module_str,
2938 	.tp_basicsize = sizeof(PyLdbModuleObject),
2939 	.tp_dealloc = (destructor)py_ldb_module_dealloc,
2940 	.tp_flags = Py_TPFLAGS_DEFAULT,
2941 	.tp_doc = "LDB module (extension)",
2942 };
2943 
2944 
2945 /**
2946  * Create a ldb_message_element from a Python object.
2947  *
2948  * This will accept any sequence objects that contains strings, or
2949  * a string object.
2950  *
2951  * A reference to set_obj will be borrowed.
2952  *
2953  * @param mem_ctx Memory context
2954  * @param set_obj Python object to convert
2955  * @param flags ldb_message_element flags to set
2956  * @param attr_name Name of the attribute
2957  * @return New ldb_message_element, allocated as child of mem_ctx
2958  */
PyObject_AsMessageElement(TALLOC_CTX * mem_ctx,PyObject * set_obj,unsigned int flags,const char * attr_name)2959 static struct ldb_message_element *PyObject_AsMessageElement(
2960 						      TALLOC_CTX *mem_ctx,
2961 						      PyObject *set_obj,
2962 						      unsigned int flags,
2963 						      const char *attr_name)
2964 {
2965 	struct ldb_message_element *me;
2966 	const char *msg = NULL;
2967 	Py_ssize_t size;
2968 	int result;
2969 
2970 	if (pyldb_MessageElement_Check(set_obj)) {
2971 		PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2972 		/* We have to talloc_reference() the memory context, not the pointer
2973 		 * which may not actually be it's own context */
2974 		if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2975 			return pyldb_MessageElement_AsMessageElement(set_obj);
2976 		}
2977 		return NULL;
2978 	}
2979 
2980 	me = talloc(mem_ctx, struct ldb_message_element);
2981 	if (me == NULL) {
2982 		PyErr_NoMemory();
2983 		return NULL;
2984 	}
2985 
2986 	me->name = talloc_strdup(me, attr_name);
2987 	me->flags = flags;
2988 	if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
2989 		me->num_values = 1;
2990 		me->values = talloc_array(me, struct ldb_val, me->num_values);
2991 		if (PyBytes_Check(set_obj)) {
2992 			char *_msg = NULL;
2993 			result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2994 			if (result != 0) {
2995 				talloc_free(me);
2996 				return NULL;
2997 			}
2998 			msg = _msg;
2999 		} else {
3000 			msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3001 			if (msg == NULL) {
3002 				talloc_free(me);
3003 				return NULL;
3004 			}
3005 		}
3006 		me->values[0].data = talloc_memdup(me,
3007 						   (const uint8_t *)msg,
3008 						   size+1);
3009 		me->values[0].length = size;
3010 	} else if (PySequence_Check(set_obj)) {
3011 		Py_ssize_t i;
3012 		me->num_values = PySequence_Size(set_obj);
3013 		me->values = talloc_array(me, struct ldb_val, me->num_values);
3014 		for (i = 0; i < me->num_values; i++) {
3015 			PyObject *obj = PySequence_GetItem(set_obj, i);
3016 			if (PyBytes_Check(obj)) {
3017 				char *_msg = NULL;
3018 				result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3019 				if (result != 0) {
3020 					talloc_free(me);
3021 					return NULL;
3022 				}
3023 				msg = _msg;
3024 			} else if (PyUnicode_Check(obj)) {
3025 				msg = PyUnicode_AsUTF8AndSize(obj, &size);
3026 				if (msg == NULL) {
3027 					talloc_free(me);
3028 					return NULL;
3029 				}
3030 			} else {
3031 				PyErr_Format(PyExc_TypeError,
3032 					     "Expected string as element %zd in list", i);
3033 				talloc_free(me);
3034 				return NULL;
3035 			}
3036 			me->values[i].data = talloc_memdup(me,
3037 							   (const uint8_t *)msg,
3038 							   size+1);
3039 			me->values[i].length = size;
3040 		}
3041 	} else {
3042 		PyErr_Format(PyExc_TypeError,
3043 			     "String or List type expected for '%s' attribute", attr_name);
3044 		talloc_free(me);
3045 		me = NULL;
3046 	}
3047 
3048 	return me;
3049 }
3050 
3051 
ldb_msg_element_to_set(struct ldb_context * ldb_ctx,struct ldb_message_element * me)3052 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3053 					struct ldb_message_element *me)
3054 {
3055 	Py_ssize_t i;
3056 	PyObject *result;
3057 
3058 	/* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3059 	result = PyList_New(me->num_values);
3060 
3061 	for (i = 0; i < me->num_values; i++) {
3062 		PyList_SetItem(result, i,
3063 			PyObject_FromLdbValue(&me->values[i]));
3064 	}
3065 
3066 	return result;
3067 }
3068 
py_ldb_msg_element_get(PyLdbMessageElementObject * self,PyObject * args)3069 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3070 {
3071 	unsigned int i;
3072 	if (!PyArg_ParseTuple(args, "I", &i))
3073 		return NULL;
3074 	if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3075 		Py_RETURN_NONE;
3076 
3077 	return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3078 }
3079 
py_ldb_msg_element_flags(PyLdbMessageElementObject * self,PyObject * args)3080 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3081 {
3082 	struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3083 	return PyInt_FromLong(el->flags);
3084 }
3085 
py_ldb_msg_element_set_flags(PyLdbMessageElementObject * self,PyObject * args)3086 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3087 {
3088 	unsigned int flags;
3089 	struct ldb_message_element *el;
3090 	if (!PyArg_ParseTuple(args, "I", &flags))
3091 		return NULL;
3092 
3093 	el = pyldb_MessageElement_AsMessageElement(self);
3094 	el->flags = flags;
3095 	Py_RETURN_NONE;
3096 }
3097 
3098 static PyMethodDef py_ldb_msg_element_methods[] = {
3099 	{ "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3100 	{ "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3101 	{ "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3102 	{ NULL },
3103 };
3104 
py_ldb_msg_element_len(PyLdbMessageElementObject * self)3105 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3106 {
3107 	return pyldb_MessageElement_AsMessageElement(self)->num_values;
3108 }
3109 
py_ldb_msg_element_find(PyLdbMessageElementObject * self,Py_ssize_t idx)3110 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3111 {
3112 	struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3113 	if (idx < 0 || idx >= el->num_values) {
3114 		PyErr_SetString(PyExc_IndexError, "Out of range");
3115 		return NULL;
3116 	}
3117 	return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3118 }
3119 
3120 static PySequenceMethods py_ldb_msg_element_seq = {
3121 	.sq_length = (lenfunc)py_ldb_msg_element_len,
3122 	.sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3123 };
3124 
py_ldb_msg_element_richcmp(PyObject * self,PyObject * other,int op)3125 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3126 {
3127 	int ret;
3128 	if (!pyldb_MessageElement_Check(other)) {
3129 		Py_INCREF(Py_NotImplemented);
3130 		return Py_NotImplemented;
3131 	}
3132 	ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3133 									  pyldb_MessageElement_AsMessageElement(other));
3134 	return richcmp(ret, op);
3135 }
3136 
py_ldb_msg_element_iter(PyLdbMessageElementObject * self)3137 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3138 {
3139 	PyObject *el = ldb_msg_element_to_set(NULL,
3140 					      pyldb_MessageElement_AsMessageElement(self));
3141 	PyObject *ret = PyObject_GetIter(el);
3142 	Py_DECREF(el);
3143 	return ret;
3144 }
3145 
PyLdbMessageElement_FromMessageElement(struct ldb_message_element * el,TALLOC_CTX * mem_ctx)3146 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3147 {
3148 	PyLdbMessageElementObject *ret;
3149 	ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3150 	if (ret == NULL) {
3151 		PyErr_NoMemory();
3152 		return NULL;
3153 	}
3154 	ret->mem_ctx = talloc_new(NULL);
3155 	if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3156 		PyErr_NoMemory();
3157 		return NULL;
3158 	}
3159 	ret->el = el;
3160 	return (PyObject *)ret;
3161 }
3162 
py_ldb_msg_element_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)3163 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3164 {
3165 	PyObject *py_elements = NULL;
3166 	struct ldb_message_element *el;
3167 	unsigned int flags = 0;
3168 	char *name = NULL;
3169 	const char * const kwnames[] = { "elements", "flags", "name", NULL };
3170 	PyLdbMessageElementObject *ret;
3171 	TALLOC_CTX *mem_ctx;
3172 	const char *msg = NULL;
3173 	Py_ssize_t size;
3174 	int result;
3175 
3176 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3177 					 discard_const_p(char *, kwnames),
3178 					 &py_elements, &flags, &name))
3179 		return NULL;
3180 
3181 	mem_ctx = talloc_new(NULL);
3182 	if (mem_ctx == NULL) {
3183 		PyErr_NoMemory();
3184 		return NULL;
3185 	}
3186 
3187 	el = talloc_zero(mem_ctx, struct ldb_message_element);
3188 	if (el == NULL) {
3189 		PyErr_NoMemory();
3190 		talloc_free(mem_ctx);
3191 		return NULL;
3192 	}
3193 
3194 	if (py_elements != NULL) {
3195 		Py_ssize_t i;
3196 		if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3197 			char *_msg = NULL;
3198 			el->num_values = 1;
3199 			el->values = talloc_array(el, struct ldb_val, 1);
3200 			if (el->values == NULL) {
3201 				talloc_free(mem_ctx);
3202 				PyErr_NoMemory();
3203 				return NULL;
3204 			}
3205 			if (PyBytes_Check(py_elements)) {
3206 				result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3207 				msg = _msg;
3208 			} else {
3209 				msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3210 				result = (msg == NULL) ? -1 : 0;
3211 			}
3212 			if (result != 0) {
3213 				talloc_free(mem_ctx);
3214 				return NULL;
3215 			}
3216 			el->values[0].data = talloc_memdup(el->values,
3217 				(const uint8_t *)msg, size + 1);
3218 			el->values[0].length = size;
3219 		} else if (PySequence_Check(py_elements)) {
3220 			el->num_values = PySequence_Size(py_elements);
3221 			el->values = talloc_array(el, struct ldb_val, el->num_values);
3222 			if (el->values == NULL) {
3223 				talloc_free(mem_ctx);
3224 				PyErr_NoMemory();
3225 				return NULL;
3226 			}
3227 			for (i = 0; i < el->num_values; i++) {
3228 				PyObject *item = PySequence_GetItem(py_elements, i);
3229 				if (item == NULL) {
3230 					talloc_free(mem_ctx);
3231 					return NULL;
3232 				}
3233 				if (PyBytes_Check(item)) {
3234 					char *_msg = NULL;
3235 					result = PyBytes_AsStringAndSize(item, &_msg, &size);
3236 					msg = _msg;
3237 				} else if (PyUnicode_Check(item)) {
3238 					msg = PyUnicode_AsUTF8AndSize(item, &size);
3239 					result = (msg == NULL) ? -1 : 0;
3240 				} else {
3241 					PyErr_Format(PyExc_TypeError,
3242 						     "Expected string as element %zd in list", i);
3243 					result = -1;
3244 				}
3245 				if (result != 0) {
3246 					talloc_free(mem_ctx);
3247 					return NULL;
3248 				}
3249 				el->values[i].data = talloc_memdup(el,
3250 					(const uint8_t *)msg, size+1);
3251 				el->values[i].length = size;
3252 			}
3253 		} else {
3254 			PyErr_SetString(PyExc_TypeError,
3255 					"Expected string or list");
3256 			talloc_free(mem_ctx);
3257 			return NULL;
3258 		}
3259 	}
3260 
3261 	el->flags = flags;
3262 	el->name = talloc_strdup(el, name);
3263 
3264 	ret = PyObject_New(PyLdbMessageElementObject, type);
3265 	if (ret == NULL) {
3266 		talloc_free(mem_ctx);
3267 		return NULL;
3268 	}
3269 
3270 	ret->mem_ctx = mem_ctx;
3271 	ret->el = el;
3272 	return (PyObject *)ret;
3273 }
3274 
py_ldb_msg_element_repr(PyLdbMessageElementObject * self)3275 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3276 {
3277 	char *element_str = NULL;
3278 	Py_ssize_t i;
3279 	struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3280 	PyObject *ret, *repr;
3281 
3282 	for (i = 0; i < el->num_values; i++) {
3283 		PyObject *o = py_ldb_msg_element_find(self, i);
3284 		repr = PyObject_Repr(o);
3285 		if (element_str == NULL)
3286 			element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3287 		else
3288 			element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3289 		Py_DECREF(repr);
3290 	}
3291 
3292 	if (element_str != NULL) {
3293 		ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3294 		talloc_free(element_str);
3295 	} else {
3296 		ret = PyUnicode_FromString("MessageElement([])");
3297 	}
3298 
3299 	return ret;
3300 }
3301 
py_ldb_msg_element_str(PyLdbMessageElementObject * self)3302 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3303 {
3304 	struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3305 
3306 	if (el->num_values == 1)
3307 		return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3308 	else
3309 		Py_RETURN_NONE;
3310 }
3311 
py_ldb_msg_element_dealloc(PyLdbMessageElementObject * self)3312 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3313 {
3314 	talloc_free(self->mem_ctx);
3315 	PyObject_Del(self);
3316 }
3317 
py_ldb_msg_element_get_text(PyObject * self,void * closure)3318 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3319 {
3320 	return wrap_text("MessageElementTextWrapper", self);
3321 }
3322 
3323 static PyGetSetDef py_ldb_msg_element_getset[] = {
3324 	{
3325 		.name = discard_const_p(char, "text"),
3326 		.get  = (getter)py_ldb_msg_element_get_text,
3327 	},
3328 	{ .name = NULL }
3329 };
3330 
3331 static PyTypeObject PyLdbMessageElement = {
3332 	.tp_name = "ldb.MessageElement",
3333 	.tp_basicsize = sizeof(PyLdbMessageElementObject),
3334 	.tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3335 	.tp_repr = (reprfunc)py_ldb_msg_element_repr,
3336 	.tp_str = (reprfunc)py_ldb_msg_element_str,
3337 	.tp_methods = py_ldb_msg_element_methods,
3338 	.tp_getset = py_ldb_msg_element_getset,
3339 	.tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3340 	.tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3341 	.tp_as_sequence = &py_ldb_msg_element_seq,
3342 	.tp_new = py_ldb_msg_element_new,
3343 	.tp_flags = Py_TPFLAGS_DEFAULT,
3344 	.tp_doc = "An element of a Message",
3345 };
3346 
3347 
py_ldb_msg_from_dict(PyTypeObject * type,PyObject * args)3348 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3349 {
3350 	PyObject *py_ldb;
3351 	PyObject *py_dict;
3352 	PyObject *py_ret;
3353 	struct ldb_message *msg;
3354 	struct ldb_context *ldb_ctx;
3355 	unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3356 
3357 	if (!PyArg_ParseTuple(args, "O!O!|I",
3358 			      &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3359 			      &mod_flags)) {
3360 		return NULL;
3361 	}
3362 
3363 	if (!PyLdb_Check(py_ldb)) {
3364 		PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3365 		return NULL;
3366 	}
3367 
3368 	/* mask only flags we are going to use */
3369 	mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3370 	if (!mod_flags) {
3371 		PyErr_SetString(PyExc_ValueError,
3372 				"FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3373 				" expected as mod_flag value");
3374 		return NULL;
3375 	}
3376 
3377 	ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3378 
3379 	msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3380 	if (!msg) {
3381 		return NULL;
3382 	}
3383 
3384 	py_ret = PyLdbMessage_FromMessage(msg);
3385 
3386 	talloc_unlink(ldb_ctx, msg);
3387 
3388 	return py_ret;
3389 }
3390 
py_ldb_msg_remove_attr(PyLdbMessageObject * self,PyObject * args)3391 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3392 {
3393 	char *name;
3394 	if (!PyArg_ParseTuple(args, "s", &name))
3395 		return NULL;
3396 
3397 	ldb_msg_remove_attr(self->msg, name);
3398 
3399 	Py_RETURN_NONE;
3400 }
3401 
py_ldb_msg_keys(PyLdbMessageObject * self,PyObject * Py_UNUSED (ignored))3402 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self,
3403 		PyObject *Py_UNUSED(ignored))
3404 {
3405 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3406 	Py_ssize_t i, j = 0;
3407 	PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3408 	if (msg->dn != NULL) {
3409 		PyList_SetItem(obj, j, PyUnicode_FromString("dn"));
3410 		j++;
3411 	}
3412 	for (i = 0; i < msg->num_elements; i++) {
3413 		PyList_SetItem(obj, j, PyUnicode_FromString(msg->elements[i].name));
3414 		j++;
3415 	}
3416 	return obj;
3417 }
3418 
py_ldb_msg_getitem_helper(PyLdbMessageObject * self,PyObject * py_name)3419 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3420 {
3421 	struct ldb_message_element *el;
3422 	const char *name;
3423 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3424 	name = PyUnicode_AsUTF8(py_name);
3425 	if (name == NULL) {
3426 		PyErr_SetNone(PyExc_TypeError);
3427 		return NULL;
3428 	}
3429 	if (!ldb_attr_cmp(name, "dn"))
3430 		return pyldb_Dn_FromDn(msg->dn);
3431 	el = ldb_msg_find_element(msg, name);
3432 	if (el == NULL) {
3433 		return NULL;
3434 	}
3435 	return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3436 }
3437 
py_ldb_msg_getitem(PyLdbMessageObject * self,PyObject * py_name)3438 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3439 {
3440 	PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3441 	if (ret == NULL) {
3442 		PyErr_SetString(PyExc_KeyError, "No such element");
3443 		return NULL;
3444 	}
3445 	return ret;
3446 }
3447 
py_ldb_msg_get(PyLdbMessageObject * self,PyObject * args,PyObject * kwargs)3448 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3449 {
3450 	PyObject *def = NULL;
3451 	const char *kwnames[] = { "name", "default", "idx", NULL };
3452 	const char *name = NULL;
3453 	int idx = -1;
3454 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3455 	struct ldb_message_element *el;
3456 
3457 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3458 					 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3459 		return NULL;
3460 	}
3461 
3462 	if (strcasecmp(name, "dn") == 0) {
3463 		return pyldb_Dn_FromDn(msg->dn);
3464 	}
3465 
3466 	el = ldb_msg_find_element(msg, name);
3467 
3468 	if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3469 		if (def != NULL) {
3470 			Py_INCREF(def);
3471 			return def;
3472 		}
3473 		Py_RETURN_NONE;
3474 	}
3475 
3476 	if (idx == -1) {
3477 		return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3478 	}
3479 
3480 	return PyObject_FromLdbValue(&el->values[idx]);
3481 }
3482 
py_ldb_msg_items(PyLdbMessageObject * self,PyObject * Py_UNUSED (ignored))3483 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
3484 		PyObject *Py_UNUSED(ignored))
3485 {
3486 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3487 	Py_ssize_t i, j = 0;
3488 	PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3489 	if (l == NULL) {
3490 		return PyErr_NoMemory();
3491 	}
3492 	if (msg->dn != NULL) {
3493 		PyObject *value = NULL;
3494 		PyObject *obj = pyldb_Dn_FromDn(msg->dn);
3495 		int res = 0;
3496 		value = Py_BuildValue("(sO)", "dn", obj);
3497 		Py_CLEAR(obj);
3498 		if (value == NULL) {
3499 			Py_CLEAR(l);
3500 			return NULL;
3501 		}
3502 		res = PyList_SetItem(l, 0, value);
3503 		if (res == -1) {
3504 			Py_CLEAR(l);
3505 			return NULL;
3506 		}
3507 		j++;
3508 	}
3509 	for (i = 0; i < msg->num_elements; i++, j++) {
3510 		PyObject *value = NULL;
3511 		PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3512 		int res = 0;
3513 		Py_CLEAR(py_el);
3514 		value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3515 		if (value == NULL ) {
3516 			Py_CLEAR(l);
3517 			return NULL;
3518 		}
3519 		res = PyList_SetItem(l, 0, value);
3520 		if (res == -1) {
3521 			Py_CLEAR(l);
3522 			return NULL;
3523 		}
3524 	}
3525 	return l;
3526 }
3527 
py_ldb_msg_elements(PyLdbMessageObject * self,PyObject * Py_UNUSED (ignored))3528 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self,
3529 		PyObject *Py_UNUSED(ignored))
3530 {
3531 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3532 	Py_ssize_t i = 0;
3533 	PyObject *l = PyList_New(msg->num_elements);
3534 	for (i = 0; i < msg->num_elements; i++) {
3535 		PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3536 	}
3537 	return l;
3538 }
3539 
py_ldb_msg_add(PyLdbMessageObject * self,PyObject * args)3540 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3541 {
3542 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3543 	PyLdbMessageElementObject *py_element;
3544 	int i, ret;
3545 	struct ldb_message_element *el;
3546 	struct ldb_message_element *el_new;
3547 
3548 	if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3549 		return NULL;
3550 
3551 	el = py_element->el;
3552 	if (el == NULL) {
3553 		PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3554 		return NULL;
3555 	}
3556 	if (el->name == NULL) {
3557 		PyErr_SetString(PyExc_ValueError,
3558 				"The element has no name");
3559 		return NULL;
3560 	}
3561 	ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3562 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3563 
3564 	/* now deep copy all attribute values */
3565 	el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3566 	if (el_new->values == NULL) {
3567 		PyErr_NoMemory();
3568 		return NULL;
3569 	}
3570 	el_new->num_values = el->num_values;
3571 
3572 	for (i = 0; i < el->num_values; i++) {
3573 		el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3574 		if (el_new->values[i].data == NULL
3575 				&& el->values[i].length != 0) {
3576 			PyErr_NoMemory();
3577 			return NULL;
3578 		}
3579 	}
3580 
3581 	Py_RETURN_NONE;
3582 }
3583 
3584 static PyMethodDef py_ldb_msg_methods[] = {
3585 	{ "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3586 		"Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3587 		"Class method to create ldb.Message object from Dictionary.\n"
3588 		"mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3589 	{ "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3590 		"S.keys() -> list\n\n"
3591 		"Return sequence of all attribute names." },
3592 	{ "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3593 		"S.remove(name)\n\n"
3594 		"Remove all entries for attributes with the specified name."},
3595 	{ "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
3596 		METH_VARARGS | METH_KEYWORDS,
3597 	  "msg.get(name,default=None,idx=None) -> string\n"
3598 	  "idx is the index into the values array\n"
3599 	  "if idx is None, then a list is returned\n"
3600 	  "if idx is not None, then the element with that index is returned\n"
3601 	  "if you pass the special name 'dn' then the DN object is returned\n"},
3602 	{ "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3603 	{ "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3604 	{ "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3605 		"S.add(element)\n\n"
3606 		"Add an element to this message." },
3607 	{ NULL },
3608 };
3609 
py_ldb_msg_iter(PyLdbMessageObject * self)3610 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3611 {
3612 	PyObject *list, *iter;
3613 
3614 	list = py_ldb_msg_keys(self, NULL);
3615 	iter = PyObject_GetIter(list);
3616 	Py_DECREF(list);
3617 	return iter;
3618 }
3619 
py_ldb_msg_setitem(PyLdbMessageObject * self,PyObject * name,PyObject * value)3620 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3621 {
3622 	const char *attr_name;
3623 
3624 	attr_name = PyUnicode_AsUTF8(name);
3625 	if (attr_name == NULL) {
3626 		PyErr_SetNone(PyExc_TypeError);
3627 		return -1;
3628 	}
3629 
3630 	if (value == NULL) {
3631 		/* delitem */
3632 		ldb_msg_remove_attr(self->msg, attr_name);
3633 	} else {
3634 		int ret;
3635 		struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3636 									   value, 0, attr_name);
3637 		if (el == NULL) {
3638 			return -1;
3639 		}
3640 		ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3641 		ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3642 		if (ret != LDB_SUCCESS) {
3643 			PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3644 			return -1;
3645 		}
3646 	}
3647 	return 0;
3648 }
3649 
py_ldb_msg_length(PyLdbMessageObject * self)3650 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3651 {
3652 	return pyldb_Message_AsMessage(self)->num_elements;
3653 }
3654 
3655 static PyMappingMethods py_ldb_msg_mapping = {
3656 	.mp_length = (lenfunc)py_ldb_msg_length,
3657 	.mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3658 	.mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3659 };
3660 
py_ldb_msg_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)3661 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3662 {
3663 	const char * const kwnames[] = { "dn", NULL };
3664 	struct ldb_message *ret;
3665 	TALLOC_CTX *mem_ctx;
3666 	PyObject *pydn = NULL;
3667 	PyLdbMessageObject *py_ret;
3668 
3669 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3670 					 discard_const_p(char *, kwnames),
3671 					 &pydn))
3672 		return NULL;
3673 
3674 	mem_ctx = talloc_new(NULL);
3675 	if (mem_ctx == NULL) {
3676 		PyErr_NoMemory();
3677 		return NULL;
3678 	}
3679 
3680 	ret = ldb_msg_new(mem_ctx);
3681 	if (ret == NULL) {
3682 		talloc_free(mem_ctx);
3683 		PyErr_NoMemory();
3684 		return NULL;
3685 	}
3686 
3687 	if (pydn != NULL) {
3688 		struct ldb_dn *dn;
3689 		if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3690 			talloc_free(mem_ctx);
3691 			return NULL;
3692 		}
3693 		ret->dn = talloc_reference(ret, dn);
3694 	}
3695 
3696 	py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3697 	if (py_ret == NULL) {
3698 		PyErr_NoMemory();
3699 		talloc_free(mem_ctx);
3700 		return NULL;
3701 	}
3702 
3703 	py_ret->mem_ctx = mem_ctx;
3704 	py_ret->msg = ret;
3705 	return (PyObject *)py_ret;
3706 }
3707 
PyLdbMessage_FromMessage(struct ldb_message * msg)3708 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3709 {
3710 	PyLdbMessageObject *ret;
3711 
3712 	ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3713 	if (ret == NULL) {
3714 		PyErr_NoMemory();
3715 		return NULL;
3716 	}
3717 	ret->mem_ctx = talloc_new(NULL);
3718 	ret->msg = talloc_reference(ret->mem_ctx, msg);
3719 	return (PyObject *)ret;
3720 }
3721 
py_ldb_msg_get_dn(PyLdbMessageObject * self,void * closure)3722 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3723 {
3724 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3725 	return pyldb_Dn_FromDn(msg->dn);
3726 }
3727 
py_ldb_msg_set_dn(PyLdbMessageObject * self,PyObject * value,void * closure)3728 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3729 {
3730 	struct ldb_message *msg = pyldb_Message_AsMessage(self);
3731 	if (!pyldb_Dn_Check(value)) {
3732 		PyErr_SetString(PyExc_TypeError, "expected dn");
3733 		return -1;
3734 	}
3735 
3736 	msg->dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
3737 	return 0;
3738 }
3739 
py_ldb_msg_get_text(PyObject * self,void * closure)3740 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3741 {
3742 	return wrap_text("MessageTextWrapper", self);
3743 }
3744 
3745 static PyGetSetDef py_ldb_msg_getset[] = {
3746 	{
3747 		.name = discard_const_p(char, "dn"),
3748 		.get  = (getter)py_ldb_msg_get_dn,
3749 		.set  = (setter)py_ldb_msg_set_dn,
3750 	},
3751 	{
3752 		.name = discard_const_p(char, "text"),
3753 		.get  = (getter)py_ldb_msg_get_text,
3754 	},
3755 	{ .name = NULL },
3756 };
3757 
py_ldb_msg_repr(PyLdbMessageObject * self)3758 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3759 {
3760 	PyObject *dict = PyDict_New(), *ret, *repr;
3761 	if (PyDict_Update(dict, (PyObject *)self) != 0)
3762 		return NULL;
3763 	repr = PyObject_Repr(dict);
3764 	if (repr == NULL) {
3765 		Py_DECREF(dict);
3766 		return NULL;
3767 	}
3768 	ret = PyUnicode_FromFormat("Message(%s)", PyUnicode_AsUTF8(repr));
3769 	Py_DECREF(repr);
3770 	Py_DECREF(dict);
3771 	return ret;
3772 }
3773 
py_ldb_msg_dealloc(PyLdbMessageObject * self)3774 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3775 {
3776 	talloc_free(self->mem_ctx);
3777 	PyObject_Del(self);
3778 }
3779 
py_ldb_msg_richcmp(PyLdbMessageObject * py_msg1,PyLdbMessageObject * py_msg2,int op)3780 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3781 			      PyLdbMessageObject *py_msg2, int op)
3782 {
3783 	struct ldb_message *msg1, *msg2;
3784 	unsigned int i;
3785 	int ret;
3786 
3787 	if (!PyLdbMessage_Check(py_msg2)) {
3788 		Py_INCREF(Py_NotImplemented);
3789 		return Py_NotImplemented;
3790 	}
3791 
3792 	msg1 = pyldb_Message_AsMessage(py_msg1),
3793 	msg2 = pyldb_Message_AsMessage(py_msg2);
3794 
3795 	if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3796 		ret = ldb_dn_compare(msg1->dn, msg2->dn);
3797 		if (ret != 0) {
3798 			return richcmp(ret, op);
3799 		}
3800 	}
3801 
3802 	ret = msg1->num_elements - msg2->num_elements;
3803 	if (ret != 0) {
3804 		return richcmp(ret, op);
3805 	}
3806 
3807 	for (i = 0; i < msg1->num_elements; i++) {
3808 		ret = ldb_msg_element_compare_name(&msg1->elements[i],
3809 						   &msg2->elements[i]);
3810 		if (ret != 0) {
3811 			return richcmp(ret, op);
3812 		}
3813 
3814 		ret = ldb_msg_element_compare(&msg1->elements[i],
3815 					      &msg2->elements[i]);
3816 		if (ret != 0) {
3817 			return richcmp(ret, op);
3818 		}
3819 	}
3820 
3821 	return richcmp(0, op);
3822 }
3823 
3824 static PyTypeObject PyLdbMessage = {
3825 	.tp_name = "ldb.Message",
3826 	.tp_methods = py_ldb_msg_methods,
3827 	.tp_getset = py_ldb_msg_getset,
3828 	.tp_as_mapping = &py_ldb_msg_mapping,
3829 	.tp_basicsize = sizeof(PyLdbMessageObject),
3830 	.tp_dealloc = (destructor)py_ldb_msg_dealloc,
3831 	.tp_new = py_ldb_msg_new,
3832 	.tp_repr = (reprfunc)py_ldb_msg_repr,
3833 	.tp_flags = Py_TPFLAGS_DEFAULT,
3834 	.tp_iter = (getiterfunc)py_ldb_msg_iter,
3835 	.tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3836 	.tp_doc = "A LDB Message",
3837 };
3838 
PyLdbTree_FromTree(struct ldb_parse_tree * tree)3839 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3840 {
3841 	PyLdbTreeObject *ret;
3842 
3843 	ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3844 	if (ret == NULL) {
3845 		PyErr_NoMemory();
3846 		return NULL;
3847 	}
3848 
3849 	ret->mem_ctx = talloc_new(NULL);
3850 	ret->tree = talloc_reference(ret->mem_ctx, tree);
3851 	return (PyObject *)ret;
3852 }
3853 
py_ldb_tree_dealloc(PyLdbTreeObject * self)3854 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3855 {
3856 	talloc_free(self->mem_ctx);
3857 	PyObject_Del(self);
3858 }
3859 
3860 static PyTypeObject PyLdbTree = {
3861 	.tp_name = "ldb.Tree",
3862 	.tp_basicsize = sizeof(PyLdbTreeObject),
3863 	.tp_dealloc = (destructor)py_ldb_tree_dealloc,
3864 	.tp_flags = Py_TPFLAGS_DEFAULT,
3865 	.tp_doc = "A search tree",
3866 };
3867 
3868 /* Ldb_module */
py_module_search(struct ldb_module * mod,struct ldb_request * req)3869 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3870 {
3871 	PyObject *py_ldb = (PyObject *)mod->private_data;
3872 	PyObject *py_result, *py_base, *py_attrs, *py_tree;
3873 
3874 	py_base = pyldb_Dn_FromDn(req->op.search.base);
3875 
3876 	if (py_base == NULL)
3877 		return LDB_ERR_OPERATIONS_ERROR;
3878 
3879 	py_tree = PyLdbTree_FromTree(req->op.search.tree);
3880 
3881 	if (py_tree == NULL)
3882 		return LDB_ERR_OPERATIONS_ERROR;
3883 
3884 	if (req->op.search.attrs == NULL) {
3885 		py_attrs = Py_None;
3886 	} else {
3887 		int i, len;
3888 		for (len = 0; req->op.search.attrs[len]; len++);
3889 		py_attrs = PyList_New(len);
3890 		for (i = 0; i < len; i++)
3891 			PyList_SetItem(py_attrs, i, PyUnicode_FromString(req->op.search.attrs[i]));
3892 	}
3893 
3894 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3895 					discard_const_p(char, "OiOO"),
3896 					py_base, req->op.search.scope, py_tree, py_attrs);
3897 
3898 	Py_DECREF(py_attrs);
3899 	Py_DECREF(py_tree);
3900 	Py_DECREF(py_base);
3901 
3902 	if (py_result == NULL) {
3903 		return LDB_ERR_PYTHON_EXCEPTION;
3904 	}
3905 
3906 	req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3907 	if (req->op.search.res == NULL) {
3908 		return LDB_ERR_PYTHON_EXCEPTION;
3909 	}
3910 
3911 	Py_DECREF(py_result);
3912 
3913 	return LDB_SUCCESS;
3914 }
3915 
py_module_add(struct ldb_module * mod,struct ldb_request * req)3916 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3917 {
3918 	PyObject *py_ldb = (PyObject *)mod->private_data;
3919 	PyObject *py_result, *py_msg;
3920 
3921 	py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3922 
3923 	if (py_msg == NULL) {
3924 		return LDB_ERR_OPERATIONS_ERROR;
3925 	}
3926 
3927 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3928 					discard_const_p(char, "O"),
3929 					py_msg);
3930 
3931 	Py_DECREF(py_msg);
3932 
3933 	if (py_result == NULL) {
3934 		return LDB_ERR_PYTHON_EXCEPTION;
3935 	}
3936 
3937 	Py_DECREF(py_result);
3938 
3939 	return LDB_SUCCESS;
3940 }
3941 
py_module_modify(struct ldb_module * mod,struct ldb_request * req)3942 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3943 {
3944 	PyObject *py_ldb = (PyObject *)mod->private_data;
3945 	PyObject *py_result, *py_msg;
3946 
3947 	py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3948 
3949 	if (py_msg == NULL) {
3950 		return LDB_ERR_OPERATIONS_ERROR;
3951 	}
3952 
3953 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3954 					discard_const_p(char, "O"),
3955 					py_msg);
3956 
3957 	Py_DECREF(py_msg);
3958 
3959 	if (py_result == NULL) {
3960 		return LDB_ERR_PYTHON_EXCEPTION;
3961 	}
3962 
3963 	Py_DECREF(py_result);
3964 
3965 	return LDB_SUCCESS;
3966 }
3967 
py_module_del(struct ldb_module * mod,struct ldb_request * req)3968 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3969 {
3970 	PyObject *py_ldb = (PyObject *)mod->private_data;
3971 	PyObject *py_result, *py_dn;
3972 
3973 	py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3974 
3975 	if (py_dn == NULL)
3976 		return LDB_ERR_OPERATIONS_ERROR;
3977 
3978 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3979 					discard_const_p(char, "O"),
3980 					py_dn);
3981 
3982 	if (py_result == NULL) {
3983 		return LDB_ERR_PYTHON_EXCEPTION;
3984 	}
3985 
3986 	Py_DECREF(py_result);
3987 
3988 	return LDB_SUCCESS;
3989 }
3990 
py_module_rename(struct ldb_module * mod,struct ldb_request * req)3991 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3992 {
3993 	PyObject *py_ldb = (PyObject *)mod->private_data;
3994 	PyObject *py_result, *py_olddn, *py_newdn;
3995 
3996 	py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3997 
3998 	if (py_olddn == NULL)
3999 		return LDB_ERR_OPERATIONS_ERROR;
4000 
4001 	py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
4002 
4003 	if (py_newdn == NULL)
4004 		return LDB_ERR_OPERATIONS_ERROR;
4005 
4006 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
4007 					discard_const_p(char, "OO"),
4008 					py_olddn, py_newdn);
4009 
4010 	Py_DECREF(py_olddn);
4011 	Py_DECREF(py_newdn);
4012 
4013 	if (py_result == NULL) {
4014 		return LDB_ERR_PYTHON_EXCEPTION;
4015 	}
4016 
4017 	Py_DECREF(py_result);
4018 
4019 	return LDB_SUCCESS;
4020 }
4021 
py_module_request(struct ldb_module * mod,struct ldb_request * req)4022 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
4023 {
4024 	PyObject *py_ldb = (PyObject *)mod->private_data;
4025 	PyObject *py_result;
4026 
4027 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
4028 					discard_const_p(char, ""));
4029 
4030 	Py_XDECREF(py_result);
4031 
4032 	return LDB_ERR_OPERATIONS_ERROR;
4033 }
4034 
py_module_extended(struct ldb_module * mod,struct ldb_request * req)4035 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
4036 {
4037 	PyObject *py_ldb = (PyObject *)mod->private_data;
4038 	PyObject *py_result;
4039 
4040 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
4041 					discard_const_p(char, ""));
4042 
4043 	Py_XDECREF(py_result);
4044 
4045 	return LDB_ERR_OPERATIONS_ERROR;
4046 }
4047 
py_module_start_transaction(struct ldb_module * mod)4048 static int py_module_start_transaction(struct ldb_module *mod)
4049 {
4050 	PyObject *py_ldb = (PyObject *)mod->private_data;
4051 	PyObject *py_result;
4052 
4053 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
4054 					discard_const_p(char, ""));
4055 
4056 	if (py_result == NULL) {
4057 		return LDB_ERR_PYTHON_EXCEPTION;
4058 	}
4059 
4060 	Py_DECREF(py_result);
4061 
4062 	return LDB_SUCCESS;
4063 }
4064 
py_module_end_transaction(struct ldb_module * mod)4065 static int py_module_end_transaction(struct ldb_module *mod)
4066 {
4067 	PyObject *py_ldb = (PyObject *)mod->private_data;
4068 	PyObject *py_result;
4069 
4070 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
4071 					discard_const_p(char, ""));
4072 
4073 	if (py_result == NULL) {
4074 		return LDB_ERR_PYTHON_EXCEPTION;
4075 	}
4076 
4077 	Py_DECREF(py_result);
4078 
4079 	return LDB_SUCCESS;
4080 }
4081 
py_module_del_transaction(struct ldb_module * mod)4082 static int py_module_del_transaction(struct ldb_module *mod)
4083 {
4084 	PyObject *py_ldb = (PyObject *)mod->private_data;
4085 	PyObject *py_result;
4086 
4087 	py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
4088 					discard_const_p(char, ""));
4089 
4090 	if (py_result == NULL) {
4091 		return LDB_ERR_PYTHON_EXCEPTION;
4092 	}
4093 
4094 	Py_DECREF(py_result);
4095 
4096 	return LDB_SUCCESS;
4097 }
4098 
py_module_destructor(struct ldb_module * mod)4099 static int py_module_destructor(struct ldb_module *mod)
4100 {
4101 	Py_DECREF((PyObject *)mod->private_data);
4102 	return 0;
4103 }
4104 
py_module_init(struct ldb_module * mod)4105 static int py_module_init(struct ldb_module *mod)
4106 {
4107 	PyObject *py_class = (PyObject *)mod->ops->private_data;
4108 	PyObject *py_result, *py_next, *py_ldb;
4109 
4110 	py_ldb = PyLdb_FromLdbContext(mod->ldb);
4111 
4112 	if (py_ldb == NULL)
4113 		return LDB_ERR_OPERATIONS_ERROR;
4114 
4115 	py_next = PyLdbModule_FromModule(mod->next);
4116 
4117 	if (py_next == NULL)
4118 		return LDB_ERR_OPERATIONS_ERROR;
4119 
4120 	py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
4121 					  py_ldb, py_next);
4122 
4123 	if (py_result == NULL) {
4124 		return LDB_ERR_PYTHON_EXCEPTION;
4125 	}
4126 
4127 	mod->private_data = py_result;
4128 
4129 	talloc_set_destructor(mod, py_module_destructor);
4130 
4131 	return ldb_next_init(mod);
4132 }
4133 
py_register_module(PyObject * module,PyObject * args)4134 static PyObject *py_register_module(PyObject *module, PyObject *args)
4135 {
4136 	int ret;
4137 	struct ldb_module_ops *ops;
4138 	PyObject *input;
4139 	PyObject *tmp = NULL;
4140 	const char *name = NULL;
4141 
4142 	if (!PyArg_ParseTuple(args, "O", &input))
4143 		return NULL;
4144 
4145 	ops = talloc_zero(NULL, struct ldb_module_ops);
4146 	if (ops == NULL) {
4147 		PyErr_NoMemory();
4148 		return NULL;
4149 	}
4150 
4151 	tmp = PyObject_GetAttrString(input, discard_const_p(char, "name"));
4152 	if (tmp == NULL) {
4153 		return NULL;
4154 	}
4155 	name = PyUnicode_AsUTF8(tmp);
4156 	if (name == NULL) {
4157 		return NULL;
4158 	}
4159 	Py_XDECREF(tmp);
4160 	Py_INCREF(input);
4161 
4162 	ops->name = talloc_strdup(ops, name);
4163 	ops->private_data = input;
4164 	ops->init_context = py_module_init;
4165 	ops->search = py_module_search;
4166 	ops->add = py_module_add;
4167 	ops->modify = py_module_modify;
4168 	ops->del = py_module_del;
4169 	ops->rename = py_module_rename;
4170 	ops->request = py_module_request;
4171 	ops->extended = py_module_extended;
4172 	ops->start_transaction = py_module_start_transaction;
4173 	ops->end_transaction = py_module_end_transaction;
4174 	ops->del_transaction = py_module_del_transaction;
4175 
4176 	ret = ldb_register_module(ops);
4177 	if (ret != LDB_SUCCESS) {
4178 		TALLOC_FREE(ops);
4179 	}
4180 
4181 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4182 
4183 	Py_RETURN_NONE;
4184 }
4185 
py_timestring(PyObject * module,PyObject * args)4186 static PyObject *py_timestring(PyObject *module, PyObject *args)
4187 {
4188 	/* most times "time_t" is a signed integer type with 32 or 64 bit:
4189 	 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4190 	long int t_val;
4191 	char *tresult;
4192 	PyObject *ret;
4193 	if (!PyArg_ParseTuple(args, "l", &t_val))
4194 		return NULL;
4195 	tresult = ldb_timestring(NULL, (time_t) t_val);
4196 	ret = PyUnicode_FromString(tresult);
4197 	talloc_free(tresult);
4198 	return ret;
4199 }
4200 
py_string_to_time(PyObject * module,PyObject * args)4201 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4202 {
4203 	char *str;
4204 	if (!PyArg_ParseTuple(args, "s", &str))
4205 		return NULL;
4206 
4207 	return PyInt_FromLong(ldb_string_to_time(str));
4208 }
4209 
py_valid_attr_name(PyObject * self,PyObject * args)4210 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4211 {
4212 	char *name;
4213 	if (!PyArg_ParseTuple(args, "s", &name))
4214 		return NULL;
4215 	return PyBool_FromLong(ldb_valid_attr_name(name));
4216 }
4217 
4218 /*
4219   encode a string using RFC2254 rules
4220  */
py_binary_encode(PyObject * self,PyObject * args)4221 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4222 {
4223 	char *str, *encoded;
4224 	Py_ssize_t size = 0;
4225 	struct ldb_val val;
4226 	PyObject *ret;
4227 
4228 	if (!PyArg_ParseTuple(args, "s#", &str, &size))
4229 		return NULL;
4230 	val.data = (uint8_t *)str;
4231 	val.length = size;
4232 
4233 	encoded = ldb_binary_encode(NULL, val);
4234 	if (encoded == NULL) {
4235 		PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4236 		return NULL;
4237 	}
4238 	ret = PyUnicode_FromString(encoded);
4239 	talloc_free(encoded);
4240 	return ret;
4241 }
4242 
4243 /*
4244   decode a string using RFC2254 rules
4245  */
py_binary_decode(PyObject * self,PyObject * args)4246 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4247 {
4248 	char *str;
4249 	struct ldb_val val;
4250 	PyObject *ret;
4251 
4252 	if (!PyArg_ParseTuple(args, "s", &str))
4253 		return NULL;
4254 
4255 	val = ldb_binary_decode(NULL, str);
4256 	if (val.data == NULL) {
4257 		PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4258 		return NULL;
4259 	}
4260 	ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4261 	talloc_free(val.data);
4262 	return ret;
4263 }
4264 
4265 static PyMethodDef py_ldb_global_methods[] = {
4266 	{ "register_module", py_register_module, METH_VARARGS,
4267 		"S.register_module(module) -> None\n\n"
4268 		"Register a LDB module."},
4269 	{ "timestring", py_timestring, METH_VARARGS,
4270 		"S.timestring(int) -> string\n\n"
4271 		"Generate a LDAP time string from a UNIX timestamp" },
4272 	{ "string_to_time", py_string_to_time, METH_VARARGS,
4273 		"S.string_to_time(string) -> int\n\n"
4274 		"Parse a LDAP time string into a UNIX timestamp." },
4275 	{ "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4276 		"S.valid_attr_name(name) -> bool\n\nn"
4277 		"Check whether the supplied name is a valid attribute name." },
4278 	{ "binary_encode", py_binary_encode, METH_VARARGS,
4279 		"S.binary_encode(string) -> string\n\n"
4280 		"Perform a RFC2254 binary encoding on a string" },
4281 	{ "binary_decode", py_binary_decode, METH_VARARGS,
4282 		"S.binary_decode(string) -> string\n\n"
4283 		"Perform a RFC2254 binary decode on a string" },
4284 	{ NULL }
4285 };
4286 
4287 #define MODULE_DOC "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server."
4288 
4289 #if PY_MAJOR_VERSION >= 3
4290 static struct PyModuleDef moduledef = {
4291 	PyModuleDef_HEAD_INIT,
4292 	.m_name = "ldb",
4293 	.m_doc = MODULE_DOC,
4294 	.m_size = -1,
4295 	.m_methods = py_ldb_global_methods,
4296 };
4297 #endif
4298 
module_init(void)4299 static PyObject* module_init(void)
4300 {
4301 	PyObject *m;
4302 
4303 	PyLdbBytesType.tp_base = &PyBytes_Type;
4304 	if (PyType_Ready(&PyLdbBytesType) < 0) {
4305 		return NULL;
4306 	}
4307 
4308 	if (PyType_Ready(&PyLdbDn) < 0)
4309 		return NULL;
4310 
4311 	if (PyType_Ready(&PyLdbMessage) < 0)
4312 		return NULL;
4313 
4314 	if (PyType_Ready(&PyLdbMessageElement) < 0)
4315 		return NULL;
4316 
4317 	if (PyType_Ready(&PyLdb) < 0)
4318 		return NULL;
4319 
4320 	if (PyType_Ready(&PyLdbModule) < 0)
4321 		return NULL;
4322 
4323 	if (PyType_Ready(&PyLdbTree) < 0)
4324 		return NULL;
4325 
4326 	if (PyType_Ready(&PyLdbResult) < 0)
4327 		return NULL;
4328 
4329 	if (PyType_Ready(&PyLdbSearchIterator) < 0)
4330 		return NULL;
4331 
4332 	if (PyType_Ready(&PyLdbControl) < 0)
4333 		return NULL;
4334 
4335 #if PY_MAJOR_VERSION >= 3
4336 	m = PyModule_Create(&moduledef);
4337 #else
4338 	m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4339 #endif
4340 	if (m == NULL)
4341 		return NULL;
4342 
4343 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4344 
4345 	ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4346 	ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4347 	ADD_LDB_INT(SEQ_NEXT);
4348 	ADD_LDB_INT(SCOPE_DEFAULT);
4349 	ADD_LDB_INT(SCOPE_BASE);
4350 	ADD_LDB_INT(SCOPE_ONELEVEL);
4351 	ADD_LDB_INT(SCOPE_SUBTREE);
4352 
4353 	ADD_LDB_INT(CHANGETYPE_NONE);
4354 	ADD_LDB_INT(CHANGETYPE_ADD);
4355 	ADD_LDB_INT(CHANGETYPE_DELETE);
4356 	ADD_LDB_INT(CHANGETYPE_MODIFY);
4357 
4358 	ADD_LDB_INT(FLAG_MOD_ADD);
4359 	ADD_LDB_INT(FLAG_MOD_REPLACE);
4360 	ADD_LDB_INT(FLAG_MOD_DELETE);
4361 	ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4362 
4363 	ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4364 	ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4365 	ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4366 	ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4367 
4368 	ADD_LDB_INT(SUCCESS);
4369 	ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4370 	ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4371 	ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4372 	ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4373 	ADD_LDB_INT(ERR_COMPARE_FALSE);
4374 	ADD_LDB_INT(ERR_COMPARE_TRUE);
4375 	ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4376 	ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4377 	ADD_LDB_INT(ERR_REFERRAL);
4378 	ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4379 	ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4380 	ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4381 	ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4382 	ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4383 	ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4384 	ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4385 	ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4386 	ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4387 	ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4388 	ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4389 	ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4390 	ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4391 	ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4392 	ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4393 	ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4394 	ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4395 	ADD_LDB_INT(ERR_BUSY);
4396 	ADD_LDB_INT(ERR_UNAVAILABLE);
4397 	ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4398 	ADD_LDB_INT(ERR_LOOP_DETECT);
4399 	ADD_LDB_INT(ERR_NAMING_VIOLATION);
4400 	ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4401 	ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4402 	ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4403 	ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4404 	ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4405 	ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4406 	ADD_LDB_INT(ERR_OTHER);
4407 
4408 	ADD_LDB_INT(FLG_RDONLY);
4409 	ADD_LDB_INT(FLG_NOSYNC);
4410 	ADD_LDB_INT(FLG_RECONNECT);
4411 	ADD_LDB_INT(FLG_NOMMAP);
4412 	ADD_LDB_INT(FLG_SHOW_BINARY);
4413 	ADD_LDB_INT(FLG_ENABLE_TRACING);
4414 	ADD_LDB_INT(FLG_DONT_CREATE_DB);
4415 
4416 	ADD_LDB_INT(PACKING_FORMAT);
4417 	ADD_LDB_INT(PACKING_FORMAT_V2);
4418 
4419 	/* Historical misspelling */
4420 	PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4421 
4422 	PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4423 
4424 	PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4425 	PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4426 
4427 	Py_INCREF(&PyLdb);
4428 	Py_INCREF(&PyLdbDn);
4429 	Py_INCREF(&PyLdbModule);
4430 	Py_INCREF(&PyLdbMessage);
4431 	Py_INCREF(&PyLdbMessageElement);
4432 	Py_INCREF(&PyLdbTree);
4433 	Py_INCREF(&PyLdbResult);
4434 	Py_INCREF(&PyLdbControl);
4435 
4436 	PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4437 	PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4438 	PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4439 	PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4440 	PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4441 	PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4442 	PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4443 
4444 	PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4445 
4446 #define ADD_LDB_STRING(val)  PyModule_AddStringConstant(m, #val, LDB_## val)
4447 
4448 	ADD_LDB_STRING(SYNTAX_DN);
4449 	ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4450 	ADD_LDB_STRING(SYNTAX_INTEGER);
4451 	ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4452 	ADD_LDB_STRING(SYNTAX_BOOLEAN);
4453 	ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4454 	ADD_LDB_STRING(SYNTAX_UTC_TIME);
4455 	ADD_LDB_STRING(OID_COMPARATOR_AND);
4456 	ADD_LDB_STRING(OID_COMPARATOR_OR);
4457 
4458 	return m;
4459 }
4460 
4461 #if PY_MAJOR_VERSION >= 3
4462 PyMODINIT_FUNC PyInit_ldb(void);
PyInit_ldb(void)4463 PyMODINIT_FUNC PyInit_ldb(void)
4464 {
4465 	return module_init();
4466 }
4467 #else
4468 void initldb(void);
initldb(void)4469 void initldb(void)
4470 {
4471 	module_init();
4472 }
4473 #endif
4474