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 5*2830Sdjl * Common Development and Distribution License (the "License"). 6*2830Sdjl * 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 */ 210Sstevel@tonic-gate /* 22*2830Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 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 #pragma ident "%Z%%M% %I% %E% SMI" 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include "nis_common.h" 360Sstevel@tonic-gate #include <string.h> 370Sstevel@tonic-gate #include <synch.h> 380Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 390Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 400Sstevel@tonic-gate #include <thread.h> 410Sstevel@tonic-gate #include <ctype.h> 420Sstevel@tonic-gate #include <stdlib.h> 430Sstevel@tonic-gate #include <signal.h> 440Sstevel@tonic-gate 450Sstevel@tonic-gate #ifndef MT_UNSAFE_YP /* Is the libnsl YP client code MT-unsafe? */ 460Sstevel@tonic-gate #define MT_UNSAFE_YP 0 /* No, not any longer */ 470Sstevel@tonic-gate #endif 480Sstevel@tonic-gate 490Sstevel@tonic-gate #if MT_UNSAFE_YP 500Sstevel@tonic-gate static mutex_t one_lane = DEFAULTMUTEX; 510Sstevel@tonic-gate #endif 520Sstevel@tonic-gate 530Sstevel@tonic-gate /* <rpcsvc/ypclnt.h> uses (char *) where it should use (const char *) */ 540Sstevel@tonic-gate typedef char *grrr; 550Sstevel@tonic-gate 560Sstevel@tonic-gate /* 570Sstevel@tonic-gate * The YP client code thinks it's being helpful by appending '\n' and '\0' 580Sstevel@tonic-gate * to the values returned by yp_match() et al. In order to do this it 590Sstevel@tonic-gate * ends up doing more malloc()ing and data copying than would otherwise 600Sstevel@tonic-gate * be necessary. If we're interested in performance we should provide 610Sstevel@tonic-gate * alternative library interfaces that skip the helpfulness and instead 620Sstevel@tonic-gate * let the XDR routines dump the value directly into the buffer where 630Sstevel@tonic-gate * we really want it. For now, though, we just use the vanilla interface. 640Sstevel@tonic-gate */ 650Sstevel@tonic-gate 660Sstevel@tonic-gate static nss_status_t 670Sstevel@tonic-gate switch_err(ypstatus, ismatch) 680Sstevel@tonic-gate int ypstatus; 690Sstevel@tonic-gate int ismatch; 700Sstevel@tonic-gate { 710Sstevel@tonic-gate switch (ypstatus) { 720Sstevel@tonic-gate case 0: 73*2830Sdjl errno = 0; 740Sstevel@tonic-gate return (NSS_SUCCESS); 750Sstevel@tonic-gate 760Sstevel@tonic-gate case YPERR_BADARGS: 770Sstevel@tonic-gate case YPERR_KEY: 78*2830Sdjl errno = 0; 790Sstevel@tonic-gate return (NSS_NOTFOUND); 800Sstevel@tonic-gate 810Sstevel@tonic-gate /* 820Sstevel@tonic-gate * When the YP server is running in DNS forwarding mode, 830Sstevel@tonic-gate * the forwarder will return YPERR_NOMORE to us if it 840Sstevel@tonic-gate * is unable to contact a server (i.e., it has timed out). 850Sstevel@tonic-gate * The NSS_NISSERVDNS_TRYAGAIN is returned for timeout errors. 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate case YPERR_NOMORE: 880Sstevel@tonic-gate if (ismatch) 890Sstevel@tonic-gate return (NSS_NISSERVDNS_TRYAGAIN); 900Sstevel@tonic-gate else 910Sstevel@tonic-gate return (NSS_NOTFOUND); 920Sstevel@tonic-gate 930Sstevel@tonic-gate case YPERR_DOMAIN: 940Sstevel@tonic-gate case YPERR_YPSERV: 950Sstevel@tonic-gate case YPERR_BUSY: 960Sstevel@tonic-gate return (NSS_TRYAGAIN); 970Sstevel@tonic-gate 980Sstevel@tonic-gate default: 990Sstevel@tonic-gate return (NSS_UNAVAIL); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /*ARGSUSED*/ 1040Sstevel@tonic-gate nss_status_t 1050Sstevel@tonic-gate _nss_nis_setent(be, dummy) 1060Sstevel@tonic-gate nis_backend_ptr_t be; 1070Sstevel@tonic-gate void *dummy; 1080Sstevel@tonic-gate { 1090Sstevel@tonic-gate if (be->enum_key != 0) { 1100Sstevel@tonic-gate free(be->enum_key); 1110Sstevel@tonic-gate be->enum_key = 0; 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate be->enum_keylen = 0; 1140Sstevel@tonic-gate return (NSS_SUCCESS); 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate nss_status_t 1180Sstevel@tonic-gate _nss_nis_endent(be, dummy) 1190Sstevel@tonic-gate nis_backend_ptr_t be; 1200Sstevel@tonic-gate void *dummy; 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate return (_nss_nis_setent(be, dummy)); 1230Sstevel@tonic-gate /* Nothing else we can clean up, is there? */ 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate void 1270Sstevel@tonic-gate massage_netdb(const char **valp, int *vallenp) 1280Sstevel@tonic-gate { 1290Sstevel@tonic-gate const char *first; 1300Sstevel@tonic-gate const char *last; 1310Sstevel@tonic-gate const char *val = *valp; 1320Sstevel@tonic-gate int vallen = *vallenp; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate if ((last = memchr(val, '#', vallen)) == 0) { 1350Sstevel@tonic-gate last = val + vallen; 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate for (first = val; first < last && isspace(*first); first++) { 1380Sstevel@tonic-gate ; 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate for (/* cstyle */; first < last && isspace(last[-1]); last--) { 1410Sstevel@tonic-gate ; 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate /* 1440Sstevel@tonic-gate * Don't check for an empty line because it shouldn't ever 1450Sstevel@tonic-gate * have made it into the YP map. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate *valp = first; 1480Sstevel@tonic-gate *vallenp = (int)(last - first); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate nss_status_t 1520Sstevel@tonic-gate _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp) 1530Sstevel@tonic-gate const char *domain; 1540Sstevel@tonic-gate const char *map; 1550Sstevel@tonic-gate const char *key; 1560Sstevel@tonic-gate char **valp; 1570Sstevel@tonic-gate int *vallenp; 1580Sstevel@tonic-gate int *ypstatusp; 1590Sstevel@tonic-gate { 1600Sstevel@tonic-gate int ypstatus; 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate #if MT_UNSAFE_YP 1630Sstevel@tonic-gate sigset_t oldmask, newmask; 1640Sstevel@tonic-gate 165*2830Sdjl (void) sigfillset(&newmask); 1660Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 1670Sstevel@tonic-gate _mutex_lock(&one_lane); 1680Sstevel@tonic-gate #endif 1690Sstevel@tonic-gate ypstatus = __yp_match_cflookup((grrr)domain, (grrr)map, 1700Sstevel@tonic-gate (grrr)key, (int)strlen(key), valp, vallenp, 0); 1710Sstevel@tonic-gate #if MT_UNSAFE_YP 1720Sstevel@tonic-gate _mutex_unlock(&one_lane); 1730Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 1740Sstevel@tonic-gate #endif 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate if (ypstatusp != 0) { 1770Sstevel@tonic-gate *ypstatusp = ypstatus; 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate return (switch_err(ypstatus, 1)); 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct) 1840Sstevel@tonic-gate * lookups when we need a reserved port. 1850Sstevel@tonic-gate */ 186*2830Sdjl 187*2830Sdjl static nss_status_t 1880Sstevel@tonic-gate _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp) 1890Sstevel@tonic-gate const char *domain; 1900Sstevel@tonic-gate const char *map; 1910Sstevel@tonic-gate const char *key; 1920Sstevel@tonic-gate char **valp; 1930Sstevel@tonic-gate int *vallenp; 1940Sstevel@tonic-gate int *ypstatusp; 1950Sstevel@tonic-gate { 1960Sstevel@tonic-gate int ypstatus; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate #if MT_UNSAFE_YP 1990Sstevel@tonic-gate sigset_t oldmask, newmask; 2000Sstevel@tonic-gate 201*2830Sdjl (void) sigfillset(&newmask); 2020Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 2030Sstevel@tonic-gate _mutex_lock(&one_lane); 2040Sstevel@tonic-gate #endif 2050Sstevel@tonic-gate ypstatus = __yp_match_rsvdport_cflookup((grrr)domain, (grrr)map, 2060Sstevel@tonic-gate (grrr)key, strlen(key), valp, vallenp, 0); 2070Sstevel@tonic-gate #if MT_UNSAFE_YP 2080Sstevel@tonic-gate _mutex_unlock(&one_lane); 2090Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 2100Sstevel@tonic-gate #endif 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate if (ypstatusp != 0) { 2130Sstevel@tonic-gate *ypstatusp = ypstatus; 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate return (switch_err(ypstatus, 1)); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate nss_status_t 2190Sstevel@tonic-gate _nss_nis_lookup(be, args, netdb, map, key, ypstatusp) 2200Sstevel@tonic-gate nis_backend_ptr_t be; 2210Sstevel@tonic-gate nss_XbyY_args_t *args; 2220Sstevel@tonic-gate int netdb; 2230Sstevel@tonic-gate const char *map; 2240Sstevel@tonic-gate const char *key; 2250Sstevel@tonic-gate int *ypstatusp; 2260Sstevel@tonic-gate { 2270Sstevel@tonic-gate nss_status_t res; 2280Sstevel@tonic-gate int vallen; 2290Sstevel@tonic-gate char *val; 2300Sstevel@tonic-gate char *free_ptr; 2310Sstevel@tonic-gate int parsestat; 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate if ((res = _nss_nis_ypmatch(be->domain, map, key, &val, &vallen, 2340Sstevel@tonic-gate ypstatusp)) != NSS_SUCCESS) { 2350Sstevel@tonic-gate return (res); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate free_ptr = val; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate if (netdb) { 2410Sstevel@tonic-gate massage_netdb((const char **)&val, &vallen); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 244*2830Sdjl args->returnval = NULL; 245*2830Sdjl args->returnlen = 0; 2460Sstevel@tonic-gate parsestat = (*args->str2ent)(val, vallen, 2470Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 2480Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 2490Sstevel@tonic-gate args->returnval = args->buf.result; 250*2830Sdjl args->returnlen = vallen; 2510Sstevel@tonic-gate res = NSS_SUCCESS; 2520Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 2530Sstevel@tonic-gate args->erange = 1; 2540Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 2550Sstevel@tonic-gate res = NSS_NOTFOUND; 2560Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate free(free_ptr); 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate return (res); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate nss_status_t 2640Sstevel@tonic-gate _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp) 2650Sstevel@tonic-gate nis_backend_ptr_t be; 2660Sstevel@tonic-gate nss_XbyY_args_t *args; 2670Sstevel@tonic-gate int netdb; 2680Sstevel@tonic-gate const char *map; 2690Sstevel@tonic-gate const char *key; 2700Sstevel@tonic-gate int *ypstatusp; 2710Sstevel@tonic-gate { 2720Sstevel@tonic-gate nss_status_t res; 2730Sstevel@tonic-gate int vallen; 2740Sstevel@tonic-gate char *val; 2750Sstevel@tonic-gate char *free_ptr; 2760Sstevel@tonic-gate int parsestat; 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate if ((res = _nss_nis_ypmatch_rsvdport(be->domain, map, key, &val, 2790Sstevel@tonic-gate &vallen, ypstatusp)) != NSS_SUCCESS) { 2800Sstevel@tonic-gate return (res); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate free_ptr = val; 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (netdb) { 2860Sstevel@tonic-gate massage_netdb((const char **)&val, &vallen); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 289*2830Sdjl args->returnval = NULL; 290*2830Sdjl args->returnlen = 0; 2910Sstevel@tonic-gate parsestat = (*args->str2ent)(val, vallen, 2920Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 2930Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 2940Sstevel@tonic-gate args->returnval = args->buf.result; 295*2830Sdjl args->returnlen = vallen; 2960Sstevel@tonic-gate res = NSS_SUCCESS; 2970Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 2980Sstevel@tonic-gate args->erange = 1; 2990Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 3000Sstevel@tonic-gate res = NSS_NOTFOUND; 3010Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate free(free_ptr); 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate return (res); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate static nss_status_t 3090Sstevel@tonic-gate do_getent(be, args, netdb) 3100Sstevel@tonic-gate nis_backend_ptr_t be; 3110Sstevel@tonic-gate nss_XbyY_args_t *args; 3120Sstevel@tonic-gate int netdb; 3130Sstevel@tonic-gate { 3140Sstevel@tonic-gate nss_status_t res; 3150Sstevel@tonic-gate int ypstatus; 3160Sstevel@tonic-gate int outkeylen, outvallen; 3170Sstevel@tonic-gate char *outkey, *outval; 3180Sstevel@tonic-gate char *free_ptr; 3190Sstevel@tonic-gate int parsestat; 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate #if MT_UNSAFE_YP 3220Sstevel@tonic-gate sigset_t oldmask, newmask; 3230Sstevel@tonic-gate 324*2830Sdjl (void) sigfillset(&newmask); 3250Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 3260Sstevel@tonic-gate _mutex_lock(&one_lane); 3270Sstevel@tonic-gate #endif 3280Sstevel@tonic-gate if (be->enum_key == 0) { 3290Sstevel@tonic-gate ypstatus = __yp_first_cflookup((grrr)be->domain, 3300Sstevel@tonic-gate (grrr)be->enum_map, &outkey, 3310Sstevel@tonic-gate &outkeylen, &outval, 3320Sstevel@tonic-gate &outvallen, 0); 3330Sstevel@tonic-gate } else { 3340Sstevel@tonic-gate ypstatus = __yp_next_cflookup((grrr)be->domain, 3350Sstevel@tonic-gate (grrr)be->enum_map, be->enum_key, 3360Sstevel@tonic-gate be->enum_keylen, &outkey, 3370Sstevel@tonic-gate &outkeylen, &outval, 3380Sstevel@tonic-gate &outvallen, 0); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate #if MT_UNSAFE_YP 3410Sstevel@tonic-gate _mutex_unlock(&one_lane); 3420Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 3430Sstevel@tonic-gate #endif 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate if ((res = switch_err(ypstatus, 0)) != NSS_SUCCESS) { 3460Sstevel@tonic-gate return (res); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate free_ptr = outval; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate if (netdb) { 3520Sstevel@tonic-gate massage_netdb((const char **)&outval, &outvallen); 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate 355*2830Sdjl args->returnval = NULL; 356*2830Sdjl args->returnlen = 0; 3570Sstevel@tonic-gate parsestat = (*args->str2ent)(outval, outvallen, 3580Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 3590Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 3600Sstevel@tonic-gate args->returnval = args->buf.result; 361*2830Sdjl args->returnlen = outvallen; 3620Sstevel@tonic-gate res = NSS_SUCCESS; 3630Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 3640Sstevel@tonic-gate args->erange = 1; 3650Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 3660Sstevel@tonic-gate res = NSS_NOTFOUND; 3670Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate free(free_ptr); 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate if (be->enum_key != 0) { 3720Sstevel@tonic-gate free(be->enum_key); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate be->enum_key = outkey; 3750Sstevel@tonic-gate be->enum_keylen = outkeylen; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate return (res); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate nss_status_t 3810Sstevel@tonic-gate _nss_nis_getent_rigid(be, args) 3820Sstevel@tonic-gate nis_backend_ptr_t be; 3830Sstevel@tonic-gate void *args; 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate return (do_getent(be, (nss_XbyY_args_t *)args, 0)); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate nss_status_t 3890Sstevel@tonic-gate _nss_nis_getent_netdb(be, args) 3900Sstevel@tonic-gate nis_backend_ptr_t be; 3910Sstevel@tonic-gate void *args; 3920Sstevel@tonic-gate { 3930Sstevel@tonic-gate return (do_getent(be, (nss_XbyY_args_t *)args, 1)); 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate struct cb_data { 3980Sstevel@tonic-gate void *args; 3990Sstevel@tonic-gate const char *filter; 4000Sstevel@tonic-gate nis_do_all_func_t func; 4010Sstevel@tonic-gate nss_status_t result; 4020Sstevel@tonic-gate }; 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate enum { ITER_NEXT = 0, ITER_STOP = 1 }; /* Should be in <rpcsvc/ypclnt.h> */ 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate /*ARGSUSED*/ 4070Sstevel@tonic-gate static int 4080Sstevel@tonic-gate do_cback(instatus, inkey, inkeylen, inval, invallen, indata) 4090Sstevel@tonic-gate int instatus; 4100Sstevel@tonic-gate const char *inkey; 4110Sstevel@tonic-gate int inkeylen; 4120Sstevel@tonic-gate const char *inval; 4130Sstevel@tonic-gate int invallen; 4140Sstevel@tonic-gate struct cb_data *indata; 4150Sstevel@tonic-gate { 4160Sstevel@tonic-gate nss_status_t res; 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate if (instatus != YP_TRUE) { 4190Sstevel@tonic-gate return (ITER_NEXT); /* yp_all may decide otherwise... */ 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate if (indata->filter != 0 && strstr(inval, indata->filter) == 0) { 4230Sstevel@tonic-gate /* 4240Sstevel@tonic-gate * Optimization: if the entry doesn't contain the filter 4250Sstevel@tonic-gate * string then it can't be the entry we want, so don't 4260Sstevel@tonic-gate * bother looking more closely at it. 4270Sstevel@tonic-gate */ 4280Sstevel@tonic-gate return (ITER_NEXT); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate res = (*indata->func)(inval, invallen, indata->args); 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate if (res == NSS_NOTFOUND) { 4340Sstevel@tonic-gate return (ITER_NEXT); 4350Sstevel@tonic-gate } else { 4360Sstevel@tonic-gate indata->result = res; 4370Sstevel@tonic-gate return (ITER_STOP); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate nss_status_t 4420Sstevel@tonic-gate _nss_nis_do_all(be, args, filter, func) 4430Sstevel@tonic-gate nis_backend_ptr_t be; 4440Sstevel@tonic-gate void *args; 4450Sstevel@tonic-gate const char *filter; 4460Sstevel@tonic-gate nis_do_all_func_t func; 4470Sstevel@tonic-gate { 4480Sstevel@tonic-gate int ypall_status; 4490Sstevel@tonic-gate struct cb_data data; 4500Sstevel@tonic-gate struct ypall_callback cback; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate data.args = args; 4530Sstevel@tonic-gate data.filter = filter; 4540Sstevel@tonic-gate data.func = func; 4550Sstevel@tonic-gate data.result = NSS_NOTFOUND; 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate cback.foreach = do_cback; 4580Sstevel@tonic-gate cback.data = (char *)&data; 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate #if MT_UNSAFE_YP 4610Sstevel@tonic-gate sigset_t oldmask, newmask; 4620Sstevel@tonic-gate 463*2830Sdjl (void) sigfillset(&newmask); 4640Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 4650Sstevel@tonic-gate _mutex_lock(&one_lane); 4660Sstevel@tonic-gate #endif 4670Sstevel@tonic-gate ypall_status = __yp_all_cflookup((grrr)be->domain, 4680Sstevel@tonic-gate (grrr) be->enum_map, &cback, 0); 4690Sstevel@tonic-gate #if MT_UNSAFE_YP 4700Sstevel@tonic-gate _mutex_unlock(&one_lane); 4710Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 4720Sstevel@tonic-gate #endif 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate switch (ypall_status) { 4750Sstevel@tonic-gate case 0: 4760Sstevel@tonic-gate return (data.result); 4770Sstevel@tonic-gate case YPERR_DOMAIN: 4780Sstevel@tonic-gate case YPERR_YPSERV: 4790Sstevel@tonic-gate case YPERR_BUSY: /* Probably never get this, but... */ 4800Sstevel@tonic-gate return (NSS_TRYAGAIN); 4810Sstevel@tonic-gate default: 4820Sstevel@tonic-gate return (NSS_UNAVAIL); 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate struct XbyY_data { 4870Sstevel@tonic-gate nss_XbyY_args_t *args; 4880Sstevel@tonic-gate nis_XY_check_func func; 4890Sstevel@tonic-gate int netdb; 4900Sstevel@tonic-gate }; 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate static nss_status_t 4930Sstevel@tonic-gate XbyY_iterator(instr, instr_len, a) 4940Sstevel@tonic-gate const char *instr; 4950Sstevel@tonic-gate int instr_len; 4960Sstevel@tonic-gate void *a; 4970Sstevel@tonic-gate { 4980Sstevel@tonic-gate struct XbyY_data *xydata = (struct XbyY_data *)a; 4990Sstevel@tonic-gate nss_XbyY_args_t *args = xydata->args; 5000Sstevel@tonic-gate nss_status_t res; 5010Sstevel@tonic-gate int parsestat; 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate if (xydata->netdb) { 5040Sstevel@tonic-gate massage_netdb(&instr, &instr_len); 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate 507*2830Sdjl args->returnval = NULL; 508*2830Sdjl args->returnlen = 0; 5090Sstevel@tonic-gate parsestat = (*args->str2ent)(instr, instr_len, 5100Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 5110Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 5120Sstevel@tonic-gate args->returnval = args->buf.result; 5130Sstevel@tonic-gate if ((*xydata->func)(args)) { 5140Sstevel@tonic-gate res = NSS_SUCCESS; 515*2830Sdjl args->returnlen = instr_len; 5160Sstevel@tonic-gate } else { 5170Sstevel@tonic-gate res = NSS_NOTFOUND; 5180Sstevel@tonic-gate args->returnval = 0; 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 5210Sstevel@tonic-gate /* 5220Sstevel@tonic-gate * If we got here because (*str2ent)() found that the buffer 5230Sstevel@tonic-gate * wasn't big enough, maybe we should quit and return erange. 5240Sstevel@tonic-gate * Instead we'll keep looking and eventually return "not 5250Sstevel@tonic-gate * found" -- it's a bug, but not an earth-shattering one. 5260Sstevel@tonic-gate */ 5270Sstevel@tonic-gate args->erange = 1; /* <== Is this a good idea? */ 5280Sstevel@tonic-gate res = NSS_NOTFOUND; 5290Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate return (res); 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate nss_status_t 5350Sstevel@tonic-gate _nss_nis_XY_all(be, args, netdb, filter, func) 5360Sstevel@tonic-gate nis_backend_ptr_t be; 5370Sstevel@tonic-gate nss_XbyY_args_t *args; 5380Sstevel@tonic-gate int netdb; 5390Sstevel@tonic-gate const char *filter; 5400Sstevel@tonic-gate nis_XY_check_func func; 5410Sstevel@tonic-gate { 5420Sstevel@tonic-gate struct XbyY_data data; 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate data.args = args; 5450Sstevel@tonic-gate data.func = func; 5460Sstevel@tonic-gate data.netdb = netdb; 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate return (_nss_nis_do_all(be, &data, filter, XbyY_iterator)); 5490Sstevel@tonic-gate /* Now how many levels of callbacks was that? */ 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate /*ARGSUSED*/ 5540Sstevel@tonic-gate nss_status_t 5550Sstevel@tonic-gate _nss_nis_destr(be, dummy) 5560Sstevel@tonic-gate nis_backend_ptr_t be; 5570Sstevel@tonic-gate void *dummy; 5580Sstevel@tonic-gate { 5590Sstevel@tonic-gate if (be != 0) { 5600Sstevel@tonic-gate /* === Should change to invoke ops[ENDENT] ? */ 561*2830Sdjl (void) _nss_nis_endent(be, 0); 5620Sstevel@tonic-gate free(be); 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate return (NSS_SUCCESS); /* In case anyone is dumb enough to check */ 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate /* We want to lock this even if the YP routines are MT-safe */ 5680Sstevel@tonic-gate static mutex_t yp_domain_lock = DEFAULTMUTEX; 5690Sstevel@tonic-gate static char *yp_domain; 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate const char * 5720Sstevel@tonic-gate _nss_nis_domain() 5730Sstevel@tonic-gate { 5740Sstevel@tonic-gate char *domain; 5750Sstevel@tonic-gate 5760Sstevel@tonic-gate /* 5770Sstevel@tonic-gate * This much locking is probably more "by the book" than necessary... 5780Sstevel@tonic-gate */ 5790Sstevel@tonic-gate sigset_t oldmask, newmask; 5800Sstevel@tonic-gate 581*2830Sdjl (void) sigfillset(&newmask); 5820Sstevel@tonic-gate (void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 5830Sstevel@tonic-gate (void) _mutex_lock(&yp_domain_lock); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate if ((domain = yp_domain) == 0) { 5860Sstevel@tonic-gate #if MT_UNSAFE_YP 5870Sstevel@tonic-gate _mutex_lock(&one_lane); 5880Sstevel@tonic-gate #endif 5890Sstevel@tonic-gate if (yp_get_default_domain(&yp_domain) == 0) { 5900Sstevel@tonic-gate domain = yp_domain; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate #if MT_UNSAFE_YP 5930Sstevel@tonic-gate _mutex_unlock(&one_lane); 5940Sstevel@tonic-gate #endif 5950Sstevel@tonic-gate } 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate _mutex_unlock(&yp_domain_lock); 5980Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate return (domain); 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate nss_backend_t * 6040Sstevel@tonic-gate _nss_nis_constr(ops, n_ops, enum_map) 6050Sstevel@tonic-gate nis_backend_op_t ops[]; 6060Sstevel@tonic-gate int n_ops; 6070Sstevel@tonic-gate const char *enum_map; 6080Sstevel@tonic-gate { 6090Sstevel@tonic-gate const char *domain; 6100Sstevel@tonic-gate nis_backend_ptr_t be; 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate if ((domain = _nss_nis_domain()) == 0 || 6130Sstevel@tonic-gate (be = (nis_backend_ptr_t)malloc(sizeof (*be))) == 0) { 6140Sstevel@tonic-gate return (0); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate be->ops = ops; 6170Sstevel@tonic-gate be->n_ops = n_ops; 6180Sstevel@tonic-gate be->domain = domain; 6190Sstevel@tonic-gate be->enum_map = enum_map; /* Don't strdup, assume valid forever */ 6200Sstevel@tonic-gate be->enum_key = 0; 6210Sstevel@tonic-gate be->enum_keylen = 0; 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate return ((nss_backend_t *)be); 6240Sstevel@tonic-gate } 625*2830Sdjl 626*2830Sdjl /* 627*2830Sdjl * This routine is used to parse lines of the form: 628*2830Sdjl * name number aliases 629*2830Sdjl * It returns 1 if the key in argp matches any one of the 630*2830Sdjl * names in the line, otherwise 0 631*2830Sdjl * Used by rpc 632*2830Sdjl */ 633*2830Sdjl int 634*2830Sdjl _nss_nis_check_name_aliases(nss_XbyY_args_t *argp, const char *line, 635*2830Sdjl int linelen) 636*2830Sdjl { 637*2830Sdjl const char *limit, *linep, *keyp; 638*2830Sdjl 639*2830Sdjl linep = line; 640*2830Sdjl limit = line + linelen; 641*2830Sdjl keyp = argp->key.name; 642*2830Sdjl 643*2830Sdjl /* compare name */ 644*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 645*2830Sdjl keyp++; 646*2830Sdjl linep++; 647*2830Sdjl } 648*2830Sdjl if (*keyp == '\0' && linep < limit && isspace(*linep)) 649*2830Sdjl return (1); 650*2830Sdjl /* skip remainder of the name, if any */ 651*2830Sdjl while (linep < limit && !isspace(*linep)) 652*2830Sdjl linep++; 653*2830Sdjl /* skip the delimiting spaces */ 654*2830Sdjl while (linep < limit && isspace(*linep)) 655*2830Sdjl linep++; 656*2830Sdjl /* compare with the aliases */ 657*2830Sdjl while (linep < limit) { 658*2830Sdjl /* 659*2830Sdjl * 1st pass: skip number 660*2830Sdjl * Other passes: skip remainder of the alias name, if any 661*2830Sdjl */ 662*2830Sdjl while (linep < limit && !isspace(*linep)) 663*2830Sdjl linep++; 664*2830Sdjl /* skip the delimiting spaces */ 665*2830Sdjl while (linep < limit && isspace(*linep)) 666*2830Sdjl linep++; 667*2830Sdjl /* compare with the alias name */ 668*2830Sdjl keyp = argp->key.name; 669*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 670*2830Sdjl *keyp == *linep) { 671*2830Sdjl keyp++; 672*2830Sdjl linep++; 673*2830Sdjl } 674*2830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 675*2830Sdjl return (1); 676*2830Sdjl } 677*2830Sdjl return (0); 678*2830Sdjl } 679