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