]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
Make LDAP_MEMORY_DEBUG a bitmask. #define LDAP_MEMORY_DEBUG_ASSERT. ITS#4990.
[openldap] / libraries / libldap / controls.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* This notice applies to changes, created by or for Novell, Inc.,
16  * to preexisting works for which notices appear elsewhere in this file.
17  *
18  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
19  *
20  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
21  * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
22  * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
23  * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
24  * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
25  * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
26  * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
27  * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 
28  *---
29  * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
30  * can be found in the file "build/LICENSE-2.0.1" in this distribution
31  * of OpenLDAP Software.
32  */
33
34 #include "portable.h"
35
36 #include <ac/stdlib.h>
37
38 #include <ac/time.h>
39 #include <ac/string.h>
40
41 #include "ldap-int.h"
42
43 /* LDAPv3 Controls (RFC 4511)
44  *
45  *      Controls ::= SEQUENCE OF control Control  
46  *
47  *      Control ::= SEQUENCE { 
48  *              controlType             LDAPOID,
49  *              criticality             BOOLEAN DEFAULT FALSE,
50  *              controlValue    OCTET STRING OPTIONAL
51  *      }
52  */
53
54 /*
55  * ldap_int_put_controls
56  */
57
58 int
59 ldap_int_put_controls(
60         LDAP *ld,
61         LDAPControl *const *ctrls,
62         BerElement *ber )
63 {
64         LDAPControl *const *c;
65
66         assert( ld != NULL );
67         assert( LDAP_VALID( ld ) );
68         assert( ber != NULL );
69
70         if( ctrls == NULL ) {
71                 /* use default server controls */
72                 ctrls = ld->ld_sctrls;
73         }
74
75         if( ctrls == NULL || *ctrls == NULL ) {
76                 return LDAP_SUCCESS;
77         }
78
79         if ( ld->ld_version < LDAP_VERSION3 ) {
80                 /* LDAPv2 doesn't support controls,
81                  * error if any control is critical
82                  */
83                 for( c = ctrls ; *c != NULL; c++ ) {
84                         if( (*c)->ldctl_iscritical ) {
85                                 ld->ld_errno = LDAP_NOT_SUPPORTED;
86                                 return ld->ld_errno;
87                         }
88                 }
89
90                 return LDAP_SUCCESS;
91         }
92
93         /* Controls are encoded as a sequence of sequences */
94         if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
95                 ld->ld_errno = LDAP_ENCODING_ERROR;
96                 return ld->ld_errno;
97         }
98
99         for( c = ctrls ; *c != NULL; c++ ) {
100                 if ( ber_printf( ber, "{s" /*}*/,
101                         (*c)->ldctl_oid ) == -1 )
102                 {
103                         ld->ld_errno = LDAP_ENCODING_ERROR;
104                         return ld->ld_errno;
105                 }
106
107                 if( (*c)->ldctl_iscritical /* only if true */
108                         &&  ( ber_printf( ber, "b",
109                                 (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
110                 {
111                         ld->ld_errno = LDAP_ENCODING_ERROR;
112                         return ld->ld_errno;
113                 }
114
115                 if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
116                         &&  ( ber_printf( ber, "O",
117                                 &((*c)->ldctl_value) ) == -1 ) )
118                 {
119                         ld->ld_errno = LDAP_ENCODING_ERROR;
120                         return ld->ld_errno;
121                 }
122
123
124                 if( ber_printf( ber, /*{*/"N}" ) == -1 ) {
125                         ld->ld_errno = LDAP_ENCODING_ERROR;
126                         return ld->ld_errno;
127                 }
128         }
129
130
131         if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
132                 ld->ld_errno = LDAP_ENCODING_ERROR;
133                 return ld->ld_errno;
134         }
135
136         return LDAP_SUCCESS;
137 }
138
139 int ldap_pvt_get_controls(
140         BerElement *ber,
141         LDAPControl ***ctrls )
142 {
143         int nctrls;
144         ber_tag_t tag;
145         ber_len_t len;
146         char *opaque;
147
148         assert( ber != NULL );
149
150         if( ctrls == NULL ) {
151                 return LDAP_SUCCESS;
152         }
153         *ctrls = NULL;
154
155         len = ber_pvt_ber_remaining( ber );
156
157         if( len == 0) {
158                 /* no controls */
159                 return LDAP_SUCCESS;
160         }
161
162         if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
163                 if( tag == LBER_ERROR ) {
164                         /* decoding error */
165                         return LDAP_DECODING_ERROR;
166                 }
167
168                 /* ignore unexpected input */
169                 return LDAP_SUCCESS;
170         }
171
172         /* set through each element */
173         nctrls = 0;
174         *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
175
176         if( *ctrls == NULL ) {
177                 return LDAP_NO_MEMORY;
178         }
179
180         *ctrls[nctrls] = NULL;
181
182         for( tag = ber_first_element( ber, &len, &opaque );
183                 tag != LBER_ERROR;
184                 tag = ber_next_element( ber, &len, opaque ) )
185         {
186                 LDAPControl *tctrl;
187                 LDAPControl **tctrls;
188
189                 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
190
191                 /* allocate pointer space for current controls (nctrls)
192                  * + this control + extra NULL
193                  */
194                 tctrls = (tctrl == NULL) ? NULL :
195                         LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
196
197                 if( tctrls == NULL ) {
198                         /* one of the above allocation failed */
199
200                         if( tctrl != NULL ) {
201                                 LDAP_FREE( tctrl );
202                         }
203
204                         ldap_controls_free(*ctrls);
205                         *ctrls = NULL;
206
207                         return LDAP_NO_MEMORY;
208                 }
209
210
211                 tctrls[nctrls++] = tctrl;
212                 tctrls[nctrls] = NULL;
213
214                 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
215
216                 if( tag == LBER_ERROR ) {
217                         *ctrls = NULL;
218                         ldap_controls_free( tctrls );
219                         return LDAP_DECODING_ERROR;
220                 }
221
222                 tag = ber_peek_tag( ber, &len );
223
224                 if( tag == LBER_BOOLEAN ) {
225                         ber_int_t crit;
226                         tag = ber_scanf( ber, "b", &crit );
227                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
228                         tag = ber_peek_tag( ber, &len );
229                 }
230
231                 if( tag == LBER_OCTETSTRING ) {
232                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
233                 } else {
234                         tctrl->ldctl_value.bv_val = NULL;
235                 }
236
237                 *ctrls = tctrls;
238         }
239                 
240         return LDAP_SUCCESS;
241 }
242
243 /*
244  * Free a LDAPControl
245  */
246 void
247 ldap_control_free( LDAPControl *c )
248 {
249         LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
250
251         if ( c != NULL ) {
252                 if( c->ldctl_oid != NULL) {
253                         LDAP_FREE( c->ldctl_oid );
254                 }
255
256                 if( c->ldctl_value.bv_val != NULL ) {
257                         LDAP_FREE( c->ldctl_value.bv_val );
258                 }
259
260                 LDAP_FREE( c );
261         }
262 }
263
264 /*
265  * Free an array of LDAPControl's
266  */
267 void
268 ldap_controls_free( LDAPControl **controls )
269 {
270         LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
271
272         if ( controls != NULL ) {
273                 int i;
274
275                 for( i=0; controls[i] != NULL; i++) {
276                         ldap_control_free( controls[i] );
277                 }
278
279                 LDAP_FREE( controls );
280         }
281 }
282
283 /*
284  * Duplicate an array of LDAPControl
285  */
286 LDAPControl **
287 ldap_controls_dup( LDAPControl *const *controls )
288 {
289         LDAPControl **new;
290         int i;
291
292         if ( controls == NULL ) {
293                 return NULL;
294         }
295
296         /* count the controls */
297         for(i=0; controls[i] != NULL; i++) /* empty */ ;
298
299         if( i < 1 ) {
300                 /* no controls to duplicate */
301                 return NULL;
302         }
303
304         new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
305
306         if( new == NULL ) {
307                 /* memory allocation failure */
308                 return NULL;
309         }
310
311         /* duplicate the controls */
312         for(i=0; controls[i] != NULL; i++) {
313                 new[i] = ldap_control_dup( controls[i] );
314
315                 if( new[i] == NULL ) {
316                         ldap_controls_free( new );
317                         return NULL;
318                 }
319         }
320
321         new[i] = NULL;
322
323         return new;
324 }
325
326 /*
327  * Duplicate a LDAPControl
328  */
329 LDAPControl *
330 ldap_control_dup( const LDAPControl *c )
331 {
332         LDAPControl *new;
333
334         if ( c == NULL ) {
335                 return NULL;
336         }
337
338         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
339
340         if( new == NULL ) {
341                 return NULL;
342         }
343
344         if( c->ldctl_oid != NULL ) {
345                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
346
347                 if(new->ldctl_oid == NULL) {
348                         LDAP_FREE( new );
349                         return NULL;
350                 }
351
352         } else {
353                 new->ldctl_oid = NULL;
354         }
355
356         if( c->ldctl_value.bv_val != NULL ) {
357                 new->ldctl_value.bv_val =
358                         (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
359
360                 if(new->ldctl_value.bv_val == NULL) {
361                         if(new->ldctl_oid != NULL) {
362                                 LDAP_FREE( new->ldctl_oid );
363                         }
364                         LDAP_FREE( new );
365                         return NULL;
366                 }
367                 
368                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
369
370                 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
371                         c->ldctl_value.bv_len );
372
373                 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
374
375         } else {
376                 new->ldctl_value.bv_len = 0;
377                 new->ldctl_value.bv_val = NULL;
378         }
379
380         new->ldctl_iscritical = c->ldctl_iscritical;
381         return new;
382 }
383
384
385 LDAPControl *
386 ldap_find_control(
387         LDAP_CONST char *oid,
388         LDAPControl **ctrls )
389 {
390         if( ctrls == NULL || *ctrls == NULL ) {
391                 return NULL;
392         }
393
394         for( ; *ctrls != NULL; ctrls++ ) {
395                 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
396                         return *ctrls;
397                 }
398         }
399
400         return NULL;
401 }
402
403 /*
404    ldap_create_control
405    
406    Internal function to create an LDAP control from the encoded BerElement.
407
408    requestOID  (IN) The OID to use in creating the control.
409    
410    ber         (IN) The encoded BerElement to use in creating the control.
411    
412    iscritical  (IN) 0 - Indicates the control is not critical to the operation.
413                                         non-zero - The control is critical to the operation.
414                                   
415    ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
416                                         SHOULD be freed by calling ldap_control_free() when done.
417 ---*/
418
419 int
420 ldap_create_control(
421         LDAP_CONST char *requestOID,
422         BerElement *ber,
423         int iscritical,
424         LDAPControl **ctrlp )
425 {
426         LDAPControl *ctrl;
427
428         assert( requestOID != NULL );
429         assert( ber != NULL );
430         assert( ctrlp != NULL );
431
432         ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
433         if ( ctrl == NULL ) {
434                 return LDAP_NO_MEMORY;
435         }
436
437         if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
438                 LDAP_FREE( ctrl );
439                 return LDAP_NO_MEMORY;
440         }
441
442         ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
443         ctrl->ldctl_iscritical = iscritical;
444
445         if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
446                 ldap_control_free( ctrl );
447                 return LDAP_NO_MEMORY;
448         }
449
450         *ctrlp = ctrl;
451         return LDAP_SUCCESS;
452 }
453
454 /*
455  * check for critical client controls and bitch if present
456  * if we ever support critical controls, we'll have to
457  * find a means for maintaining per API call control
458  * information.
459  */
460 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
461 {
462         LDAPControl *const *c;
463
464         assert( ld != NULL );
465         assert( LDAP_VALID( ld ) );
466
467         if( ctrls == NULL ) {
468                 /* use default server controls */
469                 ctrls = ld->ld_cctrls;
470         }
471
472         if( ctrls == NULL || *ctrls == NULL ) {
473                 return LDAP_SUCCESS;
474         }
475
476         for( c = ctrls ; *c != NULL; c++ ) {
477                 if( (*c)->ldctl_iscritical ) {
478                         ld->ld_errno = LDAP_NOT_SUPPORTED;
479                         return ld->ld_errno;
480                 }
481         }
482
483         return LDAP_SUCCESS;
484 }