]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
Fix last commit.
[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                         BER_BVZERO( &tctrl->ldctl_value );
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                 /* FIXME: how can a control have null OID? */
354                 new->ldctl_oid = NULL;
355         }
356
357         if( c->ldctl_value.bv_val != NULL ) {
358                 new->ldctl_value.bv_val =
359                         (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
360
361                 if(new->ldctl_value.bv_val == NULL) {
362                         if(new->ldctl_oid != NULL) {
363                                 LDAP_FREE( new->ldctl_oid );
364                         }
365                         LDAP_FREE( new );
366                         return NULL;
367                 }
368                 
369                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
370
371                 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
372                         c->ldctl_value.bv_len );
373
374                 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
375
376         } else {
377                 new->ldctl_value.bv_len = 0;
378                 new->ldctl_value.bv_val = NULL;
379         }
380
381         new->ldctl_iscritical = c->ldctl_iscritical;
382         return new;
383 }
384
385
386 LDAPControl *
387 ldap_find_control(
388         LDAP_CONST char *oid,
389         LDAPControl **ctrls )
390 {
391         if( ctrls == NULL || *ctrls == NULL ) {
392                 return NULL;
393         }
394
395         for( ; *ctrls != NULL; ctrls++ ) {
396                 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
397                         return *ctrls;
398                 }
399         }
400
401         return NULL;
402 }
403
404 /*
405    ldap_create_control
406    
407    Internal function to create an LDAP control from the encoded BerElement.
408
409    requestOID  (IN) The OID to use in creating the control.
410    
411    ber         (IN) The encoded BerElement to use in creating the control.
412    
413    iscritical  (IN) 0 - Indicates the control is not critical to the operation.
414                                         non-zero - The control is critical to the operation.
415                                   
416    ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
417                                         SHOULD be freed by calling ldap_control_free() when done.
418 ---*/
419
420 int
421 ldap_create_control(
422         LDAP_CONST char *requestOID,
423         BerElement *ber,
424         int iscritical,
425         LDAPControl **ctrlp )
426 {
427         LDAPControl *ctrl;
428
429         assert( requestOID != 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     BER_BVZERO(&ctrl->ldctl_value);
438         if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
439                 LDAP_FREE( ctrl );
440                 return LDAP_NO_MEMORY;
441         }
442
443         ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
444         ctrl->ldctl_iscritical = iscritical;
445
446         if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
447                 ldap_control_free( ctrl );
448                 return LDAP_NO_MEMORY;
449         }
450
451         *ctrlp = ctrl;
452         return LDAP_SUCCESS;
453 }
454
455 /*
456  * check for critical client controls and bitch if present
457  * if we ever support critical controls, we'll have to
458  * find a means for maintaining per API call control
459  * information.
460  */
461 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
462 {
463         LDAPControl *const *c;
464
465         assert( ld != NULL );
466         assert( LDAP_VALID( ld ) );
467
468         if( ctrls == NULL ) {
469                 /* use default server controls */
470                 ctrls = ld->ld_cctrls;
471         }
472
473         if( ctrls == NULL || *ctrls == NULL ) {
474                 return LDAP_SUCCESS;
475         }
476
477         for( c = ctrls ; *c != NULL; c++ ) {
478                 if( (*c)->ldctl_iscritical ) {
479                         ld->ld_errno = LDAP_NOT_SUPPORTED;
480                         return ld->ld_errno;
481                 }
482         }
483
484         return LDAP_SUCCESS;
485 }