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
str2auuser_s(const char * instr,int lenstr,void * ent,char * buffer,int buflen)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
str2userattr_s(const char * instr,int lenstr,void * ent,char * buffer,int buflen)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
strset_free(ssp)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
strset_add(ssp,nam)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
strset_in(ssp,nam)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
netgr_in(compat_backend_ptr_t be,const char * group,const char * user)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
netgr_set(be,netgroup)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
netgr_next_u(be,up)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
netgr_end(be)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
do_merge(be,args,instr,linelen)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
_nss_compat_setent(be,dummy)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
_nss_compat_endent(be,dummy)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
_nss_compat_destr(be,dummy)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
read_line(f,buffer,buflen)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
is_nss_lookup_by_name(int attrdb,nss_dbop_t op)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
_attrdb_compat_XY_all(be,argp,netdb,check,op_num)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
validate_ids(compat_backend_ptr_t be,nss_XbyY_args_t * argp,char * line,int * linelenp,int buflen,int extra_chars)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
_nss_compat_XY_all(be,args,check,op_num)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
_nss_compat_getent(be,a)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 *
_nss_compat_constr(ops,n_ops,filename,min_bufsize,rootp,initf,netgroups,getname_func,merge_func)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