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