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