2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2007 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.
36 #include <ac/stdlib.h>
39 #include <ac/string.h>
43 /* LDAPv3 Controls (RFC 4511)
45 * Controls ::= SEQUENCE OF control Control
47 * Control ::= SEQUENCE {
48 * controlType LDAPOID,
49 * criticality BOOLEAN DEFAULT FALSE,
50 * controlValue OCTET STRING OPTIONAL
55 * ldap_int_put_controls
59 ldap_int_put_controls(
61 LDAPControl *const *ctrls,
64 LDAPControl *const *c;
67 assert( LDAP_VALID( ld ) );
68 assert( ber != NULL );
71 /* use default server controls */
72 ctrls = ld->ld_sctrls;
75 if( ctrls == NULL || *ctrls == NULL ) {
79 if ( ld->ld_version < LDAP_VERSION3 ) {
80 /* LDAPv2 doesn't support controls,
81 * error if any control is critical
83 for( c = ctrls ; *c != NULL; c++ ) {
84 if( (*c)->ldctl_iscritical ) {
85 ld->ld_errno = LDAP_NOT_SUPPORTED;
93 /* Controls are encoded as a sequence of sequences */
94 if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
95 ld->ld_errno = LDAP_ENCODING_ERROR;
99 for( c = ctrls ; *c != NULL; c++ ) {
100 if ( ber_printf( ber, "{s" /*}*/,
101 (*c)->ldctl_oid ) == -1 )
103 ld->ld_errno = LDAP_ENCODING_ERROR;
107 if( (*c)->ldctl_iscritical /* only if true */
108 && ( ber_printf( ber, "b",
109 (ber_int_t) (*c)->ldctl_iscritical ) == -1 ) )
111 ld->ld_errno = LDAP_ENCODING_ERROR;
115 if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
116 && ( ber_printf( ber, "O",
117 &((*c)->ldctl_value) ) == -1 ) )
119 ld->ld_errno = LDAP_ENCODING_ERROR;
124 if( ber_printf( ber, /*{*/"N}" ) == -1 ) {
125 ld->ld_errno = LDAP_ENCODING_ERROR;
131 if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
132 ld->ld_errno = LDAP_ENCODING_ERROR;
139 int ldap_pvt_get_controls(
141 LDAPControl ***ctrls )
148 assert( ber != NULL );
150 if( ctrls == NULL ) {
155 len = ber_pvt_ber_remaining( ber );
162 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
163 if( tag == LBER_ERROR ) {
165 return LDAP_DECODING_ERROR;
168 /* ignore unexpected input */
172 /* set through each element */
174 *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
176 if( *ctrls == NULL ) {
177 return LDAP_NO_MEMORY;
180 *ctrls[nctrls] = NULL;
182 for( tag = ber_first_element( ber, &len, &opaque );
184 tag = ber_next_element( ber, &len, opaque ) )
187 LDAPControl **tctrls;
189 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
191 /* allocate pointer space for current controls (nctrls)
192 * + this control + extra NULL
194 tctrls = (tctrl == NULL) ? NULL :
195 LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
197 if( tctrls == NULL ) {
198 /* one of the above allocation failed */
200 if( tctrl != NULL ) {
204 ldap_controls_free(*ctrls);
207 return LDAP_NO_MEMORY;
211 tctrls[nctrls++] = tctrl;
212 tctrls[nctrls] = NULL;
214 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
216 if( tag == LBER_ERROR ) {
218 ldap_controls_free( tctrls );
219 return LDAP_DECODING_ERROR;
222 tag = ber_peek_tag( ber, &len );
224 if( tag == LBER_BOOLEAN ) {
226 tag = ber_scanf( ber, "b", &crit );
227 tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
228 tag = ber_peek_tag( ber, &len );
231 if( tag == LBER_OCTETSTRING ) {
232 tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
234 BER_BVZERO( &tctrl->ldctl_value );
247 ldap_control_free( LDAPControl *c )
249 LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
252 if( c->ldctl_oid != NULL) {
253 LDAP_FREE( c->ldctl_oid );
256 if( c->ldctl_value.bv_val != NULL ) {
257 LDAP_FREE( c->ldctl_value.bv_val );
265 * Free an array of LDAPControl's
268 ldap_controls_free( LDAPControl **controls )
270 LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
272 if ( controls != NULL ) {
275 for( i=0; controls[i] != NULL; i++) {
276 ldap_control_free( controls[i] );
279 LDAP_FREE( controls );
284 * Duplicate an array of LDAPControl
287 ldap_controls_dup( LDAPControl *const *controls )
292 if ( controls == NULL ) {
296 /* count the controls */
297 for(i=0; controls[i] != NULL; i++) /* empty */ ;
300 /* no controls to duplicate */
304 new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
307 /* memory allocation failure */
311 /* duplicate the controls */
312 for(i=0; controls[i] != NULL; i++) {
313 new[i] = ldap_control_dup( controls[i] );
315 if( new[i] == NULL ) {
316 ldap_controls_free( new );
327 * Duplicate a LDAPControl
330 ldap_control_dup( const LDAPControl *c )
338 new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
344 if( c->ldctl_oid != NULL ) {
345 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
347 if(new->ldctl_oid == NULL) {
353 /* FIXME: how can a control have null OID? */
354 new->ldctl_oid = NULL;
357 if( c->ldctl_value.bv_val != NULL ) {
358 new->ldctl_value.bv_val =
359 (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
361 if(new->ldctl_value.bv_val == NULL) {
362 if(new->ldctl_oid != NULL) {
363 LDAP_FREE( new->ldctl_oid );
369 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
371 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
372 c->ldctl_value.bv_len );
374 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
377 new->ldctl_value.bv_len = 0;
378 new->ldctl_value.bv_val = NULL;
381 new->ldctl_iscritical = c->ldctl_iscritical;
388 LDAP_CONST char *oid,
389 LDAPControl **ctrls )
391 if( ctrls == NULL || *ctrls == NULL ) {
395 for( ; *ctrls != NULL; ctrls++ ) {
396 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
407 Internal function to create an LDAP control from the encoded BerElement.
409 requestOID (IN) The OID to use in creating the control.
411 ber (IN) The encoded BerElement to use in creating the control.
413 iscritical (IN) 0 - Indicates the control is not critical to the operation.
414 non-zero - The control is critical to the operation.
416 ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
417 SHOULD be freed by calling ldap_control_free() when done.
422 LDAP_CONST char *requestOID,
425 LDAPControl **ctrlp )
429 assert( requestOID != NULL );
430 assert( ber != NULL );
431 assert( ctrlp != NULL );
433 ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
434 if ( ctrl == NULL ) {
435 return LDAP_NO_MEMORY;
438 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
440 return LDAP_NO_MEMORY;
443 ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
444 ctrl->ldctl_iscritical = iscritical;
446 if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
447 ldap_control_free( ctrl );
448 return LDAP_NO_MEMORY;
456 * check for critical client controls and bitch if present
457 * if we ever support critical controls, we'll have to
458 * find a means for maintaining per API call control
461 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
463 LDAPControl *const *c;
465 assert( ld != NULL );
466 assert( LDAP_VALID( ld ) );
468 if( ctrls == NULL ) {
469 /* use default server controls */
470 ctrls = ld->ld_cctrls;
473 if( ctrls == NULL || *ctrls == NULL ) {
477 for( c = ctrls ; *c != NULL; c++ ) {
478 if( (*c)->ldctl_iscritical ) {
479 ld->ld_errno = LDAP_NOT_SUPPORTED;