8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libldap5 / sources / ldap / common / control.c
blob01dd0df52e86e9eb3b3b6879739a5800f9c45c9b
1 #pragma ident "%Z%%M% %I% %E% SMI"
3 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.0 (the "NPL"); you may not use this file except in
7 * compliance with the NPL. You may obtain a copy of the NPL at
8 * http://www.mozilla.org/NPL/
10 * Software distributed under the NPL is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
12 * for the specific language governing rights and limitations under the
13 * NPL.
15 * The Initial Developer of this code under the NPL is Netscape
16 * Communications Corporation. Portions created by Netscape are
17 * Copyright (C) 1998 Netscape Communications Corporation. All Rights
18 * Reserved.
20 /* control.c - routines to handle ldapv3 controls */
22 #include "ldap-int.h"
24 static LDAPControl *ldap_control_dup( LDAPControl *ctrl );
25 static int ldap_control_copy_contents( LDAPControl *ctrl_dst,
26 LDAPControl *ctrl_src );
29 * Append a list of LDAPv3 controls to ber. If ctrls is NULL, use default
30 * set of controls from ld.
31 * Return an LDAP error code (LDAP_SUCCESS if all goes well).
32 * If closeseq is non-zero, we do an extra ber_put_seq() as well.
34 int
35 nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq,
36 BerElement *ber )
38 LDAPControl *c;
39 int rc, i;
41 rc = LDAP_ENCODING_ERROR; /* the most popular error */
43 /* if no controls were passed in, use global list from LDAP * */
44 LDAP_MUTEX_LOCK( ld, LDAP_CTRL_LOCK );
45 if ( ctrls == NULL ) {
46 ctrls = ld->ld_servercontrols;
49 /* if there are no controls then we are done */
50 if ( ctrls == NULL || ctrls[ 0 ] == NULL ) {
51 goto clean_exit;
55 * If we're using LDAPv2 or earlier we can't send any controls, so
56 * we just ignore them unless one is marked critical, in which case
57 * we return an error.
59 if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
60 for ( i = 0; ctrls != NULL && ctrls[i] != NULL; i++ ) {
61 if ( ctrls[i]->ldctl_iscritical ) {
62 rc = LDAP_NOT_SUPPORTED;
63 goto error_exit;
66 goto clean_exit;
70 * encode the controls as a Sequence of Sequence
72 if ( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) {
73 goto error_exit;
76 for ( i = 0; ctrls[i] != NULL; i++ ) {
77 c = ctrls[i];
79 if ( ber_printf( ber, "{s", c->ldctl_oid ) == -1 ) {
80 goto error_exit;
83 /* criticality is "BOOLEAN DEFAULT FALSE" */
84 /* therefore, it should only be encoded if it exists AND is TRUE */
85 if ( c->ldctl_iscritical ) {
86 if ( ber_printf( ber, "b", (int)c->ldctl_iscritical )
87 == -1 ) {
88 goto error_exit;
92 if ( c->ldctl_value.bv_val != NULL ) {
93 if ( ber_printf( ber, "o", c->ldctl_value.bv_val,
94 (int)c->ldctl_value.bv_len /* XXX lossy cast */ )
95 == -1 ) {
96 goto error_exit;
100 if ( ber_put_seq( ber ) == -1 ) {
101 goto error_exit;
105 if ( ber_put_seq( ber ) == -1 ) {
106 goto error_exit;
109 clean_exit:
110 LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK );
111 if ( closeseq && ber_put_seq( ber ) == -1 ) {
112 goto error_exit;
114 return( LDAP_SUCCESS );
116 error_exit:
117 LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK );
118 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
119 return( rc );
124 * Pull controls out of "ber" (if any present) and return them in "controlsp."
125 * Returns an LDAP error code.
128 nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp )
130 LDAPControl *newctrl;
131 ber_tag_t tag;
132 ber_len_t len;
133 int rc, maxcontrols, curcontrols;
134 char *last;
137 * Each LDAPMessage can have a set of controls appended
138 * to it. Controls are used to extend the functionality
139 * of an LDAP operation (e.g., add an attribute size limit
140 * to the search operation). These controls look like this:
142 * Controls ::= SEQUENCE OF Control
144 * Control ::= SEQUENCE {
145 * controlType LDAPOID,
146 * criticality BOOLEAN DEFAULT FALSE,
147 * controlValue OCTET STRING
150 LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_get_controls\n", 0, 0, 0 );
152 *controlsp = NULL;
155 * check to see if controls were included
157 if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) {
158 return( LDAP_DECODING_ERROR ); /* unexpected error */
160 if ( len == 0 ) {
161 LDAPDebug( LDAP_DEBUG_TRACE,
162 "<= nsldapi_get_controls no controls\n", 0, 0, 0 );
163 return( LDAP_SUCCESS ); /* no controls */
165 if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
166 if ( tag == LBER_ERROR ) {
167 LDAPDebug( LDAP_DEBUG_TRACE,
168 "<= nsldapi_get_controls LDAP_PROTOCOL_ERROR\n",
169 0, 0, 0 );
170 return( LDAP_DECODING_ERROR ); /* decoding error */
173 * We found something other than controls. This should never
174 * happen in LDAPv3, but we don't treat this is a hard error --
175 * we just ignore the extra stuff.
177 LDAPDebug( LDAP_DEBUG_TRACE,
178 "<= nsldapi_get_controls ignoring unrecognized data in message (tag 0x%x)\n",
179 tag, 0, 0 );
180 return( LDAP_SUCCESS );
183 maxcontrols = curcontrols = 0;
184 for ( tag = ber_first_element( ber, &len, &last );
185 tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
186 tag = ber_next_element( ber, &len, last ) ) {
187 if ( curcontrols >= maxcontrols - 1 ) {
188 #define CONTROL_GRABSIZE 5
189 maxcontrols += CONTROL_GRABSIZE;
190 *controlsp = (struct ldapcontrol **)NSLDAPI_REALLOC(
191 (char *)*controlsp, maxcontrols *
192 sizeof(struct ldapcontrol *) );
193 if ( *controlsp == NULL ) {
194 rc = LDAP_NO_MEMORY;
195 goto free_and_return;
198 if (( newctrl = (struct ldapcontrol *)NSLDAPI_CALLOC( 1,
199 sizeof(LDAPControl))) == NULL ) {
200 rc = LDAP_NO_MEMORY;
201 goto free_and_return;
204 (*controlsp)[curcontrols++] = newctrl;
205 (*controlsp)[curcontrols] = NULL;
207 if ( ber_scanf( ber, "{a", &newctrl->ldctl_oid )
208 == LBER_ERROR ) {
209 rc = LDAP_DECODING_ERROR;
210 goto free_and_return;
213 /* the criticality is optional */
214 if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) {
215 int aint;
217 if ( ber_scanf( ber, "b", &aint ) == LBER_ERROR ) {
218 rc = LDAP_DECODING_ERROR;
219 goto free_and_return;
221 newctrl->ldctl_iscritical = (char)aint; /* XXX lossy cast */
222 } else {
223 /* absent is synonomous with FALSE */
224 newctrl->ldctl_iscritical = 0;
227 /* the control value is optional */
228 if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) {
229 if ( ber_scanf( ber, "o", &newctrl->ldctl_value )
230 == LBER_ERROR ) {
231 rc = LDAP_DECODING_ERROR;
232 goto free_and_return;
234 } else {
235 (newctrl->ldctl_value).bv_val = NULL;
236 (newctrl->ldctl_value).bv_len = 0;
241 if ( tag == LBER_ERROR ) {
242 rc = LDAP_DECODING_ERROR;
243 goto free_and_return;
246 LDAPDebug( LDAP_DEBUG_TRACE,
247 "<= nsldapi_get_controls found %d controls\n", curcontrols, 0, 0 );
248 return( LDAP_SUCCESS );
250 free_and_return:;
251 ldap_controls_free( *controlsp );
252 *controlsp = NULL;
253 LDAPDebug( LDAP_DEBUG_TRACE,
254 "<= nsldapi_get_controls error 0x%x\n", rc, 0, 0 );
255 return( rc );
259 void
260 LDAP_CALL
261 ldap_control_free( LDAPControl *ctrl )
263 if ( ctrl != NULL ) {
264 if ( ctrl->ldctl_oid != NULL ) {
265 NSLDAPI_FREE( ctrl->ldctl_oid );
267 if ( ctrl->ldctl_value.bv_val != NULL ) {
268 NSLDAPI_FREE( ctrl->ldctl_value.bv_val );
270 NSLDAPI_FREE( (char *)ctrl );
275 void
276 LDAP_CALL
277 ldap_controls_free( LDAPControl **ctrls )
279 int i;
281 if ( ctrls != NULL ) {
282 for ( i = 0; ctrls[i] != NULL; i++ ) {
283 ldap_control_free( ctrls[i] );
285 NSLDAPI_FREE( (char *)ctrls );
291 #if 0
292 LDAPControl **
293 LDAP_CALL
294 ldap_control_append( LDAPControl **ctrl_src, LDAPControl *ctrl )
296 int nctrls = 0;
297 LDAPControl **ctrlp;
298 int i;
300 if ( NULL == ctrl )
301 return ( NULL );
303 /* Count the existing controls */
304 if ( NULL != ctrl_src ) {
305 while( NULL != ctrl_src[nctrls] ) {
306 nctrls++;
310 /* allocate the new control structure */
311 if ( ( ctrlp = (LDAPControl **)NSLDAPI_MALLOC( sizeof(LDAPControl *)
312 * (nctrls + 2) ) ) == NULL ) {
313 return( NULL );
315 memset( ctrlp, 0, sizeof(*ctrlp) * (nctrls + 2) );
317 for( i = 0; i < (nctrls + 1); i++ ) {
318 if ( i < nctrls ) {
319 ctrlp[i] = ldap_control_dup( ctrl_src[i] );
320 } else {
321 ctrlp[i] = ldap_control_dup( ctrl );
323 if ( NULL == ctrlp[i] ) {
324 ldap_controls_free( ctrlp );
325 return( NULL );
328 return ctrlp;
330 #endif /* 0 */
334 * Replace *ldctrls with a copy of newctrls.
335 * returns 0 if successful.
336 * return -1 if not and set error code inside LDAP *ld.
339 nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls, LDAPControl **newctrls )
341 int count;
343 if ( *ldctrls != NULL ) {
344 ldap_controls_free( *ldctrls );
347 if ( newctrls == NULL || newctrls[0] == NULL ) {
348 *ldctrls = NULL;
349 return( 0 );
352 for ( count = 0; newctrls[ count ] != NULL; ++count ) {
356 if (( *ldctrls = (LDAPControl **)NSLDAPI_MALLOC(( count + 1 ) *
357 sizeof( LDAPControl *))) == NULL ) {
358 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
359 return( -1 );
361 (*ldctrls)[ count ] = NULL;
363 for ( count = 0; newctrls[ count ] != NULL; ++count ) {
364 if (( (*ldctrls)[ count ] =
365 ldap_control_dup( newctrls[ count ] )) == NULL ) {
366 ldap_controls_free( *ldctrls );
367 *ldctrls = NULL;
368 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
369 return( -1 );
373 return( 0 );
378 * return a malloc'd copy of "ctrl" (NULL if memory allocation fails)
380 static LDAPControl *
381 /* LDAP_CALL */ /* keep this routine internal for now */
382 ldap_control_dup( LDAPControl *ctrl )
384 LDAPControl *rctrl;
386 if (( rctrl = (LDAPControl *)NSLDAPI_MALLOC( sizeof( LDAPControl )))
387 == NULL ) {
388 return( NULL );
391 if ( ldap_control_copy_contents( rctrl, ctrl ) != LDAP_SUCCESS ) {
392 NSLDAPI_FREE( rctrl );
393 return( NULL );
396 return( rctrl );
401 * duplicate the contents of "ctrl_src" and place in "ctrl_dst"
403 static int
404 /* LDAP_CALL */ /* keep this routine internal for now */
405 ldap_control_copy_contents( LDAPControl *ctrl_dst, LDAPControl *ctrl_src )
407 size_t len;
409 if ( NULL == ctrl_dst || NULL == ctrl_src ) {
410 return( LDAP_PARAM_ERROR );
413 ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical;
415 /* fill in the fields of this new control */
416 if (( ctrl_dst->ldctl_oid = nsldapi_strdup( ctrl_src->ldctl_oid ))
417 == NULL ) {
418 return( LDAP_NO_MEMORY );
421 len = (size_t)(ctrl_src->ldctl_value).bv_len;
422 if ( ctrl_src->ldctl_value.bv_val == NULL || len <= 0 ) {
423 ctrl_dst->ldctl_value.bv_len = 0;
424 ctrl_dst->ldctl_value.bv_val = NULL;
425 } else {
426 ctrl_dst->ldctl_value.bv_len = len;
427 if (( ctrl_dst->ldctl_value.bv_val = NSLDAPI_MALLOC( len ))
428 == NULL ) {
429 NSLDAPI_FREE( ctrl_dst->ldctl_oid );
430 return( LDAP_NO_MEMORY );
432 SAFEMEMCPY( ctrl_dst->ldctl_value.bv_val,
433 ctrl_src->ldctl_value.bv_val, len );
436 return ( LDAP_SUCCESS );
442 * build an allocated LDAPv3 control. Returns an LDAP error code.
445 nsldapi_build_control( char *oid, BerElement *ber, int freeber, char iscritical,
446 LDAPControl **ctrlp )
448 int rc;
449 struct berval *bvp;
451 if ( ber == NULL ) {
452 bvp = NULL;
453 } else {
454 /* allocate struct berval with contents of the BER encoding */
455 rc = ber_flatten( ber, &bvp );
456 if ( freeber ) {
457 ber_free( ber, 1 );
459 if ( rc == -1 ) {
460 return( LDAP_NO_MEMORY );
464 /* allocate the new control structure */
465 if (( *ctrlp = (LDAPControl *)NSLDAPI_MALLOC( sizeof(LDAPControl)))
466 == NULL ) {
467 if ( bvp != NULL ) {
468 ber_bvfree( bvp );
470 return( LDAP_NO_MEMORY );
473 /* fill in the fields of this new control */
474 (*ctrlp)->ldctl_iscritical = iscritical;
475 if (( (*ctrlp)->ldctl_oid = nsldapi_strdup( oid )) == NULL ) {
476 NSLDAPI_FREE( *ctrlp );
477 if ( bvp != NULL ) {
478 ber_bvfree( bvp );
480 return( LDAP_NO_MEMORY );
483 if ( bvp == NULL ) {
484 (*ctrlp)->ldctl_value.bv_len = 0;
485 (*ctrlp)->ldctl_value.bv_val = NULL;
486 } else {
487 (*ctrlp)->ldctl_value = *bvp; /* struct copy */
488 NSLDAPI_FREE( bvp ); /* free container, not contents! */
491 return( LDAP_SUCCESS );