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