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 tctrl->ldctl_value.bv_val = NULL;
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 new->ldctl_oid = NULL;
356 if( c->ldctl_value.bv_val != NULL ) {
357 new->ldctl_value.bv_val =
358 (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
360 if(new->ldctl_value.bv_val == NULL) {
361 if(new->ldctl_oid != NULL) {
362 LDAP_FREE( new->ldctl_oid );
368 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
370 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
371 c->ldctl_value.bv_len );
373 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
376 new->ldctl_value.bv_len = 0;
377 new->ldctl_value.bv_val = NULL;
380 new->ldctl_iscritical = c->ldctl_iscritical;
387 LDAP_CONST char *oid,
388 LDAPControl **ctrls )
390 if( ctrls == NULL || *ctrls == NULL ) {
394 for( ; *ctrls != NULL; ctrls++ ) {
395 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
406 Internal function to create an LDAP control from the encoded BerElement.
408 requestOID (IN) The OID to use in creating the control.
410 ber (IN) The encoded BerElement to use in creating the control.
412 iscritical (IN) 0 - Indicates the control is not critical to the operation.
413 non-zero - The control is critical to the operation.
415 ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
416 SHOULD be freed by calling ldap_control_free() when done.
421 LDAP_CONST char *requestOID,
424 LDAPControl **ctrlp )
428 assert( requestOID != NULL );
429 assert( ber != NULL );
430 assert( ctrlp != NULL );
432 ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
433 if ( ctrl == NULL ) {
434 return LDAP_NO_MEMORY;
437 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
439 return LDAP_NO_MEMORY;
442 ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
443 ctrl->ldctl_iscritical = iscritical;
445 if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
446 ldap_control_free( ctrl );
447 return LDAP_NO_MEMORY;
455 * check for critical client controls and bitch if present
456 * if we ever support critical controls, we'll have to
457 * find a means for maintaining per API call control
460 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
462 LDAPControl *const *c;
464 assert( ld != NULL );
465 assert( LDAP_VALID( ld ) );
467 if( ctrls == NULL ) {
468 /* use default server controls */
469 ctrls = ld->ld_cctrls;
472 if( ctrls == NULL || *ctrls == NULL ) {
476 for( c = ctrls ; *c != NULL; c++ ) {
477 if( (*c)->ldctl_iscritical ) {
478 ld->ld_errno = LDAP_NOT_SUPPORTED;