xref: /titanic_53/usr/src/lib/libldap5/sources/ldap/common/control.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*7c478bd9Sstevel@tonic-gate 
3*7c478bd9Sstevel@tonic-gate /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public License
6*7c478bd9Sstevel@tonic-gate  * Version 1.0 (the "NPL"); you may not use this file except in
7*7c478bd9Sstevel@tonic-gate  * compliance with the NPL.  You may obtain a copy of the NPL at
8*7c478bd9Sstevel@tonic-gate  * http://www.mozilla.org/NPL/
9*7c478bd9Sstevel@tonic-gate  *
10*7c478bd9Sstevel@tonic-gate  * Software distributed under the NPL is distributed on an "AS IS" basis,
11*7c478bd9Sstevel@tonic-gate  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
12*7c478bd9Sstevel@tonic-gate  * for the specific language governing rights and limitations under the
13*7c478bd9Sstevel@tonic-gate  * NPL.
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * The Initial Developer of this code under the NPL is Netscape
16*7c478bd9Sstevel@tonic-gate  * Communications Corporation.  Portions created by Netscape are
17*7c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
18*7c478bd9Sstevel@tonic-gate  * Reserved.
19*7c478bd9Sstevel@tonic-gate  */
20*7c478bd9Sstevel@tonic-gate /* control.c - routines to handle ldapv3 controls */
21*7c478bd9Sstevel@tonic-gate 
22*7c478bd9Sstevel@tonic-gate #include "ldap-int.h"
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate static LDAPControl *ldap_control_dup( LDAPControl *ctrl );
25*7c478bd9Sstevel@tonic-gate static int ldap_control_copy_contents( LDAPControl *ctrl_dst,
26*7c478bd9Sstevel@tonic-gate     LDAPControl *ctrl_src );
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * Append a list of LDAPv3 controls to ber.  If ctrls is NULL, use default
30*7c478bd9Sstevel@tonic-gate  * set of controls from ld.
31*7c478bd9Sstevel@tonic-gate  * Return an LDAP error code (LDAP_SUCCESS if all goes well).
32*7c478bd9Sstevel@tonic-gate  * If closeseq is non-zero, we do an extra ber_put_seq() as well.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate int
nsldapi_put_controls(LDAP * ld,LDAPControl ** ctrls,int closeseq,BerElement * ber)35*7c478bd9Sstevel@tonic-gate nsldapi_put_controls( LDAP *ld, LDAPControl **ctrls, int closeseq,
36*7c478bd9Sstevel@tonic-gate     BerElement *ber )
37*7c478bd9Sstevel@tonic-gate {
38*7c478bd9Sstevel@tonic-gate 	LDAPControl	*c;
39*7c478bd9Sstevel@tonic-gate 	int		rc, i;
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate 	rc = LDAP_ENCODING_ERROR;	/* the most popular error */
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate 	/* if no controls were passed in, use global list from LDAP * */
44*7c478bd9Sstevel@tonic-gate 	LDAP_MUTEX_LOCK( ld, LDAP_CTRL_LOCK );
45*7c478bd9Sstevel@tonic-gate 	if ( ctrls == NULL ) {
46*7c478bd9Sstevel@tonic-gate 		ctrls = ld->ld_servercontrols;
47*7c478bd9Sstevel@tonic-gate 	}
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate 	/* if there are no controls then we are done */
50*7c478bd9Sstevel@tonic-gate 	if ( ctrls == NULL || ctrls[ 0 ] == NULL ) {
51*7c478bd9Sstevel@tonic-gate 		goto clean_exit;
52*7c478bd9Sstevel@tonic-gate 	}
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate 	/*
55*7c478bd9Sstevel@tonic-gate 	 * If we're using LDAPv2 or earlier we can't send any controls, so
56*7c478bd9Sstevel@tonic-gate 	 * we just ignore them unless one is marked critical, in which case
57*7c478bd9Sstevel@tonic-gate 	 * we return an error.
58*7c478bd9Sstevel@tonic-gate 	 */
59*7c478bd9Sstevel@tonic-gate 	if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
60*7c478bd9Sstevel@tonic-gate 		for ( i = 0; ctrls != NULL && ctrls[i] != NULL; i++ ) {
61*7c478bd9Sstevel@tonic-gate 			if ( ctrls[i]->ldctl_iscritical ) {
62*7c478bd9Sstevel@tonic-gate 				rc = LDAP_NOT_SUPPORTED;
63*7c478bd9Sstevel@tonic-gate 				goto error_exit;
64*7c478bd9Sstevel@tonic-gate 			}
65*7c478bd9Sstevel@tonic-gate 		}
66*7c478bd9Sstevel@tonic-gate 		goto clean_exit;
67*7c478bd9Sstevel@tonic-gate 	}
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 	/*
70*7c478bd9Sstevel@tonic-gate 	 * encode the controls as a Sequence of Sequence
71*7c478bd9Sstevel@tonic-gate 	 */
72*7c478bd9Sstevel@tonic-gate 	if ( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) {
73*7c478bd9Sstevel@tonic-gate 		goto error_exit;
74*7c478bd9Sstevel@tonic-gate 	}
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	for ( i = 0; ctrls[i] != NULL; i++ ) {
77*7c478bd9Sstevel@tonic-gate 		c = ctrls[i];
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 		if ( ber_printf( ber, "{s", c->ldctl_oid ) == -1 ) {
80*7c478bd9Sstevel@tonic-gate 			goto error_exit;
81*7c478bd9Sstevel@tonic-gate 		}
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 		/* criticality is "BOOLEAN DEFAULT FALSE" */
84*7c478bd9Sstevel@tonic-gate 		/* therefore, it should only be encoded if it exists AND is TRUE */
85*7c478bd9Sstevel@tonic-gate 		if ( c->ldctl_iscritical ) {
86*7c478bd9Sstevel@tonic-gate 			if ( ber_printf( ber, "b", (int)c->ldctl_iscritical )
87*7c478bd9Sstevel@tonic-gate 			    == -1 ) {
88*7c478bd9Sstevel@tonic-gate 				goto error_exit;
89*7c478bd9Sstevel@tonic-gate 			}
90*7c478bd9Sstevel@tonic-gate 		}
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 		if ( c->ldctl_value.bv_val != NULL ) {
93*7c478bd9Sstevel@tonic-gate 			if ( ber_printf( ber, "o", c->ldctl_value.bv_val,
94*7c478bd9Sstevel@tonic-gate 			    (int)c->ldctl_value.bv_len /* XXX lossy cast */ )
95*7c478bd9Sstevel@tonic-gate 			    == -1 ) {
96*7c478bd9Sstevel@tonic-gate 				goto error_exit;
97*7c478bd9Sstevel@tonic-gate 			}
98*7c478bd9Sstevel@tonic-gate 		}
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 		if ( ber_put_seq( ber ) == -1 ) {
101*7c478bd9Sstevel@tonic-gate 			goto error_exit;
102*7c478bd9Sstevel@tonic-gate 		}
103*7c478bd9Sstevel@tonic-gate 	}
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	if ( ber_put_seq( ber ) == -1 ) {
106*7c478bd9Sstevel@tonic-gate 		goto error_exit;
107*7c478bd9Sstevel@tonic-gate 	}
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate clean_exit:
110*7c478bd9Sstevel@tonic-gate 	LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK );
111*7c478bd9Sstevel@tonic-gate 	if ( closeseq && ber_put_seq( ber ) == -1 ) {
112*7c478bd9Sstevel@tonic-gate 		goto error_exit;
113*7c478bd9Sstevel@tonic-gate 	}
114*7c478bd9Sstevel@tonic-gate 	return( LDAP_SUCCESS );
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate error_exit:
117*7c478bd9Sstevel@tonic-gate 	LDAP_MUTEX_UNLOCK( ld, LDAP_CTRL_LOCK );
118*7c478bd9Sstevel@tonic-gate 	LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
119*7c478bd9Sstevel@tonic-gate 	return( rc );
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate /*
124*7c478bd9Sstevel@tonic-gate  * Pull controls out of "ber" (if any present) and return them in "controlsp."
125*7c478bd9Sstevel@tonic-gate  * Returns an LDAP error code.
126*7c478bd9Sstevel@tonic-gate  */
127*7c478bd9Sstevel@tonic-gate int
nsldapi_get_controls(BerElement * ber,LDAPControl *** controlsp)128*7c478bd9Sstevel@tonic-gate nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp )
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	LDAPControl		*newctrl;
131*7c478bd9Sstevel@tonic-gate 	ber_tag_t		tag;
132*7c478bd9Sstevel@tonic-gate 	ber_len_t		len;
133*7c478bd9Sstevel@tonic-gate 	int			rc, maxcontrols, curcontrols;
134*7c478bd9Sstevel@tonic-gate 	char			*last;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	/*
137*7c478bd9Sstevel@tonic-gate 	 * Each LDAPMessage can have a set of controls appended
138*7c478bd9Sstevel@tonic-gate 	 * to it. Controls are used to extend the functionality
139*7c478bd9Sstevel@tonic-gate 	 * of an LDAP operation (e.g., add an attribute size limit
140*7c478bd9Sstevel@tonic-gate 	 * to the search operation). These controls look like this:
141*7c478bd9Sstevel@tonic-gate 	 *
142*7c478bd9Sstevel@tonic-gate 	 *	Controls ::= SEQUENCE OF Control
143*7c478bd9Sstevel@tonic-gate 	 *
144*7c478bd9Sstevel@tonic-gate 	 *	Control ::= SEQUENCE {
145*7c478bd9Sstevel@tonic-gate 	 *		controlType	LDAPOID,
146*7c478bd9Sstevel@tonic-gate 	 *		criticality	BOOLEAN DEFAULT FALSE,
147*7c478bd9Sstevel@tonic-gate 	 *		controlValue	OCTET STRING
148*7c478bd9Sstevel@tonic-gate 	 *	}
149*7c478bd9Sstevel@tonic-gate 	 */
150*7c478bd9Sstevel@tonic-gate 	LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_get_controls\n", 0, 0, 0 );
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 	*controlsp = NULL;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	/*
155*7c478bd9Sstevel@tonic-gate          * check to see if controls were included
156*7c478bd9Sstevel@tonic-gate 	 */
157*7c478bd9Sstevel@tonic-gate 	if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) {
158*7c478bd9Sstevel@tonic-gate 		return( LDAP_DECODING_ERROR );	/* unexpected error */
159*7c478bd9Sstevel@tonic-gate 	}
160*7c478bd9Sstevel@tonic-gate 	if ( len == 0 ) {
161*7c478bd9Sstevel@tonic-gate 		LDAPDebug( LDAP_DEBUG_TRACE,
162*7c478bd9Sstevel@tonic-gate 		    "<= nsldapi_get_controls no controls\n", 0, 0, 0 );
163*7c478bd9Sstevel@tonic-gate 		return( LDAP_SUCCESS );			/* no controls */
164*7c478bd9Sstevel@tonic-gate 	}
165*7c478bd9Sstevel@tonic-gate 	if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
166*7c478bd9Sstevel@tonic-gate 		if ( tag == LBER_ERROR ) {
167*7c478bd9Sstevel@tonic-gate 			LDAPDebug( LDAP_DEBUG_TRACE,
168*7c478bd9Sstevel@tonic-gate 			    "<= nsldapi_get_controls LDAP_PROTOCOL_ERROR\n",
169*7c478bd9Sstevel@tonic-gate 			    0, 0, 0 );
170*7c478bd9Sstevel@tonic-gate 			return( LDAP_DECODING_ERROR );	/* decoding error */
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 		/*
173*7c478bd9Sstevel@tonic-gate 		 * We found something other than controls.  This should never
174*7c478bd9Sstevel@tonic-gate 		 * happen in LDAPv3, but we don't treat this is a hard error --
175*7c478bd9Sstevel@tonic-gate 		 * we just ignore the extra stuff.
176*7c478bd9Sstevel@tonic-gate 		 */
177*7c478bd9Sstevel@tonic-gate 		LDAPDebug( LDAP_DEBUG_TRACE,
178*7c478bd9Sstevel@tonic-gate 		    "<= nsldapi_get_controls ignoring unrecognized data in message (tag 0x%x)\n",
179*7c478bd9Sstevel@tonic-gate 		    tag, 0, 0 );
180*7c478bd9Sstevel@tonic-gate 		return( LDAP_SUCCESS );
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	maxcontrols = curcontrols = 0;
184*7c478bd9Sstevel@tonic-gate 	for ( tag = ber_first_element( ber, &len, &last );
185*7c478bd9Sstevel@tonic-gate 	    tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
186*7c478bd9Sstevel@tonic-gate 	    tag = ber_next_element( ber, &len, last ) ) {
187*7c478bd9Sstevel@tonic-gate 		if ( curcontrols >= maxcontrols - 1 ) {
188*7c478bd9Sstevel@tonic-gate #define CONTROL_GRABSIZE	5
189*7c478bd9Sstevel@tonic-gate 			maxcontrols += CONTROL_GRABSIZE;
190*7c478bd9Sstevel@tonic-gate 			*controlsp = (struct ldapcontrol **)NSLDAPI_REALLOC(
191*7c478bd9Sstevel@tonic-gate 			    (char *)*controlsp, maxcontrols *
192*7c478bd9Sstevel@tonic-gate 			    sizeof(struct ldapcontrol *) );
193*7c478bd9Sstevel@tonic-gate 			if ( *controlsp == NULL ) {
194*7c478bd9Sstevel@tonic-gate 			    rc = LDAP_NO_MEMORY;
195*7c478bd9Sstevel@tonic-gate 			    goto free_and_return;
196*7c478bd9Sstevel@tonic-gate 			}
197*7c478bd9Sstevel@tonic-gate 		}
198*7c478bd9Sstevel@tonic-gate 		if (( newctrl = (struct ldapcontrol *)NSLDAPI_CALLOC( 1,
199*7c478bd9Sstevel@tonic-gate 		    sizeof(LDAPControl))) == NULL ) {
200*7c478bd9Sstevel@tonic-gate 			rc = LDAP_NO_MEMORY;
201*7c478bd9Sstevel@tonic-gate 			goto free_and_return;
202*7c478bd9Sstevel@tonic-gate 		}
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 		(*controlsp)[curcontrols++] = newctrl;
205*7c478bd9Sstevel@tonic-gate 		(*controlsp)[curcontrols] = NULL;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 		if ( ber_scanf( ber, "{a", &newctrl->ldctl_oid )
208*7c478bd9Sstevel@tonic-gate 		    == LBER_ERROR ) {
209*7c478bd9Sstevel@tonic-gate 			rc = LDAP_DECODING_ERROR;
210*7c478bd9Sstevel@tonic-gate 			goto free_and_return;
211*7c478bd9Sstevel@tonic-gate 		}
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		/* the criticality is optional */
214*7c478bd9Sstevel@tonic-gate 		if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) {
215*7c478bd9Sstevel@tonic-gate 			int		aint;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 			if ( ber_scanf( ber, "b", &aint ) == LBER_ERROR ) {
218*7c478bd9Sstevel@tonic-gate 				rc = LDAP_DECODING_ERROR;
219*7c478bd9Sstevel@tonic-gate 				goto free_and_return;
220*7c478bd9Sstevel@tonic-gate 			}
221*7c478bd9Sstevel@tonic-gate 			newctrl->ldctl_iscritical = (char)aint;	/* XXX lossy cast */
222*7c478bd9Sstevel@tonic-gate 		} else {
223*7c478bd9Sstevel@tonic-gate 			/* absent is synonomous with FALSE */
224*7c478bd9Sstevel@tonic-gate 			newctrl->ldctl_iscritical = 0;
225*7c478bd9Sstevel@tonic-gate 		}
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 		/* the control value is optional */
228*7c478bd9Sstevel@tonic-gate 		if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) {
229*7c478bd9Sstevel@tonic-gate 			if ( ber_scanf( ber, "o", &newctrl->ldctl_value )
230*7c478bd9Sstevel@tonic-gate 			    == LBER_ERROR ) {
231*7c478bd9Sstevel@tonic-gate 				rc = LDAP_DECODING_ERROR;
232*7c478bd9Sstevel@tonic-gate 				goto free_and_return;
233*7c478bd9Sstevel@tonic-gate 			}
234*7c478bd9Sstevel@tonic-gate 		} else {
235*7c478bd9Sstevel@tonic-gate 			(newctrl->ldctl_value).bv_val = NULL;
236*7c478bd9Sstevel@tonic-gate 			(newctrl->ldctl_value).bv_len = 0;
237*7c478bd9Sstevel@tonic-gate 		}
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	}
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	if ( tag == LBER_ERROR ) {
242*7c478bd9Sstevel@tonic-gate 		rc = LDAP_DECODING_ERROR;
243*7c478bd9Sstevel@tonic-gate 		goto free_and_return;
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	LDAPDebug( LDAP_DEBUG_TRACE,
247*7c478bd9Sstevel@tonic-gate 	    "<= nsldapi_get_controls found %d controls\n", curcontrols, 0, 0 );
248*7c478bd9Sstevel@tonic-gate 	return( LDAP_SUCCESS );
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate free_and_return:;
251*7c478bd9Sstevel@tonic-gate 	ldap_controls_free( *controlsp );
252*7c478bd9Sstevel@tonic-gate 	*controlsp = NULL;
253*7c478bd9Sstevel@tonic-gate 	LDAPDebug( LDAP_DEBUG_TRACE,
254*7c478bd9Sstevel@tonic-gate 	    "<= nsldapi_get_controls error 0x%x\n", rc, 0, 0 );
255*7c478bd9Sstevel@tonic-gate 	return( rc );
256*7c478bd9Sstevel@tonic-gate }
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate void
260*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_control_free(LDAPControl * ctrl)261*7c478bd9Sstevel@tonic-gate ldap_control_free( LDAPControl *ctrl )
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate 	if ( ctrl != NULL ) {
264*7c478bd9Sstevel@tonic-gate 		if ( ctrl->ldctl_oid != NULL ) {
265*7c478bd9Sstevel@tonic-gate 			NSLDAPI_FREE( ctrl->ldctl_oid );
266*7c478bd9Sstevel@tonic-gate 		}
267*7c478bd9Sstevel@tonic-gate 		if ( ctrl->ldctl_value.bv_val != NULL ) {
268*7c478bd9Sstevel@tonic-gate 			NSLDAPI_FREE( ctrl->ldctl_value.bv_val );
269*7c478bd9Sstevel@tonic-gate 		}
270*7c478bd9Sstevel@tonic-gate 		NSLDAPI_FREE( (char *)ctrl );
271*7c478bd9Sstevel@tonic-gate 	}
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate void
276*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_controls_free(LDAPControl ** ctrls)277*7c478bd9Sstevel@tonic-gate ldap_controls_free( LDAPControl **ctrls )
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	int	i;
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	if ( ctrls != NULL ) {
282*7c478bd9Sstevel@tonic-gate 		for ( i = 0; ctrls[i] != NULL; i++ ) {
283*7c478bd9Sstevel@tonic-gate 			ldap_control_free( ctrls[i] );
284*7c478bd9Sstevel@tonic-gate 		}
285*7c478bd9Sstevel@tonic-gate 		NSLDAPI_FREE( (char *)ctrls );
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate #if 0
292*7c478bd9Sstevel@tonic-gate LDAPControl **
293*7c478bd9Sstevel@tonic-gate LDAP_CALL
294*7c478bd9Sstevel@tonic-gate ldap_control_append( LDAPControl **ctrl_src, LDAPControl *ctrl )
295*7c478bd9Sstevel@tonic-gate {
296*7c478bd9Sstevel@tonic-gate     int nctrls = 0;
297*7c478bd9Sstevel@tonic-gate 	LDAPControl **ctrlp;
298*7c478bd9Sstevel@tonic-gate 	int i;
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	if ( NULL == ctrl )
301*7c478bd9Sstevel@tonic-gate 	    return ( NULL );
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	/* Count the existing controls */
304*7c478bd9Sstevel@tonic-gate 	if ( NULL != ctrl_src ) {
305*7c478bd9Sstevel@tonic-gate 		while( NULL != ctrl_src[nctrls] ) {
306*7c478bd9Sstevel@tonic-gate 			nctrls++;
307*7c478bd9Sstevel@tonic-gate 		}
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	/* allocate the new control structure */
311*7c478bd9Sstevel@tonic-gate 	if ( ( ctrlp = (LDAPControl **)NSLDAPI_MALLOC( sizeof(LDAPControl *)
312*7c478bd9Sstevel@tonic-gate 	    * (nctrls + 2) ) ) == NULL ) {
313*7c478bd9Sstevel@tonic-gate 		return( NULL );
314*7c478bd9Sstevel@tonic-gate 	}
315*7c478bd9Sstevel@tonic-gate 	memset( ctrlp, 0, sizeof(*ctrlp) * (nctrls + 2) );
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	for( i = 0; i < (nctrls + 1); i++ ) {
318*7c478bd9Sstevel@tonic-gate 	    if ( i < nctrls ) {
319*7c478bd9Sstevel@tonic-gate 		    ctrlp[i] = ldap_control_dup( ctrl_src[i] );
320*7c478bd9Sstevel@tonic-gate 	    } else {
321*7c478bd9Sstevel@tonic-gate 		    ctrlp[i] = ldap_control_dup( ctrl );
322*7c478bd9Sstevel@tonic-gate 	    }
323*7c478bd9Sstevel@tonic-gate 	    if ( NULL == ctrlp[i] ) {
324*7c478bd9Sstevel@tonic-gate 		    ldap_controls_free( ctrlp );
325*7c478bd9Sstevel@tonic-gate 		    return( NULL );
326*7c478bd9Sstevel@tonic-gate 	    }
327*7c478bd9Sstevel@tonic-gate 	}
328*7c478bd9Sstevel@tonic-gate 	return ctrlp;
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate #endif /* 0 */
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate /*
334*7c478bd9Sstevel@tonic-gate  * Replace *ldctrls with a copy of newctrls.
335*7c478bd9Sstevel@tonic-gate  * returns 0 if successful.
336*7c478bd9Sstevel@tonic-gate  * return -1 if not and set error code inside LDAP *ld.
337*7c478bd9Sstevel@tonic-gate  */
338*7c478bd9Sstevel@tonic-gate int
nsldapi_dup_controls(LDAP * ld,LDAPControl *** ldctrls,LDAPControl ** newctrls)339*7c478bd9Sstevel@tonic-gate nsldapi_dup_controls( LDAP *ld, LDAPControl ***ldctrls, LDAPControl **newctrls )
340*7c478bd9Sstevel@tonic-gate {
341*7c478bd9Sstevel@tonic-gate 	int	count;
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	if ( *ldctrls != NULL ) {
344*7c478bd9Sstevel@tonic-gate 		ldap_controls_free( *ldctrls );
345*7c478bd9Sstevel@tonic-gate 	}
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	if ( newctrls == NULL || newctrls[0] == NULL ) {
348*7c478bd9Sstevel@tonic-gate 		*ldctrls = NULL;
349*7c478bd9Sstevel@tonic-gate 		return( 0 );
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	for ( count = 0; newctrls[ count ] != NULL; ++count ) {
353*7c478bd9Sstevel@tonic-gate 		;
354*7c478bd9Sstevel@tonic-gate 	}
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	if (( *ldctrls = (LDAPControl **)NSLDAPI_MALLOC(( count + 1 ) *
357*7c478bd9Sstevel@tonic-gate 	    sizeof( LDAPControl *))) == NULL ) {
358*7c478bd9Sstevel@tonic-gate 		LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
359*7c478bd9Sstevel@tonic-gate 		return( -1 );
360*7c478bd9Sstevel@tonic-gate 	}
361*7c478bd9Sstevel@tonic-gate 	(*ldctrls)[ count ] = NULL;
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	for ( count = 0; newctrls[ count ] != NULL; ++count ) {
364*7c478bd9Sstevel@tonic-gate 		if (( (*ldctrls)[ count ] =
365*7c478bd9Sstevel@tonic-gate 		    ldap_control_dup( newctrls[ count ] )) == NULL ) {
366*7c478bd9Sstevel@tonic-gate 			ldap_controls_free( *ldctrls );
367*7c478bd9Sstevel@tonic-gate 			*ldctrls = NULL;
368*7c478bd9Sstevel@tonic-gate 			LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
369*7c478bd9Sstevel@tonic-gate 			return( -1 );
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 	}
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	return( 0 );
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate /*
378*7c478bd9Sstevel@tonic-gate  * return a malloc'd copy of "ctrl" (NULL if memory allocation fails)
379*7c478bd9Sstevel@tonic-gate  */
380*7c478bd9Sstevel@tonic-gate static LDAPControl *
381*7c478bd9Sstevel@tonic-gate /* LDAP_CALL */		/* keep this routine internal for now */
ldap_control_dup(LDAPControl * ctrl)382*7c478bd9Sstevel@tonic-gate ldap_control_dup( LDAPControl *ctrl )
383*7c478bd9Sstevel@tonic-gate {
384*7c478bd9Sstevel@tonic-gate 	LDAPControl	*rctrl;
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	if (( rctrl = (LDAPControl *)NSLDAPI_MALLOC( sizeof( LDAPControl )))
387*7c478bd9Sstevel@tonic-gate 	    == NULL ) {
388*7c478bd9Sstevel@tonic-gate 		return( NULL );
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	if ( ldap_control_copy_contents( rctrl, ctrl ) != LDAP_SUCCESS ) {
392*7c478bd9Sstevel@tonic-gate 		NSLDAPI_FREE( rctrl );
393*7c478bd9Sstevel@tonic-gate 		return( NULL );
394*7c478bd9Sstevel@tonic-gate 	}
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	return( rctrl );
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate /*
401*7c478bd9Sstevel@tonic-gate  * duplicate the contents of "ctrl_src" and place in "ctrl_dst"
402*7c478bd9Sstevel@tonic-gate  */
403*7c478bd9Sstevel@tonic-gate static int
404*7c478bd9Sstevel@tonic-gate /* LDAP_CALL */		/* keep this routine internal for now */
ldap_control_copy_contents(LDAPControl * ctrl_dst,LDAPControl * ctrl_src)405*7c478bd9Sstevel@tonic-gate ldap_control_copy_contents( LDAPControl *ctrl_dst, LDAPControl *ctrl_src )
406*7c478bd9Sstevel@tonic-gate {
407*7c478bd9Sstevel@tonic-gate 	size_t	len;
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 	if ( NULL == ctrl_dst || NULL == ctrl_src ) {
410*7c478bd9Sstevel@tonic-gate 		return( LDAP_PARAM_ERROR );
411*7c478bd9Sstevel@tonic-gate 	}
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 	ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical;
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	/* fill in the fields of this new control */
416*7c478bd9Sstevel@tonic-gate 	if (( ctrl_dst->ldctl_oid = nsldapi_strdup( ctrl_src->ldctl_oid ))
417*7c478bd9Sstevel@tonic-gate 	    == NULL ) {
418*7c478bd9Sstevel@tonic-gate 		return( LDAP_NO_MEMORY );
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	len = (size_t)(ctrl_src->ldctl_value).bv_len;
422*7c478bd9Sstevel@tonic-gate 	if ( ctrl_src->ldctl_value.bv_val == NULL || len <= 0 ) {
423*7c478bd9Sstevel@tonic-gate 		ctrl_dst->ldctl_value.bv_len = 0;
424*7c478bd9Sstevel@tonic-gate 		ctrl_dst->ldctl_value.bv_val = NULL;
425*7c478bd9Sstevel@tonic-gate 	} else {
426*7c478bd9Sstevel@tonic-gate 		ctrl_dst->ldctl_value.bv_len = len;
427*7c478bd9Sstevel@tonic-gate 		if (( ctrl_dst->ldctl_value.bv_val = NSLDAPI_MALLOC( len ))
428*7c478bd9Sstevel@tonic-gate 		    == NULL ) {
429*7c478bd9Sstevel@tonic-gate 			NSLDAPI_FREE( ctrl_dst->ldctl_oid );
430*7c478bd9Sstevel@tonic-gate 			return( LDAP_NO_MEMORY );
431*7c478bd9Sstevel@tonic-gate 		}
432*7c478bd9Sstevel@tonic-gate 		SAFEMEMCPY( ctrl_dst->ldctl_value.bv_val,
433*7c478bd9Sstevel@tonic-gate 		    ctrl_src->ldctl_value.bv_val, len );
434*7c478bd9Sstevel@tonic-gate 	}
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 	return ( LDAP_SUCCESS );
437*7c478bd9Sstevel@tonic-gate }
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate /*
442*7c478bd9Sstevel@tonic-gate  * build an allocated LDAPv3 control.  Returns an LDAP error code.
443*7c478bd9Sstevel@tonic-gate  */
444*7c478bd9Sstevel@tonic-gate int
nsldapi_build_control(char * oid,BerElement * ber,int freeber,char iscritical,LDAPControl ** ctrlp)445*7c478bd9Sstevel@tonic-gate nsldapi_build_control( char *oid, BerElement *ber, int freeber, char iscritical,
446*7c478bd9Sstevel@tonic-gate     LDAPControl **ctrlp )
447*7c478bd9Sstevel@tonic-gate {
448*7c478bd9Sstevel@tonic-gate 	int		rc;
449*7c478bd9Sstevel@tonic-gate 	struct berval	*bvp;
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	if ( ber == NULL ) {
452*7c478bd9Sstevel@tonic-gate 		bvp = NULL;
453*7c478bd9Sstevel@tonic-gate 	} else {
454*7c478bd9Sstevel@tonic-gate 		/* allocate struct berval with contents of the BER encoding */
455*7c478bd9Sstevel@tonic-gate 		rc = ber_flatten( ber, &bvp );
456*7c478bd9Sstevel@tonic-gate 		if ( freeber ) {
457*7c478bd9Sstevel@tonic-gate 			ber_free( ber, 1 );
458*7c478bd9Sstevel@tonic-gate 		}
459*7c478bd9Sstevel@tonic-gate 		if ( rc == -1 ) {
460*7c478bd9Sstevel@tonic-gate 			return( LDAP_NO_MEMORY );
461*7c478bd9Sstevel@tonic-gate 		}
462*7c478bd9Sstevel@tonic-gate 	}
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 	/* allocate the new control structure */
465*7c478bd9Sstevel@tonic-gate 	if (( *ctrlp = (LDAPControl *)NSLDAPI_MALLOC( sizeof(LDAPControl)))
466*7c478bd9Sstevel@tonic-gate 	    == NULL ) {
467*7c478bd9Sstevel@tonic-gate 		if ( bvp != NULL ) {
468*7c478bd9Sstevel@tonic-gate 			ber_bvfree( bvp );
469*7c478bd9Sstevel@tonic-gate 		}
470*7c478bd9Sstevel@tonic-gate 		return( LDAP_NO_MEMORY );
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	/* fill in the fields of this new control */
474*7c478bd9Sstevel@tonic-gate 	(*ctrlp)->ldctl_iscritical = iscritical;
475*7c478bd9Sstevel@tonic-gate 	if (( (*ctrlp)->ldctl_oid = nsldapi_strdup( oid )) == NULL ) {
476*7c478bd9Sstevel@tonic-gate 		NSLDAPI_FREE( *ctrlp );
477*7c478bd9Sstevel@tonic-gate 		if ( bvp != NULL ) {
478*7c478bd9Sstevel@tonic-gate 			ber_bvfree( bvp );
479*7c478bd9Sstevel@tonic-gate 		}
480*7c478bd9Sstevel@tonic-gate 		return( LDAP_NO_MEMORY );
481*7c478bd9Sstevel@tonic-gate 	}
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	if ( bvp == NULL ) {
484*7c478bd9Sstevel@tonic-gate 		(*ctrlp)->ldctl_value.bv_len = 0;
485*7c478bd9Sstevel@tonic-gate 		(*ctrlp)->ldctl_value.bv_val = NULL;
486*7c478bd9Sstevel@tonic-gate 	} else {
487*7c478bd9Sstevel@tonic-gate 		(*ctrlp)->ldctl_value = *bvp;	/* struct copy */
488*7c478bd9Sstevel@tonic-gate 		NSLDAPI_FREE( bvp );	/* free container, not contents! */
489*7c478bd9Sstevel@tonic-gate 	}
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	return( LDAP_SUCCESS );
492*7c478bd9Sstevel@tonic-gate }
493