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