Skip to content

Commit ca45ede

Browse files
author
stroeder
committed
Fixes for memory leaks by Chris Mikkelson
1 parent 06f4b34 commit ca45ede

2 files changed

Lines changed: 634 additions & 0 deletions

File tree

Modules/ldapcontrol.c

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

0 commit comments

Comments
 (0)