1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001 by Sun Microsystems, Inc. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gate /* 9*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public 10*7c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file 11*7c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of 12*7c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/ 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS 15*7c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 16*7c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing 17*7c478bd9Sstevel@tonic-gate * rights and limitations under the License. 18*7c478bd9Sstevel@tonic-gate * 19*7c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released 20*7c478bd9Sstevel@tonic-gate * March 31, 1998. 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape 23*7c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 24*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All 25*7c478bd9Sstevel@tonic-gate * Rights Reserved. 26*7c478bd9Sstevel@tonic-gate * 27*7c478bd9Sstevel@tonic-gate * Contributor(s): 28*7c478bd9Sstevel@tonic-gate */ 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan. 31*7c478bd9Sstevel@tonic-gate * All rights reserved. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * ufn.c 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #if 0 38*7c478bd9Sstevel@tonic-gate #ifndef lint 39*7c478bd9Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; 40*7c478bd9Sstevel@tonic-gate #endif 41*7c478bd9Sstevel@tonic-gate #endif 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include "ldap-int.h" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate typedef int (LDAP_CALL *cancelptype)( void *cancelparm ); 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate static int ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, 48*7c478bd9Sstevel@tonic-gate char *prefix, char **attrs, int attrsonly, 49*7c478bd9Sstevel@tonic-gate LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, 50*7c478bd9Sstevel@tonic-gate char *tag1, char *tag2, char *tag3 ); 51*7c478bd9Sstevel@tonic-gate static LDAPMessage *ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ); 52*7c478bd9Sstevel@tonic-gate static LDAPMessage *ldap_ufn_expand( LDAP *ld, 53*7c478bd9Sstevel@tonic-gate LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, char **dns, 54*7c478bd9Sstevel@tonic-gate char *filter, int scope, char **attrs, int aonly, int *err ); 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * ldap_ufn_search_ctx - do user friendly searching; provide cancel feature; 58*7c478bd9Sstevel@tonic-gate * specify ldapfilter.conf tags for each phase of search 59*7c478bd9Sstevel@tonic-gate * 60*7c478bd9Sstevel@tonic-gate * ld LDAP descriptor 61*7c478bd9Sstevel@tonic-gate * ufncomp the exploded user friendly name to look for 62*7c478bd9Sstevel@tonic-gate * ncomp number of elements in ufncomp 63*7c478bd9Sstevel@tonic-gate * prefix where to start searching 64*7c478bd9Sstevel@tonic-gate * attrs list of attribute types to return for matches 65*7c478bd9Sstevel@tonic-gate * attrsonly 1 => attributes only 0 => attributes and values 66*7c478bd9Sstevel@tonic-gate * res will contain the result of the search 67*7c478bd9Sstevel@tonic-gate * cancelproc routine that returns non-zero if operation should be 68*7c478bd9Sstevel@tonic-gate * cancelled. This can be NULL. If it is non-NULL, the 69*7c478bd9Sstevel@tonic-gate * routine will be called periodically. 70*7c478bd9Sstevel@tonic-gate * cancelparm void * that is passed to cancelproc 71*7c478bd9Sstevel@tonic-gate * tag[123] the ldapfilter.conf tag that will be used in phases 72*7c478bd9Sstevel@tonic-gate * 1, 2, and 3 of the search, respectively 73*7c478bd9Sstevel@tonic-gate * 74*7c478bd9Sstevel@tonic-gate * Example: 75*7c478bd9Sstevel@tonic-gate * char *attrs[] = { "mail", "title", 0 }; 76*7c478bd9Sstevel@tonic-gate * char *ufncomp[] = { "howes", "umich", "us", 0 } 77*7c478bd9Sstevel@tonic-gate * LDAPMessage *res; 78*7c478bd9Sstevel@tonic-gate * error = ldap_ufn_search_ctx( ld, ufncomp, 3, NULL, attrs, attrsonly, 79*7c478bd9Sstevel@tonic-gate * &res, acancelproc, along, "ufn first", 80*7c478bd9Sstevel@tonic-gate * "ufn intermediate", "ufn last" ); 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate static int 84*7c478bd9Sstevel@tonic-gate ldap_ufn_search_ctx( 85*7c478bd9Sstevel@tonic-gate LDAP *ld, 86*7c478bd9Sstevel@tonic-gate char **ufncomp, 87*7c478bd9Sstevel@tonic-gate int ncomp, 88*7c478bd9Sstevel@tonic-gate char *prefix, 89*7c478bd9Sstevel@tonic-gate char **attrs, 90*7c478bd9Sstevel@tonic-gate int attrsonly, 91*7c478bd9Sstevel@tonic-gate LDAPMessage **res, 92*7c478bd9Sstevel@tonic-gate LDAP_CANCELPROC_CALLBACK *cancelproc, 93*7c478bd9Sstevel@tonic-gate void *cancelparm, 94*7c478bd9Sstevel@tonic-gate char *tag1, 95*7c478bd9Sstevel@tonic-gate char *tag2, 96*7c478bd9Sstevel@tonic-gate char *tag3 97*7c478bd9Sstevel@tonic-gate ) 98*7c478bd9Sstevel@tonic-gate { 99*7c478bd9Sstevel@tonic-gate char *dn, *ftag = NULL; 100*7c478bd9Sstevel@tonic-gate char **dns = NULL; 101*7c478bd9Sstevel@tonic-gate int max, i, err, scope = 0, phase, tries; 102*7c478bd9Sstevel@tonic-gate LDAPFiltInfo *fi; 103*7c478bd9Sstevel@tonic-gate LDAPMessage *tmpcand; 104*7c478bd9Sstevel@tonic-gate LDAPMessage *candidates; 105*7c478bd9Sstevel@tonic-gate static char *objattrs[] = { "objectClass", NULL }; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * look up ufn components from most to least significant. 109*7c478bd9Sstevel@tonic-gate * there are 3 phases. 110*7c478bd9Sstevel@tonic-gate * phase 1 search the root for orgs or countries 111*7c478bd9Sstevel@tonic-gate * phase 2 search for orgs 112*7c478bd9Sstevel@tonic-gate * phase 3 search for a person 113*7c478bd9Sstevel@tonic-gate * in phases 1 and 2, we are building a list of candidate DNs, 114*7c478bd9Sstevel@tonic-gate * below which we will search for the final component of the ufn. 115*7c478bd9Sstevel@tonic-gate * for each component we try the filters listed in the 116*7c478bd9Sstevel@tonic-gate * filterconfig file, first one-level (except the last compoment), 117*7c478bd9Sstevel@tonic-gate * then subtree. if any of them produce any results, we go on to 118*7c478bd9Sstevel@tonic-gate * the next component. 119*7c478bd9Sstevel@tonic-gate */ 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate *res = NULL; 122*7c478bd9Sstevel@tonic-gate candidates = NULL; 123*7c478bd9Sstevel@tonic-gate phase = 1; 124*7c478bd9Sstevel@tonic-gate for ( ncomp--; ncomp != -1; ncomp-- ) { 125*7c478bd9Sstevel@tonic-gate if ( *ufncomp[ncomp] == '"' ) { 126*7c478bd9Sstevel@tonic-gate char *quote; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL ) 129*7c478bd9Sstevel@tonic-gate *quote = '\0'; 130*7c478bd9Sstevel@tonic-gate strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 ); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate if ( ncomp == 0 ) 133*7c478bd9Sstevel@tonic-gate phase = 3; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate switch ( phase ) { 136*7c478bd9Sstevel@tonic-gate case 1: 137*7c478bd9Sstevel@tonic-gate ftag = tag1; 138*7c478bd9Sstevel@tonic-gate scope = LDAP_SCOPE_ONELEVEL; 139*7c478bd9Sstevel@tonic-gate break; 140*7c478bd9Sstevel@tonic-gate case 2: 141*7c478bd9Sstevel@tonic-gate ftag = tag2; 142*7c478bd9Sstevel@tonic-gate scope = LDAP_SCOPE_ONELEVEL; 143*7c478bd9Sstevel@tonic-gate break; 144*7c478bd9Sstevel@tonic-gate case 3: 145*7c478bd9Sstevel@tonic-gate ftag = tag3; 146*7c478bd9Sstevel@tonic-gate scope = LDAP_SCOPE_SUBTREE; 147*7c478bd9Sstevel@tonic-gate break; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * construct an array of DN's to search below from the 152*7c478bd9Sstevel@tonic-gate * list of candidates. 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if ( candidates == NULL ) { 156*7c478bd9Sstevel@tonic-gate if ( prefix != NULL ) { 157*7c478bd9Sstevel@tonic-gate if ( (dns = (char **)NSLDAPI_MALLOC( 158*7c478bd9Sstevel@tonic-gate sizeof(char *) * 2 )) == NULL ) { 159*7c478bd9Sstevel@tonic-gate err = LDAP_NO_MEMORY; 160*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 161*7c478bd9Sstevel@tonic-gate return( err ); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate dns[0] = nsldapi_strdup( prefix ); 164*7c478bd9Sstevel@tonic-gate dns[1] = NULL; 165*7c478bd9Sstevel@tonic-gate } else { 166*7c478bd9Sstevel@tonic-gate dns = NULL; 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate } else { 169*7c478bd9Sstevel@tonic-gate i = 0, max = 0; 170*7c478bd9Sstevel@tonic-gate for ( tmpcand = candidates; tmpcand != NULL && 171*7c478bd9Sstevel@tonic-gate tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT; 172*7c478bd9Sstevel@tonic-gate tmpcand = tmpcand->lm_chain ) 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL ) 175*7c478bd9Sstevel@tonic-gate continue; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if ( dns == NULL ) { 178*7c478bd9Sstevel@tonic-gate if ( (dns = (char **)NSLDAPI_MALLOC( 179*7c478bd9Sstevel@tonic-gate sizeof(char *) * 8 )) == NULL ) { 180*7c478bd9Sstevel@tonic-gate err = LDAP_NO_MEMORY; 181*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, 182*7c478bd9Sstevel@tonic-gate NULL, NULL ); 183*7c478bd9Sstevel@tonic-gate return( err ); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate max = 8; 186*7c478bd9Sstevel@tonic-gate } else if ( i >= max ) { 187*7c478bd9Sstevel@tonic-gate if ( (dns = (char **)NSLDAPI_REALLOC( 188*7c478bd9Sstevel@tonic-gate dns, sizeof(char *) * 2 * max )) 189*7c478bd9Sstevel@tonic-gate == NULL ) { 190*7c478bd9Sstevel@tonic-gate err = LDAP_NO_MEMORY; 191*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, 192*7c478bd9Sstevel@tonic-gate NULL, NULL ); 193*7c478bd9Sstevel@tonic-gate return( err ); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate max *= 2; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate dns[i++] = dn; 198*7c478bd9Sstevel@tonic-gate dns[i] = NULL; 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate ldap_msgfree( candidates ); 201*7c478bd9Sstevel@tonic-gate candidates = NULL; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate tries = 0; 204*7c478bd9Sstevel@tonic-gate tryagain: 205*7c478bd9Sstevel@tonic-gate tries++; 206*7c478bd9Sstevel@tonic-gate for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag, 207*7c478bd9Sstevel@tonic-gate ufncomp[ncomp] ); fi != NULL; 208*7c478bd9Sstevel@tonic-gate fi = ldap_getnextfilter( ld->ld_filtd ) ) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate if ( (candidates = ldap_ufn_expand( ld, cancelproc, 211*7c478bd9Sstevel@tonic-gate cancelparm, dns, fi->lfi_filter, scope, 212*7c478bd9Sstevel@tonic-gate phase == 3 ? attrs : objattrs, 213*7c478bd9Sstevel@tonic-gate phase == 3 ? attrsonly : 1, &err )) != NULL ) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate break; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if ( err == -1 || err == LDAP_USER_CANCELLED ) { 219*7c478bd9Sstevel@tonic-gate if ( dns != NULL ) { 220*7c478bd9Sstevel@tonic-gate ldap_value_free( dns ); 221*7c478bd9Sstevel@tonic-gate dns = NULL; 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate return( err ); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate if ( candidates == NULL ) { 228*7c478bd9Sstevel@tonic-gate if ( tries < 2 && phase != 3 ) { 229*7c478bd9Sstevel@tonic-gate scope = LDAP_SCOPE_SUBTREE; 230*7c478bd9Sstevel@tonic-gate goto tryagain; 231*7c478bd9Sstevel@tonic-gate } else { 232*7c478bd9Sstevel@tonic-gate if ( dns != NULL ) { 233*7c478bd9Sstevel@tonic-gate ldap_value_free( dns ); 234*7c478bd9Sstevel@tonic-gate dns = NULL; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate return( err ); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* go on to the next component */ 241*7c478bd9Sstevel@tonic-gate if ( phase == 1 ) 242*7c478bd9Sstevel@tonic-gate phase++; 243*7c478bd9Sstevel@tonic-gate if ( dns != NULL ) { 244*7c478bd9Sstevel@tonic-gate ldap_value_free( dns ); 245*7c478bd9Sstevel@tonic-gate dns = NULL; 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate *res = candidates; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate return( err ); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate int 254*7c478bd9Sstevel@tonic-gate LDAP_CALL 255*7c478bd9Sstevel@tonic-gate ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs, int attrsonly, 256*7c478bd9Sstevel@tonic-gate LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, 257*7c478bd9Sstevel@tonic-gate char *tag1, char *tag2, char *tag3 ) 258*7c478bd9Sstevel@tonic-gate { 259*7c478bd9Sstevel@tonic-gate char **ufncomp, **prefixcomp; 260*7c478bd9Sstevel@tonic-gate char *pbuf; 261*7c478bd9Sstevel@tonic-gate int ncomp, pcomp, i, err = 0; 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* getfilter stuff must be inited before we are called */ 264*7c478bd9Sstevel@tonic-gate if ( ld->ld_filtd == NULL ) { 265*7c478bd9Sstevel@tonic-gate err = LDAP_PARAM_ERROR; 266*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 267*7c478bd9Sstevel@tonic-gate return( err ); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* call ldap_explode_dn() to break the ufn into its components */ 271*7c478bd9Sstevel@tonic-gate if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL ) { 272*7c478bd9Sstevel@tonic-gate err = LDAP_LOCAL_ERROR; 273*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 274*7c478bd9Sstevel@tonic-gate return( err ); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ ) 277*7c478bd9Sstevel@tonic-gate ; /* NULL */ 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* more than two components => try it fully qualified first */ 280*7c478bd9Sstevel@tonic-gate if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) { 281*7c478bd9Sstevel@tonic-gate err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs, 282*7c478bd9Sstevel@tonic-gate attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate if ( ldap_count_entries( ld, *res ) > 0 ) { 285*7c478bd9Sstevel@tonic-gate ldap_value_free( ufncomp ); 286*7c478bd9Sstevel@tonic-gate return( err ); 287*7c478bd9Sstevel@tonic-gate } else { 288*7c478bd9Sstevel@tonic-gate ldap_msgfree( *res ); 289*7c478bd9Sstevel@tonic-gate *res = NULL; 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate if ( ld->ld_ufnprefix == NULL ) { 294*7c478bd9Sstevel@tonic-gate ldap_value_free( ufncomp ); 295*7c478bd9Sstevel@tonic-gate return( err ); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* if that failed, or < 2 components, use the prefix */ 299*7c478bd9Sstevel@tonic-gate if ( (prefixcomp = ldap_explode_dn( ld->ld_ufnprefix, 0 )) == NULL ) { 300*7c478bd9Sstevel@tonic-gate ldap_value_free( ufncomp ); 301*7c478bd9Sstevel@tonic-gate err = LDAP_LOCAL_ERROR; 302*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 303*7c478bd9Sstevel@tonic-gate return( err ); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ ) 306*7c478bd9Sstevel@tonic-gate ; /* NULL */ 307*7c478bd9Sstevel@tonic-gate if ( (pbuf = (char *)NSLDAPI_MALLOC( strlen( ld->ld_ufnprefix ) + 1 )) 308*7c478bd9Sstevel@tonic-gate == NULL ) { 309*7c478bd9Sstevel@tonic-gate ldap_value_free( ufncomp ); 310*7c478bd9Sstevel@tonic-gate ldap_value_free( prefixcomp ); 311*7c478bd9Sstevel@tonic-gate err = LDAP_NO_MEMORY; 312*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 313*7c478bd9Sstevel@tonic-gate return( err ); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate for ( i = 0; i < pcomp; i++ ) { 317*7c478bd9Sstevel@tonic-gate int j; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate *pbuf = '\0'; 320*7c478bd9Sstevel@tonic-gate for ( j = i; j < pcomp; j++ ) { 321*7c478bd9Sstevel@tonic-gate strcat( pbuf, prefixcomp[j] ); 322*7c478bd9Sstevel@tonic-gate if ( j + 1 < pcomp ) 323*7c478bd9Sstevel@tonic-gate strcat( pbuf, "," ); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs, 326*7c478bd9Sstevel@tonic-gate attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if ( ldap_count_entries( ld, *res ) > 0 ) { 329*7c478bd9Sstevel@tonic-gate break; 330*7c478bd9Sstevel@tonic-gate } else { 331*7c478bd9Sstevel@tonic-gate ldap_msgfree( *res ); 332*7c478bd9Sstevel@tonic-gate *res = NULL; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate ldap_value_free( ufncomp ); 337*7c478bd9Sstevel@tonic-gate ldap_value_free( prefixcomp ); 338*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( pbuf ); 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate return( err ); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * same as ldap_ufn_search_ct, except without the ability to specify 345*7c478bd9Sstevel@tonic-gate * ldapfilter.conf tags. 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate int 348*7c478bd9Sstevel@tonic-gate LDAP_CALL 349*7c478bd9Sstevel@tonic-gate ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs, int attrsonly, 350*7c478bd9Sstevel@tonic-gate LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm ) 351*7c478bd9Sstevel@tonic-gate { 352*7c478bd9Sstevel@tonic-gate return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc, 353*7c478bd9Sstevel@tonic-gate cancelparm, "ufn first", "ufn intermediate", "ufn last" ) ); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate /* 357*7c478bd9Sstevel@tonic-gate * same as ldap_ufn_search_c without the cancel function 358*7c478bd9Sstevel@tonic-gate */ 359*7c478bd9Sstevel@tonic-gate int 360*7c478bd9Sstevel@tonic-gate LDAP_CALL 361*7c478bd9Sstevel@tonic-gate ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs, int attrsonly, 362*7c478bd9Sstevel@tonic-gate LDAPMessage **res ) 363*7c478bd9Sstevel@tonic-gate { 364*7c478bd9Sstevel@tonic-gate struct timeval tv; 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate tv.tv_sec = ld->ld_timelimit; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, 369*7c478bd9Sstevel@tonic-gate ld->ld_timelimit ? ldap_ufn_timeout : NULL, 370*7c478bd9Sstevel@tonic-gate ld->ld_timelimit ? (void *) &tv : NULL, 371*7c478bd9Sstevel@tonic-gate "ufn first", "ufn intermediate", "ufn last" ) ); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate /* 376*7c478bd9Sstevel@tonic-gate * ldap_msg_merge - merge two ldap search result chains. the more 377*7c478bd9Sstevel@tonic-gate * serious of the two error result codes is kept. 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate static LDAPMessage * 381*7c478bd9Sstevel@tonic-gate ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ) 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate LDAPMessage *end, *aprev, *aend, *bprev, *bend; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate if ( a == NULL ) 386*7c478bd9Sstevel@tonic-gate return( b ); 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate if ( b == NULL ) 389*7c478bd9Sstevel@tonic-gate return( a ); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* find the ends of the a and b chains */ 392*7c478bd9Sstevel@tonic-gate aprev = NULL; 393*7c478bd9Sstevel@tonic-gate for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain ) 394*7c478bd9Sstevel@tonic-gate aprev = aend; 395*7c478bd9Sstevel@tonic-gate bprev = NULL; 396*7c478bd9Sstevel@tonic-gate for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain ) 397*7c478bd9Sstevel@tonic-gate bprev = bend; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* keep result a */ 400*7c478bd9Sstevel@tonic-gate if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) { 401*7c478bd9Sstevel@tonic-gate /* remove result b */ 402*7c478bd9Sstevel@tonic-gate ldap_msgfree( bend ); 403*7c478bd9Sstevel@tonic-gate if ( bprev != NULL ) 404*7c478bd9Sstevel@tonic-gate bprev->lm_chain = NULL; 405*7c478bd9Sstevel@tonic-gate else 406*7c478bd9Sstevel@tonic-gate b = NULL; 407*7c478bd9Sstevel@tonic-gate end = aend; 408*7c478bd9Sstevel@tonic-gate if ( aprev != NULL ) 409*7c478bd9Sstevel@tonic-gate aprev->lm_chain = NULL; 410*7c478bd9Sstevel@tonic-gate else 411*7c478bd9Sstevel@tonic-gate a = NULL; 412*7c478bd9Sstevel@tonic-gate /* keep result b */ 413*7c478bd9Sstevel@tonic-gate } else { 414*7c478bd9Sstevel@tonic-gate /* remove result a */ 415*7c478bd9Sstevel@tonic-gate ldap_msgfree( aend ); 416*7c478bd9Sstevel@tonic-gate if ( aprev != NULL ) 417*7c478bd9Sstevel@tonic-gate aprev->lm_chain = NULL; 418*7c478bd9Sstevel@tonic-gate else 419*7c478bd9Sstevel@tonic-gate a = NULL; 420*7c478bd9Sstevel@tonic-gate end = bend; 421*7c478bd9Sstevel@tonic-gate if ( bprev != NULL ) 422*7c478bd9Sstevel@tonic-gate bprev->lm_chain = NULL; 423*7c478bd9Sstevel@tonic-gate else 424*7c478bd9Sstevel@tonic-gate b = NULL; 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) || 428*7c478bd9Sstevel@tonic-gate (b == NULL && aprev == NULL) ) 429*7c478bd9Sstevel@tonic-gate return( end ); 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate if ( a == NULL ) { 432*7c478bd9Sstevel@tonic-gate bprev->lm_chain = end; 433*7c478bd9Sstevel@tonic-gate return( b ); 434*7c478bd9Sstevel@tonic-gate } else if ( b == NULL ) { 435*7c478bd9Sstevel@tonic-gate aprev->lm_chain = end; 436*7c478bd9Sstevel@tonic-gate return( a ); 437*7c478bd9Sstevel@tonic-gate } else { 438*7c478bd9Sstevel@tonic-gate bprev->lm_chain = end; 439*7c478bd9Sstevel@tonic-gate aprev->lm_chain = b; 440*7c478bd9Sstevel@tonic-gate return( a ); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate static LDAPMessage * 445*7c478bd9Sstevel@tonic-gate ldap_ufn_expand( LDAP *ld, LDAP_CANCELPROC_CALLBACK *cancelproc, 446*7c478bd9Sstevel@tonic-gate void *cancelparm, char **dns, char *filter, int scope, 447*7c478bd9Sstevel@tonic-gate char **attrs, int aonly, int *err ) 448*7c478bd9Sstevel@tonic-gate { 449*7c478bd9Sstevel@tonic-gate LDAPMessage *tmpcand, *tmpres; 450*7c478bd9Sstevel@tonic-gate char *dn; 451*7c478bd9Sstevel@tonic-gate int i, msgid; 452*7c478bd9Sstevel@tonic-gate struct timeval tv; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* search for this component below the current candidates */ 455*7c478bd9Sstevel@tonic-gate tmpcand = NULL; 456*7c478bd9Sstevel@tonic-gate i = 0; 457*7c478bd9Sstevel@tonic-gate do { 458*7c478bd9Sstevel@tonic-gate if ( dns != NULL ) 459*7c478bd9Sstevel@tonic-gate dn = dns[i]; 460*7c478bd9Sstevel@tonic-gate else 461*7c478bd9Sstevel@tonic-gate dn = ""; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if (( msgid = ldap_search( ld, dn, scope, filter, attrs, 464*7c478bd9Sstevel@tonic-gate aonly )) == -1 ) { 465*7c478bd9Sstevel@tonic-gate ldap_msgfree( tmpcand ); 466*7c478bd9Sstevel@tonic-gate *err = LDAP_GET_LDERRNO( ld, NULL, NULL ); 467*7c478bd9Sstevel@tonic-gate return( NULL ); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate tv.tv_sec = 0; 471*7c478bd9Sstevel@tonic-gate tv.tv_usec = 100000; /* 1/10 of a second */ 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate do { 474*7c478bd9Sstevel@tonic-gate *err = ldap_result( ld, msgid, 1, &tv, &tmpres ); 475*7c478bd9Sstevel@tonic-gate if ( *err == 0 && cancelproc != NULL && 476*7c478bd9Sstevel@tonic-gate (*cancelproc)( cancelparm ) != 0 ) { 477*7c478bd9Sstevel@tonic-gate ldap_abandon( ld, msgid ); 478*7c478bd9Sstevel@tonic-gate *err = LDAP_USER_CANCELLED; 479*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, *err, NULL, NULL ); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate } while ( *err == 0 ); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if ( *err == LDAP_USER_CANCELLED || *err < 0 || 484*7c478bd9Sstevel@tonic-gate ( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) { 485*7c478bd9Sstevel@tonic-gate ldap_msgfree( tmpcand ); 486*7c478bd9Sstevel@tonic-gate return( NULL ); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate tmpcand = ldap_msg_merge( ld, tmpcand, tmpres ); 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate i++; 492*7c478bd9Sstevel@tonic-gate } while ( dns != NULL && dns[i] != NULL ); 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate if ( ldap_count_entries( ld, tmpcand ) > 0 ) { 495*7c478bd9Sstevel@tonic-gate return( tmpcand ); 496*7c478bd9Sstevel@tonic-gate } else { 497*7c478bd9Sstevel@tonic-gate ldap_msgfree( tmpcand ); 498*7c478bd9Sstevel@tonic-gate return( NULL ); 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate /* 503*7c478bd9Sstevel@tonic-gate * ldap_ufn_setfilter - set the filter config file used in ufn searching 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate LDAPFiltDesc * 507*7c478bd9Sstevel@tonic-gate LDAP_CALL 508*7c478bd9Sstevel@tonic-gate ldap_ufn_setfilter( LDAP *ld, char *fname ) 509*7c478bd9Sstevel@tonic-gate { 510*7c478bd9Sstevel@tonic-gate if ( ld->ld_filtd != NULL ) 511*7c478bd9Sstevel@tonic-gate ldap_getfilter_free( ld->ld_filtd ); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate return( ld->ld_filtd = ldap_init_getfilter( fname ) ); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate void 517*7c478bd9Sstevel@tonic-gate LDAP_CALL 518*7c478bd9Sstevel@tonic-gate ldap_ufn_setprefix( LDAP *ld, char *prefix ) 519*7c478bd9Sstevel@tonic-gate { 520*7c478bd9Sstevel@tonic-gate if ( ld->ld_ufnprefix != NULL ) 521*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( ld->ld_ufnprefix ); 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate ld->ld_ufnprefix = nsldapi_strdup( prefix ); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate int 527*7c478bd9Sstevel@tonic-gate LDAP_C 528*7c478bd9Sstevel@tonic-gate ldap_ufn_timeout( void *tvparam ) 529*7c478bd9Sstevel@tonic-gate { 530*7c478bd9Sstevel@tonic-gate struct timeval *tv; 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate tv = (struct timeval *)tvparam; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate if ( tv->tv_sec != 0 ) { 535*7c478bd9Sstevel@tonic-gate tv->tv_usec = tv->tv_sec * 1000000; /* sec => micro sec */ 536*7c478bd9Sstevel@tonic-gate tv->tv_sec = 0; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate tv->tv_usec -= 100000; /* 1/10 of a second */ 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate return( tv->tv_usec <= 0 ? 1 : 0 ); 541*7c478bd9Sstevel@tonic-gate } 542