]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
9925357b0c2065a50d6764155424bd0f5b47eea2
[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( 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_val != NULL ) {
340                 new->ldctl_value.bv_val =
341                         (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
342
343                 if(new->ldctl_value.bv_val == NULL) {
344                         if(new->ldctl_oid != NULL) {
345                                 LDAP_FREE( new->ldctl_oid );
346                         }
347                         LDAP_FREE( new );
348                         return NULL;
349                 }
350                 
351                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
352
353                 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
354                         c->ldctl_value.bv_len );
355
356                 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
357
358         } else {
359                 new->ldctl_value.bv_len = 0;
360                 new->ldctl_value.bv_val = NULL;
361         }
362
363         new->ldctl_iscritical = c->ldctl_iscritical;
364         return new;
365 }
366
367 /*
368  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
369  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
370  */
371 /* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
372 /*---
373  * This notice applies to changes, created by or for Novell, Inc.,
374  * to preexisting works for which notices appear elsewhere in this file.
375  *
376  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
377  *
378  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
379  * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
380  * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
381  * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
382  * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
383  * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
384  * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
385  * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 
386  *---
387  * Modification to OpenLDAP source by Novell, Inc.
388  * June 2000 sfs  Added control utilities
389  */
390 /*---
391    ldap_create_control
392    
393    Internal function to create an LDAP control from the encoded BerElement.
394
395    requestOID  (IN) The OID to use in creating the control.
396    
397    ber         (IN) The encoded BerElement to use in creating the control.
398    
399    iscritical  (IN) 0 - Indicates the control is not critical to the operation.
400                                         non-zero - The control is critical to the operation.
401                                   
402    ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
403                                         SHOULD be freed by calling ldap_control_free() when done.
404 ---*/
405
406 int
407 ldap_create_control(
408         LDAP_CONST char *requestOID,
409         BerElement *ber,
410         int iscritical,
411         LDAPControl **ctrlp )
412 {
413         LDAPControl *ctrl;
414         struct berval *bvalp;
415
416         if ( requestOID == NULL || ctrlp == NULL ) {
417                 return LDAP_PARAM_ERROR;
418         }
419
420         ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
421         if ( ctrl == NULL ) {
422                 return LDAP_NO_MEMORY;
423         }
424
425         if ( ber_flatten( ber, &bvalp ) == -1 ) {
426                 LDAP_FREE( ctrl );
427                 return LDAP_NO_MEMORY;
428         }
429
430         ctrl->ldctl_value = *bvalp;
431         ber_memfree( bvalp );
432
433         ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
434         ctrl->ldctl_iscritical = iscritical;
435
436         if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
437                 ldap_control_free( ctrl );
438                 return LDAP_NO_MEMORY;
439         }
440
441         *ctrlp = ctrl;
442         return LDAP_SUCCESS;
443 }
444
445 /*
446  * check for critical client controls and bitch if present
447  * if we ever support critical controls, we'll have to
448  * find a means for maintaining per API call control
449  * information.
450  */
451 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
452 {
453         LDAPControl *const *c;
454
455         assert( ld != NULL );
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 }