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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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