1 #include "common.h"
2 #include "message.h"
3 #include "errors.h"
4 #include "ldapcontrol.h"
5 #include "constants.h"
6 
7 /*
8  * Converts an LDAP message into a Python structure.
9  *
10  * On success, returns a list of dictionaries.
11  * On failure, returns NULL, and sets an error.
12  *
13  * The message m is always freed, regardless of return value.
14  *
15  * If add_ctrls is non-zero, per-entry/referral/partial/intermediate
16  * controls will be added as a third item to each entry tuple
17  *
18  * If add_intermediates is non-zero, intermediate/partial results will
19  * be returned
20  */
21 PyObject *
LDAPmessage_to_python(LDAP * ld,LDAPMessage * m,int add_ctrls,int add_intermediates)22 LDAPmessage_to_python(LDAP *ld, LDAPMessage *m, int add_ctrls, int add_intermediates)
23 {
24     /* we convert an LDAP message into a python structure.
25      * It is always a list of dictionaries.
26      * We always free m.
27      */
28 
29     PyObject *result, *pyctrls = 0;
30     LDAPMessage* entry;
31     LDAPControl **req_ctrls = 0;
32     int rc;
33 
34     result = PyList_New(0);
35     if (result == NULL) {
36         ldap_msgfree(m);
37         return NULL;
38     }
39 
40     for(
41         entry = ldap_first_entry(ld, m);
42         entry != NULL;
43         entry = ldap_next_entry(ld, entry)
44     ) {
45         char *dn;
46         char *attr;
47         BerElement *ber = NULL;
48         PyObject* entrytuple;
49         PyObject* attrdict;
50 
51         dn = ldap_get_dn(ld, entry);
52         if (dn == NULL)  {
53             Py_DECREF(result);
54             ldap_msgfree(m);
55             return LDAPerror(ld);
56         }
57 
58         attrdict = PyDict_New();
59         if (attrdict == NULL) {
60             Py_DECREF(result);
61             ldap_msgfree(m);
62             ldap_memfree(dn);
63             return NULL;
64         }
65 
66         rc = ldap_get_entry_controls( ld, entry, &req_ctrls );
67         if (rc) {
68             Py_DECREF(result);
69             ldap_msgfree(m);
70             ldap_memfree(dn);
71             return LDAPerror(ld);
72         }
73 
74         /* convert req_ctrls to list of tuples */
75         if ( ! ( pyctrls = LDAPControls_to_List( req_ctrls ) ) ) {
76             int err = LDAP_NO_MEMORY;
77             ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
78             Py_DECREF(result);
79             ldap_msgfree(m);
80             ldap_memfree(dn);
81             ldap_controls_free(req_ctrls);
82             return LDAPerror(ld);
83         }
84         ldap_controls_free(req_ctrls);
85 
86         /* Fill attrdict with lists */
87         for (
88             attr = ldap_first_attribute(ld, entry, &ber);
89             attr != NULL;
90             attr = ldap_next_attribute(ld, entry, ber)
91         ) {
92             PyObject* valuelist;
93             PyObject *attr_key;
94             struct berval **bvals;
95 
96             attr_key = PyBytes_FromString(attr);
97             bvals = ldap_get_values_len(ld, entry, attr);
98 
99             /* Find which list to append to */
100             if ( PyDict_Contains(attrdict, attr_key) ) {
101                 valuelist = PyDict_GetItem(attrdict, attr_key);
102                 if (valuelist != NULL)
103                     /* own the ref from here */
104                     Py_INCREF(valuelist);
105             } else {
106                 valuelist = PyList_New(0);
107                 if (
108                     valuelist != NULL &&
109                     PyDict_SetItem(attrdict, attr_key, valuelist) == -1
110                 ) {
111                     Py_DECREF(valuelist);
112                     valuelist = NULL; /* catch error later */
113                 }
114             }
115 
116             if (valuelist == NULL) {
117                 Py_DECREF(attrdict);
118                 Py_DECREF(result);
119                 if (ber != NULL)
120                     ber_free(ber, 0);
121                 ldap_msgfree(m);
122                 ldap_memfree(attr);
123                 ldap_memfree(dn);
124                 Py_XDECREF(pyctrls);
125                 return NULL;
126             }
127 
128             if (bvals != NULL) {
129                 Py_ssize_t i;
130 
131                 for (i=0; bvals[i]; i++) {
132                     PyObject *valuestr;
133                     valuestr = LDAPberval_to_object(bvals[i]);
134                     if (PyList_Append( valuelist, valuestr ) == -1) {
135                         Py_DECREF(attrdict);
136                         Py_DECREF(result);
137                         Py_DECREF(valuestr);
138                         Py_DECREF(valuelist);
139                         if (ber != NULL)
140                             ber_free(ber, 0);
141                         ldap_msgfree(m);
142                         ldap_memfree(attr);
143                         ldap_memfree(dn);
144                         Py_XDECREF(pyctrls);
145                         return NULL;
146                     }
147                     Py_DECREF(valuestr);
148                 }
149 
150                 ldap_value_free_len(bvals);
151             }
152 
153             Py_DECREF(valuelist);
154             ldap_memfree(attr);
155         }
156 
157         if (add_ctrls) {
158             entrytuple = Py_BuildValue("(yOO)", dn, attrdict, pyctrls);
159         } else {
160             entrytuple = Py_BuildValue("(yO)", dn, attrdict);
161         }
162         ldap_memfree(dn);
163         Py_DECREF(attrdict);
164         Py_XDECREF(pyctrls);
165         PyList_Append(result, entrytuple);
166         Py_DECREF(entrytuple);
167         if (ber != NULL)
168             ber_free(ber, 0);
169 
170     }
171 
172     for(
173         entry = ldap_first_reference(ld,m);
174         entry != NULL;
175         entry = ldap_next_reference(ld,entry)
176     ) {
177         char **refs = NULL;
178         PyObject* entrytuple;
179         PyObject* reflist = PyList_New(0);
180 
181         if (reflist == NULL)  {
182             Py_DECREF(result);
183             ldap_msgfree(m);
184             return NULL;
185         }
186 
187         if (ldap_parse_reference(ld, entry, &refs, &req_ctrls, 0) != LDAP_SUCCESS) {
188             Py_DECREF(reflist);
189             Py_DECREF(result);
190             ldap_msgfree(m);
191             return LDAPerror(ld);
192         }
193 
194         /* convert req_ctrls to list of tuples */
195         if ( ! ( pyctrls = LDAPControls_to_List( req_ctrls ) ) ) {
196             int err = LDAP_NO_MEMORY;
197             ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
198                   Py_DECREF(reflist);
199             Py_DECREF(result);
200             ldap_msgfree(m);
201             ldap_controls_free(req_ctrls);
202             return LDAPerror(ld);
203         }
204         ldap_controls_free(req_ctrls);
205         if (refs) {
206             Py_ssize_t i;
207             for (i=0; refs[i] != NULL; i++) {
208                 PyObject *refstr = PyBytes_FromString(refs[i]);
209                 PyList_Append(reflist, refstr);
210                 Py_DECREF(refstr);
211             }
212             ber_memvfree( (void **) refs );
213         }
214         if (add_ctrls) {
215             entrytuple = Py_BuildValue("(yOO)", NULL, reflist, pyctrls);
216         } else {
217             entrytuple = Py_BuildValue("(yO)", NULL, reflist);
218         }
219         Py_DECREF(reflist);
220         Py_XDECREF(pyctrls);
221         PyList_Append(result, entrytuple);
222         Py_DECREF(entrytuple);
223     }
224 
225     if (add_intermediates) {
226         for(
227             entry = ldap_first_message(ld,m);
228             entry != NULL;
229             entry = ldap_next_message(ld,entry)
230         ) {
231             /* list of tuples */
232             /* each tuple is OID, Berval, controllist */
233             if ( LDAP_RES_INTERMEDIATE == ldap_msgtype( entry ) ) {
234                 PyObject* valtuple;
235                 PyObject *valuestr;
236                 char *retoid = 0;
237                 struct berval *retdata = 0;
238 
239                 if (ldap_parse_intermediate( ld, entry, &retoid, &retdata, &req_ctrls, 0 ) != LDAP_SUCCESS) {
240                     Py_DECREF(result);
241                     ldap_msgfree(m);
242                     return LDAPerror(ld);
243                 }
244 
245                 /* convert req_ctrls to list of tuples */
246                 if ( ! ( pyctrls = LDAPControls_to_List( req_ctrls ) ) ) {
247                     int err = LDAP_NO_MEMORY;
248                     ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
249                     Py_DECREF(result);
250                     ldap_msgfree(m);
251                     ldap_controls_free(req_ctrls);
252                     ldap_memfree(retoid);
253                     ber_bvfree(retdata);
254                     return LDAPerror(ld);
255                 }
256                 ldap_controls_free(req_ctrls);
257 
258                 valuestr = LDAPberval_to_object(retdata);
259                 ber_bvfree( retdata );
260                 valtuple = Py_BuildValue("(yOO)", retoid, valuestr ? valuestr : Py_None, pyctrls);
261                 ldap_memfree( retoid );
262                 Py_DECREF(valuestr);
263                 Py_XDECREF(pyctrls);
264                 PyList_Append(result, valtuple);
265                 Py_DECREF(valtuple);
266             }
267         }
268     }
269 
270     ldap_msgfree(m);
271     return result;
272 
273 }
274