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 * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
30 * can be found in the file "build/LICENSE-2.0.1" in this distribution
31 * of OpenLDAP Software.
33 /* Portions Copyright (C) The Internet Society (1997)
34 * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
37 /* LDAPv3 Controls (RFC2251)
39 * Controls ::= SEQUENCE OF Control
41 * Control ::= SEQUENCE {
42 * controlType LDAPOID,
43 * criticality BOOLEAN DEFAULT FALSE,
44 * controlValue OCTET STRING OPTIONAL
50 #include <ac/stdlib.h>
53 #include <ac/string.h>
59 * ldap_int_put_controls
63 ldap_int_put_controls(
65 LDAPControl *const *ctrls,
68 LDAPControl *const *c;
71 assert( LDAP_VALID(ld) );
72 assert( ber != NULL );
75 /* use default server controls */
76 ctrls = ld->ld_sctrls;
79 if( ctrls == NULL || *ctrls == NULL ) {
83 if ( ld->ld_version < LDAP_VERSION3 ) {
84 /* LDAPv2 doesn't support controls,
85 * error if any control is critical
87 for( c = ctrls ; *c != NULL; c++ ) {
88 if( (*c)->ldctl_iscritical ) {
89 ld->ld_errno = LDAP_NOT_SUPPORTED;
97 /* Controls are encoded as a sequence of sequences */
98 if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
99 ld->ld_errno = LDAP_ENCODING_ERROR;
103 for( c = ctrls ; *c != NULL; c++ ) {
104 if ( ber_printf( ber, "{s" /*}*/,
105 (*c)->ldctl_oid ) == -1 )
107 ld->ld_errno = LDAP_ENCODING_ERROR;
111 if( (*c)->ldctl_iscritical /* only if true */
112 && ( ber_printf( ber, "b",
113 (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
115 ld->ld_errno = LDAP_ENCODING_ERROR;
119 if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
120 && ( ber_printf( ber, "O",
121 &((*c)->ldctl_value) ) == -1 ) )
123 ld->ld_errno = LDAP_ENCODING_ERROR;
128 if( ber_printf( ber, /*{*/"N}" ) == -1 ) {
129 ld->ld_errno = LDAP_ENCODING_ERROR;
135 if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
136 ld->ld_errno = LDAP_ENCODING_ERROR;
143 int ldap_pvt_get_controls(
145 LDAPControl ***ctrls )
152 assert( ber != NULL );
154 if( ctrls == NULL ) {
159 len = ber_pvt_ber_remaining( ber );
166 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
167 if( tag == LBER_ERROR ) {
169 return LDAP_DECODING_ERROR;
172 /* ignore unexpected input */
176 /* set through each element */
178 *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
180 if( *ctrls == NULL ) {
181 return LDAP_NO_MEMORY;
184 *ctrls[nctrls] = NULL;
186 for( tag = ber_first_element( ber, &len, &opaque );
188 tag = ber_next_element( ber, &len, opaque ) )
191 LDAPControl **tctrls;
193 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
195 /* allocate pointer space for current controls (nctrls)
196 * + this control + extra NULL
198 tctrls = (tctrl == NULL) ? NULL :
199 LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
201 if( tctrls == NULL ) {
202 /* one of the above allocation failed */
204 if( tctrl != NULL ) {
208 ldap_controls_free(*ctrls);
211 return LDAP_NO_MEMORY;
215 tctrls[nctrls++] = tctrl;
216 tctrls[nctrls] = NULL;
218 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
220 if( tag == LBER_ERROR ) {
222 ldap_controls_free( tctrls );
223 return LDAP_DECODING_ERROR;
226 tag = ber_peek_tag( ber, &len );
228 if( tag == LBER_BOOLEAN ) {
230 tag = ber_scanf( ber, "b", &crit );
231 tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
232 tag = ber_peek_tag( ber, &len );
235 if( tag == LBER_OCTETSTRING ) {
236 tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
238 tctrl->ldctl_value.bv_val = NULL;
251 ldap_control_free( LDAPControl *c )
253 #ifdef LDAP_MEMORY_DEBUG
258 if( c->ldctl_oid != NULL) {
259 LDAP_FREE( c->ldctl_oid );
262 if( c->ldctl_value.bv_val != NULL ) {
263 LDAP_FREE( c->ldctl_value.bv_val );
271 * Free an array of LDAPControl's
274 ldap_controls_free( LDAPControl **controls )
276 #ifdef LDAP_MEMORY_DEBUG
277 assert( controls != NULL );
280 if ( controls != NULL ) {
283 for( i=0; controls[i] != NULL; i++) {
284 ldap_control_free( controls[i] );
287 LDAP_FREE( controls );
292 * Duplicate an array of LDAPControl
295 ldap_controls_dup( LDAPControl *const *controls )
300 if ( controls == NULL ) {
304 /* count the controls */
305 for(i=0; controls[i] != NULL; i++) /* empty */ ;
308 /* no controls to duplicate */
312 new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
315 /* memory allocation failure */
319 /* duplicate the controls */
320 for(i=0; controls[i] != NULL; i++) {
321 new[i] = ldap_control_dup( controls[i] );
323 if( new[i] == NULL ) {
324 ldap_controls_free( new );
335 * Duplicate a LDAPControl
338 ldap_control_dup( const LDAPControl *c )
346 new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
352 if( c->ldctl_oid != NULL ) {
353 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
355 if(new->ldctl_oid == NULL) {
361 new->ldctl_oid = NULL;
364 if( c->ldctl_value.bv_val != NULL ) {
365 new->ldctl_value.bv_val =
366 (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
368 if(new->ldctl_value.bv_val == NULL) {
369 if(new->ldctl_oid != NULL) {
370 LDAP_FREE( new->ldctl_oid );
376 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
378 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
379 c->ldctl_value.bv_len );
381 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
384 new->ldctl_value.bv_len = 0;
385 new->ldctl_value.bv_val = NULL;
388 new->ldctl_iscritical = c->ldctl_iscritical;
395 LDAP_CONST char *oid,
396 LDAPControl **ctrls )
398 if( ctrls == NULL || *ctrls == NULL ) {
402 for( ; *ctrls != NULL; ctrls++ ) {
403 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
414 Internal function to create an LDAP control from the encoded BerElement.
416 requestOID (IN) The OID to use in creating the control.
418 ber (IN) The encoded BerElement to use in creating the control.
420 iscritical (IN) 0 - Indicates the control is not critical to the operation.
421 non-zero - The control is critical to the operation.
423 ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
424 SHOULD be freed by calling ldap_control_free() when done.
429 LDAP_CONST char *requestOID,
432 LDAPControl **ctrlp )
436 assert( requestOID != NULL );
437 assert( ber != NULL );
438 assert( ctrlp != NULL );
440 ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
441 if ( ctrl == NULL ) {
442 return LDAP_NO_MEMORY;
445 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
447 return LDAP_NO_MEMORY;
450 ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
451 ctrl->ldctl_iscritical = iscritical;
453 if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
454 ldap_control_free( ctrl );
455 return LDAP_NO_MEMORY;
463 * check for critical client controls and bitch if present
464 * if we ever support critical controls, we'll have to
465 * find a means for maintaining per API call control
468 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
470 LDAPControl *const *c;
472 assert( ld != NULL );
473 assert( LDAP_VALID(ld) );
475 if( ctrls == NULL ) {
476 /* use default server controls */
477 ctrls = ld->ld_cctrls;
480 if( ctrls == NULL || *ctrls == NULL ) {
484 for( c = ctrls ; *c != NULL; c++ ) {
485 if( (*c)->ldctl_iscritical ) {
486 ld->ld_errno = LDAP_NOT_SUPPORTED;