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