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 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * 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 */ 217c478bd9Sstevel@tonic-gate /* 22*2b4a7802SBaban Kenkre * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate * Common code and structures used by name-service-switch "compat" backends. 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * Most of the code in the "compat" backend is a perverted form of code from 287c478bd9Sstevel@tonic-gate * the "files" backend; this file is no exception. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <ctype.h> 357c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 367c478bd9Sstevel@tonic-gate #include <user_attr.h> 37cb5caa98Sdjl #include <pwd.h> 38cb5caa98Sdjl #include <shadow.h> 39cb5caa98Sdjl #include <grp.h> 40cb5caa98Sdjl #include <unistd.h> /* for GF_PATH */ 41cb5caa98Sdjl #include <dlfcn.h> 427c478bd9Sstevel@tonic-gate #include "compat_common.h" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* 457c478bd9Sstevel@tonic-gate * This should be in a header. 467c478bd9Sstevel@tonic-gate */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate extern int yp_get_default_domain(char **domain); 497c478bd9Sstevel@tonic-gate 50cb5caa98Sdjl /* from libc */ 51cb5caa98Sdjl extern int str2passwd(const char *instr, int lenstr, void *ent, 52cb5caa98Sdjl char *buffer, int buflen); 53cb5caa98Sdjl extern int str2spwd(const char *instr, int lenstr, void *ent, 54cb5caa98Sdjl char *buffer, int buflen); 55cb5caa98Sdjl extern int str2group(const char *instr, int lenstr, void *ent, 56cb5caa98Sdjl char *buffer, int buflen); 57cb5caa98Sdjl 58cb5caa98Sdjl /* from libnsl */ 59cb5caa98Sdjl extern char *_strtok_escape(char *, char *, char **); 60cb5caa98Sdjl 61cb5caa98Sdjl /* 62cb5caa98Sdjl * str2auuser_s and str2userattr_s are very simple version 63cb5caa98Sdjl * of the str2auuser() and str2userattr() that can be found in 64cb5caa98Sdjl * libnsl. They only copy the user name into the userstr_t 65cb5caa98Sdjl * or au_user_str_t structure (so check on user name can be 66cb5caa98Sdjl * performed). 67cb5caa98Sdjl */ 68cb5caa98Sdjl static int 69cb5caa98Sdjl str2auuser_s( 70cb5caa98Sdjl const char *instr, 71cb5caa98Sdjl int lenstr, 72cb5caa98Sdjl void *ent, 73cb5caa98Sdjl char *buffer, 74cb5caa98Sdjl int buflen) 75cb5caa98Sdjl { 76cb5caa98Sdjl char *last = NULL; 77cb5caa98Sdjl char *sep = KV_TOKEN_DELIMIT; 78cb5caa98Sdjl au_user_str_t *au_user = (au_user_str_t *)ent; 79cb5caa98Sdjl 80cb5caa98Sdjl if (lenstr >= buflen) 81cb5caa98Sdjl return (NSS_STR_PARSE_ERANGE); 82cb5caa98Sdjl (void) strncpy(buffer, instr, buflen); 83cb5caa98Sdjl au_user->au_name = _strtok_escape(buffer, sep, &last); 84cb5caa98Sdjl return (0); 85cb5caa98Sdjl } 86cb5caa98Sdjl 87cb5caa98Sdjl static int 88cb5caa98Sdjl str2userattr_s( 89cb5caa98Sdjl const char *instr, 90cb5caa98Sdjl int lenstr, 91cb5caa98Sdjl void *ent, 92cb5caa98Sdjl char *buffer, 93cb5caa98Sdjl int buflen) 94cb5caa98Sdjl { 95cb5caa98Sdjl char *last = NULL; 96cb5caa98Sdjl char *sep = KV_TOKEN_DELIMIT; 97cb5caa98Sdjl userstr_t *user = (userstr_t *)ent; 98cb5caa98Sdjl 99cb5caa98Sdjl if (lenstr >= buflen) 100cb5caa98Sdjl return (NSS_STR_PARSE_ERANGE); 101cb5caa98Sdjl (void) strncpy(buffer, instr, buflen); 102cb5caa98Sdjl user->name = _strtok_escape(buffer, sep, &last); 103cb5caa98Sdjl return (0); 104cb5caa98Sdjl } 105cb5caa98Sdjl 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * Routines to manage list of "-" users for get{pw, sp, gr}ent(). Current 1087c478bd9Sstevel@tonic-gate * implementation is completely moronic; we use a linked list. But then 1097c478bd9Sstevel@tonic-gate * that's what it's always done in 4.x... 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate struct setofstrings { 1137c478bd9Sstevel@tonic-gate char *name; 1147c478bd9Sstevel@tonic-gate struct setofstrings *next; 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * === Should get smart and malloc the string and pointer as one 1177c478bd9Sstevel@tonic-gate * object rather than two. 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate }; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate static void 1227c478bd9Sstevel@tonic-gate strset_free(ssp) 1237c478bd9Sstevel@tonic-gate strset_t *ssp; 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate strset_t cur, nxt; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate for (cur = *ssp; cur != 0; cur = nxt) { 1287c478bd9Sstevel@tonic-gate nxt = cur->next; 1297c478bd9Sstevel@tonic-gate free(cur->name); 1307c478bd9Sstevel@tonic-gate free(cur); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate *ssp = 0; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate static boolean_t 1367c478bd9Sstevel@tonic-gate strset_add(ssp, nam) 1377c478bd9Sstevel@tonic-gate strset_t *ssp; 1387c478bd9Sstevel@tonic-gate const char *nam; 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate strset_t new; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (0 == (new = (strset_t)malloc(sizeof (*new)))) { 1437c478bd9Sstevel@tonic-gate return (B_FALSE); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate if (0 == (new->name = malloc(strlen(nam) + 1))) { 1467c478bd9Sstevel@tonic-gate free(new); 1477c478bd9Sstevel@tonic-gate return (B_FALSE); 1487c478bd9Sstevel@tonic-gate } 149cb5caa98Sdjl (void) strcpy(new->name, nam); 1507c478bd9Sstevel@tonic-gate new->next = *ssp; 1517c478bd9Sstevel@tonic-gate *ssp = new; 1527c478bd9Sstevel@tonic-gate return (B_TRUE); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate static boolean_t 1567c478bd9Sstevel@tonic-gate strset_in(ssp, nam) 1577c478bd9Sstevel@tonic-gate const strset_t *ssp; 1587c478bd9Sstevel@tonic-gate const char *nam; 1597c478bd9Sstevel@tonic-gate { 1607c478bd9Sstevel@tonic-gate strset_t cur; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate for (cur = *ssp; cur != 0; cur = cur->next) { 1637c478bd9Sstevel@tonic-gate if (strcmp(cur->name, nam) == 0) { 1647c478bd9Sstevel@tonic-gate return (B_TRUE); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate return (B_FALSE); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * Lookup and enumeration routines for +@group and -@group. 1727c478bd9Sstevel@tonic-gate * 1737c478bd9Sstevel@tonic-gate * This code knows a lot more about lib/libc/port/gen/getnetgrent.c than 1747c478bd9Sstevel@tonic-gate * is really healthy. The set/get/end routines below duplicate code 1757c478bd9Sstevel@tonic-gate * from that file, but keep the state information per-backend-instance 1767c478bd9Sstevel@tonic-gate * instead of just per-process. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate extern void _nss_initf_netgroup(nss_db_params_t *); 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * Should really share the db_root in getnetgrent.c in order to get the 1827c478bd9Sstevel@tonic-gate * resource-management quotas right, but this will have to do. 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(netgr_db_root); 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static boolean_t 1877c478bd9Sstevel@tonic-gate netgr_in(compat_backend_ptr_t be, const char *group, const char *user) 1887c478bd9Sstevel@tonic-gate { 1897c478bd9Sstevel@tonic-gate if (be->yp_domain == 0) { 1907c478bd9Sstevel@tonic-gate if (yp_get_default_domain((char **)&be->yp_domain) != 0) { 1917c478bd9Sstevel@tonic-gate return (B_FALSE); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate return (innetgr(group, 0, user, be->yp_domain)); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate static void 1987c478bd9Sstevel@tonic-gate netgr_set(be, netgroup) 1997c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 2007c478bd9Sstevel@tonic-gate const char *netgroup; 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * ===> Need comment to explain that this first "if" is optimizing 2047c478bd9Sstevel@tonic-gate * for the same-netgroup-as-last-time case 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate if (be->getnetgrent_backend != 0 && 2077c478bd9Sstevel@tonic-gate NSS_INVOKE_DBOP(be->getnetgrent_backend, 2087c478bd9Sstevel@tonic-gate NSS_DBOP_SETENT, 2097c478bd9Sstevel@tonic-gate (void *) netgroup) != NSS_SUCCESS) { 2107c478bd9Sstevel@tonic-gate NSS_INVOKE_DBOP(be->getnetgrent_backend, NSS_DBOP_DESTRUCTOR, 2117c478bd9Sstevel@tonic-gate 0); 2127c478bd9Sstevel@tonic-gate be->getnetgrent_backend = 0; 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate if (be->getnetgrent_backend == 0) { 2157c478bd9Sstevel@tonic-gate struct nss_setnetgrent_args args; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate args.netgroup = netgroup; 2187c478bd9Sstevel@tonic-gate args.iterator = 0; 219cb5caa98Sdjl (void) nss_search(&netgr_db_root, _nss_initf_netgroup, 2207c478bd9Sstevel@tonic-gate NSS_DBOP_NETGROUP_SET, &args); 2217c478bd9Sstevel@tonic-gate be->getnetgrent_backend = args.iterator; 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate static boolean_t 2267c478bd9Sstevel@tonic-gate netgr_next_u(be, up) 2277c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 2287c478bd9Sstevel@tonic-gate char **up; 2297c478bd9Sstevel@tonic-gate { 2307c478bd9Sstevel@tonic-gate if (be->netgr_buffer == 0 && 2317c478bd9Sstevel@tonic-gate (be->netgr_buffer = malloc(NSS_BUFLEN_NETGROUP)) == 0) { 2327c478bd9Sstevel@tonic-gate /* Out of memory */ 2337c478bd9Sstevel@tonic-gate return (B_FALSE); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate do { 2377c478bd9Sstevel@tonic-gate struct nss_getnetgrent_args args; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate args.buffer = be->netgr_buffer; 2407c478bd9Sstevel@tonic-gate args.buflen = NSS_BUFLEN_NETGROUP; 2417c478bd9Sstevel@tonic-gate args.status = NSS_NETGR_NO; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (be->getnetgrent_backend != 0) { 2447c478bd9Sstevel@tonic-gate NSS_INVOKE_DBOP(be->getnetgrent_backend, 2457c478bd9Sstevel@tonic-gate NSS_DBOP_GETENT, &args); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate if (args.status == NSS_NETGR_FOUND) { 2497c478bd9Sstevel@tonic-gate *up = args.retp[NSS_NETGR_USER]; 2507c478bd9Sstevel@tonic-gate } else { 2517c478bd9Sstevel@tonic-gate return (B_FALSE); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate } while (*up == 0); 2547c478bd9Sstevel@tonic-gate return (B_TRUE); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate static void 2587c478bd9Sstevel@tonic-gate netgr_end(be) 2597c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 2607c478bd9Sstevel@tonic-gate { 2617c478bd9Sstevel@tonic-gate if (be->getnetgrent_backend != 0) { 2627c478bd9Sstevel@tonic-gate NSS_INVOKE_DBOP(be->getnetgrent_backend, 2637c478bd9Sstevel@tonic-gate NSS_DBOP_DESTRUCTOR, 0); 2647c478bd9Sstevel@tonic-gate be->getnetgrent_backend = 0; 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate if (be->netgr_buffer != 0) { 2677c478bd9Sstevel@tonic-gate free(be->netgr_buffer); 2687c478bd9Sstevel@tonic-gate be->netgr_buffer = 0; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate #define MAXFIELDS 9 /* Sufficient for passwd (7), shadow (9), group (4) */ 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate static nss_status_t 2767c478bd9Sstevel@tonic-gate do_merge(be, args, instr, linelen) 2777c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 2787c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 2797c478bd9Sstevel@tonic-gate const char *instr; 2807c478bd9Sstevel@tonic-gate int linelen; 2817c478bd9Sstevel@tonic-gate { 2827c478bd9Sstevel@tonic-gate char *fields[MAXFIELDS]; 2837c478bd9Sstevel@tonic-gate int i; 2847c478bd9Sstevel@tonic-gate int overrides; 2857c478bd9Sstevel@tonic-gate const char *p; 2867c478bd9Sstevel@tonic-gate const char *end = instr + linelen; 287cb5caa98Sdjl nss_status_t res = NSS_NOTFOUND; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * Potential optimization: only perform the field-splitting nonsense 2917c478bd9Sstevel@tonic-gate * once per input line (at present, "+" and "+@netgroup" entries 2927c478bd9Sstevel@tonic-gate * will cause us to do this multiple times in getent() requests). 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate for (i = 0; i < MAXFIELDS; i++) { 2967c478bd9Sstevel@tonic-gate fields[i] = 0; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate for (p = instr, overrides = 0, i = 0; /* no test */; i++) { 2997c478bd9Sstevel@tonic-gate const char *q = memchr(p, ':', end - p); 3007c478bd9Sstevel@tonic-gate const char *r = (q == 0) ? end : q; 3017c478bd9Sstevel@tonic-gate ssize_t len = r - p; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate if (len > 0) { 3047c478bd9Sstevel@tonic-gate char *s = malloc(len + 1); 3057c478bd9Sstevel@tonic-gate if (s == 0) { 3067c478bd9Sstevel@tonic-gate overrides = -1; /* Indicates "you lose" */ 3077c478bd9Sstevel@tonic-gate break; 3087c478bd9Sstevel@tonic-gate } 309cb5caa98Sdjl (void) memcpy(s, p, len); 3107c478bd9Sstevel@tonic-gate s[len] = '\0'; 3117c478bd9Sstevel@tonic-gate fields[i] = s; 3127c478bd9Sstevel@tonic-gate overrides++; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate if (q == 0) { 3157c478bd9Sstevel@tonic-gate /* End of line */ 3167c478bd9Sstevel@tonic-gate break; 3177c478bd9Sstevel@tonic-gate } else { 3187c478bd9Sstevel@tonic-gate /* Skip the colon at (*q) */ 3197c478bd9Sstevel@tonic-gate p = q + 1; 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate if (overrides == 1) { 323cb5caa98Sdjl /* 324cb5caa98Sdjl * return result here if /etc file format is requested 325cb5caa98Sdjl */ 326cb5caa98Sdjl if (be->return_string_data != 1) { 3277c478bd9Sstevel@tonic-gate /* No real overrides, return (*args) intact */ 3287c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 329cb5caa98Sdjl } else { 330cb5caa98Sdjl free(fields[0]); 331cb5caa98Sdjl fields[0] = NULL; 332cb5caa98Sdjl } 333cb5caa98Sdjl } 334cb5caa98Sdjl 335cb5caa98Sdjl if (overrides > 1 || be->return_string_data == 1) { 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * The zero'th field is always nonempty (+/-...), but at least 3387c478bd9Sstevel@tonic-gate * one other field was also nonempty, i.e. wants to override 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate switch ((*be->mergef)(be, args, (const char **)fields)) { 3417c478bd9Sstevel@tonic-gate case NSS_STR_PARSE_SUCCESS: 342cb5caa98Sdjl if (be->return_string_data != 1) 3437c478bd9Sstevel@tonic-gate args->returnval = args->buf.result; 344cb5caa98Sdjl else 345cb5caa98Sdjl args->returnval = args->buf.buffer; 3467c478bd9Sstevel@tonic-gate args->erange = 0; 3477c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 3487c478bd9Sstevel@tonic-gate break; 3497c478bd9Sstevel@tonic-gate case NSS_STR_PARSE_ERANGE: 3507c478bd9Sstevel@tonic-gate args->returnval = 0; 3517c478bd9Sstevel@tonic-gate args->erange = 1; 3527c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate case NSS_STR_PARSE_PARSE: 3557c478bd9Sstevel@tonic-gate args->returnval = 0; 3567c478bd9Sstevel@tonic-gate args->erange = 0; 3577c478bd9Sstevel@tonic-gate /* ===> Very likely the wrong thing to do... */ 3587c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 3597c478bd9Sstevel@tonic-gate break; 3607c478bd9Sstevel@tonic-gate } 361cb5caa98Sdjl } else if (res != NSS_SUCCESS) { 3627c478bd9Sstevel@tonic-gate args->returnval = 0; 3637c478bd9Sstevel@tonic-gate args->erange = 0; 3647c478bd9Sstevel@tonic-gate res = NSS_UNAVAIL; /* ==> Right? */ 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate for (i = 0; i < MAXFIELDS; i++) { 3687c478bd9Sstevel@tonic-gate if (fields[i] != 0) { 3697c478bd9Sstevel@tonic-gate free(fields[i]); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate return (res); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3777c478bd9Sstevel@tonic-gate nss_status_t 3787c478bd9Sstevel@tonic-gate _nss_compat_setent(be, dummy) 3797c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 3807c478bd9Sstevel@tonic-gate void *dummy; 3817c478bd9Sstevel@tonic-gate { 3827c478bd9Sstevel@tonic-gate if (be->f == 0) { 3837c478bd9Sstevel@tonic-gate if (be->filename == 0) { 3847c478bd9Sstevel@tonic-gate /* Backend isn't initialized properly? */ 3857c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 3867c478bd9Sstevel@tonic-gate } 387004388ebScasper if ((be->f = fopen(be->filename, "rF")) == 0) { 3887c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate } else { 391004388ebScasper rewind(be->f); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate strset_free(&be->minuses); 3947c478bd9Sstevel@tonic-gate /* ===> ??? nss_endent(be->db_rootp, be->db_initf, &be->db_context); */ 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate if ((strcmp(be->filename, USERATTR_FILENAME) == 0) || 3977c478bd9Sstevel@tonic-gate (strcmp(be->filename, AUDITUSER_FILENAME) == 0)) 3987c478bd9Sstevel@tonic-gate be->state = GETENT_ATTRDB; 3997c478bd9Sstevel@tonic-gate else 4007c478bd9Sstevel@tonic-gate be->state = GETENT_FILE; 4017c478bd9Sstevel@tonic-gate 402e37190e5Smichen be->return_string_data = 0; 403e37190e5Smichen 4047c478bd9Sstevel@tonic-gate /* ===> ?? netgroup stuff? */ 4057c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4097c478bd9Sstevel@tonic-gate nss_status_t 4107c478bd9Sstevel@tonic-gate _nss_compat_endent(be, dummy) 4117c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 4127c478bd9Sstevel@tonic-gate void *dummy; 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate if (be->f != 0) { 415cb5caa98Sdjl (void) fclose(be->f); 4167c478bd9Sstevel@tonic-gate be->f = 0; 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate if (be->buf != 0) { 4197c478bd9Sstevel@tonic-gate free(be->buf); 4207c478bd9Sstevel@tonic-gate be->buf = 0; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate nss_endent(be->db_rootp, be->db_initf, &be->db_context); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate be->state = GETENT_FILE; /* Probably superfluous but comforting */ 4257c478bd9Sstevel@tonic-gate strset_free(&be->minuses); 4267c478bd9Sstevel@tonic-gate netgr_end(be); 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate /* 4297c478bd9Sstevel@tonic-gate * Question: from the point of view of resource-freeing vs. time to 4307c478bd9Sstevel@tonic-gate * start up again, how much should we do in endent() and how much 4317c478bd9Sstevel@tonic-gate * in the destructor? 4327c478bd9Sstevel@tonic-gate */ 4337c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4377c478bd9Sstevel@tonic-gate nss_status_t 4387c478bd9Sstevel@tonic-gate _nss_compat_destr(be, dummy) 4397c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 4407c478bd9Sstevel@tonic-gate void *dummy; 4417c478bd9Sstevel@tonic-gate { 4427c478bd9Sstevel@tonic-gate if (be != 0) { 4437c478bd9Sstevel@tonic-gate if (be->f != 0) { 444cb5caa98Sdjl (void) _nss_compat_endent(be, 0); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate nss_delete(be->db_rootp); 4477c478bd9Sstevel@tonic-gate nss_delete(&netgr_db_root); 448ad0e80f7Smichen free(be->workarea); 4497c478bd9Sstevel@tonic-gate free(be); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); /* In case anyone is dumb enough to check */ 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate static int 4557c478bd9Sstevel@tonic-gate read_line(f, buffer, buflen) 456004388ebScasper FILE *f; 4577c478bd9Sstevel@tonic-gate char *buffer; 4587c478bd9Sstevel@tonic-gate int buflen; 4597c478bd9Sstevel@tonic-gate { 4607c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 4617c478bd9Sstevel@tonic-gate while (1) { 4627c478bd9Sstevel@tonic-gate int linelen; 4637c478bd9Sstevel@tonic-gate 464004388ebScasper if (fgets(buffer, buflen, f) == 0) { 4657c478bd9Sstevel@tonic-gate /* End of file */ 4667c478bd9Sstevel@tonic-gate return (-1); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate linelen = strlen(buffer); 4697c478bd9Sstevel@tonic-gate /* linelen >= 1 (since fgets didn't return 0) */ 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (buffer[linelen - 1] == '\n') { 4727c478bd9Sstevel@tonic-gate /* 4737c478bd9Sstevel@tonic-gate * ===> The code below that calls read_line() doesn't 4747c478bd9Sstevel@tonic-gate * play by the rules; it assumes in places that 4757c478bd9Sstevel@tonic-gate * the line is null-terminated. For now we'll 4767c478bd9Sstevel@tonic-gate * humour it. 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate buffer[--linelen] = '\0'; 4797c478bd9Sstevel@tonic-gate return (linelen); 4807c478bd9Sstevel@tonic-gate } 481004388ebScasper if (feof(f)) { 4827c478bd9Sstevel@tonic-gate /* Line is last line in file, and has no newline */ 4837c478bd9Sstevel@tonic-gate return (linelen); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate /* Line too long for buffer; toss it and loop for next line */ 4867c478bd9Sstevel@tonic-gate /* ===== should syslog() in cases where previous code did */ 487004388ebScasper while (fgets(buffer, buflen, f) != 0 && 4887c478bd9Sstevel@tonic-gate buffer[strlen(buffer) - 1] != '\n') { 4897c478bd9Sstevel@tonic-gate ; 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } 492cb5caa98Sdjl /*NOTREACHED*/ 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 495738d7c77Svk154806 static int 496738d7c77Svk154806 is_nss_lookup_by_name(int attrdb, nss_dbop_t op) 497738d7c77Svk154806 { 4987c478bd9Sstevel@tonic-gate int result = 0; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if ((attrdb != 0) && 5017c478bd9Sstevel@tonic-gate ((op == NSS_DBOP_AUDITUSER_BYNAME) || 5027c478bd9Sstevel@tonic-gate (op == NSS_DBOP_USERATTR_BYNAME))) { 5037c478bd9Sstevel@tonic-gate result = 1; 5047c478bd9Sstevel@tonic-gate } else if ((attrdb == 0) && 5057c478bd9Sstevel@tonic-gate ((op == NSS_DBOP_GROUP_BYNAME) || 5067c478bd9Sstevel@tonic-gate (op == NSS_DBOP_PASSWD_BYNAME) || 5077c478bd9Sstevel@tonic-gate (op == NSS_DBOP_SHADOW_BYNAME))) { 5087c478bd9Sstevel@tonic-gate result = 1; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate return (result); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5157c478bd9Sstevel@tonic-gate nss_status_t 5167c478bd9Sstevel@tonic-gate _attrdb_compat_XY_all(be, argp, netdb, check, op_num) 5177c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 5187c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp; 5197c478bd9Sstevel@tonic-gate int netdb; 5207c478bd9Sstevel@tonic-gate compat_XY_check_func check; 5217c478bd9Sstevel@tonic-gate nss_dbop_t op_num; 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate int parsestat; 5247c478bd9Sstevel@tonic-gate int (*func)(); 5257c478bd9Sstevel@tonic-gate const char *filter = argp->key.name; 5267c478bd9Sstevel@tonic-gate nss_status_t res; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate #ifdef DEBUG 5297c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[compat_common.c: _attrdb_compat_XY_all]\n"); 5307c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate if (be->buf == 0 && 5337c478bd9Sstevel@tonic-gate (be->buf = malloc(be->minbuf)) == 0) { 5347c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 5357c478bd9Sstevel@tonic-gate } 536cb5caa98Sdjl if (check != NULL) 537cb5caa98Sdjl if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) 5387c478bd9Sstevel@tonic-gate return (res); 539cb5caa98Sdjl 5407c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 5417c478bd9Sstevel@tonic-gate 542cb5caa98Sdjl /* 543cb5caa98Sdjl * assume a NULL buf.result pointer is an indication 544cb5caa98Sdjl * that the lookup result should be returned in /etc 545767b0abfSmichen * file format (if called from _nss_compat_getent(), 546767b0abfSmichen * be->return_string_data and argp->buf.result 547767b0abfSmichen * would be set already if argp->buf.result is NULL) 548cb5caa98Sdjl */ 549767b0abfSmichen if (check != NULL) { 550cb5caa98Sdjl if (argp->buf.result == NULL) { 551cb5caa98Sdjl be->return_string_data = 1; 552cb5caa98Sdjl 553cb5caa98Sdjl /* 554cb5caa98Sdjl * the code executed later needs the result struct 555cb5caa98Sdjl * as working area 556cb5caa98Sdjl */ 557ad0e80f7Smichen argp->buf.result = be->workarea; 558767b0abfSmichen } else 559e37190e5Smichen be->return_string_data = 0; 560e37190e5Smichen } 561cb5caa98Sdjl 562767b0abfSmichen /* 563767b0abfSmichen * use an alternate str2ent function if necessary 564767b0abfSmichen */ 565767b0abfSmichen if (be->return_string_data == 1) 566767b0abfSmichen func = be->str2ent_alt; 567767b0abfSmichen else 568767b0abfSmichen func = argp->str2ent; 569767b0abfSmichen 5707c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 5717c478bd9Sstevel@tonic-gate while (1) { 5727c478bd9Sstevel@tonic-gate int linelen; 5737c478bd9Sstevel@tonic-gate char *instr = be->buf; 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate if ((linelen = read_line(be->f, instr, be->minbuf)) < 0) { 5767c478bd9Sstevel@tonic-gate /* End of file */ 5777c478bd9Sstevel@tonic-gate argp->returnval = 0; 5787c478bd9Sstevel@tonic-gate argp->erange = 0; 5797c478bd9Sstevel@tonic-gate break; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate if (filter != 0 && strstr(instr, filter) == 0) { 5827c478bd9Sstevel@tonic-gate /* 5837c478bd9Sstevel@tonic-gate * Optimization: if the entry doesn't contain the 5847c478bd9Sstevel@tonic-gate * filter string then it can't be the entry we want, 5857c478bd9Sstevel@tonic-gate * so don't bother looking more closely at it. 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate continue; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate if (netdb) { 5907c478bd9Sstevel@tonic-gate char *first; 5917c478bd9Sstevel@tonic-gate char *last; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) { 5947c478bd9Sstevel@tonic-gate last = instr + linelen; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate *last-- = '\0'; /* Nuke '\n' or #comment */ 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* 5997c478bd9Sstevel@tonic-gate * Skip leading whitespace. Normally there isn't 6007c478bd9Sstevel@tonic-gate * any, so it's not worth calling strspn(). 6017c478bd9Sstevel@tonic-gate */ 6027c478bd9Sstevel@tonic-gate for (first = instr; isspace(*first); first++) { 6037c478bd9Sstevel@tonic-gate ; 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate if (*first == '\0') { 6067c478bd9Sstevel@tonic-gate continue; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate * Found something non-blank on the line. Skip back 6107c478bd9Sstevel@tonic-gate * over any trailing whitespace; since we know 6117c478bd9Sstevel@tonic-gate * there's non-whitespace earlier in the line, 6127c478bd9Sstevel@tonic-gate * checking for termination is easy. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate while (isspace(*last)) { 6157c478bd9Sstevel@tonic-gate --last; 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate linelen = last - first + 1; 6187c478bd9Sstevel@tonic-gate if (first != instr) { 6197c478bd9Sstevel@tonic-gate instr = first; 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate argp->returnval = 0; 6237c478bd9Sstevel@tonic-gate parsestat = (*func)(instr, linelen, argp->buf.result, 6247c478bd9Sstevel@tonic-gate argp->buf.buffer, argp->buf.buflen); 6257c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 6267c478bd9Sstevel@tonic-gate argp->returnval = argp->buf.result; 6277c478bd9Sstevel@tonic-gate if (check == 0 || (*check)(argp)) { 628cb5caa98Sdjl int len; 629cb5caa98Sdjl 630cb5caa98Sdjl if (be->return_string_data != 1) { 631cb5caa98Sdjl res = NSS_SUCCESS; 632cb5caa98Sdjl break; 633cb5caa98Sdjl } 634cb5caa98Sdjl 635cb5caa98Sdjl /* copy string data to result buffer */ 636cb5caa98Sdjl argp->buf.result = NULL; 637cb5caa98Sdjl argp->returnval = argp->buf.buffer; 638cb5caa98Sdjl if ((len = strlcpy(argp->buf.buffer, instr, 639cb5caa98Sdjl argp->buf.buflen)) >= 640cb5caa98Sdjl argp->buf.buflen) { 641cb5caa98Sdjl argp->returnval = NULL; 642cb5caa98Sdjl res = NSS_NOTFOUND; 643cb5caa98Sdjl argp->erange = 1; 644cb5caa98Sdjl break; 645cb5caa98Sdjl } 646cb5caa98Sdjl 647cb5caa98Sdjl argp->returnlen = len; 6487c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 6497c478bd9Sstevel@tonic-gate break; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 652cb5caa98Sdjl res = NSS_NOTFOUND; 6537c478bd9Sstevel@tonic-gate argp->erange = 1; 6547c478bd9Sstevel@tonic-gate break; 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 6597c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 6607c478bd9Sstevel@tonic-gate */ 6617c478bd9Sstevel@tonic-gate if (check != 0 && !argp->stayopen) { 6627c478bd9Sstevel@tonic-gate (void) _nss_compat_endent(be, 0); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS) { 666cb5caa98Sdjl /* 667cb5caa98Sdjl * tell the nss_search() and nss_getent() below 668cb5caa98Sdjl * if the result should be returned in the /etc 669cb5caa98Sdjl * file format 670cb5caa98Sdjl */ 671cb5caa98Sdjl if (be->return_string_data == 1) 672cb5caa98Sdjl argp->buf.result = NULL; 673cb5caa98Sdjl 6747c478bd9Sstevel@tonic-gate if ((op_num == NSS_DBOP_USERATTR_BYNAME) || 6757c478bd9Sstevel@tonic-gate (op_num == NSS_DBOP_AUDITUSER_BYNAME)) { 6767c478bd9Sstevel@tonic-gate res = nss_search(be->db_rootp, 6777c478bd9Sstevel@tonic-gate be->db_initf, 6787c478bd9Sstevel@tonic-gate op_num, 6797c478bd9Sstevel@tonic-gate argp); 6807c478bd9Sstevel@tonic-gate } else { 6817c478bd9Sstevel@tonic-gate res = nss_getent(be->db_rootp, 6827c478bd9Sstevel@tonic-gate be->db_initf, &be->db_context, argp); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS) { 6857c478bd9Sstevel@tonic-gate argp->returnval = 0; 6867c478bd9Sstevel@tonic-gate argp->erange = 0; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate return (res); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 693*2b4a7802SBaban Kenkre static int 694*2b4a7802SBaban Kenkre validate_ids(compat_backend_ptr_t be, nss_XbyY_args_t *argp, 695*2b4a7802SBaban Kenkre char *line, int *linelenp, int buflen, int extra_chars) 696*2b4a7802SBaban Kenkre { 697*2b4a7802SBaban Kenkre if (be->return_string_data != 1) { 698*2b4a7802SBaban Kenkre struct passwd *p; 699*2b4a7802SBaban Kenkre struct group *g; 700*2b4a7802SBaban Kenkre /* 701*2b4a7802SBaban Kenkre * The data is already marshalled into 702*2b4a7802SBaban Kenkre * struct passwd or group. 703*2b4a7802SBaban Kenkre */ 704*2b4a7802SBaban Kenkre if (strcmp(be->filename, PASSWD) == 0) { 705*2b4a7802SBaban Kenkre p = (struct passwd *)argp->returnval; 706*2b4a7802SBaban Kenkre if (p->pw_uid > MAXUID) 707*2b4a7802SBaban Kenkre p->pw_uid = UID_NOBODY; 708*2b4a7802SBaban Kenkre if (p->pw_gid > MAXUID) 709*2b4a7802SBaban Kenkre p->pw_gid = GID_NOBODY; 710*2b4a7802SBaban Kenkre } else if (strcmp(be->filename, GF_PATH) == 0) { 711*2b4a7802SBaban Kenkre g = (struct group *)argp->returnval; 712*2b4a7802SBaban Kenkre if (g->gr_gid > MAXUID) 713*2b4a7802SBaban Kenkre g->gr_gid = GID_NOBODY; 714*2b4a7802SBaban Kenkre } 715*2b4a7802SBaban Kenkre return (NSS_STR_PARSE_SUCCESS); 716*2b4a7802SBaban Kenkre } 717*2b4a7802SBaban Kenkre 718*2b4a7802SBaban Kenkre /* 719*2b4a7802SBaban Kenkre * The data needs to be returned in string format therefore 720*2b4a7802SBaban Kenkre * validate the return string. 721*2b4a7802SBaban Kenkre */ 722*2b4a7802SBaban Kenkre if (strcmp(be->filename, PASSWD) == 0) 723*2b4a7802SBaban Kenkre return (validate_passwd_ids(line, linelenp, buflen, 724*2b4a7802SBaban Kenkre extra_chars)); 725*2b4a7802SBaban Kenkre else if (strcmp(be->filename, GF_PATH) == 0) 726*2b4a7802SBaban Kenkre return (validate_group_ids(line, linelenp, buflen, 727*2b4a7802SBaban Kenkre extra_chars)); 728*2b4a7802SBaban Kenkre return (NSS_STR_PARSE_SUCCESS); 729*2b4a7802SBaban Kenkre } 730*2b4a7802SBaban Kenkre 7317c478bd9Sstevel@tonic-gate nss_status_t 7327c478bd9Sstevel@tonic-gate _nss_compat_XY_all(be, args, check, op_num) 7337c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 7347c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 7357c478bd9Sstevel@tonic-gate compat_XY_check_func check; 7367c478bd9Sstevel@tonic-gate nss_dbop_t op_num; 7377c478bd9Sstevel@tonic-gate { 7387c478bd9Sstevel@tonic-gate nss_status_t res; 7397c478bd9Sstevel@tonic-gate int parsestat; 740cb5caa98Sdjl 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate if (be->buf == 0 && 7437c478bd9Sstevel@tonic-gate (be->buf = malloc(be->minbuf)) == 0) { 7447c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); /* really panic, malloc failed */ 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) { 7487c478bd9Sstevel@tonic-gate return (res); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 7527c478bd9Sstevel@tonic-gate 753cb5caa98Sdjl /* 754cb5caa98Sdjl * assume a NULL buf.result pointer is an indication 755cb5caa98Sdjl * that the lookup result should be returned in /etc 756cb5caa98Sdjl * file format 757cb5caa98Sdjl */ 758cb5caa98Sdjl if (args->buf.result == NULL) { 759cb5caa98Sdjl 760cb5caa98Sdjl be->return_string_data = 1; 761cb5caa98Sdjl 762cb5caa98Sdjl /* 763cb5caa98Sdjl * the code executed later needs the result struct 764cb5caa98Sdjl * as working area 765cb5caa98Sdjl */ 766ad0e80f7Smichen args->buf.result = be->workarea; 767cb5caa98Sdjl 768ad0e80f7Smichen be->str2ent_save = args->str2ent; 769ad0e80f7Smichen args->str2ent = be->str2ent_alt; 770e37190e5Smichen } else 771e37190e5Smichen be->return_string_data = 0; 772cb5caa98Sdjl 7737c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 7747c478bd9Sstevel@tonic-gate while (1) { 7757c478bd9Sstevel@tonic-gate int linelen; 7767c478bd9Sstevel@tonic-gate char *instr = be->buf; 7777c478bd9Sstevel@tonic-gate char *colon; 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate linelen = read_line(be->f, instr, be->minbuf); 7807c478bd9Sstevel@tonic-gate if (linelen < 0) { 7817c478bd9Sstevel@tonic-gate /* End of file */ 7827c478bd9Sstevel@tonic-gate args->returnval = 0; 7837c478bd9Sstevel@tonic-gate args->erange = 0; 7847c478bd9Sstevel@tonic-gate break; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate args->returnval = 0; /* reset for both types of entries */ 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate if (instr[0] != '+' && instr[0] != '-') { 7907c478bd9Sstevel@tonic-gate /* Simple, wholesome, God-fearing entry */ 7917c478bd9Sstevel@tonic-gate parsestat = (*args->str2ent)(instr, linelen, 7927c478bd9Sstevel@tonic-gate args->buf.result, 7937c478bd9Sstevel@tonic-gate args->buf.buffer, 7947c478bd9Sstevel@tonic-gate args->buf.buflen); 7957c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 7967c478bd9Sstevel@tonic-gate args->returnval = args->buf.result; 7977c478bd9Sstevel@tonic-gate if ((*check)(args) != 0) { 798cb5caa98Sdjl int len; 799*2b4a7802SBaban Kenkre 800*2b4a7802SBaban Kenkre parsestat = validate_ids(be, args, 801*2b4a7802SBaban Kenkre instr, &linelen, be->minbuf, 1); 802*2b4a7802SBaban Kenkre if (parsestat == 803*2b4a7802SBaban Kenkre NSS_STR_PARSE_ERANGE) { 804*2b4a7802SBaban Kenkre args->erange = 1; 805*2b4a7802SBaban Kenkre res = NSS_NOTFOUND; 806*2b4a7802SBaban Kenkre break; 807*2b4a7802SBaban Kenkre } else if (parsestat != 808*2b4a7802SBaban Kenkre NSS_STR_PARSE_SUCCESS) { 809*2b4a7802SBaban Kenkre continue; 810*2b4a7802SBaban Kenkre } 811*2b4a7802SBaban Kenkre 812cb5caa98Sdjl if (be->return_string_data != 1) { 8137c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 8147c478bd9Sstevel@tonic-gate break; 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate 817cb5caa98Sdjl /* 818cb5caa98Sdjl * copy string data to 819cb5caa98Sdjl * result buffer 820cb5caa98Sdjl */ 821cb5caa98Sdjl args->buf.result = NULL; 822ad0e80f7Smichen args->str2ent = be->str2ent_save; 823cb5caa98Sdjl if ((len = strlcpy(args->buf.buffer, 824cb5caa98Sdjl instr, args->buf.buflen)) >= 825cb5caa98Sdjl args->buf.buflen) 826cb5caa98Sdjl parsestat = 827cb5caa98Sdjl NSS_STR_PARSE_ERANGE; 828cb5caa98Sdjl else { 829cb5caa98Sdjl args->returnval = 830cb5caa98Sdjl args->buf.buffer; 831cb5caa98Sdjl args->returnlen = len; 832cb5caa98Sdjl res = NSS_SUCCESS; 833cb5caa98Sdjl break; 834cb5caa98Sdjl } 835cb5caa98Sdjl } else 836cb5caa98Sdjl continue; 837cb5caa98Sdjl } 838cb5caa98Sdjl 8397c478bd9Sstevel@tonic-gate /* ===> Check the Dani logic here... */ 8407c478bd9Sstevel@tonic-gate 841cb5caa98Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) { 8427c478bd9Sstevel@tonic-gate args->erange = 1; 8437c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 8447c478bd9Sstevel@tonic-gate break; 8457c478bd9Sstevel@tonic-gate /* should we just skip this one long line ? */ 8467c478bd9Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) */ 8477c478bd9Sstevel@tonic-gate /* don't care ! */ 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate /* ==> ?? */ continue; 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 852cb5caa98Sdjl 8537c478bd9Sstevel@tonic-gate /* 8547c478bd9Sstevel@tonic-gate * Process "+", "+name", "+@netgroup", "-name" or "-@netgroup" 8557c478bd9Sstevel@tonic-gate * 8567c478bd9Sstevel@tonic-gate * This code is optimized for lookups by name. 8577c478bd9Sstevel@tonic-gate * 8587c478bd9Sstevel@tonic-gate * For lookups by identifier search key cannot be matched with 8597c478bd9Sstevel@tonic-gate * the name of the "+" or "-" entry. So nss_search() is to be 8607c478bd9Sstevel@tonic-gate * called before extracting the name i.e. via (*be->getnamef)(). 8617c478bd9Sstevel@tonic-gate * 8627c478bd9Sstevel@tonic-gate * But for lookups by name, search key is compared with the name 8637c478bd9Sstevel@tonic-gate * of the "+" or "-" entry to acquire a match and thus 8647c478bd9Sstevel@tonic-gate * unnesessary calls to nss_search() is eliminated. Also for 8657c478bd9Sstevel@tonic-gate * matching "-" entries, calls to nss_search() is eliminated. 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate if ((colon = strchr(instr, ':')) != 0) { 8697c478bd9Sstevel@tonic-gate *colon = '\0'; /* terminate field to extract name */ 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (instr[1] == '@') { 8737c478bd9Sstevel@tonic-gate /* 8747c478bd9Sstevel@tonic-gate * Case 1: 8757c478bd9Sstevel@tonic-gate * The entry is of the form "+@netgroup" or 8767c478bd9Sstevel@tonic-gate * "-@netgroup". If we're performing a lookup by name, 8777c478bd9Sstevel@tonic-gate * we can simply extract the name from the search key 8787c478bd9Sstevel@tonic-gate * (i.e. args->key.name). If not, then we must call 8797c478bd9Sstevel@tonic-gate * nss_search() before extracting the name via the 8807c478bd9Sstevel@tonic-gate * get_XXname() function. i.e. (*be->getnamef)(args). 8817c478bd9Sstevel@tonic-gate */ 882738d7c77Svk154806 if (is_nss_lookup_by_name(0, op_num) != 0) { 8837c478bd9Sstevel@tonic-gate /* compare then search */ 8847c478bd9Sstevel@tonic-gate if (!be->permit_netgroups || 8857c478bd9Sstevel@tonic-gate !netgr_in(be, instr + 2, args->key.name)) 8867c478bd9Sstevel@tonic-gate continue; 8877c478bd9Sstevel@tonic-gate if (instr[0] == '+') { 8887c478bd9Sstevel@tonic-gate /* need to search for "+" entry */ 889cb5caa98Sdjl (void) nss_search(be->db_rootp, 890cb5caa98Sdjl be->db_initf, op_num, args); 8917c478bd9Sstevel@tonic-gate if (args->returnval == 0) 8927c478bd9Sstevel@tonic-gate continue; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate } else { 8957c478bd9Sstevel@tonic-gate /* search then compare */ 896cb5caa98Sdjl (void) nss_search(be->db_rootp, 897cb5caa98Sdjl be->db_initf, op_num, args); 8987c478bd9Sstevel@tonic-gate if (args->returnval == 0) 8997c478bd9Sstevel@tonic-gate continue; 9007c478bd9Sstevel@tonic-gate if (!be->permit_netgroups || 901738d7c77Svk154806 !netgr_in(be, instr + 2, 902738d7c77Svk154806 (*be->getnamef)(args))) 9037c478bd9Sstevel@tonic-gate continue; 9047c478bd9Sstevel@tonic-gate } 905738d7c77Svk154806 } else if (instr[1] == '\0') { 9067c478bd9Sstevel@tonic-gate /* 9077c478bd9Sstevel@tonic-gate * Case 2: 9087c478bd9Sstevel@tonic-gate * The entry is of the form "+" or "-". The former 9097c478bd9Sstevel@tonic-gate * allows all entries from name services. The latter 9107c478bd9Sstevel@tonic-gate * is illegal and ought to be ignored. 9117c478bd9Sstevel@tonic-gate */ 9127c478bd9Sstevel@tonic-gate if (instr[0] == '-') 9137c478bd9Sstevel@tonic-gate continue; 9147c478bd9Sstevel@tonic-gate /* need to search for "+" entry */ 915cb5caa98Sdjl (void) nss_search(be->db_rootp, be->db_initf, 916cb5caa98Sdjl op_num, args); 9177c478bd9Sstevel@tonic-gate if (args->returnval == 0) 9187c478bd9Sstevel@tonic-gate continue; 919738d7c77Svk154806 } else { 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * Case 3: 9227c478bd9Sstevel@tonic-gate * The entry is of the form "+name" or "-name". 9237c478bd9Sstevel@tonic-gate * If we're performing a lookup by name, we can simply 9247c478bd9Sstevel@tonic-gate * extract the name from the search key 9257c478bd9Sstevel@tonic-gate * (i.e. args->key.name). If not, then we must call 9267c478bd9Sstevel@tonic-gate * nss_search() before extracting the name via the 9277c478bd9Sstevel@tonic-gate * get_XXname() function. i.e. (*be->getnamef)(args). 9287c478bd9Sstevel@tonic-gate */ 929738d7c77Svk154806 if (is_nss_lookup_by_name(0, op_num) != 0) { 9307c478bd9Sstevel@tonic-gate /* compare then search */ 9317c478bd9Sstevel@tonic-gate if (strcmp(instr + 1, args->key.name) != 0) 9327c478bd9Sstevel@tonic-gate continue; 9337c478bd9Sstevel@tonic-gate if (instr[0] == '+') { 9347c478bd9Sstevel@tonic-gate /* need to search for "+" entry */ 935cb5caa98Sdjl (void) nss_search(be->db_rootp, 936cb5caa98Sdjl be->db_initf, op_num, args); 9377c478bd9Sstevel@tonic-gate if (args->returnval == 0) 9387c478bd9Sstevel@tonic-gate continue; 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate } else { 9417c478bd9Sstevel@tonic-gate /* search then compare */ 942cb5caa98Sdjl (void) nss_search(be->db_rootp, 943cb5caa98Sdjl be->db_initf, op_num, args); 9447c478bd9Sstevel@tonic-gate if (args->returnval == 0) 9457c478bd9Sstevel@tonic-gate continue; 9467c478bd9Sstevel@tonic-gate if (strcmp(instr + 1, (*be->getnamef)(args)) 9477c478bd9Sstevel@tonic-gate != 0) 9487c478bd9Sstevel@tonic-gate continue; 9497c478bd9Sstevel@tonic-gate } 950738d7c77Svk154806 } 9517c478bd9Sstevel@tonic-gate if (instr[0] == '-') { 9527c478bd9Sstevel@tonic-gate /* no need to search for "-" entry */ 9537c478bd9Sstevel@tonic-gate args->returnval = 0; 9547c478bd9Sstevel@tonic-gate args->erange = 0; 9557c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 9567c478bd9Sstevel@tonic-gate } else { 9577c478bd9Sstevel@tonic-gate if (colon != 0) 9587c478bd9Sstevel@tonic-gate *colon = ':'; /* restoration */ 9597c478bd9Sstevel@tonic-gate res = do_merge(be, args, instr, linelen); 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate break; 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9657c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 9667c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate if (!args->stayopen) { 9697c478bd9Sstevel@tonic-gate (void) _nss_compat_endent(be, 0); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate 972cb5caa98Sdjl if (be->return_string_data == 1) { 973ad0e80f7Smichen args->str2ent = be->str2ent_save; 974cb5caa98Sdjl } 975cb5caa98Sdjl 9767c478bd9Sstevel@tonic-gate return (res); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate nss_status_t 9807c478bd9Sstevel@tonic-gate _nss_compat_getent(be, a) 9817c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 9827c478bd9Sstevel@tonic-gate void *a; 9837c478bd9Sstevel@tonic-gate { 9847c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; 9857c478bd9Sstevel@tonic-gate nss_status_t res; 9867c478bd9Sstevel@tonic-gate char *colon = 0; /* <=== need comment re lifetime */ 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if (be->f == 0) { 9897c478bd9Sstevel@tonic-gate if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) { 9907c478bd9Sstevel@tonic-gate return (res); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate if (be->buf == 0 && 9957c478bd9Sstevel@tonic-gate (be->buf = malloc(be->minbuf)) == 0) { 9967c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); /* really panic, malloc failed */ 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 999cb5caa98Sdjl /* 1000cb5caa98Sdjl * assume a NULL buf.result pointer is an indication 1001cb5caa98Sdjl * that the lookup result should be returned in /etc 1002cb5caa98Sdjl * file format 1003cb5caa98Sdjl */ 1004cb5caa98Sdjl if (args->buf.result == NULL) { 1005cb5caa98Sdjl be->return_string_data = 1; 1006cb5caa98Sdjl 1007cb5caa98Sdjl /* 1008cb5caa98Sdjl * the code executed later needs the result struct 1009cb5caa98Sdjl * as working area 1010cb5caa98Sdjl */ 1011ad0e80f7Smichen args->buf.result = be->workarea; 1012e37190e5Smichen } else 1013e37190e5Smichen be->return_string_data = 0; 1014cb5caa98Sdjl 10157c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 10167c478bd9Sstevel@tonic-gate while (1) { 10177c478bd9Sstevel@tonic-gate char *instr = be->buf; 10187c478bd9Sstevel@tonic-gate int linelen; 10197c478bd9Sstevel@tonic-gate char *name; /* === Need more distinctive label */ 10207c478bd9Sstevel@tonic-gate const char *savename; 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate /* 10237c478bd9Sstevel@tonic-gate * In the code below... 10247c478bd9Sstevel@tonic-gate * break means "I found one, I think" (i.e. goto the 10257c478bd9Sstevel@tonic-gate * code after the end of the switch statement), 10267c478bd9Sstevel@tonic-gate * continue means "Next candidate" 10277c478bd9Sstevel@tonic-gate * (i.e. loop around to the switch statement), 10287c478bd9Sstevel@tonic-gate * return means "I'm quite sure" (either Yes or No). 10297c478bd9Sstevel@tonic-gate */ 10307c478bd9Sstevel@tonic-gate switch (be->state) { 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate case GETENT_DONE: 10337c478bd9Sstevel@tonic-gate args->returnval = 0; 10347c478bd9Sstevel@tonic-gate args->erange = 0; 10357c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate case GETENT_ATTRDB: 1038cb5caa98Sdjl args->key.name = NULL; 10397c478bd9Sstevel@tonic-gate res = _attrdb_compat_XY_all(be, 10407c478bd9Sstevel@tonic-gate args, 1, (compat_XY_check_func)NULL, 0); 10417c478bd9Sstevel@tonic-gate return (res); 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate case GETENT_FILE: 10447c478bd9Sstevel@tonic-gate linelen = read_line(be->f, instr, be->minbuf); 10457c478bd9Sstevel@tonic-gate if (linelen < 0) { 10467c478bd9Sstevel@tonic-gate /* End of file */ 10477c478bd9Sstevel@tonic-gate be->state = GETENT_DONE; 10487c478bd9Sstevel@tonic-gate continue; 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate if ((colon = strchr(instr, ':')) != 0) { 10517c478bd9Sstevel@tonic-gate *colon = '\0'; 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate if (instr[0] == '-') { 10547c478bd9Sstevel@tonic-gate if (instr[1] != '@') { 1055cb5caa98Sdjl (void) strset_add(&be->minuses, 1056cb5caa98Sdjl instr + 1); 10577c478bd9Sstevel@tonic-gate } else if (be->permit_netgroups) { 10587c478bd9Sstevel@tonic-gate netgr_set(be, instr + 2); 10597c478bd9Sstevel@tonic-gate while (netgr_next_u(be, &name)) { 1060cb5caa98Sdjl (void) strset_add(&be->minuses, 10617c478bd9Sstevel@tonic-gate name); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate netgr_end(be); 10647c478bd9Sstevel@tonic-gate } /* Else (silently) ignore the entry */ 10657c478bd9Sstevel@tonic-gate continue; 10667c478bd9Sstevel@tonic-gate } else if (instr[0] != '+') { 10677c478bd9Sstevel@tonic-gate int parsestat; 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * Normal entry, no +/- nonsense 10707c478bd9Sstevel@tonic-gate */ 10717c478bd9Sstevel@tonic-gate if (colon != 0) { 10727c478bd9Sstevel@tonic-gate *colon = ':'; 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate args->returnval = 0; 10757c478bd9Sstevel@tonic-gate parsestat = (*args->str2ent)(instr, linelen, 10767c478bd9Sstevel@tonic-gate args->buf.result, 10777c478bd9Sstevel@tonic-gate args->buf.buffer, 10787c478bd9Sstevel@tonic-gate args->buf.buflen); 10797c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 1080cb5caa98Sdjl int len; 1081cb5caa98Sdjl 1082cb5caa98Sdjl if (be->return_string_data != 1) { 1083cb5caa98Sdjl args->returnval = 1084cb5caa98Sdjl args->buf.result; 10857c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); 10867c478bd9Sstevel@tonic-gate } 1087cb5caa98Sdjl 1088cb5caa98Sdjl /* 1089cb5caa98Sdjl * copy string data to 1090cb5caa98Sdjl * result buffer 1091cb5caa98Sdjl */ 1092cb5caa98Sdjl args->buf.result = NULL; 1093cb5caa98Sdjl args->returnval = 1094cb5caa98Sdjl args->buf.buffer; 1095cb5caa98Sdjl if ((len = strlcpy(args->buf.buffer, 1096cb5caa98Sdjl instr, args->buf.buflen)) >= 1097cb5caa98Sdjl args->buf.buflen) 1098cb5caa98Sdjl parsestat = 1099cb5caa98Sdjl NSS_STR_PARSE_ERANGE; 1100cb5caa98Sdjl else { 1101cb5caa98Sdjl args->returnlen = len; 1102cb5caa98Sdjl return (NSS_SUCCESS); 1103cb5caa98Sdjl } 1104cb5caa98Sdjl } 11057c478bd9Sstevel@tonic-gate /* ==> ?? Treat ERANGE differently ?? */ 11067c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_ERANGE) { 11077c478bd9Sstevel@tonic-gate args->returnval = 0; 11087c478bd9Sstevel@tonic-gate args->erange = 1; 11097c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate /* Skip the offending entry, get next */ 11127c478bd9Sstevel@tonic-gate continue; 11137c478bd9Sstevel@tonic-gate } else if (instr[1] == '\0') { 11147c478bd9Sstevel@tonic-gate /* Plain "+" */ 11157c478bd9Sstevel@tonic-gate nss_setent(be->db_rootp, be->db_initf, 11167c478bd9Sstevel@tonic-gate &be->db_context); 11177c478bd9Sstevel@tonic-gate be->state = GETENT_ALL; 11187c478bd9Sstevel@tonic-gate be->linelen = linelen; 1119ad0e80f7Smichen 11207c478bd9Sstevel@tonic-gate continue; 11217c478bd9Sstevel@tonic-gate } else if (instr[1] == '@') { 11227c478bd9Sstevel@tonic-gate /* "+@netgroup" */ 11237c478bd9Sstevel@tonic-gate netgr_set(be, instr + 2); 11247c478bd9Sstevel@tonic-gate be->state = GETENT_NETGROUP; 11257c478bd9Sstevel@tonic-gate be->linelen = linelen; 11267c478bd9Sstevel@tonic-gate continue; 11277c478bd9Sstevel@tonic-gate } else { 11287c478bd9Sstevel@tonic-gate /* "+name" */ 11297c478bd9Sstevel@tonic-gate name = instr + 1; 11307c478bd9Sstevel@tonic-gate break; 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate /* NOTREACHED */ 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate case GETENT_ALL: 11357c478bd9Sstevel@tonic-gate linelen = be->linelen; 11367c478bd9Sstevel@tonic-gate args->returnval = 0; 1137ad0e80f7Smichen if (be->return_string_data == 1) { 1138ad0e80f7Smichen be->str2ent_save = args->str2ent; 1139ad0e80f7Smichen args->str2ent = be->str2ent_alt; 1140ad0e80f7Smichen } 1141ad0e80f7Smichen 1142cb5caa98Sdjl (void) nss_getent(be->db_rootp, be->db_initf, 11437c478bd9Sstevel@tonic-gate &be->db_context, args); 11447c478bd9Sstevel@tonic-gate if (args->returnval == 0) { 11457c478bd9Sstevel@tonic-gate /* ==> ?? Treat ERANGE differently ?? */ 11467c478bd9Sstevel@tonic-gate nss_endent(be->db_rootp, be->db_initf, 11477c478bd9Sstevel@tonic-gate &be->db_context); 11487c478bd9Sstevel@tonic-gate be->state = GETENT_FILE; 1149ad0e80f7Smichen if (be->return_string_data == 1) 1150ad0e80f7Smichen args->str2ent = be->str2ent_save; 11517c478bd9Sstevel@tonic-gate continue; 11527c478bd9Sstevel@tonic-gate } 1153ad0e80f7Smichen if (strset_in(&be->minuses, (*be->getnamef)(args))) 11547c478bd9Sstevel@tonic-gate continue; 11557c478bd9Sstevel@tonic-gate name = 0; /* tell code below we've done the lookup */ 1156ad0e80f7Smichen if (be->return_string_data == 1) 1157ad0e80f7Smichen args->str2ent = be->str2ent_save; 11587c478bd9Sstevel@tonic-gate break; 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate case GETENT_NETGROUP: 11617c478bd9Sstevel@tonic-gate linelen = be->linelen; 11627c478bd9Sstevel@tonic-gate if (!netgr_next_u(be, &name)) { 11637c478bd9Sstevel@tonic-gate netgr_end(be); 11647c478bd9Sstevel@tonic-gate be->state = GETENT_FILE; 11657c478bd9Sstevel@tonic-gate continue; 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate /* pass "name" variable to code below... */ 11687c478bd9Sstevel@tonic-gate break; 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate if (name != 0) { 11727c478bd9Sstevel@tonic-gate if (strset_in(&be->minuses, name)) { 11737c478bd9Sstevel@tonic-gate continue; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate /* 11767c478bd9Sstevel@tonic-gate * Do a getXXXnam(name). If we were being pure, 11777c478bd9Sstevel@tonic-gate * we'd introduce yet another function-pointer 11787c478bd9Sstevel@tonic-gate * that the database-specific code had to supply 11797c478bd9Sstevel@tonic-gate * to us. Instead we'll be grotty and hard-code 11807c478bd9Sstevel@tonic-gate * the knowledge that 11817c478bd9Sstevel@tonic-gate * (a) The username is always passwd in key.name, 11827c478bd9Sstevel@tonic-gate * (b) NSS_DBOP_PASSWD_BYNAME == 11837c478bd9Sstevel@tonic-gate * NSS_DBOP_SHADOW_BYNAME == 11847c478bd9Sstevel@tonic-gate * NSS_DBOP_next_iter. 11857c478bd9Sstevel@tonic-gate */ 11867c478bd9Sstevel@tonic-gate savename = args->key.name; 11877c478bd9Sstevel@tonic-gate args->key.name = name; 11887c478bd9Sstevel@tonic-gate args->returnval = 0; 1189ad0e80f7Smichen if (be->return_string_data == 1) { 1190ad0e80f7Smichen be->str2ent_save = args->str2ent; 1191ad0e80f7Smichen args->str2ent = be->str2ent_alt; 1192ad0e80f7Smichen } 1193ad0e80f7Smichen 1194cb5caa98Sdjl (void) nss_search(be->db_rootp, be->db_initf, 11957c478bd9Sstevel@tonic-gate NSS_DBOP_next_iter, args); 1196ad0e80f7Smichen 1197ad0e80f7Smichen if (be->return_string_data == 1) 1198ad0e80f7Smichen args->str2ent = be->str2ent_save; 11997c478bd9Sstevel@tonic-gate args->key.name = savename; /* In case anyone cares */ 12007c478bd9Sstevel@tonic-gate } 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * Found one via "+", "+name" or "@netgroup". 12037c478bd9Sstevel@tonic-gate * Override some fields if the /etc file says to do so. 12047c478bd9Sstevel@tonic-gate */ 12057c478bd9Sstevel@tonic-gate if (args->returnval == 0) { 12067c478bd9Sstevel@tonic-gate /* ==> ?? Should treat erange differently? */ 12077c478bd9Sstevel@tonic-gate continue; 12087c478bd9Sstevel@tonic-gate } 12097c478bd9Sstevel@tonic-gate /* 'colon' was set umpteen iterations ago in GETENT_FILE */ 12107c478bd9Sstevel@tonic-gate if (colon != 0) { 12117c478bd9Sstevel@tonic-gate *colon = ':'; 12127c478bd9Sstevel@tonic-gate colon = 0; 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate return (do_merge(be, args, instr, linelen)); 12157c478bd9Sstevel@tonic-gate } 1216cb5caa98Sdjl /*NOTREACHED*/ 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate /* We don't use this directly; we just copy the bits when we want to */ 12207c478bd9Sstevel@tonic-gate /* initialize the variable (in the compat_backend struct) that we do use */ 12217c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context_initval); 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate nss_backend_t * 12247c478bd9Sstevel@tonic-gate _nss_compat_constr(ops, n_ops, filename, min_bufsize, rootp, initf, netgroups, 12257c478bd9Sstevel@tonic-gate getname_func, merge_func) 12267c478bd9Sstevel@tonic-gate compat_backend_op_t ops[]; 12277c478bd9Sstevel@tonic-gate int n_ops; 12287c478bd9Sstevel@tonic-gate const char *filename; 12297c478bd9Sstevel@tonic-gate int min_bufsize; 12307c478bd9Sstevel@tonic-gate nss_db_root_t *rootp; 12317c478bd9Sstevel@tonic-gate nss_db_initf_t initf; 12327c478bd9Sstevel@tonic-gate int netgroups; 12337c478bd9Sstevel@tonic-gate compat_get_name getname_func; 12347c478bd9Sstevel@tonic-gate compat_merge_func merge_func; 12357c478bd9Sstevel@tonic-gate { 12367c478bd9Sstevel@tonic-gate compat_backend_ptr_t be; 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate if ((be = (compat_backend_ptr_t)malloc(sizeof (*be))) == 0) { 12397c478bd9Sstevel@tonic-gate return (0); 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate be->ops = ops; 12427c478bd9Sstevel@tonic-gate be->n_ops = n_ops; 12437c478bd9Sstevel@tonic-gate be->filename = filename; 12447c478bd9Sstevel@tonic-gate be->f = 0; 12457c478bd9Sstevel@tonic-gate be->minbuf = min_bufsize; 12467c478bd9Sstevel@tonic-gate be->buf = 0; 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate be->db_rootp = rootp; 12497c478bd9Sstevel@tonic-gate be->db_initf = initf; 12507c478bd9Sstevel@tonic-gate be->db_context = context_initval; 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate be->getnamef = getname_func; 12537c478bd9Sstevel@tonic-gate be->mergef = merge_func; 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate be->state = GETENT_FILE; /* i.e. do Automatic setent(); */ 1256ad0e80f7Smichen if (strcmp(be->filename, USERATTR_FILENAME) == 0) { 1257ad0e80f7Smichen be->state = GETENT_ATTRDB; 1258ad0e80f7Smichen be->str2ent_alt = str2userattr_s; 1259ad0e80f7Smichen be->workarea = calloc(1, sizeof (userstr_t)); 1260ad0e80f7Smichen } else if (strcmp(be->filename, AUDITUSER_FILENAME) == 0) { 1261ad0e80f7Smichen be->state = GETENT_ATTRDB; 1262ad0e80f7Smichen be->str2ent_alt = str2auuser_s; 1263ad0e80f7Smichen be->workarea = calloc(1, sizeof (au_user_str_t)); 1264ad0e80f7Smichen } else if (strcmp(be->filename, PASSWD) == 0) { 1265ad0e80f7Smichen be->str2ent_alt = str2passwd; 1266ad0e80f7Smichen be->workarea = calloc(1, sizeof (struct passwd)); 1267ad0e80f7Smichen } else if (strcmp(be->filename, SHADOW) == 0) { 1268ad0e80f7Smichen be->str2ent_alt = str2spwd; 1269ad0e80f7Smichen be->workarea = calloc(1, sizeof (struct spwd)); 1270ad0e80f7Smichen } else { /* group */ 1271ad0e80f7Smichen be->str2ent_alt = str2group; 1272ad0e80f7Smichen be->workarea = calloc(1, sizeof (struct group)); 1273ad0e80f7Smichen } 1274ad0e80f7Smichen if (be->workarea == NULL) 1275ad0e80f7Smichen return (NULL); 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate be->minuses = 0; 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate be->permit_netgroups = netgroups; 12807c478bd9Sstevel@tonic-gate be->yp_domain = 0; 12817c478bd9Sstevel@tonic-gate be->getnetgrent_backend = 0; 12827c478bd9Sstevel@tonic-gate be->netgr_buffer = 0; 1283cb5caa98Sdjl be->return_string_data = 0; 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate return ((nss_backend_t *)be); 12867c478bd9Sstevel@tonic-gate } 1287