1 /* $OpenLDAP: pkg/ldap/libraries/libldap/controls.c,v 1.48.2.5 2008/02/11 23:26:41 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2008 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
59 if ( ber_printf( ber
, "{s" /*}*/, c
->ldctl_oid
) == -1 ) {
60 return LDAP_ENCODING_ERROR
;
63 if ( c
->ldctl_iscritical
/* only if true */
64 && ( ber_printf( ber
, "b",
65 (ber_int_t
) c
->ldctl_iscritical
) == -1 ) )
67 return LDAP_ENCODING_ERROR
;
70 if ( !BER_BVISNULL( &c
->ldctl_value
) /* only if we have a value */
71 && ( ber_printf( ber
, "O", &c
->ldctl_value
) == -1 ) )
73 return LDAP_ENCODING_ERROR
;
76 if ( ber_printf( ber
, /*{*/"N}" ) == -1 ) {
77 return LDAP_ENCODING_ERROR
;
85 * ldap_int_put_controls
89 ldap_int_put_controls(
91 LDAPControl
*const *ctrls
,
94 LDAPControl
*const *c
;
97 assert( LDAP_VALID( ld
) );
98 assert( ber
!= NULL
);
100 if( ctrls
== NULL
) {
101 /* use default server controls */
102 ctrls
= ld
->ld_sctrls
;
105 if( ctrls
== NULL
|| *ctrls
== NULL
) {
109 if ( ld
->ld_version
< LDAP_VERSION3
) {
110 /* LDAPv2 doesn't support controls,
111 * error if any control is critical
113 for( c
= ctrls
; *c
!= NULL
; c
++ ) {
114 if( (*c
)->ldctl_iscritical
) {
115 ld
->ld_errno
= LDAP_NOT_SUPPORTED
;
123 /* Controls are encoded as a sequence of sequences */
124 if( ber_printf( ber
, "t{"/*}*/, LDAP_TAG_CONTROLS
) == -1 ) {
125 ld
->ld_errno
= LDAP_ENCODING_ERROR
;
129 for( c
= ctrls
; *c
!= NULL
; c
++ ) {
130 ld
->ld_errno
= ldap_pvt_put_control( *c
, ber
);
131 if ( ld
->ld_errno
!= LDAP_SUCCESS
) {
137 if( ber_printf( ber
, /*{*/ "}" ) == -1 ) {
138 ld
->ld_errno
= LDAP_ENCODING_ERROR
;
145 int ldap_pvt_get_controls(
147 LDAPControl
***ctrls
)
154 assert( ber
!= NULL
);
156 if( ctrls
== NULL
) {
161 len
= ber_pvt_ber_remaining( ber
);
168 if(( tag
= ber_peek_tag( ber
, &len
)) != LDAP_TAG_CONTROLS
) {
169 if( tag
== LBER_ERROR
) {
171 return LDAP_DECODING_ERROR
;
174 /* ignore unexpected input */
178 /* set through each element */
180 *ctrls
= LDAP_MALLOC( 1 * sizeof(LDAPControl
*) );
182 if( *ctrls
== NULL
) {
183 return LDAP_NO_MEMORY
;
186 *ctrls
[nctrls
] = NULL
;
188 for( tag
= ber_first_element( ber
, &len
, &opaque
);
190 tag
= ber_next_element( ber
, &len
, opaque
) )
193 LDAPControl
**tctrls
;
195 tctrl
= LDAP_CALLOC( 1, sizeof(LDAPControl
) );
197 /* allocate pointer space for current controls (nctrls)
198 * + this control + extra NULL
200 tctrls
= (tctrl
== NULL
) ? NULL
:
201 LDAP_REALLOC(*ctrls
, (nctrls
+2) * sizeof(LDAPControl
*));
203 if( tctrls
== NULL
) {
204 /* one of the above allocation failed */
206 if( tctrl
!= NULL
) {
210 ldap_controls_free(*ctrls
);
213 return LDAP_NO_MEMORY
;
217 tctrls
[nctrls
++] = tctrl
;
218 tctrls
[nctrls
] = NULL
;
220 tag
= ber_scanf( ber
, "{a" /*}*/, &tctrl
->ldctl_oid
);
222 if( tag
== LBER_ERROR
) {
224 ldap_controls_free( tctrls
);
225 return LDAP_DECODING_ERROR
;
228 tag
= ber_peek_tag( ber
, &len
);
230 if( tag
== LBER_BOOLEAN
) {
232 tag
= ber_scanf( ber
, "b", &crit
);
233 tctrl
->ldctl_iscritical
= crit
? (char) 0 : (char) ~0;
234 tag
= ber_peek_tag( ber
, &len
);
237 if( tag
== LBER_OCTETSTRING
) {
238 tag
= ber_scanf( ber
, "o", &tctrl
->ldctl_value
);
240 BER_BVZERO( &tctrl
->ldctl_value
);
253 ldap_control_free( LDAPControl
*c
)
255 LDAP_MEMORY_DEBUG_ASSERT( c
!= NULL
);
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 LDAP_MEMORY_DEBUG_ASSERT( controls
!= NULL
);
278 if ( controls
!= NULL
) {
281 for( i
=0; controls
[i
] != NULL
; i
++) {
282 ldap_control_free( controls
[i
] );
285 LDAP_FREE( controls
);
290 * Duplicate an array of LDAPControl
293 ldap_controls_dup( LDAPControl
*const *controls
)
298 if ( controls
== NULL
) {
302 /* count the controls */
303 for(i
=0; controls
[i
] != NULL
; i
++) /* empty */ ;
306 /* no controls to duplicate */
310 new = (LDAPControl
**) LDAP_MALLOC( (i
+1) * sizeof(LDAPControl
*) );
313 /* memory allocation failure */
317 /* duplicate the controls */
318 for(i
=0; controls
[i
] != NULL
; i
++) {
319 new[i
] = ldap_control_dup( controls
[i
] );
321 if( new[i
] == NULL
) {
322 ldap_controls_free( new );
333 * Duplicate a LDAPControl
336 ldap_control_dup( const LDAPControl
*c
)
340 if ( c
== NULL
|| c
->ldctl_oid
== NULL
) {
344 new = (LDAPControl
*) LDAP_MALLOC( sizeof(LDAPControl
) );
350 new->ldctl_oid
= LDAP_STRDUP( c
->ldctl_oid
);
352 if(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
;
386 * Find a LDAPControl - deprecated
390 LDAP_CONST
char *oid
,
391 LDAPControl
**ctrls
)
393 if( ctrls
== NULL
|| *ctrls
== NULL
) {
397 for( ; *ctrls
!= NULL
; ctrls
++ ) {
398 if( strcmp( (*ctrls
)->ldctl_oid
, oid
) == 0 ) {
411 LDAP_CONST
char *oid
,
413 LDAPControl
***nextctrlp
)
415 if ( oid
== NULL
|| ctrls
== NULL
|| *ctrls
== NULL
) {
419 for( ; *ctrls
!= NULL
; ctrls
++ ) {
420 if( strcmp( (*ctrls
)->ldctl_oid
, oid
) == 0 ) {
421 if ( nextctrlp
!= NULL
) {
422 *nextctrlp
= ctrls
+ 1;
429 if ( nextctrlp
!= NULL
) {
437 * Create a LDAPControl, optionally from ber - deprecated
441 LDAP_CONST
char *requestOID
,
444 LDAPControl
**ctrlp
)
448 assert( requestOID
!= NULL
);
449 assert( ctrlp
!= NULL
);
451 ctrl
= (LDAPControl
*) LDAP_MALLOC( sizeof(LDAPControl
) );
452 if ( ctrl
== NULL
) {
453 return LDAP_NO_MEMORY
;
456 BER_BVZERO(&ctrl
->ldctl_value
);
457 if ( ber
&& ( ber_flatten2( ber
, &ctrl
->ldctl_value
, 1 ) == -1 )) {
459 return LDAP_NO_MEMORY
;
462 ctrl
->ldctl_oid
= LDAP_STRDUP( requestOID
);
463 ctrl
->ldctl_iscritical
= iscritical
;
465 if ( requestOID
!= NULL
&& ctrl
->ldctl_oid
== NULL
) {
466 ldap_control_free( ctrl
);
467 return LDAP_NO_MEMORY
;
475 * Create a LDAPControl, optionally from value
479 LDAP_CONST
char *requestOID
,
481 struct berval
*value
,
483 LDAPControl
**ctrlp
)
487 assert( requestOID
!= NULL
);
488 assert( ctrlp
!= NULL
);
490 ctrl
= (LDAPControl
*) LDAP_CALLOC( sizeof(LDAPControl
), 1 );
491 if ( ctrl
== NULL
) {
492 return LDAP_NO_MEMORY
;
495 ctrl
->ldctl_iscritical
= iscritical
;
496 if ( requestOID
!= NULL
) {
497 ctrl
->ldctl_oid
= LDAP_STRDUP( requestOID
);
498 if ( ctrl
->ldctl_oid
== NULL
) {
499 ldap_control_free( ctrl
);
500 return LDAP_NO_MEMORY
;
504 if ( value
&& !BER_BVISNULL( value
) ) {
506 ber_dupbv( &ctrl
->ldctl_value
, value
);
507 if ( BER_BVISNULL( &ctrl
->ldctl_value
) ) {
508 ldap_control_free( ctrl
);
509 return LDAP_NO_MEMORY
;
513 ctrl
->ldctl_value
= *value
;
523 * check for critical client controls and bitch if present
524 * if we ever support critical controls, we'll have to
525 * find a means for maintaining per API call control
528 int ldap_int_client_controls( LDAP
*ld
, LDAPControl
**ctrls
)
530 LDAPControl
*const *c
;
532 assert( ld
!= NULL
);
533 assert( LDAP_VALID( ld
) );
535 if( ctrls
== NULL
) {
536 /* use default server controls */
537 ctrls
= ld
->ld_cctrls
;
540 if( ctrls
== NULL
|| *ctrls
== NULL
) {
544 for( c
= ctrls
; *c
!= NULL
; c
++ ) {
545 if( (*c
)->ldctl_iscritical
) {
546 ld
->ld_errno
= LDAP_NOT_SUPPORTED
;