10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * 3*3857Sstevel * Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved. 4*3857Sstevel * Use is subject to license terms. 50Sstevel@tonic-gate * 60Sstevel@tonic-gate */ 70Sstevel@tonic-gate 80Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 90Sstevel@tonic-gate 100Sstevel@tonic-gate /* 110Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan. 120Sstevel@tonic-gate * All rights reserved. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * ufn.c 150Sstevel@tonic-gate */ 160Sstevel@tonic-gate 170Sstevel@tonic-gate #ifndef lint 180Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n"; 190Sstevel@tonic-gate #endif 200Sstevel@tonic-gate 210Sstevel@tonic-gate #include <stdio.h> 220Sstevel@tonic-gate #include <string.h> 230Sstevel@tonic-gate #include <ctype.h> 240Sstevel@tonic-gate #include <stdlib.h> /* malloc(), realloc(), free() */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #ifdef MACOS 270Sstevel@tonic-gate #include <stdlib.h> 280Sstevel@tonic-gate #include "macos.h" 290Sstevel@tonic-gate #else /* MACOS */ 300Sstevel@tonic-gate #if defined( DOS ) || defined( _WIN32 ) 310Sstevel@tonic-gate #include "msdos.h" 320Sstevel@tonic-gate #else /* DOS */ 330Sstevel@tonic-gate #include <sys/time.h> 340Sstevel@tonic-gate #include <sys/types.h> 350Sstevel@tonic-gate #include <sys/socket.h> 360Sstevel@tonic-gate #endif /* DOS */ 370Sstevel@tonic-gate #endif /* MACOS */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include "lber.h" 400Sstevel@tonic-gate #include "ldap.h" 410Sstevel@tonic-gate #include "ldap-private.h" 420Sstevel@tonic-gate #include "ldap-int.h" 430Sstevel@tonic-gate #ifdef SUN 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * to include definition of FILTERFILE and or TEMPLATEFILE 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate #include "ldapconfig.h" 480Sstevel@tonic-gate #endif 490Sstevel@tonic-gate 500Sstevel@tonic-gate #ifdef NEEDPROTOS 510Sstevel@tonic-gate typedef int (*cancelptype)( void *cancelparm ); 520Sstevel@tonic-gate #else /* NEEDPROTOS */ 530Sstevel@tonic-gate typedef int (*cancelptype)(); 540Sstevel@tonic-gate #endif /* NEEDPROTOS */ 550Sstevel@tonic-gate 560Sstevel@tonic-gate #ifdef NEEDPROTOS 570Sstevel@tonic-gate static int ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, 580Sstevel@tonic-gate char *prefix, char **attrs, int attrsonly, LDAPMessage **res, 590Sstevel@tonic-gate cancelptype cancelproc, void *cancelparm, char *tag1, char *tag2, 600Sstevel@tonic-gate char *tag3 ); 610Sstevel@tonic-gate static LDAPMessage *ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ); 620Sstevel@tonic-gate static LDAPMessage *ldap_ufn_expand( LDAP *ld, cancelptype cancelproc, 630Sstevel@tonic-gate void *cancelparm, char **dns, char *filter, int scope, 640Sstevel@tonic-gate char **attrs, int aonly, int *err ); 650Sstevel@tonic-gate LDAPFiltDesc *ldap_ufn_setfilter( LDAP *ld, char *fname ); 660Sstevel@tonic-gate #else /* NEEDPROTOS */ 670Sstevel@tonic-gate static LDAPMessage *ldap_msg_merge(); 680Sstevel@tonic-gate static LDAPMessage *ldap_ufn_expand(); 690Sstevel@tonic-gate LDAPFiltDesc *ldap_ufn_setfilter(); 700Sstevel@tonic-gate #endif /* NEEDPROTOS */ 710Sstevel@tonic-gate static LDAPMessage *ldap_msg_merge(); 720Sstevel@tonic-gate static LDAPMessage *ldap_ufn_expand(); 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * ldap_ufn_search_ctx - do user friendly searching; provide cancel feature; 760Sstevel@tonic-gate * specify ldapfilter.conf tags for each phase of search 770Sstevel@tonic-gate * 780Sstevel@tonic-gate * ld LDAP descriptor 790Sstevel@tonic-gate * ufncomp the exploded user friendly name to look for 800Sstevel@tonic-gate * ncomp number of elements in ufncomp 810Sstevel@tonic-gate * prefix where to start searching 820Sstevel@tonic-gate * attrs list of attribute types to return for matches 830Sstevel@tonic-gate * attrsonly 1 => attributes only 0 => attributes and values 840Sstevel@tonic-gate * res will contain the result of the search 850Sstevel@tonic-gate * cancelproc routine that returns non-zero if operation should be 860Sstevel@tonic-gate * cancelled. This can be NULL. If it is non-NULL, the 870Sstevel@tonic-gate * routine will be called periodically. 880Sstevel@tonic-gate * cancelparm void * that is passed to cancelproc 890Sstevel@tonic-gate * tag[123] the ldapfilter.conf tag that will be used in phases 900Sstevel@tonic-gate * 1, 2, and 3 of the search, respectively 910Sstevel@tonic-gate * 920Sstevel@tonic-gate * Example: 930Sstevel@tonic-gate * char *attrs[] = { "mail", "title", 0 }; 940Sstevel@tonic-gate * char *ufncomp[] = { "howes", "umich", "us", 0 } 950Sstevel@tonic-gate * LDAPMessage *res; 960Sstevel@tonic-gate * error = ldap_ufn_search_ctx( ld, ufncomp, 3, NULL, attrs, attrsonly, 970Sstevel@tonic-gate * &res, acancelproc, along, "ufn first", 980Sstevel@tonic-gate * "ufn intermediate", "ufn last" ); 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate static int 1020Sstevel@tonic-gate ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix, 1030Sstevel@tonic-gate char **attrs, int attrsonly, LDAPMessage **res, cancelptype cancelproc, 1040Sstevel@tonic-gate void *cancelparm, char *tag1, char *tag2, char *tag3 ) 1050Sstevel@tonic-gate { 1060Sstevel@tonic-gate char *dn, *ftag; 1070Sstevel@tonic-gate char **dns; 1080Sstevel@tonic-gate int max, i, err, scope, phase, tries; 1090Sstevel@tonic-gate LDAPFiltInfo *fi; 1100Sstevel@tonic-gate LDAPMessage *tmpcand; 1110Sstevel@tonic-gate LDAPMessage *candidates; 1120Sstevel@tonic-gate /* LDAPMessage *ldap_msg_merge(), *ldap_ufn_expand(); */ 1130Sstevel@tonic-gate static char *objattrs[] = { "objectClass", NULL }; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* 1160Sstevel@tonic-gate * look up ufn components from most to least significant. 1170Sstevel@tonic-gate * there are 3 phases. 1180Sstevel@tonic-gate * phase 1 search the root for orgs or countries 1190Sstevel@tonic-gate * phase 2 search for orgs 1200Sstevel@tonic-gate * phase 3 search for a person 1210Sstevel@tonic-gate * in phases 1 and 2, we are building a list of candidate DNs, 1220Sstevel@tonic-gate * below which we will search for the final component of the ufn. 1230Sstevel@tonic-gate * for each component we try the filters listed in the 1240Sstevel@tonic-gate * filterconfig file, first one-level (except the last compoment), 1250Sstevel@tonic-gate * then subtree. if any of them produce any results, we go on to 1260Sstevel@tonic-gate * the next component. 1270Sstevel@tonic-gate */ 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 1300Sstevel@tonic-gate LOCK_LDAP(ld); 1310Sstevel@tonic-gate #endif 1320Sstevel@tonic-gate *res = NULL; 1330Sstevel@tonic-gate candidates = NULL; 1340Sstevel@tonic-gate phase = 1; 1350Sstevel@tonic-gate for ( ncomp--; ncomp != -1; ncomp-- ) { 1360Sstevel@tonic-gate if ( *ufncomp[ncomp] == '"' ) { 1370Sstevel@tonic-gate char *quote; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL ) 1400Sstevel@tonic-gate *quote = '\0'; 1410Sstevel@tonic-gate (void) strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 ); 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate if ( ncomp == 0 ) 1440Sstevel@tonic-gate phase = 3; 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate switch ( phase ) { 1470Sstevel@tonic-gate case 1: 1480Sstevel@tonic-gate ftag = tag1; 1490Sstevel@tonic-gate scope = LDAP_SCOPE_ONELEVEL; 1500Sstevel@tonic-gate break; 1510Sstevel@tonic-gate case 2: 1520Sstevel@tonic-gate ftag = tag2; 1530Sstevel@tonic-gate scope = LDAP_SCOPE_ONELEVEL; 1540Sstevel@tonic-gate break; 1550Sstevel@tonic-gate case 3: 1560Sstevel@tonic-gate ftag = tag3; 1570Sstevel@tonic-gate scope = LDAP_SCOPE_SUBTREE; 1580Sstevel@tonic-gate break; 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate /* 1620Sstevel@tonic-gate * construct an array of DN's to search below from the 1630Sstevel@tonic-gate * list of candidates. 1640Sstevel@tonic-gate */ 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate if ( candidates == NULL ) { 1670Sstevel@tonic-gate if ( prefix != NULL ) { 1680Sstevel@tonic-gate if ( (dns = (char **) malloc( sizeof(char *) 1690Sstevel@tonic-gate * 2 )) == NULL ) { 1700Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 1710Sstevel@tonic-gate UNLOCK_LDAP(ld); 1720Sstevel@tonic-gate #endif 1730Sstevel@tonic-gate return( ld->ld_errno = LDAP_NO_MEMORY ); 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate dns[0] = strdup( prefix ); 1760Sstevel@tonic-gate dns[1] = NULL; 1770Sstevel@tonic-gate } else { 1780Sstevel@tonic-gate dns = NULL; 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate } else { 1810Sstevel@tonic-gate i = 0, max = 0; 1820Sstevel@tonic-gate for ( tmpcand = candidates; tmpcand != NULL && 1830Sstevel@tonic-gate tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT; 1840Sstevel@tonic-gate tmpcand = tmpcand->lm_chain ) 1850Sstevel@tonic-gate { 1860Sstevel@tonic-gate if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL ) 1870Sstevel@tonic-gate continue; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate if ( dns == NULL ) { 1900Sstevel@tonic-gate if ( (dns = (char **) malloc( 1910Sstevel@tonic-gate sizeof(char *) * 8 )) == NULL ) { 1920Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY; 1930Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 1940Sstevel@tonic-gate UNLOCK_LDAP(ld); 1950Sstevel@tonic-gate #endif 1960Sstevel@tonic-gate return( LDAP_NO_MEMORY ); 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate max = 8; 1990Sstevel@tonic-gate } else if ( i >= max ) { 2000Sstevel@tonic-gate if ( (dns = (char **) realloc( dns, 2010Sstevel@tonic-gate sizeof(char *) * 2 * max )) 2020Sstevel@tonic-gate == NULL ) 2030Sstevel@tonic-gate { 2040Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY; 2050Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 2060Sstevel@tonic-gate UNLOCK_LDAP(ld); 2070Sstevel@tonic-gate #endif 2080Sstevel@tonic-gate return( LDAP_NO_MEMORY ); 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate max *= 2; 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate dns[i++] = dn; 2130Sstevel@tonic-gate dns[i] = NULL; 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate ldap_msgfree( candidates ); 2160Sstevel@tonic-gate candidates = NULL; 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate tries = 0; 2190Sstevel@tonic-gate tryagain: 2200Sstevel@tonic-gate tries++; 2210Sstevel@tonic-gate for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag, 2220Sstevel@tonic-gate ufncomp[ncomp] ); fi != NULL; 2230Sstevel@tonic-gate fi = ldap_getnextfilter( ld->ld_filtd ) ) 2240Sstevel@tonic-gate { 2250Sstevel@tonic-gate if ( (candidates = ldap_ufn_expand( ld, cancelproc, 2260Sstevel@tonic-gate cancelparm, dns, fi->lfi_filter, scope, 2270Sstevel@tonic-gate phase == 3 ? attrs : objattrs, 2280Sstevel@tonic-gate phase == 3 ? attrsonly : 1, &err )) != NULL ) 2290Sstevel@tonic-gate { 2300Sstevel@tonic-gate break; 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate if ( err == -1 || err == LDAP_USER_CANCELLED ) { 2340Sstevel@tonic-gate if ( dns != NULL ) { 2350Sstevel@tonic-gate ldap_value_free( dns ); 2360Sstevel@tonic-gate dns = NULL; 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 2390Sstevel@tonic-gate UNLOCK_LDAP(ld); 2400Sstevel@tonic-gate #endif 2410Sstevel@tonic-gate return( err ); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate if ( candidates == NULL ) { 2460Sstevel@tonic-gate if ( tries < 2 && phase != 3 ) { 2470Sstevel@tonic-gate scope = LDAP_SCOPE_SUBTREE; 2480Sstevel@tonic-gate goto tryagain; 2490Sstevel@tonic-gate } else { 2500Sstevel@tonic-gate if ( dns != NULL ) { 2510Sstevel@tonic-gate ldap_value_free( dns ); 2520Sstevel@tonic-gate dns = NULL; 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 2550Sstevel@tonic-gate UNLOCK_LDAP(ld); 2560Sstevel@tonic-gate #endif 2570Sstevel@tonic-gate return( err ); 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate /* go on to the next component */ 2620Sstevel@tonic-gate if ( phase == 1 ) 2630Sstevel@tonic-gate phase++; 2640Sstevel@tonic-gate if ( dns != NULL ) { 2650Sstevel@tonic-gate ldap_value_free( dns ); 2660Sstevel@tonic-gate dns = NULL; 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate *res = candidates; 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 2720Sstevel@tonic-gate UNLOCK_LDAP(ld); 2730Sstevel@tonic-gate #endif 2740Sstevel@tonic-gate return( err ); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate int 2780Sstevel@tonic-gate ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs, int attrsonly, 2790Sstevel@tonic-gate LDAPMessage **res, cancelptype cancelproc, void *cancelparm, 2800Sstevel@tonic-gate char *tag1, char *tag2, char *tag3 ) 2810Sstevel@tonic-gate { 2820Sstevel@tonic-gate char **ufncomp, **prefixcomp; 2830Sstevel@tonic-gate char *pbuf; 2840Sstevel@tonic-gate int ncomp, pcomp, i, err; 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 2870Sstevel@tonic-gate LOCK_LDAP(ld); 2880Sstevel@tonic-gate #endif 2890Sstevel@tonic-gate /* initialize the getfilter stuff if it's not already */ 2900Sstevel@tonic-gate if ( ld->ld_filtd == NULL && ldap_ufn_setfilter( ld, FILTERFILE ) 2910Sstevel@tonic-gate == NULL ) { 2920Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 2930Sstevel@tonic-gate UNLOCK_LDAP(ld); 2940Sstevel@tonic-gate #endif 2950Sstevel@tonic-gate return( ld->ld_errno = LDAP_LOCAL_ERROR ); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* call ldap_explode_dn() to break the ufn into its components */ 2990Sstevel@tonic-gate if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL ) { 3000Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 3010Sstevel@tonic-gate UNLOCK_LDAP(ld); 3020Sstevel@tonic-gate #endif 3030Sstevel@tonic-gate return( ld->ld_errno = LDAP_LOCAL_ERROR ); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ ) 3060Sstevel@tonic-gate ; /* NULL */ 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* more than two components => try it fully qualified first */ 3090Sstevel@tonic-gate if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) { 3100Sstevel@tonic-gate err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs, 3110Sstevel@tonic-gate attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate if ( ldap_count_entries( ld, *res ) > 0 ) { 3140Sstevel@tonic-gate ldap_value_free( ufncomp ); 3150Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 3160Sstevel@tonic-gate UNLOCK_LDAP(ld); 3170Sstevel@tonic-gate #endif 3180Sstevel@tonic-gate return( err ); 3190Sstevel@tonic-gate } else { 3200Sstevel@tonic-gate ldap_msgfree( *res ); 3210Sstevel@tonic-gate *res = NULL; 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate if ( ld->ld_ufnprefix == NULL ) { 3260Sstevel@tonic-gate ldap_value_free( ufncomp ); 3270Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 3280Sstevel@tonic-gate UNLOCK_LDAP(ld); 3290Sstevel@tonic-gate #endif 3300Sstevel@tonic-gate return( err ); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* if that failed, or < 2 components, use the prefix */ 3340Sstevel@tonic-gate if ( (prefixcomp = ldap_explode_dn( ld->ld_ufnprefix, 0 )) == NULL ) { 3350Sstevel@tonic-gate ldap_value_free( ufncomp ); 3360Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 3370Sstevel@tonic-gate UNLOCK_LDAP(ld); 3380Sstevel@tonic-gate #endif 3390Sstevel@tonic-gate return( ld->ld_errno = LDAP_LOCAL_ERROR ); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ ) 3420Sstevel@tonic-gate ; /* NULL */ 3430Sstevel@tonic-gate if ( (pbuf = (char *) malloc( strlen( ld->ld_ufnprefix ) + 1 )) 3440Sstevel@tonic-gate == NULL ) { 3450Sstevel@tonic-gate ldap_value_free( ufncomp ); 3460Sstevel@tonic-gate ldap_value_free( prefixcomp ); 3470Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 3480Sstevel@tonic-gate UNLOCK_LDAP(ld); 3490Sstevel@tonic-gate #endif 3500Sstevel@tonic-gate return( ld->ld_errno = LDAP_NO_MEMORY ); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate for ( i = 0; i < pcomp; i++ ) { 3540Sstevel@tonic-gate int j; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate *pbuf = '\0'; 3570Sstevel@tonic-gate for ( j = i; j < pcomp; j++ ) { 3580Sstevel@tonic-gate (void) strcat( pbuf, prefixcomp[j] ); 3590Sstevel@tonic-gate if ( j + 1 < pcomp ) 3600Sstevel@tonic-gate (void) strcat( pbuf, "," ); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs, 3630Sstevel@tonic-gate attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 ); 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate if ( ldap_count_entries( ld, *res ) > 0 ) { 3660Sstevel@tonic-gate break; 3670Sstevel@tonic-gate } else { 3680Sstevel@tonic-gate ldap_msgfree( *res ); 3690Sstevel@tonic-gate *res = NULL; 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate ldap_value_free( ufncomp ); 3740Sstevel@tonic-gate ldap_value_free( prefixcomp ); 3750Sstevel@tonic-gate free( pbuf ); 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 3780Sstevel@tonic-gate UNLOCK_LDAP(ld); 3790Sstevel@tonic-gate #endif 3800Sstevel@tonic-gate return( err ); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * same as ldap_ufn_search_ct, except without the ability to specify 3850Sstevel@tonic-gate * ldapfilter.conf tags. 3860Sstevel@tonic-gate */ 3870Sstevel@tonic-gate int 3880Sstevel@tonic-gate ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs, int attrsonly, 3890Sstevel@tonic-gate LDAPMessage **res, cancelptype cancelproc, void *cancelparm ) 3900Sstevel@tonic-gate { 3910Sstevel@tonic-gate return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc, 3920Sstevel@tonic-gate cancelparm, "ufn first", "ufn intermediate", "ufn last" ) ); 3930Sstevel@tonic-gate } 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate /* 3960Sstevel@tonic-gate * same as ldap_ufn_search_c without the cancel function 3970Sstevel@tonic-gate */ 3980Sstevel@tonic-gate int 3990Sstevel@tonic-gate ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs, int attrsonly, 4000Sstevel@tonic-gate LDAPMessage **res ) 4010Sstevel@tonic-gate { 4020Sstevel@tonic-gate struct timeval tv; 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate tv.tv_sec = ld->ld_timelimit; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, 4070Sstevel@tonic-gate ld->ld_timelimit ? ldap_ufn_timeout : NULL, 4080Sstevel@tonic-gate ld->ld_timelimit ? (void *) &tv : NULL, 4090Sstevel@tonic-gate "ufn first", "ufn intermediate", "ufn last" ) ); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * ldap_msg_merge - merge two ldap search result chains. the more 4150Sstevel@tonic-gate * serious of the two error result codes is kept. 4160Sstevel@tonic-gate */ 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate static LDAPMessage * 4190Sstevel@tonic-gate ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b ) 4200Sstevel@tonic-gate { 4210Sstevel@tonic-gate LDAPMessage *end, *aprev, *aend, *bprev, *bend; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate if ( a == NULL ) 4240Sstevel@tonic-gate return( b ); 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate if ( b == NULL ) 4270Sstevel@tonic-gate return( a ); 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate /* find the ends of the a and b chains */ 4300Sstevel@tonic-gate aprev = NULL; 4310Sstevel@tonic-gate for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain ) 4320Sstevel@tonic-gate aprev = aend; 4330Sstevel@tonic-gate bprev = NULL; 4340Sstevel@tonic-gate for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain ) 4350Sstevel@tonic-gate bprev = bend; 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* keep result a */ 4380Sstevel@tonic-gate if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) { 4390Sstevel@tonic-gate /* remove result b */ 4400Sstevel@tonic-gate ldap_msgfree( bend ); 4410Sstevel@tonic-gate if ( bprev != NULL ) 4420Sstevel@tonic-gate bprev->lm_chain = NULL; 4430Sstevel@tonic-gate else 4440Sstevel@tonic-gate b = NULL; 4450Sstevel@tonic-gate end = aend; 4460Sstevel@tonic-gate if ( aprev != NULL ) 4470Sstevel@tonic-gate aprev->lm_chain = NULL; 4480Sstevel@tonic-gate else 4490Sstevel@tonic-gate a = NULL; 4500Sstevel@tonic-gate /* keep result b */ 4510Sstevel@tonic-gate } else { 4520Sstevel@tonic-gate /* remove result a */ 4530Sstevel@tonic-gate ldap_msgfree( aend ); 4540Sstevel@tonic-gate if ( aprev != NULL ) 4550Sstevel@tonic-gate aprev->lm_chain = NULL; 4560Sstevel@tonic-gate else 4570Sstevel@tonic-gate a = NULL; 4580Sstevel@tonic-gate end = bend; 4590Sstevel@tonic-gate if ( bprev != NULL ) 4600Sstevel@tonic-gate bprev->lm_chain = NULL; 4610Sstevel@tonic-gate else 4620Sstevel@tonic-gate b = NULL; 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) || 4660Sstevel@tonic-gate (b == NULL && aprev == NULL) ) 4670Sstevel@tonic-gate return( end ); 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate if ( a == NULL ) { 4700Sstevel@tonic-gate bprev->lm_chain = end; 4710Sstevel@tonic-gate return( b ); 4720Sstevel@tonic-gate } else if ( b == NULL ) { 4730Sstevel@tonic-gate aprev->lm_chain = end; 4740Sstevel@tonic-gate return( a ); 4750Sstevel@tonic-gate } else { 4760Sstevel@tonic-gate bprev->lm_chain = end; 4770Sstevel@tonic-gate aprev->lm_chain = b; 4780Sstevel@tonic-gate return( a ); 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate static LDAPMessage * 4830Sstevel@tonic-gate ldap_ufn_expand( LDAP *ld, cancelptype cancelproc, void *cancelparm, 4840Sstevel@tonic-gate char **dns, char *filter, int scope, char **attrs, int aonly, 4850Sstevel@tonic-gate int *err ) 4860Sstevel@tonic-gate { 4870Sstevel@tonic-gate LDAPMessage *tmpcand, *tmpres; 4880Sstevel@tonic-gate char *dn; 4890Sstevel@tonic-gate int i, msgid; 4900Sstevel@tonic-gate struct timeval tv; 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate /* search for this component below the current candidates */ 4930Sstevel@tonic-gate tmpcand = NULL; 4940Sstevel@tonic-gate i = 0; 4950Sstevel@tonic-gate do { 4960Sstevel@tonic-gate if ( dns != NULL ) 4970Sstevel@tonic-gate dn = dns[i]; 4980Sstevel@tonic-gate else 4990Sstevel@tonic-gate dn = ""; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate if (( msgid = ldap_search( ld, dn, scope, filter, attrs, 5020Sstevel@tonic-gate aonly )) == -1 ) { 5030Sstevel@tonic-gate ldap_msgfree( tmpcand ); 5040Sstevel@tonic-gate *err = ld->ld_errno; 5050Sstevel@tonic-gate return( NULL ); 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate tv.tv_sec = 0; 5090Sstevel@tonic-gate tv.tv_usec = 100000; /* 1/10 of a second */ 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate do { 5120Sstevel@tonic-gate *err = ldap_result( ld, msgid, 1, &tv, &tmpres ); 5130Sstevel@tonic-gate if ( *err == 0 && cancelproc != NULL && 5140Sstevel@tonic-gate (*cancelproc)( cancelparm ) != 0 ) { 5150Sstevel@tonic-gate ldap_abandon( ld, msgid ); 5160Sstevel@tonic-gate *err = LDAP_USER_CANCELLED; 5170Sstevel@tonic-gate ld->ld_errno = LDAP_USER_CANCELLED; 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate } while ( *err == 0 ); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if ( *err == LDAP_USER_CANCELLED || *err < 0 || 5220Sstevel@tonic-gate ( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) { 5230Sstevel@tonic-gate ldap_msgfree( tmpcand ); 5240Sstevel@tonic-gate return( NULL ); 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate tmpcand = ldap_msg_merge( ld, tmpcand, tmpres ); 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate i++; 5300Sstevel@tonic-gate } while ( dns != NULL && dns[i] != NULL ); 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate if ( ldap_count_entries( ld, tmpcand ) > 0 ) { 5330Sstevel@tonic-gate return( tmpcand ); 5340Sstevel@tonic-gate } else { 5350Sstevel@tonic-gate ldap_msgfree( tmpcand ); 5360Sstevel@tonic-gate return( NULL ); 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate /* 5410Sstevel@tonic-gate * ldap_ufn_setfilter - set the filter config file used in ufn searching 5420Sstevel@tonic-gate */ 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate LDAPFiltDesc * 5450Sstevel@tonic-gate ldap_ufn_setfilter( LDAP *ld, char *fname ) 5460Sstevel@tonic-gate { 5470Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 5480Sstevel@tonic-gate LDAPFiltDesc *rv; 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate LOCK_LDAP(ld); 5510Sstevel@tonic-gate #endif 5520Sstevel@tonic-gate if ( ld->ld_filtd != NULL ) 5530Sstevel@tonic-gate ldap_getfilter_free( ld->ld_filtd ); 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 5560Sstevel@tonic-gate ld->ld_filtd = ldap_init_getfilter( fname ); 5570Sstevel@tonic-gate rv = ld->ld_filtd; 5580Sstevel@tonic-gate UNLOCK_LDAP(ld); 5590Sstevel@tonic-gate return( rv ); 5600Sstevel@tonic-gate #else 5610Sstevel@tonic-gate return( ld->ld_filtd = ldap_init_getfilter( fname ) ); 5620Sstevel@tonic-gate #endif 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate void 5660Sstevel@tonic-gate ldap_ufn_setprefix( LDAP *ld, char *prefix ) 5670Sstevel@tonic-gate { 5680Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 5690Sstevel@tonic-gate LOCK_LDAP(ld); 5700Sstevel@tonic-gate #endif 5710Sstevel@tonic-gate if ( ld->ld_ufnprefix != NULL ) 5720Sstevel@tonic-gate free( ld->ld_ufnprefix ); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate ld->ld_ufnprefix = strdup( prefix ); 5750Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT ) 5760Sstevel@tonic-gate UNLOCK_LDAP(ld); 5770Sstevel@tonic-gate #endif 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate int 5810Sstevel@tonic-gate ldap_ufn_timeout( void *tvparam ) 5820Sstevel@tonic-gate { 5830Sstevel@tonic-gate struct timeval *tv; 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate tv = (struct timeval *)tvparam; 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate if ( tv->tv_sec != 0 ) { 5880Sstevel@tonic-gate tv->tv_usec = tv->tv_sec * 1000000; /* sec => micro sec */ 5890Sstevel@tonic-gate tv->tv_sec = 0; 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate tv->tv_usec -= 100000; /* 1/10 of a second */ 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate return( tv->tv_usec <= 0 ? 1 : 0 ); 5940Sstevel@tonic-gate } 595