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