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 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 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 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 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 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 */ 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 */ 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 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