1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright (c) 1996, by Sun Microsystems, Inc.
25 * All rights reserved.
26 *
27 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <string.h>
34 #include "table.h"
35 #include "util.h"
36 #include "getgroup.h"
37
38 /*
39 * Stolen mostly, from getnetgrent.c
40 *
41 * my_getgroup() performs the same function as _getgroup(), but operates
42 * on /etc/netgroup directly, rather than doing yp lookups.
43 *
44 * /etc/netgroup must first loaded into a hash table so the matching
45 * function can look up lines quickly.
46 */
47
48
49 /* To check for cycles in netgroups */
50 struct list {
51 char *name;
52 struct list *nxt;
53 };
54
55 static char *any();
56 static char *match();
57 static char *fill();
58
59
60 void
61 freegrouplist(revhandle_t *hdl)
62 {
63 struct grouplist *gl, *next;
64
65 for (gl = hdl->grouplist; gl != NULL; gl = next) {
66 next = gl->gl_nxt;
67
68 FREE(gl->gl_name);
69 FREE(gl->gl_domain);
70 FREE(gl->gl_machine);
71 FREE(gl);
72 }
73 hdl->grouplist = NULL;
74 }
75
76
77
78 /*
79 * recursive function to find the members of netgroup "group". "list" is
80 * the path followed through the netgroups so far, to check for cycles.
81 */
82 void
83 doit(char *group, struct list *list, revhandle_t *hdl)
84 {
85 register char *p, *q;
86 register struct list *ls;
87 struct list tmplist;
88 char *val;
89 struct grouplist *gpls;
90
91
92 /*
93 * check for non-existing groups
94 */
95 if ((val = match(group, hdl)) == NULL) {
96 return;
97 }
98
99
100 /*
101 * check for cycles
102 */
103 for (ls = list; ls != NULL; ls = ls->nxt) {
104 if (strcmp(ls->name, group) == 0) {
105 (void) fprintf(stderr,
106 "Cycle detected in /etc/netgroup: %s.\n",
107 group);
108 return;
109 }
110 }
111
112
113 ls = &tmplist;
114 ls->name = group;
115 ls->nxt = list;
116 list = ls;
117
118 p = val;
119 while (p != NULL) {
120 while (*p == ' ' || *p == '\t')
121 p++;
122 if (*p == EOS || *p == '#')
123 break;
124 if (*p == '(') {
125 gpls = MALLOC(struct grouplist);
126 p++;
127
128 if (!(p = fill(p, &gpls->gl_machine, ','))) {
129 goto syntax_error;
130 }
131 if (!(p = fill(p, &gpls->gl_name, ','))) {
132 goto syntax_error;
133 }
134 if (!(p = fill(p, &gpls->gl_domain, ')'))) {
135 goto syntax_error;
136 }
137 gpls->gl_nxt = hdl->grouplist;
138 hdl->grouplist = gpls;
139 } else {
140 q = any(p, " \t\n#");
141 if (q && *q == '#')
142 break;
143 *q = EOS;
144 doit(p, list, hdl);
145 *q = ' ';
146 }
147 p = any(p, " \t");
148 }
149 return;
150
151 syntax_error:
152 (void) fprintf(stderr, "syntax error in /etc/netgroup\n");
153 (void) fprintf(stderr, "--- %s %s\n", group, val);
154 }
155
156
157
158
159 /*
160 * Fill a buffer "target" selectively from buffer "start".
161 * "termchar" terminates the information in start, and preceding
162 * or trailing white space is ignored. If the buffer "start" is
163 * empty, "target" is filled with "*". The location just after the
164 * terminating character is returned.
165 */
166 static char *
167 fill(start, target, termchar)
168 char *start;
169 char **target;
170 char termchar;
171 {
172 register char *p;
173 register char *q;
174 register char *r;
175 int size;
176
177 for (p = start; *p == ' ' || *p == '\t'; p++)
178 ;
179 r = strchr(p, termchar);
180 if (r == (char *)NULL) {
181 return ((char *)NULL);
182 }
183 if (p == r) {
184 *target = NULL;
185 } else {
186 for (q = r-1; *q == ' ' || *q == '\t'; q--)
187 ;
188 size = q-p+1;
189 STRNCPY(*target, p, size);
190 }
191 return (r+1);
192 }
193
194
195 /*
196 * scans cp, looking for a match with any character
197 * in match. Returns pointer to place in cp that matched
198 * (or NULL if no match)
199 */
200 static char *
201 any(cp, match)
202 register char *cp;
203 char *match;
204 {
205 register char *mp, c;
206
207 while (c = *cp) {
208 for (mp = match; *mp; mp++)
209 if (*mp == c)
210 return (cp);
211 cp++;
212 }
213 return (NULL);
214 }
215
216
217
218 /*
219 * The equivalent of yp_match. Returns the match, or NULL if there is none.
220 */
221 static char *
222 match(char *group, revhandle_t *hdl)
223 {
224 return (lookup(hdl->ngtable, group));
225 }