]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
Removed numerous memory leaks detected by Mark Meredith.
[openldap] / libraries / libldap / controls.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5
6 /* LDAPv3 Controls (RFC2251)
7  *
8  *      Controls ::= SEQUENCE OF Control  
9  *
10  *      Control ::= SEQUENCE { 
11  *              controlType             LDAPOID,
12  *              criticality             BOOLEAN DEFAULT FALSE,
13  *              controlValue    OCTET STRING OPTIONAL
14  *      }
15  */
16
17 #include "portable.h"
18
19 #include <ac/stdlib.h>
20
21 #include <ac/time.h>
22 #include <ac/string.h>
23
24 #include "ldap-int.h"
25
26
27 /*
28  * ldap_int_put_controls
29  */
30
31 int ldap_int_put_controls(
32         LDAP *ld,
33         LDAPControl **ctrls,
34         BerElement *ber )
35 {
36         LDAPControl **c;
37
38         assert( ld != NULL );
39         assert( ber != NULL );
40
41         if( ctrls == NULL ) {
42                 /* use default server controls */
43                 ctrls = ld->ld_sctrls;
44         }
45
46         if( ctrls == NULL || *ctrls == NULL ) {
47                 return LDAP_SUCCESS;
48         }
49
50         if ( ld->ld_version < LDAP_VERSION3 ) {
51                 /* LDAPv2 doesn't support controls,
52                  * error if any control is critical
53                  */
54                 for( c = ctrls ; *c != NULL; c++ ) {
55                         if( (*c)->ldctl_iscritical ) {
56                                 ld->ld_errno = LDAP_NOT_SUPPORTED;
57                                 return ld->ld_errno;
58                         }
59                 }
60
61                 return LDAP_SUCCESS;
62         }
63
64         /* Controls are encoded as a sequence of sequences */
65         if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
66                 ld->ld_errno = LDAP_ENCODING_ERROR;
67                 return ld->ld_errno;
68         }
69
70         for( c = ctrls ; *c != NULL; c++ ) {
71                 if ( ber_printf( ber, "{s" /*}*/,
72                         (*c)->ldctl_oid ) == -1 )
73                 {
74                         ld->ld_errno = LDAP_ENCODING_ERROR;
75                         return ld->ld_errno;
76                 }
77
78                 if( (*c)->ldctl_iscritical /* only if true */
79                         &&  ( ber_printf( ber, "b",
80                                 (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
81                 {
82                         ld->ld_errno = LDAP_ENCODING_ERROR;
83                         return ld->ld_errno;
84                 }
85
86                 if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
87                         &&  ( ber_printf( ber, "O",
88                                 &((*c)->ldctl_value) ) == -1 ) )
89                 {
90                         ld->ld_errno = LDAP_ENCODING_ERROR;
91                         return ld->ld_errno;
92                 }
93
94
95                 if( ber_printf( ber, /*{*/"}" ) == -1 ) {
96                         ld->ld_errno = LDAP_ENCODING_ERROR;
97                         return ld->ld_errno;
98                 }
99         }
100
101
102         if( ber_printf( ber, /*{*/"}" ) == -1 ) {
103                 ld->ld_errno = LDAP_ENCODING_ERROR;
104                 return ld->ld_errno;
105         }
106
107         return LDAP_SUCCESS;
108 }
109
110 int ldap_int_get_controls(
111         BerElement *ber,
112         LDAPControl ***ctrls )
113 {
114         int nctrls;
115         ber_tag_t tag;
116         ber_len_t len;
117         char *opaque;
118
119         assert( ber != NULL );
120
121         if( ctrls == NULL ) {
122                 return LDAP_SUCCESS;
123         }
124         *ctrls = NULL;
125
126         len = ber_pvt_ber_remaining(ber);
127
128         if( len == 0) {
129                 /* no controls */
130                 return LDAP_SUCCESS;
131         }
132
133
134         if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
135                 if( tag == LBER_ERROR ) {
136                         /* decoding error */
137                         return LDAP_DECODING_ERROR;
138                 }
139
140                 /* ignore unexpected input */
141                 return LDAP_SUCCESS;
142         }
143
144         /* set through each element */
145         nctrls = 0;
146         *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
147
148         if( *ctrls == NULL ) {
149                 return LDAP_NO_MEMORY;
150         }
151
152         ctrls[nctrls] = NULL;
153
154         for( tag = ber_first_element( ber, &len, &opaque );
155                 tag != LBER_ERROR;
156                 tag = ber_next_element( ber, &len, opaque ) )
157         {
158                 LDAPControl *tctrl;
159                 LDAPControl **tctrls;
160
161                 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
162
163                 /* allocate pointer space for current controls (nctrls)
164                  * + this control + extra NULL
165                  */
166                 tctrls = (tctrl == NULL) ? NULL :
167                         LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
168
169                 if( tctrls == NULL ) {
170                         /* one of the above allocation failed */
171
172                         if( tctrl != NULL ) {
173                                 LDAP_FREE( tctrl );
174                         }
175
176                         ldap_controls_free(*ctrls);
177                         *ctrls = NULL;
178
179                         return LDAP_NO_MEMORY;
180                 }
181
182
183                 tctrls[nctrls++] = tctrl;
184                 tctrls[nctrls] = NULL;
185
186                 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
187
188                 if( tag != LBER_ERROR ) {
189                         tag = ber_peek_tag( ber, &len );
190                 }
191
192                 if( tag == LBER_BOOLEAN ) {
193                         ber_int_t crit;
194                         tag = ber_scanf( ber, "b", &crit );
195                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
196                 }
197
198                 if( tag != LBER_ERROR ) {
199                         tag = ber_peek_tag( ber, &len );
200                 }
201
202                 if( tag == LBER_OCTETSTRING ) {
203                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
204
205                 } else {
206                         tctrl->ldctl_value.bv_val = NULL;
207                 }
208
209                 if( tag == LBER_ERROR ) {
210                         *ctrls = NULL;
211                         ldap_controls_free( tctrls );
212                         return LDAP_DECODING_ERROR;
213                 }
214
215                 *ctrls = tctrls;
216         }
217                 
218         return LDAP_SUCCESS;
219 }
220
221 /*
222  * Free a LDAPControl
223  */
224 void
225 ldap_control_free( LDAPControl *c )
226 {
227         assert( c != NULL );
228
229         if ( c != NULL ) {
230                 if( c->ldctl_oid != NULL) {
231                         LDAP_FREE( c->ldctl_oid );
232                 }
233
234                 if( c->ldctl_value.bv_val != NULL ) {
235                         LDAP_FREE( c->ldctl_value.bv_val );
236                 }
237
238                 LDAP_FREE( c );
239         }
240 }
241
242 /*
243  * Free an array of LDAPControl's
244  */
245 void
246 ldap_controls_free( LDAPControl **controls )
247 {
248         assert( controls != NULL );
249
250         if ( controls != NULL ) {
251                 LDAPControl *c;
252
253                 for(c = *controls; c != NULL; c++) {
254                         ldap_control_free( c );
255                 }
256
257                 LDAP_FREE( controls );
258         }
259 }
260
261 /*
262  * Duplicate an array of LDAPControl
263  */
264 LDAPControl **ldap_controls_dup( LDAPControl **controls )
265 {
266         LDAPControl **new;
267         int i;
268
269         if ( controls == NULL ) {
270                 return NULL;
271         }
272
273         /* count the controls */
274         for(i=0; controls[i] != NULL; i++) /* empty */ ;
275
276         if( i < 1 ) {
277                 /* no controls to duplicate */
278                 return NULL;
279         }
280
281         new = (LDAPControl **) LDAP_MALLOC( i * sizeof(LDAPControl *) );
282
283         if( new == NULL ) {
284                 /* memory allocation failure */
285                 return NULL;
286         }
287
288         /* duplicate the controls */
289         for(i=0; controls[i] != NULL; i++) {
290                 new[i] = ldap_control_dup( controls[i] );
291
292                 if( new[i] == NULL ) {
293                         ldap_controls_free( new );
294                         return NULL;
295                 }
296         }
297
298         new[i] = NULL;
299
300         return new;
301 }
302
303 /*
304  * Duplicate a LDAPControl
305  */
306 LDAPControl *ldap_control_dup( LDAPControl *c )
307 {
308         LDAPControl *new;
309
310         if ( c == NULL ) {
311                 return NULL;
312         }
313
314         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
315
316         if( new == NULL ) {
317                 return NULL;
318         }
319
320         if( c->ldctl_oid != NULL ) {
321                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
322
323                 if(new->ldctl_oid == NULL) {
324                         LDAP_FREE( new );
325                         return NULL;
326                 }
327
328         } else {
329                 new->ldctl_oid = NULL;
330         }
331
332         if( c->ldctl_value.bv_len > 0 ) {
333                 new->ldctl_value.bv_val = (char *) LDAP_MALLOC( c->ldctl_value.bv_len );
334
335                 if(new->ldctl_value.bv_val == NULL) {
336                         if(new->ldctl_oid != NULL) {
337                                 LDAP_FREE( new->ldctl_oid );
338                         }
339                         LDAP_FREE( new );
340                         return NULL;
341                 }
342                 
343                 SAFEMEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
344                         c->ldctl_value.bv_len );
345
346                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
347
348         } else {
349                 new->ldctl_value.bv_len = 0;
350                 new->ldctl_value.bv_val = NULL;
351         }
352
353         new->ldctl_iscritical = c->ldctl_iscritical;
354         return new;
355 }