]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
Misc LDAPbis comment update
[openldap] / libraries / libldap / controls.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2006 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 #ifdef LDAP_MEMORY_DEBUG
250         assert( c != NULL );
251 #endif
252
253         if ( c != NULL ) {
254                 if( c->ldctl_oid != NULL) {
255                         LDAP_FREE( c->ldctl_oid );
256                 }
257
258                 if( c->ldctl_value.bv_val != NULL ) {
259                         LDAP_FREE( c->ldctl_value.bv_val );
260                 }
261
262                 LDAP_FREE( c );
263         }
264 }
265
266 /*
267  * Free an array of LDAPControl's
268  */
269 void
270 ldap_controls_free( LDAPControl **controls )
271 {
272 #ifdef LDAP_MEMORY_DEBUG
273         assert( controls != NULL );
274 #endif
275
276         if ( controls != NULL ) {
277                 int i;
278
279                 for( i=0; controls[i] != NULL; i++) {
280                         ldap_control_free( controls[i] );
281                 }
282
283                 LDAP_FREE( controls );
284         }
285 }
286
287 /*
288  * Duplicate an array of LDAPControl
289  */
290 LDAPControl **
291 ldap_controls_dup( LDAPControl *const *controls )
292 {
293         LDAPControl **new;
294         int i;
295
296         if ( controls == NULL ) {
297                 return NULL;
298         }
299
300         /* count the controls */
301         for(i=0; controls[i] != NULL; i++) /* empty */ ;
302
303         if( i < 1 ) {
304                 /* no controls to duplicate */
305                 return NULL;
306         }
307
308         new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
309
310         if( new == NULL ) {
311                 /* memory allocation failure */
312                 return NULL;
313         }
314
315         /* duplicate the controls */
316         for(i=0; controls[i] != NULL; i++) {
317                 new[i] = ldap_control_dup( controls[i] );
318
319                 if( new[i] == NULL ) {
320                         ldap_controls_free( new );
321                         return NULL;
322                 }
323         }
324
325         new[i] = NULL;
326
327         return new;
328 }
329
330 /*
331  * Duplicate a LDAPControl
332  */
333 LDAPControl *
334 ldap_control_dup( const LDAPControl *c )
335 {
336         LDAPControl *new;
337
338         if ( c == NULL ) {
339                 return NULL;
340         }
341
342         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
343
344         if( new == NULL ) {
345                 return NULL;
346         }
347
348         if( c->ldctl_oid != NULL ) {
349                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
350
351                 if(new->ldctl_oid == NULL) {
352                         LDAP_FREE( new );
353                         return NULL;
354                 }
355
356         } else {
357                 new->ldctl_oid = NULL;
358         }
359
360         if( c->ldctl_value.bv_val != NULL ) {
361                 new->ldctl_value.bv_val =
362                         (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
363
364                 if(new->ldctl_value.bv_val == NULL) {
365                         if(new->ldctl_oid != NULL) {
366                                 LDAP_FREE( new->ldctl_oid );
367                         }
368                         LDAP_FREE( new );
369                         return NULL;
370                 }
371                 
372                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
373
374                 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
375                         c->ldctl_value.bv_len );
376
377                 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
378
379         } else {
380                 new->ldctl_value.bv_len = 0;
381                 new->ldctl_value.bv_val = NULL;
382         }
383
384         new->ldctl_iscritical = c->ldctl_iscritical;
385         return new;
386 }
387
388
389 LDAPControl *
390 ldap_find_control(
391         LDAP_CONST char *oid,
392         LDAPControl **ctrls )
393 {
394         if( ctrls == NULL || *ctrls == NULL ) {
395                 return NULL;
396         }
397
398         for( ; *ctrls != NULL; ctrls++ ) {
399                 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
400                         return *ctrls;
401                 }
402         }
403
404         return NULL;
405 }
406
407 /*
408    ldap_create_control
409    
410    Internal function to create an LDAP control from the encoded BerElement.
411
412    requestOID  (IN) The OID to use in creating the control.
413    
414    ber         (IN) The encoded BerElement to use in creating the control.
415    
416    iscritical  (IN) 0 - Indicates the control is not critical to the operation.
417                                         non-zero - The control is critical to the operation.
418                                   
419    ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
420                                         SHOULD be freed by calling ldap_control_free() when done.
421 ---*/
422
423 int
424 ldap_create_control(
425         LDAP_CONST char *requestOID,
426         BerElement *ber,
427         int iscritical,
428         LDAPControl **ctrlp )
429 {
430         LDAPControl *ctrl;
431
432         assert( requestOID != NULL );
433         assert( ber != NULL );
434         assert( ctrlp != NULL );
435
436         ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
437         if ( ctrl == NULL ) {
438                 return LDAP_NO_MEMORY;
439         }
440
441         if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
442                 LDAP_FREE( ctrl );
443                 return LDAP_NO_MEMORY;
444         }
445
446         ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
447         ctrl->ldctl_iscritical = iscritical;
448
449         if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
450                 ldap_control_free( ctrl );
451                 return LDAP_NO_MEMORY;
452         }
453
454         *ctrlp = ctrl;
455         return LDAP_SUCCESS;
456 }
457
458 /*
459  * check for critical client controls and bitch if present
460  * if we ever support critical controls, we'll have to
461  * find a means for maintaining per API call control
462  * information.
463  */
464 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
465 {
466         LDAPControl *const *c;
467
468         assert( ld != NULL );
469         assert( LDAP_VALID( ld ) );
470
471         if( ctrls == NULL ) {
472                 /* use default server controls */
473                 ctrls = ld->ld_cctrls;
474         }
475
476         if( ctrls == NULL || *ctrls == NULL ) {
477                 return LDAP_SUCCESS;
478         }
479
480         for( c = ctrls ; *c != NULL; c++ ) {
481                 if( (*c)->ldctl_iscritical ) {
482                         ld->ld_errno = LDAP_NOT_SUPPORTED;
483                         return ld->ld_errno;
484                 }
485         }
486
487         return LDAP_SUCCESS;
488 }