2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2004 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* This notice applies to changes, created by or for Novell, Inc.,
16 * to preexisting works for which notices appear elsewhere in this file.
18 * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
20 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
21 * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
22 * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
23 * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
24 * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
25 * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
26 * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
27 * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
29 * Modification to OpenLDAP source by Novell, Inc.
30 * June 2000 sfs Added control utilities
32 * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
33 * can be found in the file "build/LICENSE-2.0.1" in this distribution
34 * of OpenLDAP Software.
36 /* Portions Copyright (C) The Internet Society (1997)
37 * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
40 /* LDAPv3 Controls (RFC2251)
42 * Controls ::= SEQUENCE OF Control
44 * Control ::= SEQUENCE {
45 * controlType LDAPOID,
46 * criticality BOOLEAN DEFAULT FALSE,
47 * controlValue OCTET STRING OPTIONAL
53 #include <ac/stdlib.h>
56 #include <ac/string.h>
62 * ldap_int_put_controls
66 ldap_int_put_controls(
68 LDAPControl *const *ctrls,
71 LDAPControl *const *c;
74 assert( LDAP_VALID(ld) );
75 assert( ber != NULL );
78 /* use default server controls */
79 ctrls = ld->ld_sctrls;
82 if( ctrls == NULL || *ctrls == NULL ) {
86 if ( ld->ld_version < LDAP_VERSION3 ) {
87 /* LDAPv2 doesn't support controls,
88 * error if any control is critical
90 for( c = ctrls ; *c != NULL; c++ ) {
91 if( (*c)->ldctl_iscritical ) {
92 ld->ld_errno = LDAP_NOT_SUPPORTED;
100 /* Controls are encoded as a sequence of sequences */
101 if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
102 ld->ld_errno = LDAP_ENCODING_ERROR;
106 for( c = ctrls ; *c != NULL; c++ ) {
107 if ( ber_printf( ber, "{s" /*}*/,
108 (*c)->ldctl_oid ) == -1 )
110 ld->ld_errno = LDAP_ENCODING_ERROR;
114 if( (*c)->ldctl_iscritical /* only if true */
115 && ( ber_printf( ber, "b",
116 (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
118 ld->ld_errno = LDAP_ENCODING_ERROR;
122 if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
123 && ( ber_printf( ber, "O",
124 &((*c)->ldctl_value) ) == -1 ) )
126 ld->ld_errno = LDAP_ENCODING_ERROR;
131 if( ber_printf( ber, /*{*/"N}" ) == -1 ) {
132 ld->ld_errno = LDAP_ENCODING_ERROR;
138 if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
139 ld->ld_errno = LDAP_ENCODING_ERROR;
146 int ldap_pvt_get_controls(
148 LDAPControl ***ctrls )
155 assert( ber != NULL );
157 if( ctrls == NULL ) {
162 len = ber_pvt_ber_remaining( ber );
169 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
170 if( tag == LBER_ERROR ) {
172 return LDAP_DECODING_ERROR;
175 /* ignore unexpected input */
179 /* set through each element */
181 *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
183 if( *ctrls == NULL ) {
184 return LDAP_NO_MEMORY;
187 *ctrls[nctrls] = NULL;
189 for( tag = ber_first_element( ber, &len, &opaque );
191 tag = ber_next_element( ber, &len, opaque ) )
194 LDAPControl **tctrls;
196 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
198 /* allocate pointer space for current controls (nctrls)
199 * + this control + extra NULL
201 tctrls = (tctrl == NULL) ? NULL :
202 LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
204 if( tctrls == NULL ) {
205 /* one of the above allocation failed */
207 if( tctrl != NULL ) {
211 ldap_controls_free(*ctrls);
214 return LDAP_NO_MEMORY;
218 tctrls[nctrls++] = tctrl;
219 tctrls[nctrls] = NULL;
221 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
223 if( tag == LBER_ERROR ) {
225 ldap_controls_free( tctrls );
226 return LDAP_DECODING_ERROR;
229 tag = ber_peek_tag( ber, &len );
231 if( tag == LBER_BOOLEAN ) {
233 tag = ber_scanf( ber, "b", &crit );
234 tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
235 tag = ber_peek_tag( ber, &len );
238 if( tag == LBER_OCTETSTRING ) {
239 tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
241 tctrl->ldctl_value.bv_val = NULL;
254 ldap_control_free( LDAPControl *c )
256 #ifdef LDAP_MEMORY_DEBUG
261 if( c->ldctl_oid != NULL) {
262 LDAP_FREE( c->ldctl_oid );
265 if( c->ldctl_value.bv_val != NULL ) {
266 LDAP_FREE( c->ldctl_value.bv_val );
274 * Free an array of LDAPControl's
277 ldap_controls_free( LDAPControl **controls )
279 #ifdef LDAP_MEMORY_DEBUG
280 assert( controls != NULL );
283 if ( controls != NULL ) {
286 for( i=0; controls[i] != NULL; i++) {
287 ldap_control_free( controls[i] );
290 LDAP_FREE( controls );
295 * Duplicate an array of LDAPControl
298 ldap_controls_dup( LDAPControl *const *controls )
303 if ( controls == NULL ) {
307 /* count the controls */
308 for(i=0; controls[i] != NULL; i++) /* empty */ ;
311 /* no controls to duplicate */
315 new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
318 /* memory allocation failure */
322 /* duplicate the controls */
323 for(i=0; controls[i] != NULL; i++) {
324 new[i] = ldap_control_dup( controls[i] );
326 if( new[i] == NULL ) {
327 ldap_controls_free( new );
338 * Duplicate a LDAPControl
341 ldap_control_dup( const LDAPControl *c )
349 new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
355 if( c->ldctl_oid != NULL ) {
356 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
358 if(new->ldctl_oid == NULL) {
364 new->ldctl_oid = NULL;
367 if( c->ldctl_value.bv_val != NULL ) {
368 new->ldctl_value.bv_val =
369 (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
371 if(new->ldctl_value.bv_val == NULL) {
372 if(new->ldctl_oid != NULL) {
373 LDAP_FREE( new->ldctl_oid );
379 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
381 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
382 c->ldctl_value.bv_len );
384 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
387 new->ldctl_value.bv_len = 0;
388 new->ldctl_value.bv_val = NULL;
391 new->ldctl_iscritical = c->ldctl_iscritical;
398 Internal function to create an LDAP control from the encoded BerElement.
400 requestOID (IN) The OID to use in creating the control.
402 ber (IN) The encoded BerElement to use in creating the control.
404 iscritical (IN) 0 - Indicates the control is not critical to the operation.
405 non-zero - The control is critical to the operation.
407 ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
408 SHOULD be freed by calling ldap_control_free() when done.
413 LDAP_CONST char *requestOID,
416 LDAPControl **ctrlp )
420 assert( requestOID != NULL );
421 assert( ber != NULL );
422 assert( ctrlp != NULL );
424 ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
425 if ( ctrl == NULL ) {
426 return LDAP_NO_MEMORY;
429 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
431 return LDAP_NO_MEMORY;
434 ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
435 ctrl->ldctl_iscritical = iscritical;
437 if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
438 ldap_control_free( ctrl );
439 return LDAP_NO_MEMORY;
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
452 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
454 LDAPControl *const *c;
456 assert( ld != NULL );
457 assert( LDAP_VALID(ld) );
459 if( ctrls == NULL ) {
460 /* use default server controls */
461 ctrls = ld->ld_cctrls;
464 if( ctrls == NULL || *ctrls == NULL ) {
468 for( c = ctrls ; *c != NULL; c++ ) {
469 if( (*c)->ldctl_iscritical ) {
470 ld->ld_errno = LDAP_NOT_SUPPORTED;