Line data Source code
1 : /* See https://www.python-ldap.org/ for details. */
2 :
3 : #include "common.h"
4 : #include "LDAPObject.h"
5 : #include "ldapcontrol.h"
6 : #include "berval.h"
7 : #include "constants.h"
8 :
9 : #include "lber.h"
10 :
11 : /* Prints to stdout the contents of an array of LDAPControl objects */
12 :
13 : /* XXX: This is a debugging tool, and the printf generates some warnings
14 : * about pointer types. I left it here in case something breaks and we
15 : * need to inspect an LDAPControl structure.
16 :
17 : static void
18 : LDAPControl_DumpList( LDAPControl** lcs ) {
19 : LDAPControl** lcp;
20 : LDAPControl* lc;
21 : for ( lcp = lcs; *lcp; lcp++ ) {
22 : lc = *lcp;
23 : printf("OID: %s\nCriticality: %d\nBER length: %d\nBER value: %x\n",
24 : lc->ldctl_oid, lc->ldctl_iscritical, lc->ldctl_value.bv_len,
25 : lc->ldctl_value.bv_val);
26 : }
27 : } */
28 :
29 : /* Free a single LDAPControl object created by Tuple_to_LDAPControl */
30 :
31 : static void
32 14 : LDAPControl_DEL( LDAPControl* lc )
33 : {
34 14 : if (lc == NULL)
35 0 : return;
36 :
37 14 : if (lc->ldctl_oid)
38 14 : PyMem_DEL(lc->ldctl_oid);
39 14 : PyMem_DEL(lc);
40 : }
41 :
42 : /* Free an array of LDAPControl objects created by LDAPControls_from_object */
43 :
44 : void
45 453 : LDAPControl_List_DEL( LDAPControl** lcs )
46 : {
47 : LDAPControl** lcp;
48 453 : if (lcs == NULL)
49 429 : return;
50 :
51 38 : for ( lcp = lcs; *lcp; lcp++ )
52 14 : LDAPControl_DEL( *lcp );
53 :
54 24 : PyMem_DEL( lcs );
55 : }
56 :
57 : /* Takes a tuple of the form:
58 : * (OID: string, Criticality: int/boolean, Value: string/None)
59 : * and converts it into an LDAPControl structure.
60 : *
61 : * The Value string should represent an ASN.1 encoded structure.
62 : */
63 :
64 : static LDAPControl*
65 18 : Tuple_to_LDAPControl( PyObject* tup )
66 : {
67 : char *oid;
68 : char iscritical;
69 : struct berval berbytes;
70 : PyObject *bytes;
71 18 : LDAPControl *lc = NULL;
72 : Py_ssize_t len;
73 :
74 18 : if (!PyTuple_Check(tup)) {
75 4 : LDAPerror_TypeError("expected a tuple", tup);
76 22 : return NULL;
77 : }
78 :
79 14 : if (!PyArg_ParseTuple( tup, "sbO", &oid, &iscritical, &bytes ))
80 0 : return NULL;
81 :
82 14 : lc = PyMem_NEW(LDAPControl, 1);
83 14 : if (lc == NULL) {
84 0 : PyErr_NoMemory();
85 0 : return NULL;
86 : }
87 :
88 14 : lc->ldctl_iscritical = iscritical;
89 :
90 14 : len = strlen(oid);
91 14 : lc->ldctl_oid = PyMem_NEW(char, len + 1);
92 14 : if (lc->ldctl_oid == NULL) {
93 0 : PyErr_NoMemory();
94 0 : LDAPControl_DEL(lc);
95 0 : return NULL;
96 : }
97 14 : memcpy(lc->ldctl_oid, oid, len + 1);
98 :
99 : /* The berval can either be None or a String */
100 14 : if (PyNone_Check(bytes)) {
101 4 : berbytes.bv_len = 0;
102 4 : berbytes.bv_val = NULL;
103 : }
104 10 : else if (PyBytes_Check(bytes)) {
105 10 : berbytes.bv_len = PyBytes_Size(bytes);
106 10 : berbytes.bv_val = PyBytes_AsString(bytes);
107 : }
108 : else {
109 0 : LDAPerror_TypeError("expected bytes", bytes);
110 0 : LDAPControl_DEL(lc);
111 0 : return NULL;
112 : }
113 :
114 14 : lc->ldctl_value = berbytes;
115 :
116 14 : return lc;
117 : }
118 :
119 : /* Convert a list of tuples (of a format acceptable to the Tuple_to_LDAPControl
120 : * function) into an array of LDAPControl objects. */
121 :
122 : int
123 60 : LDAPControls_from_object(PyObject* list, LDAPControl ***controls_ret)
124 : {
125 : Py_ssize_t len, i;
126 : LDAPControl** ldcs;
127 : LDAPControl* ldc;
128 : PyObject* item;
129 :
130 60 : if (!PySequence_Check(list)) {
131 32 : LDAPerror_TypeError("expected a list", list);
132 32 : return 0;
133 : }
134 :
135 28 : len = PySequence_Length(list);
136 28 : ldcs = PyMem_NEW(LDAPControl*, len + 1);
137 28 : if (ldcs == NULL) {
138 0 : PyErr_NoMemory();
139 0 : return 0;
140 : }
141 :
142 42 : for (i = 0; i < len; i++) {
143 18 : item = PySequence_GetItem(list, i);
144 18 : if (item == NULL) {
145 0 : PyMem_DEL(ldcs);
146 0 : return 0;
147 : }
148 :
149 18 : ldc = Tuple_to_LDAPControl(item);
150 18 : if (ldc == NULL) {
151 4 : Py_DECREF(item);
152 4 : PyMem_DEL(ldcs);
153 4 : return 0;
154 : }
155 :
156 14 : ldcs[i] = ldc;
157 14 : Py_DECREF(item);
158 : }
159 :
160 24 : ldcs[len] = NULL;
161 24 : *controls_ret = ldcs;
162 24 : return 1;
163 : }
164 :
165 : PyObject*
166 267 : LDAPControls_to_List(LDAPControl **ldcs)
167 : {
168 267 : PyObject *res = 0, *pyctrl;
169 267 : LDAPControl **tmp = ldcs;
170 267 : Py_ssize_t num_ctrls = 0, i;
171 :
172 267 : if (tmp)
173 33 : while (*tmp++) num_ctrls++;
174 :
175 267 : if ((res = PyList_New(num_ctrls)) == NULL) {
176 0 : return NULL;
177 : }
178 :
179 304 : for (i = 0; i < num_ctrls; i++) {
180 111 : pyctrl = Py_BuildValue("sbO&",
181 37 : ldcs[i]->ldctl_oid,
182 37 : ldcs[i]->ldctl_iscritical,
183 37 : LDAPberval_to_object, &ldcs[i]->ldctl_value);
184 37 : if (pyctrl == NULL) {
185 0 : Py_DECREF(res);
186 0 : return NULL;
187 : }
188 37 : PyList_SET_ITEM(res, i, pyctrl);
189 : }
190 267 : return res;
191 : }
192 :
193 :
194 :
195 : /* --------------- en-/decoders ------------- */
196 :
197 : /* Matched Values, aka, Values Return Filter */
198 : static PyObject*
199 1 : encode_rfc3876(PyObject *self, PyObject *args)
200 : {
201 1 : PyObject *res = 0;
202 : int err;
203 1 : BerElement *vrber = 0;
204 : char *vrFilter;
205 : struct berval *ctrl_val;
206 :
207 1 : if (!PyArg_ParseTuple(args, "s:encode_valuesreturnfilter_control", &vrFilter)) {
208 0 : goto endlbl;
209 : }
210 :
211 1 : if (!(vrber = ber_alloc_t(LBER_USE_DER))) {
212 0 : LDAPerr(LDAP_NO_MEMORY);
213 0 : goto endlbl;
214 : }
215 :
216 1 : err = ldap_put_vrFilter(vrber, vrFilter);
217 1 : if (err == -1) {
218 0 : LDAPerr(LDAP_FILTER_ERROR);
219 0 : goto endlbl;
220 : }
221 :
222 1 : err = ber_flatten(vrber, &ctrl_val);
223 1 : if (err == -1) {
224 0 : LDAPerr(LDAP_NO_MEMORY);
225 0 : goto endlbl;
226 : }
227 :
228 1 : res = LDAPberval_to_object(ctrl_val);
229 1 : ber_bvfree(ctrl_val);
230 :
231 1 : endlbl:
232 1 : if (vrber)
233 1 : ber_free(vrber, 1);
234 :
235 1 : return res;
236 : }
237 :
238 : static PyObject*
239 1 : encode_rfc2696(PyObject *self, PyObject *args)
240 : {
241 1 : PyObject *res = 0;
242 1 : BerElement *ber = 0;
243 : struct berval cookie, *ctrl_val;
244 : Py_ssize_t cookie_len;
245 : unsigned long size;
246 : ber_tag_t tag;
247 :
248 1 : if (!PyArg_ParseTuple(args, "is#:encode_page_control", &size,
249 : &cookie.bv_val, &cookie_len)) {
250 0 : goto endlbl;
251 : }
252 1 : cookie.bv_len = (ber_len_t) cookie_len;
253 :
254 1 : if (!(ber = ber_alloc_t(LBER_USE_DER))) {
255 0 : LDAPerr(LDAP_NO_MEMORY);
256 0 : goto endlbl;
257 : }
258 :
259 1 : tag = ber_printf(ber, "{i", size);
260 1 : if (tag == LBER_ERROR) {
261 0 : LDAPerr(LDAP_ENCODING_ERROR);
262 0 : goto endlbl;
263 : }
264 :
265 1 : if (!cookie.bv_len)
266 0 : tag = ber_printf(ber, "o", "", 0);
267 : else
268 1 : tag = ber_printf(ber, "O", &cookie);
269 1 : if (tag == LBER_ERROR) {
270 0 : LDAPerr(LDAP_ENCODING_ERROR);
271 0 : goto endlbl;
272 : }
273 :
274 1 : tag = ber_printf(ber, /*{ */ "N}");
275 1 : if (tag == LBER_ERROR) {
276 0 : LDAPerr(LDAP_ENCODING_ERROR);
277 0 : goto endlbl;
278 : }
279 :
280 1 : if (-1 == ber_flatten(ber, &ctrl_val)) {
281 0 : LDAPerr(LDAP_NO_MEMORY);
282 0 : goto endlbl;
283 : }
284 :
285 1 : res = LDAPberval_to_object(ctrl_val);
286 1 : ber_bvfree(ctrl_val);
287 :
288 1 : endlbl:
289 1 : if (ber)
290 1 : ber_free(ber, 1);
291 1 : return res;
292 : }
293 :
294 :
295 : static PyObject*
296 1 : decode_rfc2696(PyObject *self, PyObject *args)
297 : {
298 1 : PyObject *res = 0;
299 1 : BerElement *ber = 0;
300 : struct berval ldctl_value;
301 : ber_tag_t tag;
302 : struct berval *cookiep;
303 1 : unsigned long count = 0;
304 : Py_ssize_t ldctl_value_len;
305 :
306 1 : if (!PyArg_ParseTuple(args, "s#:decode_page_control",
307 : &ldctl_value.bv_val, &ldctl_value_len)) {
308 0 : goto endlbl;
309 : }
310 1 : ldctl_value.bv_len = (ber_len_t) ldctl_value_len;
311 :
312 1 : if (!(ber = ber_init(&ldctl_value))) {
313 0 : LDAPerr(LDAP_NO_MEMORY);
314 0 : goto endlbl;
315 : }
316 :
317 1 : tag = ber_scanf(ber, "{iO", &count, &cookiep);
318 1 : if (tag == LBER_ERROR) {
319 0 : LDAPerr(LDAP_DECODING_ERROR);
320 0 : goto endlbl;
321 : }
322 :
323 1 : res = Py_BuildValue("(kO&)", count, LDAPberval_to_object, cookiep);
324 1 : ber_bvfree(cookiep);
325 :
326 1 : endlbl:
327 1 : if (ber)
328 1 : ber_free(ber, 1);
329 1 : return res;
330 : }
331 :
332 : static PyObject*
333 1 : encode_assertion_control(PyObject *self, PyObject *args)
334 : {
335 : int err;
336 1 : PyObject *res = 0;
337 : char *assertion_filterstr;
338 : struct berval ctrl_val;
339 1 : LDAP *ld = NULL;
340 :
341 1 : if (!PyArg_ParseTuple(args, "s:encode_assertion_control",
342 : &assertion_filterstr)) {
343 0 : goto endlbl;
344 : }
345 :
346 : /* XXX: ldap_create() is a nasty and slow hack. It's creating a full blown
347 : * LDAP object just to encode assertion controls.
348 : */
349 1 : Py_BEGIN_ALLOW_THREADS
350 1 : err = ldap_create(&ld);
351 1 : Py_END_ALLOW_THREADS
352 :
353 1 : if (err != LDAP_SUCCESS)
354 1 : return LDAPerror(ld, "ldap_create");
355 :
356 1 : err = ldap_create_assertion_control_value(ld,assertion_filterstr,&ctrl_val);
357 :
358 1 : if (err != LDAP_SUCCESS) {
359 0 : LDAPerror(ld, "ldap_create_assertion_control_value");
360 0 : Py_BEGIN_ALLOW_THREADS
361 0 : ldap_unbind_ext(ld, NULL, NULL);
362 0 : Py_END_ALLOW_THREADS
363 0 : return NULL;
364 : }
365 1 : Py_BEGIN_ALLOW_THREADS
366 1 : ldap_unbind_ext(ld, NULL, NULL);
367 1 : Py_END_ALLOW_THREADS
368 :
369 1 : res = LDAPberval_to_object(&ctrl_val);
370 1 : if (ctrl_val.bv_val != NULL) {
371 1 : ber_memfree(ctrl_val.bv_val);
372 : }
373 1 : endlbl:
374 :
375 1 : return res;
376 : }
377 :
378 : static PyMethodDef methods[] = {
379 : {"encode_page_control", encode_rfc2696, METH_VARARGS },
380 : {"decode_page_control", decode_rfc2696, METH_VARARGS },
381 : {"encode_valuesreturnfilter_control", encode_rfc3876, METH_VARARGS },
382 : {"encode_assertion_control", encode_assertion_control, METH_VARARGS },
383 : { NULL, NULL }
384 : };
385 :
386 : void
387 1 : LDAPinit_control(PyObject *d)
388 : {
389 1 : LDAPadd_methods(d, methods);
390 1 : }
|