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