xref: /onnv-gate/usr/src/lib/nsswitch/nis/common/nis_common.c (revision 8040:42abce45ef67)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
216812Sraf 
220Sstevel@tonic-gate /*
236812Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * nis_common.c
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * Common code and structures used by name-service-switch "nis" backends.
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include "nis_common.h"
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <synch.h>
360Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
370Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
380Sstevel@tonic-gate #include <thread.h>
390Sstevel@tonic-gate #include <ctype.h>
400Sstevel@tonic-gate #include <stdlib.h>
410Sstevel@tonic-gate #include <signal.h>
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #ifndef	MT_UNSAFE_YP		/* Is the libnsl YP client code MT-unsafe? */
440Sstevel@tonic-gate #define	MT_UNSAFE_YP	0	/* No, not any longer */
450Sstevel@tonic-gate #endif
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #if	MT_UNSAFE_YP
480Sstevel@tonic-gate static mutex_t	one_lane = DEFAULTMUTEX;
490Sstevel@tonic-gate #endif
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /* <rpcsvc/ypclnt.h> uses (char *) where it should use (const char *) */
520Sstevel@tonic-gate typedef char *grrr;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate  * The YP client code thinks it's being helpful by appending '\n' and '\0'
560Sstevel@tonic-gate  *   to the values returned by yp_match() et al.  In order to do this it
570Sstevel@tonic-gate  *   ends up doing more malloc()ing and data copying than would otherwise
580Sstevel@tonic-gate  *   be necessary.  If we're interested in performance we should provide
590Sstevel@tonic-gate  *   alternative library interfaces that skip the helpfulness and instead
600Sstevel@tonic-gate  *   let the XDR routines dump the value directly into the buffer where
610Sstevel@tonic-gate  *   we really want it.  For now, though, we just use the vanilla interface.
620Sstevel@tonic-gate  */
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static nss_status_t
switch_err(ypstatus,ismatch)650Sstevel@tonic-gate switch_err(ypstatus, ismatch)
660Sstevel@tonic-gate 	int			ypstatus;
670Sstevel@tonic-gate 	int			ismatch;
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	switch (ypstatus) {
700Sstevel@tonic-gate 	case 0:
712830Sdjl 		errno = 0;
720Sstevel@tonic-gate 		return (NSS_SUCCESS);
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	case YPERR_BADARGS:
750Sstevel@tonic-gate 	case YPERR_KEY:
762830Sdjl 		errno = 0;
770Sstevel@tonic-gate 		return (NSS_NOTFOUND);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 		/*
800Sstevel@tonic-gate 		 *  When the YP server is running in DNS forwarding mode,
810Sstevel@tonic-gate 		 *  the forwarder will return YPERR_NOMORE to us if it
820Sstevel@tonic-gate 		 *  is unable to contact a server (i.e., it has timed out).
830Sstevel@tonic-gate 		 *  The NSS_NISSERVDNS_TRYAGAIN is returned for timeout errors.
840Sstevel@tonic-gate 		 */
850Sstevel@tonic-gate 	case YPERR_NOMORE:
860Sstevel@tonic-gate 		if (ismatch)
870Sstevel@tonic-gate 			return (NSS_NISSERVDNS_TRYAGAIN);
880Sstevel@tonic-gate 		else
890Sstevel@tonic-gate 			return (NSS_NOTFOUND);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	case YPERR_DOMAIN:
920Sstevel@tonic-gate 	case YPERR_YPSERV:
930Sstevel@tonic-gate 	case YPERR_BUSY:
940Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	default:
970Sstevel@tonic-gate 		return (NSS_UNAVAIL);
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*ARGSUSED*/
1020Sstevel@tonic-gate nss_status_t
_nss_nis_setent(be,dummy)1030Sstevel@tonic-gate _nss_nis_setent(be, dummy)
1040Sstevel@tonic-gate 	nis_backend_ptr_t	be;
1050Sstevel@tonic-gate 	void			*dummy;
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	if (be->enum_key != 0) {
1080Sstevel@tonic-gate 		free(be->enum_key);
1090Sstevel@tonic-gate 		be->enum_key = 0;
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 	be->enum_keylen = 0;
1120Sstevel@tonic-gate 	return (NSS_SUCCESS);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate nss_status_t
_nss_nis_endent(be,dummy)1160Sstevel@tonic-gate _nss_nis_endent(be, dummy)
1170Sstevel@tonic-gate 	nis_backend_ptr_t	be;
1180Sstevel@tonic-gate 	void			*dummy;
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate 	return (_nss_nis_setent(be, dummy));
1210Sstevel@tonic-gate 	/* Nothing else we can clean up, is there? */
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate void
massage_netdb(const char ** valp,int * vallenp)1250Sstevel@tonic-gate massage_netdb(const char **valp, int *vallenp)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate 	const char		*first;
1280Sstevel@tonic-gate 	const char		*last;
1290Sstevel@tonic-gate 	const char		*val	= *valp;
1300Sstevel@tonic-gate 	int			vallen	= *vallenp;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	if ((last = memchr(val, '#', vallen)) == 0) {
1330Sstevel@tonic-gate 		last = val + vallen;
1340Sstevel@tonic-gate 	}
1350Sstevel@tonic-gate 	for (first = val;  first < last && isspace(*first);  first++) {
1360Sstevel@tonic-gate 		;
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 	for (/* cstyle */;  first < last && isspace(last[-1]);  last--) {
1390Sstevel@tonic-gate 		;
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 	/*
1420Sstevel@tonic-gate 	 * Don't check for an empty line because it shouldn't ever
1430Sstevel@tonic-gate 	 *   have made it into the YP map.
1440Sstevel@tonic-gate 	 */
1450Sstevel@tonic-gate 	*valp = first;
1460Sstevel@tonic-gate 	*vallenp = (int)(last - first);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate nss_status_t
_nss_nis_ypmatch(domain,map,key,valp,vallenp,ypstatusp)1500Sstevel@tonic-gate _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp)
1510Sstevel@tonic-gate 	const char		*domain;
1520Sstevel@tonic-gate 	const char		*map;
1530Sstevel@tonic-gate 	const char		*key;
1540Sstevel@tonic-gate 	char			**valp;
1550Sstevel@tonic-gate 	int			*vallenp;
1560Sstevel@tonic-gate 	int			*ypstatusp;
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 	int			ypstatus;
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate #if	MT_UNSAFE_YP
1610Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
1620Sstevel@tonic-gate 
1632830Sdjl 	(void) sigfillset(&newmask);
1646812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
1656812Sraf 	(void) mutex_lock(&one_lane);
1660Sstevel@tonic-gate #endif
1670Sstevel@tonic-gate 	ypstatus = __yp_match_cflookup((grrr)domain, (grrr)map,
1680Sstevel@tonic-gate 			    (grrr)key, (int)strlen(key), valp, vallenp, 0);
1690Sstevel@tonic-gate #if	MT_UNSAFE_YP
1706812Sraf 	(void) mutex_unlock(&one_lane);
1716812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
1720Sstevel@tonic-gate #endif
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	if (ypstatusp != 0) {
1750Sstevel@tonic-gate 		*ypstatusp = ypstatus;
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate 	return (switch_err(ypstatus, 1));
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate /*
1810Sstevel@tonic-gate  * XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct)
1820Sstevel@tonic-gate  * lookups when we need a reserved port.
1830Sstevel@tonic-gate  */
1842830Sdjl 
1852830Sdjl static nss_status_t
_nss_nis_ypmatch_rsvdport(domain,map,key,valp,vallenp,ypstatusp)1860Sstevel@tonic-gate _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp)
1870Sstevel@tonic-gate 	const char		*domain;
1880Sstevel@tonic-gate 	const char		*map;
1890Sstevel@tonic-gate 	const char		*key;
1900Sstevel@tonic-gate 	char			**valp;
1910Sstevel@tonic-gate 	int			*vallenp;
1920Sstevel@tonic-gate 	int			*ypstatusp;
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	int			ypstatus;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate #if	MT_UNSAFE_YP
1970Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
1980Sstevel@tonic-gate 
1992830Sdjl 	(void) sigfillset(&newmask);
2006812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
2016812Sraf 	(void) mutex_lock(&one_lane);
2020Sstevel@tonic-gate #endif
2030Sstevel@tonic-gate 	ypstatus = __yp_match_rsvdport_cflookup((grrr)domain, (grrr)map,
2040Sstevel@tonic-gate 			    (grrr)key, strlen(key), valp, vallenp, 0);
2050Sstevel@tonic-gate #if	MT_UNSAFE_YP
2066812Sraf 	(void) mutex_unlock(&one_lane);
2076812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
2080Sstevel@tonic-gate #endif
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if (ypstatusp != 0) {
2110Sstevel@tonic-gate 		*ypstatusp = ypstatus;
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 	return (switch_err(ypstatus, 1));
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate nss_status_t
_nss_nis_lookup(be,args,netdb,map,key,ypstatusp)2170Sstevel@tonic-gate _nss_nis_lookup(be, args, netdb, map, key, ypstatusp)
2180Sstevel@tonic-gate 	nis_backend_ptr_t	be;
2190Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
2200Sstevel@tonic-gate 	int			netdb;
2210Sstevel@tonic-gate 	const char		*map;
2220Sstevel@tonic-gate 	const char		*key;
2230Sstevel@tonic-gate 	int			*ypstatusp;
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	nss_status_t		res;
2260Sstevel@tonic-gate 	int			vallen;
2270Sstevel@tonic-gate 	char			*val;
2280Sstevel@tonic-gate 	char			*free_ptr;
2290Sstevel@tonic-gate 	int			parsestat;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	if ((res = _nss_nis_ypmatch(be->domain, map, key, &val, &vallen,
2320Sstevel@tonic-gate 				    ypstatusp)) != NSS_SUCCESS) {
2330Sstevel@tonic-gate 		return (res);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 
236*8040SBaban.Kenkre@Sun.COM 	parsestat = NSS_STR_PARSE_SUCCESS;
237*8040SBaban.Kenkre@Sun.COM 	if (strcmp(map, "passwd.byname") == 0 ||
238*8040SBaban.Kenkre@Sun.COM 	    strcmp(map, "passwd.byuid") == 0) {
239*8040SBaban.Kenkre@Sun.COM 		parsestat = validate_passwd_ids(&val, &vallen, 1);
240*8040SBaban.Kenkre@Sun.COM 	} else if (strcmp(map, "group.byname") == 0)
241*8040SBaban.Kenkre@Sun.COM 		parsestat = validate_group_ids(&val, &vallen, 1);
242*8040SBaban.Kenkre@Sun.COM 	if (parsestat != NSS_STR_PARSE_SUCCESS) {
243*8040SBaban.Kenkre@Sun.COM 		free(val);
244*8040SBaban.Kenkre@Sun.COM 		return (NSS_NOTFOUND);
245*8040SBaban.Kenkre@Sun.COM 	}
246*8040SBaban.Kenkre@Sun.COM 
2470Sstevel@tonic-gate 	free_ptr = val;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	if (netdb) {
2500Sstevel@tonic-gate 		massage_netdb((const char **)&val, &vallen);
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 
2532830Sdjl 	args->returnval = NULL;
2542830Sdjl 	args->returnlen = 0;
2550Sstevel@tonic-gate 	parsestat = (*args->str2ent)(val, vallen,
2560Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
2570Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
2580Sstevel@tonic-gate 		args->returnval = args->buf.result;
2592830Sdjl 		args->returnlen = vallen;
2600Sstevel@tonic-gate 		res = NSS_SUCCESS;
2610Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
2620Sstevel@tonic-gate 		args->erange = 1;
2630Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
2640Sstevel@tonic-gate 		res = NSS_NOTFOUND;
2650Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	free(free_ptr);
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	return (res);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate nss_status_t
_nss_nis_lookup_rsvdport(be,args,netdb,map,key,ypstatusp)2730Sstevel@tonic-gate _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp)
2740Sstevel@tonic-gate 	nis_backend_ptr_t	be;
2750Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
2760Sstevel@tonic-gate 	int			netdb;
2770Sstevel@tonic-gate 	const char		*map;
2780Sstevel@tonic-gate 	const char		*key;
2790Sstevel@tonic-gate 	int			*ypstatusp;
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	nss_status_t		res;
2820Sstevel@tonic-gate 	int			vallen;
2830Sstevel@tonic-gate 	char			*val;
2840Sstevel@tonic-gate 	char			*free_ptr;
2850Sstevel@tonic-gate 	int			parsestat;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if ((res = _nss_nis_ypmatch_rsvdport(be->domain, map, key, &val,
2880Sstevel@tonic-gate 				    &vallen, ypstatusp)) != NSS_SUCCESS) {
2890Sstevel@tonic-gate 		return (res);
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	free_ptr = val;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if (netdb) {
2950Sstevel@tonic-gate 		massage_netdb((const char **)&val, &vallen);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 
2982830Sdjl 	args->returnval = NULL;
2992830Sdjl 	args->returnlen = 0;
3000Sstevel@tonic-gate 	parsestat = (*args->str2ent)(val, vallen,
3010Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
3020Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
3030Sstevel@tonic-gate 		args->returnval = args->buf.result;
3042830Sdjl 		args->returnlen = vallen;
3050Sstevel@tonic-gate 		res = NSS_SUCCESS;
3060Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
3070Sstevel@tonic-gate 		args->erange = 1;
3080Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
3090Sstevel@tonic-gate 		res = NSS_NOTFOUND;
3100Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	free(free_ptr);
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	return (res);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate static nss_status_t
do_getent(be,args,netdb)3180Sstevel@tonic-gate do_getent(be, args, netdb)
3190Sstevel@tonic-gate 	nis_backend_ptr_t	be;
3200Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
3210Sstevel@tonic-gate 	int			netdb;
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	nss_status_t		res;
3240Sstevel@tonic-gate 	int			ypstatus;
3250Sstevel@tonic-gate 	int			outkeylen, outvallen;
3260Sstevel@tonic-gate 	char			*outkey, *outval;
3270Sstevel@tonic-gate 	char			*free_ptr;
3280Sstevel@tonic-gate 	int			parsestat;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate #if	MT_UNSAFE_YP
3310Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
3320Sstevel@tonic-gate 
3332830Sdjl 	(void) sigfillset(&newmask);
3346812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
3356812Sraf 	(void) mutex_lock(&one_lane);
3360Sstevel@tonic-gate #endif
3370Sstevel@tonic-gate 	if (be->enum_key == 0) {
3380Sstevel@tonic-gate 		ypstatus = __yp_first_cflookup((grrr)be->domain,
3390Sstevel@tonic-gate 					    (grrr)be->enum_map, &outkey,
3400Sstevel@tonic-gate 					    &outkeylen, &outval,
3410Sstevel@tonic-gate 					    &outvallen, 0);
3420Sstevel@tonic-gate 	} else {
3430Sstevel@tonic-gate 		ypstatus = __yp_next_cflookup((grrr)be->domain,
3440Sstevel@tonic-gate 					    (grrr)be->enum_map, be->enum_key,
3450Sstevel@tonic-gate 					    be->enum_keylen, &outkey,
3460Sstevel@tonic-gate 					    &outkeylen, &outval,
3470Sstevel@tonic-gate 					    &outvallen, 0);
3480Sstevel@tonic-gate 	}
3490Sstevel@tonic-gate #if	MT_UNSAFE_YP
3506812Sraf 	(void) mutex_unlock(&one_lane);
3516812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
3520Sstevel@tonic-gate #endif
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	if ((res = switch_err(ypstatus, 0)) != NSS_SUCCESS) {
3550Sstevel@tonic-gate 		return (res);
3560Sstevel@tonic-gate 	}
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	free_ptr = outval;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if (netdb) {
3610Sstevel@tonic-gate 		massage_netdb((const char **)&outval, &outvallen);
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate 
3642830Sdjl 	args->returnval = NULL;
3652830Sdjl 	args->returnlen = 0;
3660Sstevel@tonic-gate 	parsestat = (*args->str2ent)(outval, outvallen,
3670Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
3680Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
3690Sstevel@tonic-gate 		args->returnval = args->buf.result;
3702830Sdjl 		args->returnlen = outvallen;
3710Sstevel@tonic-gate 		res = NSS_SUCCESS;
3720Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
3730Sstevel@tonic-gate 		args->erange = 1;
3740Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
3750Sstevel@tonic-gate 		res = NSS_NOTFOUND;
3760Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	free(free_ptr);
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	if (be->enum_key != 0) {
3810Sstevel@tonic-gate 		free(be->enum_key);
3820Sstevel@tonic-gate 	}
3830Sstevel@tonic-gate 	be->enum_key = outkey;
3840Sstevel@tonic-gate 	be->enum_keylen = outkeylen;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	return (res);
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate nss_status_t
_nss_nis_getent_rigid(be,args)3900Sstevel@tonic-gate _nss_nis_getent_rigid(be, args)
3910Sstevel@tonic-gate 	nis_backend_ptr_t	be;
3920Sstevel@tonic-gate 	void			*args;
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate 	return (do_getent(be, (nss_XbyY_args_t *)args, 0));
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate nss_status_t
_nss_nis_getent_netdb(be,args)3980Sstevel@tonic-gate _nss_nis_getent_netdb(be, args)
3990Sstevel@tonic-gate 	nis_backend_ptr_t	be;
4000Sstevel@tonic-gate 	void			*args;
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate 	return (do_getent(be, (nss_XbyY_args_t *)args, 1));
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate struct cb_data {
4070Sstevel@tonic-gate 	void			*args;
4080Sstevel@tonic-gate 	const char		*filter;
4090Sstevel@tonic-gate 	nis_do_all_func_t	func;
4100Sstevel@tonic-gate 	nss_status_t		result;
4110Sstevel@tonic-gate };
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate enum { ITER_NEXT = 0, ITER_STOP = 1 };	/* Should be in <rpcsvc/ypclnt.h> */
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate /*ARGSUSED*/
4160Sstevel@tonic-gate static int
do_cback(instatus,inkey,inkeylen,inval,invallen,indata)4170Sstevel@tonic-gate do_cback(instatus, inkey, inkeylen, inval, invallen, indata)
4180Sstevel@tonic-gate 	int			instatus;
4190Sstevel@tonic-gate 	const char		*inkey;
4200Sstevel@tonic-gate 	int			inkeylen;
4210Sstevel@tonic-gate 	const char		*inval;
4220Sstevel@tonic-gate 	int			invallen;
4230Sstevel@tonic-gate 	struct cb_data		*indata;
4240Sstevel@tonic-gate {
4250Sstevel@tonic-gate 	nss_status_t		res;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	if (instatus != YP_TRUE) {
4280Sstevel@tonic-gate 		return (ITER_NEXT);	/* yp_all may decide otherwise... */
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	if (indata->filter != 0 && strstr(inval, indata->filter) == 0) {
4320Sstevel@tonic-gate 		/*
4330Sstevel@tonic-gate 		 * Optimization:  if the entry doesn't contain the filter
4340Sstevel@tonic-gate 		 *   string then it can't be the entry we want, so don't
4350Sstevel@tonic-gate 		 *   bother looking more closely at it.
4360Sstevel@tonic-gate 		 */
4370Sstevel@tonic-gate 		return (ITER_NEXT);
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	res = (*indata->func)(inval, invallen, indata->args);
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	if (res == NSS_NOTFOUND) {
4430Sstevel@tonic-gate 		return (ITER_NEXT);
4440Sstevel@tonic-gate 	} else {
4450Sstevel@tonic-gate 		indata->result = res;
4460Sstevel@tonic-gate 		return (ITER_STOP);
4470Sstevel@tonic-gate 	}
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate nss_status_t
_nss_nis_do_all(be,args,filter,func)4510Sstevel@tonic-gate _nss_nis_do_all(be, args, filter, func)
4520Sstevel@tonic-gate 	nis_backend_ptr_t	be;
4530Sstevel@tonic-gate 	void			*args;
4540Sstevel@tonic-gate 	const char		*filter;
4550Sstevel@tonic-gate 	nis_do_all_func_t	func;
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate 	int			ypall_status;
4580Sstevel@tonic-gate 	struct cb_data		data;
4590Sstevel@tonic-gate 	struct ypall_callback	cback;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	data.args	= args;
4620Sstevel@tonic-gate 	data.filter	= filter;
4630Sstevel@tonic-gate 	data.func	= func;
4640Sstevel@tonic-gate 	data.result	= NSS_NOTFOUND;
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	cback.foreach	= do_cback;
4670Sstevel@tonic-gate 	cback.data	= (char *)&data;
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate #if	MT_UNSAFE_YP
4700Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
4710Sstevel@tonic-gate 
4722830Sdjl 	(void) sigfillset(&newmask);
4736812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
4746812Sraf 	(void) mutex_lock(&one_lane);
4750Sstevel@tonic-gate #endif
4760Sstevel@tonic-gate 	ypall_status = __yp_all_cflookup((grrr)be->domain,
4770Sstevel@tonic-gate 			(grrr) be->enum_map, &cback, 0);
4780Sstevel@tonic-gate #if	MT_UNSAFE_YP
4796812Sraf 	(void) mutex_unlock(&one_lane);
4806812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
4810Sstevel@tonic-gate #endif
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	switch (ypall_status) {
4840Sstevel@tonic-gate 	    case 0:
4850Sstevel@tonic-gate 		return (data.result);
4860Sstevel@tonic-gate 	    case YPERR_DOMAIN:
4870Sstevel@tonic-gate 	    case YPERR_YPSERV:
4880Sstevel@tonic-gate 	    case YPERR_BUSY:		/* Probably never get this, but... */
4890Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
4900Sstevel@tonic-gate 	    default:
4910Sstevel@tonic-gate 		return (NSS_UNAVAIL);
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate struct XbyY_data {
4960Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
4970Sstevel@tonic-gate 	nis_XY_check_func	func;
4980Sstevel@tonic-gate 	int			netdb;
4990Sstevel@tonic-gate };
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate static nss_status_t
XbyY_iterator(instr,instr_len,a)5020Sstevel@tonic-gate XbyY_iterator(instr, instr_len, a)
5030Sstevel@tonic-gate 	const char		*instr;
5040Sstevel@tonic-gate 	int			instr_len;
5050Sstevel@tonic-gate 	void			*a;
5060Sstevel@tonic-gate {
5070Sstevel@tonic-gate 	struct XbyY_data	*xydata	= (struct XbyY_data *)a;
5080Sstevel@tonic-gate 	nss_XbyY_args_t		*args	= xydata->args;
5090Sstevel@tonic-gate 	nss_status_t		res;
5100Sstevel@tonic-gate 	int			parsestat;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	if (xydata->netdb) {
5130Sstevel@tonic-gate 		massage_netdb(&instr, &instr_len);
5140Sstevel@tonic-gate 	}
5150Sstevel@tonic-gate 
5162830Sdjl 	args->returnval = NULL;
5172830Sdjl 	args->returnlen = 0;
5180Sstevel@tonic-gate 	parsestat = (*args->str2ent)(instr, instr_len,
5190Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
5200Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
5210Sstevel@tonic-gate 		args->returnval = args->buf.result;
5220Sstevel@tonic-gate 		if ((*xydata->func)(args)) {
5230Sstevel@tonic-gate 			res = NSS_SUCCESS;
5242830Sdjl 			args->returnlen = instr_len;
5250Sstevel@tonic-gate 		} else {
5260Sstevel@tonic-gate 			res = NSS_NOTFOUND;
5270Sstevel@tonic-gate 			args->returnval = 0;
5280Sstevel@tonic-gate 		}
5290Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
5300Sstevel@tonic-gate 		/*
5310Sstevel@tonic-gate 		 * If we got here because (*str2ent)() found that the buffer
5320Sstevel@tonic-gate 		 * wasn't big enough, maybe we should quit and return erange.
5330Sstevel@tonic-gate 		 * Instead we'll keep looking and eventually return "not
5340Sstevel@tonic-gate 		 * found" -- it's a bug, but not an earth-shattering one.
5350Sstevel@tonic-gate 		 */
5360Sstevel@tonic-gate 		args->erange = 1;	/* <== Is this a good idea? */
5370Sstevel@tonic-gate 		res = NSS_NOTFOUND;
5380Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	return (res);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate nss_status_t
_nss_nis_XY_all(be,args,netdb,filter,func)5440Sstevel@tonic-gate _nss_nis_XY_all(be, args, netdb, filter, func)
5450Sstevel@tonic-gate 	nis_backend_ptr_t	be;
5460Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
5470Sstevel@tonic-gate 	int			netdb;
5480Sstevel@tonic-gate 	const char		*filter;
5490Sstevel@tonic-gate 	nis_XY_check_func	func;
5500Sstevel@tonic-gate {
5510Sstevel@tonic-gate 	struct XbyY_data	data;
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	data.args = args;
5540Sstevel@tonic-gate 	data.func = func;
5550Sstevel@tonic-gate 	data.netdb = netdb;
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	return (_nss_nis_do_all(be, &data, filter, XbyY_iterator));
5580Sstevel@tonic-gate 	/* Now how many levels of callbacks was that? */
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate /*ARGSUSED*/
5630Sstevel@tonic-gate nss_status_t
_nss_nis_destr(be,dummy)5640Sstevel@tonic-gate _nss_nis_destr(be, dummy)
5650Sstevel@tonic-gate 	nis_backend_ptr_t	be;
5660Sstevel@tonic-gate 	void			*dummy;
5670Sstevel@tonic-gate {
5680Sstevel@tonic-gate 	if (be != 0) {
5690Sstevel@tonic-gate 		/* === Should change to invoke ops[ENDENT] ? */
5702830Sdjl 		(void) _nss_nis_endent(be, 0);
5710Sstevel@tonic-gate 		free(be);
5720Sstevel@tonic-gate 	}
5730Sstevel@tonic-gate 	return (NSS_SUCCESS);	/* In case anyone is dumb enough to check */
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate /* We want to lock this even if the YP routines are MT-safe */
5770Sstevel@tonic-gate static mutex_t	yp_domain_lock = DEFAULTMUTEX;
5780Sstevel@tonic-gate static char	*yp_domain;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate const char *
_nss_nis_domain()5810Sstevel@tonic-gate _nss_nis_domain()
5820Sstevel@tonic-gate {
5830Sstevel@tonic-gate 	char			*domain;
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	/*
5860Sstevel@tonic-gate 	 * This much locking is probably more "by the book" than necessary...
5870Sstevel@tonic-gate 	 */
5880Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
5890Sstevel@tonic-gate 
5902830Sdjl 	(void) sigfillset(&newmask);
5916812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
5926812Sraf 	(void) mutex_lock(&yp_domain_lock);
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	if ((domain = yp_domain) == 0) {
5950Sstevel@tonic-gate #if	MT_UNSAFE_YP
5966812Sraf 		(void) mutex_lock(&one_lane);
5970Sstevel@tonic-gate #endif
5980Sstevel@tonic-gate 		if (yp_get_default_domain(&yp_domain) == 0) {
5990Sstevel@tonic-gate 			domain = yp_domain;
6000Sstevel@tonic-gate 		}
6010Sstevel@tonic-gate #if	MT_UNSAFE_YP
6026812Sraf 		(void) mutex_unlock(&one_lane);
6030Sstevel@tonic-gate #endif
6040Sstevel@tonic-gate 	}
6050Sstevel@tonic-gate 
6066812Sraf 	(void) mutex_unlock(&yp_domain_lock);
6076812Sraf 	(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	return (domain);
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate nss_backend_t *
_nss_nis_constr(ops,n_ops,enum_map)6130Sstevel@tonic-gate _nss_nis_constr(ops, n_ops, enum_map)
6140Sstevel@tonic-gate 	nis_backend_op_t	ops[];
6150Sstevel@tonic-gate 	int			n_ops;
6160Sstevel@tonic-gate 	const char		*enum_map;
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate 	const char		*domain;
6190Sstevel@tonic-gate 	nis_backend_ptr_t	be;
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 	if ((domain = _nss_nis_domain()) == 0 ||
6220Sstevel@tonic-gate 	    (be = (nis_backend_ptr_t)malloc(sizeof (*be))) == 0) {
6230Sstevel@tonic-gate 		return (0);
6240Sstevel@tonic-gate 	}
6250Sstevel@tonic-gate 	be->ops		= ops;
6260Sstevel@tonic-gate 	be->n_ops	= n_ops;
6270Sstevel@tonic-gate 	be->domain	= domain;
6280Sstevel@tonic-gate 	be->enum_map	= enum_map;   /* Don't strdup, assume valid forever */
6290Sstevel@tonic-gate 	be->enum_key	= 0;
6300Sstevel@tonic-gate 	be->enum_keylen	= 0;
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	return ((nss_backend_t *)be);
6330Sstevel@tonic-gate }
6342830Sdjl 
6352830Sdjl /*
6362830Sdjl  * This routine is used to parse lines of the form:
6372830Sdjl  * 	name number aliases
6382830Sdjl  * It returns 1 if the key in argp matches any one of the
6392830Sdjl  * names in the line, otherwise 0
6402830Sdjl  * Used by rpc
6412830Sdjl  */
6422830Sdjl int
_nss_nis_check_name_aliases(nss_XbyY_args_t * argp,const char * line,int linelen)6432830Sdjl _nss_nis_check_name_aliases(nss_XbyY_args_t *argp, const char *line,
6442830Sdjl 	int linelen)
6452830Sdjl {
6462830Sdjl 	const char	*limit, *linep, *keyp;
6472830Sdjl 
6482830Sdjl 	linep = line;
6492830Sdjl 	limit = line + linelen;
6502830Sdjl 	keyp = argp->key.name;
6512830Sdjl 
6522830Sdjl 	/* compare name */
6532830Sdjl 	while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
6542830Sdjl 		keyp++;
6552830Sdjl 		linep++;
6562830Sdjl 	}
6572830Sdjl 	if (*keyp == '\0' && linep < limit && isspace(*linep))
6582830Sdjl 		return (1);
6592830Sdjl 	/* skip remainder of the name, if any */
6602830Sdjl 	while (linep < limit && !isspace(*linep))
6612830Sdjl 		linep++;
6622830Sdjl 	/* skip the delimiting spaces */
6632830Sdjl 	while (linep < limit && isspace(*linep))
6642830Sdjl 		linep++;
6652830Sdjl 	/* compare with the aliases */
6662830Sdjl 	while (linep < limit) {
6672830Sdjl 		/*
6682830Sdjl 		 * 1st pass: skip number
6692830Sdjl 		 * Other passes: skip remainder of the alias name, if any
6702830Sdjl 		 */
6712830Sdjl 		while (linep < limit && !isspace(*linep))
6722830Sdjl 			linep++;
6732830Sdjl 		/* skip the delimiting spaces */
6742830Sdjl 		while (linep < limit && isspace(*linep))
6752830Sdjl 			linep++;
6762830Sdjl 		/* compare with the alias name */
6772830Sdjl 		keyp = argp->key.name;
6782830Sdjl 		while (*keyp && linep < limit && !isspace(*linep) &&
6796812Sraf 		    *keyp == *linep) {
6802830Sdjl 			keyp++;
6812830Sdjl 			linep++;
6822830Sdjl 		}
6832830Sdjl 		if (*keyp == '\0' && (linep == limit || isspace(*linep)))
6842830Sdjl 			return (1);
6852830Sdjl 	}
6862830Sdjl 	return (0);
6872830Sdjl }
688