source: vendor/current/lib/ldb/pyldb.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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