]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
f3af141e1ea29c73ce025ceb104139fb37d23a78
[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                         tag = ber_peek_tag( ber, &len );
192                 }
193
194                 if( tag == LBER_BOOLEAN ) {
195                         ber_int_t crit;
196                         tag = ber_scanf( ber, "b", &crit );
197                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
198                 }
199
200                 if( tag != LBER_ERROR ) {
201                         tag = ber_peek_tag( ber, &len );
202                 }
203
204                 if( tag == LBER_OCTETSTRING ) {
205                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
206
207                 } else {
208                         tctrl->ldctl_value.bv_val = NULL;
209                 }
210
211                 if( tag == LBER_ERROR ) {
212                         *ctrls = NULL;
213                         ldap_controls_free( tctrls );
214                         return LDAP_DECODING_ERROR;
215                 }
216
217                 *ctrls = tctrls;
218         }
219                 
220         return LDAP_SUCCESS;
221 }
222
223 /*
224  * Free a LDAPControl
225  */
226 void
227 ldap_control_free( LDAPControl *c )
228 {
229 #ifdef LDAP_MEMORY_DEBUG
230         assert( c != NULL );
231 #endif
232
233         if ( c != NULL ) {
234                 if( c->ldctl_oid != NULL) {
235                         LDAP_FREE( c->ldctl_oid );
236                 }
237
238                 if( c->ldctl_value.bv_val != NULL ) {
239                         LDAP_FREE( c->ldctl_value.bv_val );
240                 }
241
242                 LDAP_FREE( c );
243         }
244 }
245
246 /*
247  * Free an array of LDAPControl's
248  */
249 void
250 ldap_controls_free( LDAPControl **controls )
251 {
252 #ifdef LDAP_MEMORY_DEBUG
253         assert( controls != NULL );
254 #endif
255
256         if ( controls != NULL ) {
257                 int i;
258
259                 for( i=0; controls[i] != NULL; i++) {
260                         ldap_control_free( controls[i] );
261                 }
262
263                 LDAP_FREE( controls );
264         }
265 }
266
267 /*
268  * Duplicate an array of LDAPControl
269  */
270 LDAPControl **
271 ldap_controls_dup( LDAPControl *const *controls )
272 {
273         LDAPControl **new;
274         int i;
275
276         if ( controls == NULL ) {
277                 return NULL;
278         }
279
280         /* count the controls */
281         for(i=0; controls[i] != NULL; i++) /* empty */ ;
282
283         if( i < 1 ) {
284                 /* no controls to duplicate */
285                 return NULL;
286         }
287
288         new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
289
290         if( new == NULL ) {
291                 /* memory allocation failure */
292                 return NULL;
293         }
294
295         /* duplicate the controls */
296         for(i=0; controls[i] != NULL; i++) {
297                 new[i] = ldap_control_dup( controls[i] );
298
299                 if( new[i] == NULL ) {
300                         ldap_controls_free( new );
301                         return NULL;
302                 }
303         }
304
305         new[i] = NULL;
306
307         return new;
308 }
309
310 /*
311  * Duplicate a LDAPControl
312  */
313 LDAPControl *
314 ldap_control_dup( const LDAPControl *c )
315 {
316         LDAPControl *new;
317
318         if ( c == NULL ) {
319                 return NULL;
320         }
321
322         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
323
324         if( new == NULL ) {
325                 return NULL;
326         }
327
328         if( c->ldctl_oid != NULL ) {
329                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
330
331                 if(new->ldctl_oid == NULL) {
332                         LDAP_FREE( new );
333                         return NULL;
334                 }
335
336         } else {
337                 new->ldctl_oid = NULL;
338         }
339
340         if( c->ldctl_value.bv_val != NULL ) {
341                 new->ldctl_value.bv_val =
342                         (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
343
344                 if(new->ldctl_value.bv_val == NULL) {
345                         if(new->ldctl_oid != NULL) {
346                                 LDAP_FREE( new->ldctl_oid );
347                         }
348                         LDAP_FREE( new );
349                         return NULL;
350                 }
351                 
352                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
353
354                 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
355                         c->ldctl_value.bv_len );
356
357                 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
358
359         } else {
360                 new->ldctl_value.bv_len = 0;
361                 new->ldctl_value.bv_val = NULL;
362         }
363
364         new->ldctl_iscritical = c->ldctl_iscritical;
365         return new;
366 }
367
368 /*
369  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
370  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
371  */
372 /* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
373 /*---
374  * This notice applies to changes, created by or for Novell, Inc.,
375  * to preexisting works for which notices appear elsewhere in this file.
376  *
377  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
378  *
379  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
380  * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
381  * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
382  * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
383  * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
384  * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
385  * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
386  * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 
387  *---
388  * Modification to OpenLDAP source by Novell, Inc.
389  * June 2000 sfs  Added control utilities
390  */
391 /*---
392    ldap_create_control
393    
394    Internal function to create an LDAP control from the encoded BerElement.
395
396    requestOID  (IN) The OID to use in creating the control.
397    
398    ber         (IN) The encoded BerElement to use in creating the control.
399    
400    iscritical  (IN) 0 - Indicates the control is not critical to the operation.
401                                         non-zero - The control is critical to the operation.
402                                   
403    ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
404                                         SHOULD be freed by calling ldap_control_free() when done.
405 ---*/
406
407 int
408 ldap_create_control(
409         LDAP_CONST char *requestOID,
410         BerElement *ber,
411         int iscritical,
412         LDAPControl **ctrlp )
413 {
414         LDAPControl *ctrl;
415         struct berval *bvalp;
416
417         assert( requestOID != NULL );
418         assert( ber != NULL );
419         assert( ctrlp != NULL );
420
421         ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
422         if ( ctrl == NULL ) {
423                 return LDAP_NO_MEMORY;
424         }
425
426         if ( ber_flatten( ber, &bvalp ) == -1 ) {
427                 LDAP_FREE( ctrl );
428                 return LDAP_NO_MEMORY;
429         }
430
431         ctrl->ldctl_value = *bvalp;
432         ber_memfree( bvalp );
433
434         ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
435         ctrl->ldctl_iscritical = iscritical;
436
437         if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
438                 ldap_control_free( ctrl );
439                 return LDAP_NO_MEMORY;
440         }
441
442         *ctrlp = ctrl;
443         return LDAP_SUCCESS;
444 }
445
446 /*
447  * check for critical client controls and bitch if present
448  * if we ever support critical controls, we'll have to
449  * find a means for maintaining per API call control
450  * information.
451  */
452 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
453 {
454         LDAPControl *const *c;
455
456         assert( ld != NULL );
457         assert( LDAP_VALID(ld) );
458
459         if( ctrls == NULL ) {
460                 /* use default server controls */
461                 ctrls = ld->ld_cctrls;
462         }
463
464         if( ctrls == NULL || *ctrls == NULL ) {
465                 return LDAP_SUCCESS;
466         }
467
468         for( c = ctrls ; *c != NULL; c++ ) {
469                 if( (*c)->ldctl_iscritical ) {
470                         ld->ld_errno = LDAP_NOT_SUPPORTED;
471                         return ld->ld_errno;
472                 }
473         }
474
475         return LDAP_SUCCESS;
476 }