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 #ifdef LDAP_MEMORY_DEBUG
254 if( c->ldctl_oid != NULL) {
255 LDAP_FREE( c->ldctl_oid );
258 if( c->ldctl_value.bv_val != NULL ) {
259 LDAP_FREE( c->ldctl_value.bv_val );
267 * Free an array of LDAPControl's
270 ldap_controls_free( LDAPControl **controls )
272 #ifdef LDAP_MEMORY_DEBUG
273 assert( controls != NULL );
276 if ( controls != NULL ) {
279 for( i=0; controls[i] != NULL; i++) {
280 ldap_control_free( controls[i] );
283 LDAP_FREE( controls );
288 * Duplicate an array of LDAPControl
291 ldap_controls_dup( LDAPControl *const *controls )
296 if ( controls == NULL ) {
300 /* count the controls */
301 for(i=0; controls[i] != NULL; i++) /* empty */ ;
304 /* no controls to duplicate */
308 new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
311 /* memory allocation failure */
315 /* duplicate the controls */
316 for(i=0; controls[i] != NULL; i++) {
317 new[i] = ldap_control_dup( controls[i] );
319 if( new[i] == NULL ) {
320 ldap_controls_free( new );
331 * Duplicate a LDAPControl
334 ldap_control_dup( const LDAPControl *c )
342 new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
348 if( c->ldctl_oid != NULL ) {
349 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
351 if(new->ldctl_oid == NULL) {
357 new->ldctl_oid = NULL;
360 if( c->ldctl_value.bv_val != NULL ) {
361 new->ldctl_value.bv_val =
362 (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
364 if(new->ldctl_value.bv_val == NULL) {
365 if(new->ldctl_oid != NULL) {
366 LDAP_FREE( new->ldctl_oid );
372 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
374 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
375 c->ldctl_value.bv_len );
377 new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
380 new->ldctl_value.bv_len = 0;
381 new->ldctl_value.bv_val = NULL;
384 new->ldctl_iscritical = c->ldctl_iscritical;
391 LDAP_CONST char *oid,
392 LDAPControl **ctrls )
394 if( ctrls == NULL || *ctrls == NULL ) {
398 for( ; *ctrls != NULL; ctrls++ ) {
399 if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
410 Internal function to create an LDAP control from the encoded BerElement.
412 requestOID (IN) The OID to use in creating the control.
414 ber (IN) The encoded BerElement to use in creating the control.
416 iscritical (IN) 0 - Indicates the control is not critical to the operation.
417 non-zero - The control is critical to the operation.
419 ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
420 SHOULD be freed by calling ldap_control_free() when done.
425 LDAP_CONST char *requestOID,
428 LDAPControl **ctrlp )
432 assert( requestOID != NULL );
433 assert( ber != NULL );
434 assert( ctrlp != NULL );
436 ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
437 if ( ctrl == NULL ) {
438 return LDAP_NO_MEMORY;
441 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) {
443 return LDAP_NO_MEMORY;
446 ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
447 ctrl->ldctl_iscritical = iscritical;
449 if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
450 ldap_control_free( ctrl );
451 return LDAP_NO_MEMORY;
459 * check for critical client controls and bitch if present
460 * if we ever support critical controls, we'll have to
461 * find a means for maintaining per API call control
464 int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
466 LDAPControl *const *c;
468 assert( ld != NULL );
469 assert( LDAP_VALID( ld ) );
471 if( ctrls == NULL ) {
472 /* use default server controls */
473 ctrls = ld->ld_cctrls;
476 if( ctrls == NULL || *ctrls == NULL ) {
480 for( c = ctrls ; *c != NULL; c++ ) {
481 if( (*c)->ldctl_iscritical ) {
482 ld->ld_errno = LDAP_NOT_SUPPORTED;