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
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gate /*
247c478bd9Sstevel@tonic-gate * Copyright (c) 1996, by Sun Microsystems, Inc.
257c478bd9Sstevel@tonic-gate * All rights reserved.
267c478bd9Sstevel@tonic-gate */
27*55fea89dSDan Cross
287c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SMI4.1 1.5 */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <ctype.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include "table.h"
347c478bd9Sstevel@tonic-gate #include "util.h"
357c478bd9Sstevel@tonic-gate #include "getgroup.h"
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate #define MAXGROUPLEN 1024
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate * Stolen mostly, from getnetgrent.c
417c478bd9Sstevel@tonic-gate *
427c478bd9Sstevel@tonic-gate * my_getgroup() performs the same function as _getgroup(), but operates
437c478bd9Sstevel@tonic-gate * on /etc/netgroup directly, rather than doing yp lookups.
447c478bd9Sstevel@tonic-gate *
457c478bd9Sstevel@tonic-gate * /etc/netgroup must first loaded into a hash table so the matching
467c478bd9Sstevel@tonic-gate * function can look up lines quickly.
477c478bd9Sstevel@tonic-gate */
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /* To check for cycles in netgroups */
517c478bd9Sstevel@tonic-gate struct list {
527c478bd9Sstevel@tonic-gate char *name;
537c478bd9Sstevel@tonic-gate struct list *nxt;
547c478bd9Sstevel@tonic-gate };
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate extern stringtable ngtable; /* stored info from /etc/netgroup */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate static struct grouplist *grouplist; /* stores a list of users in a group */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate static char *any();
627c478bd9Sstevel@tonic-gate static char *match();
637c478bd9Sstevel@tonic-gate static char *fill();
647c478bd9Sstevel@tonic-gate static void freegrouplist();
657c478bd9Sstevel@tonic-gate static void doit();
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate static void
freegrouplist()707c478bd9Sstevel@tonic-gate freegrouplist()
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate struct grouplist *gl;
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate for (gl = grouplist; gl != NULL; gl = gl->gl_nxt) {
757c478bd9Sstevel@tonic-gate FREE(gl->gl_name);
767c478bd9Sstevel@tonic-gate FREE(gl->gl_domain);
777c478bd9Sstevel@tonic-gate FREE(gl->gl_machine);
787c478bd9Sstevel@tonic-gate FREE(gl);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate grouplist = NULL;
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate struct grouplist *
my_getgroup(group)877c478bd9Sstevel@tonic-gate my_getgroup(group)
887c478bd9Sstevel@tonic-gate char *group;
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate freegrouplist();
917c478bd9Sstevel@tonic-gate doit(group, (struct list *) NULL);
927c478bd9Sstevel@tonic-gate return (grouplist);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate * recursive function to find the members of netgroup "group". "list" is
1017c478bd9Sstevel@tonic-gate * the path followed through the netgroups so far, to check for cycles.
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate static void
doit(group,list)1047c478bd9Sstevel@tonic-gate doit(group, list)
1057c478bd9Sstevel@tonic-gate char *group;
1067c478bd9Sstevel@tonic-gate struct list *list;
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate register char *p, *q;
1097c478bd9Sstevel@tonic-gate register struct list *ls;
1107c478bd9Sstevel@tonic-gate struct list tmplist;
1117c478bd9Sstevel@tonic-gate char *val;
1127c478bd9Sstevel@tonic-gate struct grouplist *gpls;
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate * check for non-existing groups
1177c478bd9Sstevel@tonic-gate */
1187c478bd9Sstevel@tonic-gate if ((val = match(group)) == NULL) {
1197c478bd9Sstevel@tonic-gate return;
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate * check for cycles
1257c478bd9Sstevel@tonic-gate */
1267c478bd9Sstevel@tonic-gate for (ls = list; ls != NULL; ls = ls->nxt) {
1277c478bd9Sstevel@tonic-gate if (strcmp(ls->name, group) == 0) {
1287c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
1297c478bd9Sstevel@tonic-gate "Cycle detected in /etc/netgroup: %s.\n",
1307c478bd9Sstevel@tonic-gate group);
1317c478bd9Sstevel@tonic-gate return;
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate ls = &tmplist;
1377c478bd9Sstevel@tonic-gate ls->name = group;
1387c478bd9Sstevel@tonic-gate ls->nxt = list;
1397c478bd9Sstevel@tonic-gate list = ls;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate p = val;
1427c478bd9Sstevel@tonic-gate while (p != NULL) {
1437c478bd9Sstevel@tonic-gate while (*p == ' ' || *p == '\t')
1447c478bd9Sstevel@tonic-gate p++;
1457c478bd9Sstevel@tonic-gate if (*p == EOS || *p == '#')
1467c478bd9Sstevel@tonic-gate break;
1477c478bd9Sstevel@tonic-gate if (*p == '(') {
1487c478bd9Sstevel@tonic-gate gpls = MALLOC(struct grouplist);
1497c478bd9Sstevel@tonic-gate p++;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (!(p = fill(p, &gpls->gl_machine, ','))) {
1527c478bd9Sstevel@tonic-gate goto syntax_error;
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate if (!(p = fill(p, &gpls->gl_name, ','))) {
1557c478bd9Sstevel@tonic-gate goto syntax_error;
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate if (!(p = fill(p, &gpls->gl_domain, ')'))) {
1587c478bd9Sstevel@tonic-gate goto syntax_error;
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate gpls->gl_nxt = grouplist;
1617c478bd9Sstevel@tonic-gate grouplist = gpls;
1627c478bd9Sstevel@tonic-gate } else {
1637c478bd9Sstevel@tonic-gate q = any(p, " \t\n#");
1647c478bd9Sstevel@tonic-gate if (q && *q == '#')
1657c478bd9Sstevel@tonic-gate break;
1667c478bd9Sstevel@tonic-gate *q = EOS;
1677c478bd9Sstevel@tonic-gate doit(p, list);
1687c478bd9Sstevel@tonic-gate *q = ' ';
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate p = any(p, " \t");
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate return;
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate syntax_error:
1757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "syntax error in /etc/netgroup\n");
1767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "--- %s %s\n", group, val);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate * Fill a buffer "target" selectively from buffer "start".
1847c478bd9Sstevel@tonic-gate * "termchar" terminates the information in start, and preceding
1857c478bd9Sstevel@tonic-gate * or trailing white space is ignored. If the buffer "start" is
1867c478bd9Sstevel@tonic-gate * empty, "target" is filled with "*". The location just after the
1877c478bd9Sstevel@tonic-gate * terminating character is returned.
1887c478bd9Sstevel@tonic-gate */
1897c478bd9Sstevel@tonic-gate static char *
fill(start,target,termchar)1907c478bd9Sstevel@tonic-gate fill(start, target, termchar)
1917c478bd9Sstevel@tonic-gate char *start;
1927c478bd9Sstevel@tonic-gate char **target;
1937c478bd9Sstevel@tonic-gate char termchar;
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate register char *p;
1967c478bd9Sstevel@tonic-gate register char *q;
1977c478bd9Sstevel@tonic-gate register char *r;
1987c478bd9Sstevel@tonic-gate int size;
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate for (p = start; *p == ' ' || *p == '\t'; p++)
2017c478bd9Sstevel@tonic-gate ;
2027c478bd9Sstevel@tonic-gate r = strchr(p, termchar);
2037c478bd9Sstevel@tonic-gate if (r == (char *)NULL) {
2047c478bd9Sstevel@tonic-gate return ((char *)NULL);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate if (p == r) {
2077c478bd9Sstevel@tonic-gate *target = NULL;
2087c478bd9Sstevel@tonic-gate } else {
2097c478bd9Sstevel@tonic-gate for (q = r-1; *q == ' ' || *q == '\t'; q--)
2107c478bd9Sstevel@tonic-gate ;
2117c478bd9Sstevel@tonic-gate size = q-p+1;
2127c478bd9Sstevel@tonic-gate STRNCPY(*target, p, size);
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate return (r+1);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate * scans cp, looking for a match with any character
2207c478bd9Sstevel@tonic-gate * in match. Returns pointer to place in cp that matched
2217c478bd9Sstevel@tonic-gate * (or NULL if no match)
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate static char *
any(cp,match)2247c478bd9Sstevel@tonic-gate any(cp, match)
2257c478bd9Sstevel@tonic-gate register char *cp;
2267c478bd9Sstevel@tonic-gate char *match;
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate register char *mp, c;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate while (c = *cp) {
2317c478bd9Sstevel@tonic-gate for (mp = match; *mp; mp++)
2327c478bd9Sstevel@tonic-gate if (*mp == c)
2337c478bd9Sstevel@tonic-gate return (cp);
2347c478bd9Sstevel@tonic-gate cp++;
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate return (NULL);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate * The equivalent of yp_match. Returns the match, or NULL if there is none.
2437c478bd9Sstevel@tonic-gate */
2447c478bd9Sstevel@tonic-gate static char *
match(group)2457c478bd9Sstevel@tonic-gate match(group)
2467c478bd9Sstevel@tonic-gate char *group;
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate return (lookup(ngtable, group));
2497c478bd9Sstevel@tonic-gate }
250