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