17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * nis_common.c 297c478bd9Sstevel@tonic-gate * 307c478bd9Sstevel@tonic-gate * Common code and structures used by name-service-switch "nis" backends. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include "nis_common.h" 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <synch.h> 367c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 377c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 387c478bd9Sstevel@tonic-gate #include <thread.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 417c478bd9Sstevel@tonic-gate #include <signal.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #ifndef MT_UNSAFE_YP /* Is the libnsl YP client code MT-unsafe? */ 447c478bd9Sstevel@tonic-gate #define MT_UNSAFE_YP 0 /* No, not any longer */ 457c478bd9Sstevel@tonic-gate #endif 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 487c478bd9Sstevel@tonic-gate static mutex_t one_lane = DEFAULTMUTEX; 497c478bd9Sstevel@tonic-gate #endif 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* <rpcsvc/ypclnt.h> uses (char *) where it should use (const char *) */ 527c478bd9Sstevel@tonic-gate typedef char *grrr; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * The YP client code thinks it's being helpful by appending '\n' and '\0' 567c478bd9Sstevel@tonic-gate * to the values returned by yp_match() et al. In order to do this it 577c478bd9Sstevel@tonic-gate * ends up doing more malloc()ing and data copying than would otherwise 587c478bd9Sstevel@tonic-gate * be necessary. If we're interested in performance we should provide 597c478bd9Sstevel@tonic-gate * alternative library interfaces that skip the helpfulness and instead 607c478bd9Sstevel@tonic-gate * let the XDR routines dump the value directly into the buffer where 617c478bd9Sstevel@tonic-gate * we really want it. For now, though, we just use the vanilla interface. 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static nss_status_t 657c478bd9Sstevel@tonic-gate switch_err(ypstatus, ismatch) 667c478bd9Sstevel@tonic-gate int ypstatus; 677c478bd9Sstevel@tonic-gate int ismatch; 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate switch (ypstatus) { 707c478bd9Sstevel@tonic-gate case 0: 71cb5caa98Sdjl errno = 0; 727c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate case YPERR_BADARGS: 757c478bd9Sstevel@tonic-gate case YPERR_KEY: 76cb5caa98Sdjl errno = 0; 777c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * When the YP server is running in DNS forwarding mode, 817c478bd9Sstevel@tonic-gate * the forwarder will return YPERR_NOMORE to us if it 827c478bd9Sstevel@tonic-gate * is unable to contact a server (i.e., it has timed out). 837c478bd9Sstevel@tonic-gate * The NSS_NISSERVDNS_TRYAGAIN is returned for timeout errors. 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate case YPERR_NOMORE: 867c478bd9Sstevel@tonic-gate if (ismatch) 877c478bd9Sstevel@tonic-gate return (NSS_NISSERVDNS_TRYAGAIN); 887c478bd9Sstevel@tonic-gate else 897c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate case YPERR_DOMAIN: 927c478bd9Sstevel@tonic-gate case YPERR_YPSERV: 937c478bd9Sstevel@tonic-gate case YPERR_BUSY: 947c478bd9Sstevel@tonic-gate return (NSS_TRYAGAIN); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate default: 977c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1027c478bd9Sstevel@tonic-gate nss_status_t 1037c478bd9Sstevel@tonic-gate _nss_nis_setent(be, dummy) 1047c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 1057c478bd9Sstevel@tonic-gate void *dummy; 1067c478bd9Sstevel@tonic-gate { 1077c478bd9Sstevel@tonic-gate if (be->enum_key != 0) { 1087c478bd9Sstevel@tonic-gate free(be->enum_key); 1097c478bd9Sstevel@tonic-gate be->enum_key = 0; 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate be->enum_keylen = 0; 1127c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate nss_status_t 1167c478bd9Sstevel@tonic-gate _nss_nis_endent(be, dummy) 1177c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 1187c478bd9Sstevel@tonic-gate void *dummy; 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate return (_nss_nis_setent(be, dummy)); 1217c478bd9Sstevel@tonic-gate /* Nothing else we can clean up, is there? */ 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate void 1257c478bd9Sstevel@tonic-gate massage_netdb(const char **valp, int *vallenp) 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate const char *first; 1287c478bd9Sstevel@tonic-gate const char *last; 1297c478bd9Sstevel@tonic-gate const char *val = *valp; 1307c478bd9Sstevel@tonic-gate int vallen = *vallenp; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if ((last = memchr(val, '#', vallen)) == 0) { 1337c478bd9Sstevel@tonic-gate last = val + vallen; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate for (first = val; first < last && isspace(*first); first++) { 1367c478bd9Sstevel@tonic-gate ; 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate for (/* cstyle */; first < last && isspace(last[-1]); last--) { 1397c478bd9Sstevel@tonic-gate ; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * Don't check for an empty line because it shouldn't ever 1437c478bd9Sstevel@tonic-gate * have made it into the YP map. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate *valp = first; 1467c478bd9Sstevel@tonic-gate *vallenp = (int)(last - first); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate nss_status_t 1507c478bd9Sstevel@tonic-gate _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp) 1517c478bd9Sstevel@tonic-gate const char *domain; 1527c478bd9Sstevel@tonic-gate const char *map; 1537c478bd9Sstevel@tonic-gate const char *key; 1547c478bd9Sstevel@tonic-gate char **valp; 1557c478bd9Sstevel@tonic-gate int *vallenp; 1567c478bd9Sstevel@tonic-gate int *ypstatusp; 1577c478bd9Sstevel@tonic-gate { 1587c478bd9Sstevel@tonic-gate int ypstatus; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 1617c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask; 1627c478bd9Sstevel@tonic-gate 163cb5caa98Sdjl (void) sigfillset(&newmask); 1647257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 1657257d1b4Sraf (void) mutex_lock(&one_lane); 1667c478bd9Sstevel@tonic-gate #endif 1677c478bd9Sstevel@tonic-gate ypstatus = __yp_match_cflookup((grrr)domain, (grrr)map, 1687c478bd9Sstevel@tonic-gate (grrr)key, (int)strlen(key), valp, vallenp, 0); 1697c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 1707257d1b4Sraf (void) mutex_unlock(&one_lane); 1717257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 1727c478bd9Sstevel@tonic-gate #endif 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if (ypstatusp != 0) { 1757c478bd9Sstevel@tonic-gate *ypstatusp = ypstatus; 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate return (switch_err(ypstatus, 1)); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct) 1827c478bd9Sstevel@tonic-gate * lookups when we need a reserved port. 1837c478bd9Sstevel@tonic-gate */ 184cb5caa98Sdjl 185cb5caa98Sdjl static nss_status_t 1867c478bd9Sstevel@tonic-gate _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp) 1877c478bd9Sstevel@tonic-gate const char *domain; 1887c478bd9Sstevel@tonic-gate const char *map; 1897c478bd9Sstevel@tonic-gate const char *key; 1907c478bd9Sstevel@tonic-gate char **valp; 1917c478bd9Sstevel@tonic-gate int *vallenp; 1927c478bd9Sstevel@tonic-gate int *ypstatusp; 1937c478bd9Sstevel@tonic-gate { 1947c478bd9Sstevel@tonic-gate int ypstatus; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 1977c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask; 1987c478bd9Sstevel@tonic-gate 199cb5caa98Sdjl (void) sigfillset(&newmask); 2007257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 2017257d1b4Sraf (void) mutex_lock(&one_lane); 2027c478bd9Sstevel@tonic-gate #endif 2037c478bd9Sstevel@tonic-gate ypstatus = __yp_match_rsvdport_cflookup((grrr)domain, (grrr)map, 2047c478bd9Sstevel@tonic-gate (grrr)key, strlen(key), valp, vallenp, 0); 2057c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 2067257d1b4Sraf (void) mutex_unlock(&one_lane); 2077257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 2087c478bd9Sstevel@tonic-gate #endif 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (ypstatusp != 0) { 2117c478bd9Sstevel@tonic-gate *ypstatusp = ypstatus; 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate return (switch_err(ypstatus, 1)); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate nss_status_t 2177c478bd9Sstevel@tonic-gate _nss_nis_lookup(be, args, netdb, map, key, ypstatusp) 2187c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 2197c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 2207c478bd9Sstevel@tonic-gate int netdb; 2217c478bd9Sstevel@tonic-gate const char *map; 2227c478bd9Sstevel@tonic-gate const char *key; 2237c478bd9Sstevel@tonic-gate int *ypstatusp; 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate nss_status_t res; 2267c478bd9Sstevel@tonic-gate int vallen; 2277c478bd9Sstevel@tonic-gate char *val; 2287c478bd9Sstevel@tonic-gate char *free_ptr; 2297c478bd9Sstevel@tonic-gate int parsestat; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate if ((res = _nss_nis_ypmatch(be->domain, map, key, &val, &vallen, 2327c478bd9Sstevel@tonic-gate ypstatusp)) != NSS_SUCCESS) { 2337c478bd9Sstevel@tonic-gate return (res); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 236*2b4a7802SBaban Kenkre parsestat = NSS_STR_PARSE_SUCCESS; 237*2b4a7802SBaban Kenkre if (strcmp(map, "passwd.byname") == 0 || 238*2b4a7802SBaban Kenkre strcmp(map, "passwd.byuid") == 0) { 239*2b4a7802SBaban Kenkre parsestat = validate_passwd_ids(&val, &vallen, 1); 240*2b4a7802SBaban Kenkre } else if (strcmp(map, "group.byname") == 0) 241*2b4a7802SBaban Kenkre parsestat = validate_group_ids(&val, &vallen, 1); 242*2b4a7802SBaban Kenkre if (parsestat != NSS_STR_PARSE_SUCCESS) { 243*2b4a7802SBaban Kenkre free(val); 244*2b4a7802SBaban Kenkre return (NSS_NOTFOUND); 245*2b4a7802SBaban Kenkre } 246*2b4a7802SBaban Kenkre 2477c478bd9Sstevel@tonic-gate free_ptr = val; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (netdb) { 2507c478bd9Sstevel@tonic-gate massage_netdb((const char **)&val, &vallen); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 253cb5caa98Sdjl args->returnval = NULL; 254cb5caa98Sdjl args->returnlen = 0; 2557c478bd9Sstevel@tonic-gate parsestat = (*args->str2ent)(val, vallen, 2567c478bd9Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 2577c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 2587c478bd9Sstevel@tonic-gate args->returnval = args->buf.result; 259cb5caa98Sdjl args->returnlen = vallen; 2607c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 2617c478bd9Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 2627c478bd9Sstevel@tonic-gate args->erange = 1; 2637c478bd9Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 2647c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 2657c478bd9Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate free(free_ptr); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate return (res); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate nss_status_t 2737c478bd9Sstevel@tonic-gate _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp) 2747c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 2757c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 2767c478bd9Sstevel@tonic-gate int netdb; 2777c478bd9Sstevel@tonic-gate const char *map; 2787c478bd9Sstevel@tonic-gate const char *key; 2797c478bd9Sstevel@tonic-gate int *ypstatusp; 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate nss_status_t res; 2827c478bd9Sstevel@tonic-gate int vallen; 2837c478bd9Sstevel@tonic-gate char *val; 2847c478bd9Sstevel@tonic-gate char *free_ptr; 2857c478bd9Sstevel@tonic-gate int parsestat; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if ((res = _nss_nis_ypmatch_rsvdport(be->domain, map, key, &val, 2887c478bd9Sstevel@tonic-gate &vallen, ypstatusp)) != NSS_SUCCESS) { 2897c478bd9Sstevel@tonic-gate return (res); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate free_ptr = val; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate if (netdb) { 2957c478bd9Sstevel@tonic-gate massage_netdb((const char **)&val, &vallen); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 298cb5caa98Sdjl args->returnval = NULL; 299cb5caa98Sdjl args->returnlen = 0; 3007c478bd9Sstevel@tonic-gate parsestat = (*args->str2ent)(val, vallen, 3017c478bd9Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 3027c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 3037c478bd9Sstevel@tonic-gate args->returnval = args->buf.result; 304cb5caa98Sdjl args->returnlen = vallen; 3057c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 3067c478bd9Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 3077c478bd9Sstevel@tonic-gate args->erange = 1; 3087c478bd9Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 3097c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 3107c478bd9Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate free(free_ptr); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate return (res); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate static nss_status_t 3187c478bd9Sstevel@tonic-gate do_getent(be, args, netdb) 3197c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 3207c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 3217c478bd9Sstevel@tonic-gate int netdb; 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate nss_status_t res; 3247c478bd9Sstevel@tonic-gate int ypstatus; 3257c478bd9Sstevel@tonic-gate int outkeylen, outvallen; 3267c478bd9Sstevel@tonic-gate char *outkey, *outval; 3277c478bd9Sstevel@tonic-gate char *free_ptr; 3287c478bd9Sstevel@tonic-gate int parsestat; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 3317c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask; 3327c478bd9Sstevel@tonic-gate 333cb5caa98Sdjl (void) sigfillset(&newmask); 3347257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 3357257d1b4Sraf (void) mutex_lock(&one_lane); 3367c478bd9Sstevel@tonic-gate #endif 3377c478bd9Sstevel@tonic-gate if (be->enum_key == 0) { 3387c478bd9Sstevel@tonic-gate ypstatus = __yp_first_cflookup((grrr)be->domain, 3397c478bd9Sstevel@tonic-gate (grrr)be->enum_map, &outkey, 3407c478bd9Sstevel@tonic-gate &outkeylen, &outval, 3417c478bd9Sstevel@tonic-gate &outvallen, 0); 3427c478bd9Sstevel@tonic-gate } else { 3437c478bd9Sstevel@tonic-gate ypstatus = __yp_next_cflookup((grrr)be->domain, 3447c478bd9Sstevel@tonic-gate (grrr)be->enum_map, be->enum_key, 3457c478bd9Sstevel@tonic-gate be->enum_keylen, &outkey, 3467c478bd9Sstevel@tonic-gate &outkeylen, &outval, 3477c478bd9Sstevel@tonic-gate &outvallen, 0); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 3507257d1b4Sraf (void) mutex_unlock(&one_lane); 3517257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 3527c478bd9Sstevel@tonic-gate #endif 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if ((res = switch_err(ypstatus, 0)) != NSS_SUCCESS) { 3557c478bd9Sstevel@tonic-gate return (res); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate free_ptr = outval; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (netdb) { 3617c478bd9Sstevel@tonic-gate massage_netdb((const char **)&outval, &outvallen); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 364cb5caa98Sdjl args->returnval = NULL; 365cb5caa98Sdjl args->returnlen = 0; 3667c478bd9Sstevel@tonic-gate parsestat = (*args->str2ent)(outval, outvallen, 3677c478bd9Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 3687c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 3697c478bd9Sstevel@tonic-gate args->returnval = args->buf.result; 370cb5caa98Sdjl args->returnlen = outvallen; 3717c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 3727c478bd9Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 3737c478bd9Sstevel@tonic-gate args->erange = 1; 3747c478bd9Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 3757c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 3767c478bd9Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate free(free_ptr); 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate if (be->enum_key != 0) { 3817c478bd9Sstevel@tonic-gate free(be->enum_key); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate be->enum_key = outkey; 3847c478bd9Sstevel@tonic-gate be->enum_keylen = outkeylen; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate return (res); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate nss_status_t 3907c478bd9Sstevel@tonic-gate _nss_nis_getent_rigid(be, args) 3917c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 3927c478bd9Sstevel@tonic-gate void *args; 3937c478bd9Sstevel@tonic-gate { 3947c478bd9Sstevel@tonic-gate return (do_getent(be, (nss_XbyY_args_t *)args, 0)); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate nss_status_t 3987c478bd9Sstevel@tonic-gate _nss_nis_getent_netdb(be, args) 3997c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 4007c478bd9Sstevel@tonic-gate void *args; 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate return (do_getent(be, (nss_XbyY_args_t *)args, 1)); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate struct cb_data { 4077c478bd9Sstevel@tonic-gate void *args; 4087c478bd9Sstevel@tonic-gate const char *filter; 4097c478bd9Sstevel@tonic-gate nis_do_all_func_t func; 4107c478bd9Sstevel@tonic-gate nss_status_t result; 4117c478bd9Sstevel@tonic-gate }; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate enum { ITER_NEXT = 0, ITER_STOP = 1 }; /* Should be in <rpcsvc/ypclnt.h> */ 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4167c478bd9Sstevel@tonic-gate static int 4177c478bd9Sstevel@tonic-gate do_cback(instatus, inkey, inkeylen, inval, invallen, indata) 4187c478bd9Sstevel@tonic-gate int instatus; 4197c478bd9Sstevel@tonic-gate const char *inkey; 4207c478bd9Sstevel@tonic-gate int inkeylen; 4217c478bd9Sstevel@tonic-gate const char *inval; 4227c478bd9Sstevel@tonic-gate int invallen; 4237c478bd9Sstevel@tonic-gate struct cb_data *indata; 4247c478bd9Sstevel@tonic-gate { 4257c478bd9Sstevel@tonic-gate nss_status_t res; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if (instatus != YP_TRUE) { 4287c478bd9Sstevel@tonic-gate return (ITER_NEXT); /* yp_all may decide otherwise... */ 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if (indata->filter != 0 && strstr(inval, indata->filter) == 0) { 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * Optimization: if the entry doesn't contain the filter 4347c478bd9Sstevel@tonic-gate * string then it can't be the entry we want, so don't 4357c478bd9Sstevel@tonic-gate * bother looking more closely at it. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate return (ITER_NEXT); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate res = (*indata->func)(inval, invallen, indata->args); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate if (res == NSS_NOTFOUND) { 4437c478bd9Sstevel@tonic-gate return (ITER_NEXT); 4447c478bd9Sstevel@tonic-gate } else { 4457c478bd9Sstevel@tonic-gate indata->result = res; 4467c478bd9Sstevel@tonic-gate return (ITER_STOP); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate nss_status_t 4517c478bd9Sstevel@tonic-gate _nss_nis_do_all(be, args, filter, func) 4527c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 4537c478bd9Sstevel@tonic-gate void *args; 4547c478bd9Sstevel@tonic-gate const char *filter; 4557c478bd9Sstevel@tonic-gate nis_do_all_func_t func; 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate int ypall_status; 4587c478bd9Sstevel@tonic-gate struct cb_data data; 4597c478bd9Sstevel@tonic-gate struct ypall_callback cback; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate data.args = args; 4627c478bd9Sstevel@tonic-gate data.filter = filter; 4637c478bd9Sstevel@tonic-gate data.func = func; 4647c478bd9Sstevel@tonic-gate data.result = NSS_NOTFOUND; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate cback.foreach = do_cback; 4677c478bd9Sstevel@tonic-gate cback.data = (char *)&data; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 4707c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask; 4717c478bd9Sstevel@tonic-gate 472cb5caa98Sdjl (void) sigfillset(&newmask); 4737257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 4747257d1b4Sraf (void) mutex_lock(&one_lane); 4757c478bd9Sstevel@tonic-gate #endif 4767c478bd9Sstevel@tonic-gate ypall_status = __yp_all_cflookup((grrr)be->domain, 4777c478bd9Sstevel@tonic-gate (grrr) be->enum_map, &cback, 0); 4787c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 4797257d1b4Sraf (void) mutex_unlock(&one_lane); 4807257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 4817c478bd9Sstevel@tonic-gate #endif 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate switch (ypall_status) { 4847c478bd9Sstevel@tonic-gate case 0: 4857c478bd9Sstevel@tonic-gate return (data.result); 4867c478bd9Sstevel@tonic-gate case YPERR_DOMAIN: 4877c478bd9Sstevel@tonic-gate case YPERR_YPSERV: 4887c478bd9Sstevel@tonic-gate case YPERR_BUSY: /* Probably never get this, but... */ 4897c478bd9Sstevel@tonic-gate return (NSS_TRYAGAIN); 4907c478bd9Sstevel@tonic-gate default: 4917c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate struct XbyY_data { 4967c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 4977c478bd9Sstevel@tonic-gate nis_XY_check_func func; 4987c478bd9Sstevel@tonic-gate int netdb; 4997c478bd9Sstevel@tonic-gate }; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate static nss_status_t 5027c478bd9Sstevel@tonic-gate XbyY_iterator(instr, instr_len, a) 5037c478bd9Sstevel@tonic-gate const char *instr; 5047c478bd9Sstevel@tonic-gate int instr_len; 5057c478bd9Sstevel@tonic-gate void *a; 5067c478bd9Sstevel@tonic-gate { 5077c478bd9Sstevel@tonic-gate struct XbyY_data *xydata = (struct XbyY_data *)a; 5087c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args = xydata->args; 5097c478bd9Sstevel@tonic-gate nss_status_t res; 5107c478bd9Sstevel@tonic-gate int parsestat; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (xydata->netdb) { 5137c478bd9Sstevel@tonic-gate massage_netdb(&instr, &instr_len); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 516cb5caa98Sdjl args->returnval = NULL; 517cb5caa98Sdjl args->returnlen = 0; 5187c478bd9Sstevel@tonic-gate parsestat = (*args->str2ent)(instr, instr_len, 5197c478bd9Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 5207c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 5217c478bd9Sstevel@tonic-gate args->returnval = args->buf.result; 5227c478bd9Sstevel@tonic-gate if ((*xydata->func)(args)) { 5237c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 524cb5caa98Sdjl args->returnlen = instr_len; 5257c478bd9Sstevel@tonic-gate } else { 5267c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 5277c478bd9Sstevel@tonic-gate args->returnval = 0; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * If we got here because (*str2ent)() found that the buffer 5327c478bd9Sstevel@tonic-gate * wasn't big enough, maybe we should quit and return erange. 5337c478bd9Sstevel@tonic-gate * Instead we'll keep looking and eventually return "not 5347c478bd9Sstevel@tonic-gate * found" -- it's a bug, but not an earth-shattering one. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate args->erange = 1; /* <== Is this a good idea? */ 5377c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 5387c478bd9Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate return (res); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate nss_status_t 5447c478bd9Sstevel@tonic-gate _nss_nis_XY_all(be, args, netdb, filter, func) 5457c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 5467c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 5477c478bd9Sstevel@tonic-gate int netdb; 5487c478bd9Sstevel@tonic-gate const char *filter; 5497c478bd9Sstevel@tonic-gate nis_XY_check_func func; 5507c478bd9Sstevel@tonic-gate { 5517c478bd9Sstevel@tonic-gate struct XbyY_data data; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate data.args = args; 5547c478bd9Sstevel@tonic-gate data.func = func; 5557c478bd9Sstevel@tonic-gate data.netdb = netdb; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate return (_nss_nis_do_all(be, &data, filter, XbyY_iterator)); 5587c478bd9Sstevel@tonic-gate /* Now how many levels of callbacks was that? */ 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5637c478bd9Sstevel@tonic-gate nss_status_t 5647c478bd9Sstevel@tonic-gate _nss_nis_destr(be, dummy) 5657c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 5667c478bd9Sstevel@tonic-gate void *dummy; 5677c478bd9Sstevel@tonic-gate { 5687c478bd9Sstevel@tonic-gate if (be != 0) { 5697c478bd9Sstevel@tonic-gate /* === Should change to invoke ops[ENDENT] ? */ 570cb5caa98Sdjl (void) _nss_nis_endent(be, 0); 5717c478bd9Sstevel@tonic-gate free(be); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); /* In case anyone is dumb enough to check */ 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* We want to lock this even if the YP routines are MT-safe */ 5777c478bd9Sstevel@tonic-gate static mutex_t yp_domain_lock = DEFAULTMUTEX; 5787c478bd9Sstevel@tonic-gate static char *yp_domain; 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate const char * 5817c478bd9Sstevel@tonic-gate _nss_nis_domain() 5827c478bd9Sstevel@tonic-gate { 5837c478bd9Sstevel@tonic-gate char *domain; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * This much locking is probably more "by the book" than necessary... 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask; 5897c478bd9Sstevel@tonic-gate 590cb5caa98Sdjl (void) sigfillset(&newmask); 5917257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 5927257d1b4Sraf (void) mutex_lock(&yp_domain_lock); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate if ((domain = yp_domain) == 0) { 5957c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 5967257d1b4Sraf (void) mutex_lock(&one_lane); 5977c478bd9Sstevel@tonic-gate #endif 5987c478bd9Sstevel@tonic-gate if (yp_get_default_domain(&yp_domain) == 0) { 5997c478bd9Sstevel@tonic-gate domain = yp_domain; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate #if MT_UNSAFE_YP 6027257d1b4Sraf (void) mutex_unlock(&one_lane); 6037c478bd9Sstevel@tonic-gate #endif 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067257d1b4Sraf (void) mutex_unlock(&yp_domain_lock); 6077257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate return (domain); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate nss_backend_t * 6137c478bd9Sstevel@tonic-gate _nss_nis_constr(ops, n_ops, enum_map) 6147c478bd9Sstevel@tonic-gate nis_backend_op_t ops[]; 6157c478bd9Sstevel@tonic-gate int n_ops; 6167c478bd9Sstevel@tonic-gate const char *enum_map; 6177c478bd9Sstevel@tonic-gate { 6187c478bd9Sstevel@tonic-gate const char *domain; 6197c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if ((domain = _nss_nis_domain()) == 0 || 6227c478bd9Sstevel@tonic-gate (be = (nis_backend_ptr_t)malloc(sizeof (*be))) == 0) { 6237c478bd9Sstevel@tonic-gate return (0); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate be->ops = ops; 6267c478bd9Sstevel@tonic-gate be->n_ops = n_ops; 6277c478bd9Sstevel@tonic-gate be->domain = domain; 6287c478bd9Sstevel@tonic-gate be->enum_map = enum_map; /* Don't strdup, assume valid forever */ 6297c478bd9Sstevel@tonic-gate be->enum_key = 0; 6307c478bd9Sstevel@tonic-gate be->enum_keylen = 0; 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate return ((nss_backend_t *)be); 6337c478bd9Sstevel@tonic-gate } 634cb5caa98Sdjl 635cb5caa98Sdjl /* 636cb5caa98Sdjl * This routine is used to parse lines of the form: 637cb5caa98Sdjl * name number aliases 638cb5caa98Sdjl * It returns 1 if the key in argp matches any one of the 639cb5caa98Sdjl * names in the line, otherwise 0 640cb5caa98Sdjl * Used by rpc 641cb5caa98Sdjl */ 642cb5caa98Sdjl int 643cb5caa98Sdjl _nss_nis_check_name_aliases(nss_XbyY_args_t *argp, const char *line, 644cb5caa98Sdjl int linelen) 645cb5caa98Sdjl { 646cb5caa98Sdjl const char *limit, *linep, *keyp; 647cb5caa98Sdjl 648cb5caa98Sdjl linep = line; 649cb5caa98Sdjl limit = line + linelen; 650cb5caa98Sdjl keyp = argp->key.name; 651cb5caa98Sdjl 652cb5caa98Sdjl /* compare name */ 653cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 654cb5caa98Sdjl keyp++; 655cb5caa98Sdjl linep++; 656cb5caa98Sdjl } 657cb5caa98Sdjl if (*keyp == '\0' && linep < limit && isspace(*linep)) 658cb5caa98Sdjl return (1); 659cb5caa98Sdjl /* skip remainder of the name, if any */ 660cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 661cb5caa98Sdjl linep++; 662cb5caa98Sdjl /* skip the delimiting spaces */ 663cb5caa98Sdjl while (linep < limit && isspace(*linep)) 664cb5caa98Sdjl linep++; 665cb5caa98Sdjl /* compare with the aliases */ 666cb5caa98Sdjl while (linep < limit) { 667cb5caa98Sdjl /* 668cb5caa98Sdjl * 1st pass: skip number 669cb5caa98Sdjl * Other passes: skip remainder of the alias name, if any 670cb5caa98Sdjl */ 671cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 672cb5caa98Sdjl linep++; 673cb5caa98Sdjl /* skip the delimiting spaces */ 674cb5caa98Sdjl while (linep < limit && isspace(*linep)) 675cb5caa98Sdjl linep++; 676cb5caa98Sdjl /* compare with the alias name */ 677cb5caa98Sdjl keyp = argp->key.name; 678cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 679cb5caa98Sdjl *keyp == *linep) { 680cb5caa98Sdjl keyp++; 681cb5caa98Sdjl linep++; 682cb5caa98Sdjl } 683cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 684cb5caa98Sdjl return (1); 685cb5caa98Sdjl } 686cb5caa98Sdjl return (0); 687cb5caa98Sdjl } 688