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 * Copyright 1990 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <grp.h>
31 #include <grpadj.h>
32 #include <rpcsvc/ypclnt.h>
33 #include <string.h>
34 #include <malloc.h>
35
36 extern void rewind();
37 extern long strtol();
38 extern int fclose();
39
40 void setgraent(void);
41 void endgraent(void);
42
43 static struct gradata {
44 char *domain;
45 FILE *grfa;
46 char *yp;
47 int yplen;
48 char *oldyp;
49 int oldyplen;
50 struct list {
51 char *name;
52 struct list *nxt;
53 } *minuslist; /* list of - items */
54 struct group_adjunct interpgra;
55 char interpline[BUFSIZ+1];
56 struct group_adjunct *sv;
57 } *gradata, *_gradata(void);
58
59 static char *GROUPADJ = "/etc/security/group.adjunct";
60
61 static struct group_adjunct *interpret(char *, int);
62 static struct group_adjunct *interpretwithsave(char *, int,
63 struct group_adjunct *);
64 static struct group_adjunct *save(struct group_adjunct *);
65 static struct group_adjunct *getnamefromyellow(char *,
66 struct group_adjunct *);
67 static int onminuslist(struct group_adjunct *);
68 static int matchname(char [], struct group_adjunct **, char *);
69 static void freeminuslist(void);
70 static void getnextfromyellow(void);
71 static void getfirstfromyellow(void);
72 static void addtominuslist(char *);
73
74
75 static struct gradata *
_gradata(void)76 _gradata(void)
77 {
78 struct gradata *g = gradata;
79
80 if (g == 0) {
81 g = (struct gradata *)calloc(1, sizeof (struct gradata));
82 gradata = g;
83 }
84 return (g);
85 }
86
87 struct group_adjunct *
getgranam(char * name)88 getgranam(char *name)
89 {
90 struct gradata *g = _gradata();
91 struct group_adjunct *gra;
92 char line[BUFSIZ+1];
93
94 setgraent();
95 if (g == 0)
96 return (0);
97 if (!g->grfa)
98 return (NULL);
99 while (fgets(line, BUFSIZ, g->grfa) != NULL) {
100 if ((gra = interpret(line, strlen(line))) == NULL)
101 continue;
102 if (matchname(line, &gra, name)) {
103 endgraent();
104 return (gra);
105 }
106 }
107 endgraent();
108 return (NULL);
109 }
110
111 void
setgraent(void)112 setgraent(void)
113 {
114 struct gradata *g = _gradata();
115
116 if (g == NULL)
117 return;
118 if (g->domain == NULL)
119 (void) yp_get_default_domain(&g->domain);
120 if (!g->grfa)
121 g->grfa = fopen(GROUPADJ, "r");
122 else
123 rewind(g->grfa);
124 if (g->yp)
125 free(g->yp);
126 g->yp = NULL;
127 freeminuslist();
128 }
129
130 void
endgraent(void)131 endgraent(void)
132 {
133 struct gradata *g = _gradata();
134
135 if (g == 0)
136 return;
137 if (g->grfa) {
138 (void) fclose(g->grfa);
139 g->grfa = NULL;
140 }
141 if (g->yp)
142 free(g->yp);
143 g->yp = NULL;
144 freeminuslist();
145 }
146
147 struct group_adjunct *
fgetgraent(FILE * f)148 fgetgraent(FILE *f)
149 {
150 char line1[BUFSIZ+1];
151
152 if(fgets(line1, BUFSIZ, f) == NULL)
153 return (NULL);
154 return (interpret(line1, strlen(line1)));
155 }
156
157 static char *
grskip(char * p,int c)158 grskip(char *p, int c)
159 {
160 while(*p && *p != c && *p != '\n') ++p;
161 if (*p == '\n')
162 *p = '\0';
163 else if (*p != '\0')
164 *p++ = '\0';
165 return (p);
166 }
167
168 struct group_adjunct *
getgraent(void)169 getgraent(void)
170 {
171 struct gradata *g = _gradata();
172 char line1[BUFSIZ+1];
173 static struct group_adjunct *savegra;
174 struct group_adjunct *gra;
175
176 if (g == 0)
177 return (0);
178 if (g->domain == NULL) {
179 (void) yp_get_default_domain(&g->domain);
180 }
181 if(!g->grfa && !(g->grfa = fopen(GROUPADJ, "r")))
182 return (NULL);
183 again:
184 if (g->yp) {
185 gra = interpretwithsave(g->yp, g->yplen, savegra);
186 free(g->yp);
187 if (gra == NULL)
188 return (NULL);
189 getnextfromyellow();
190 if (onminuslist(gra))
191 goto again;
192 else
193 return (gra);
194 }
195 else if (fgets(line1, BUFSIZ, g->grfa) == NULL)
196 return (NULL);
197 if ((gra = interpret(line1, strlen(line1))) == NULL)
198 return (NULL);
199 switch(line1[0]) {
200 case '+':
201 if (strcmp(gra->gra_name, "+") == 0) {
202 getfirstfromyellow();
203 savegra = save(gra);
204 goto again;
205 }
206 /*
207 * else look up this entry in NIS
208 */
209 savegra = save(gra);
210 gra = getnamefromyellow(gra->gra_name+1, savegra);
211 if (gra == NULL)
212 goto again;
213 else if (onminuslist(gra))
214 goto again;
215 else
216 return (gra);
217 break;
218 case '-':
219 addtominuslist(gra->gra_name+1);
220 goto again;
221 break;
222 default:
223 if (onminuslist(gra))
224 goto again;
225 return (gra);
226 break;
227 }
228 /* NOTREACHED */
229 }
230
231 static struct group_adjunct *
interpret(char * val,int len)232 interpret(char *val, int len)
233 {
234 struct gradata *g = _gradata();
235 char *p;
236
237 if (g == 0)
238 return (0);
239 strncpy(g->interpline, val, len);
240 p = g->interpline;
241 g->interpline[len] = '\n';
242 g->interpline[len+1] = 0;
243 g->interpgra.gra_name = p;
244 p = grskip(p,':');
245 if (strcmp(g->interpgra.gra_name, "+") == 0) {
246 /* we are going to the NIS - fix the
247 * rest of the struct as much as is needed
248 */
249 g->interpgra.gra_passwd = "";
250 return (&g->interpgra);
251 }
252 g->interpgra.gra_passwd = p;
253 while(*p && *p != '\n') p++;
254 *p = '\0';
255 return (&g->interpgra);
256 }
257
258 static void
freeminuslist(void)259 freeminuslist(void)
260 {
261 struct gradata *g = _gradata();
262 struct list *ls;
263
264 if (g == 0)
265 return;
266 for (ls = g->minuslist; ls != NULL; ls = ls->nxt) {
267 free(ls->name);
268 free(ls);
269 }
270 g->minuslist = NULL;
271 }
272
273 static struct group_adjunct *
interpretwithsave(char * val,int len,struct group_adjunct * savegra)274 interpretwithsave(char *val, int len, struct group_adjunct *savegra)
275 {
276 struct gradata *g = _gradata();
277 struct group_adjunct *gra;
278
279 if (g == 0)
280 return (0);
281 if ((gra = interpret(val, len)) == NULL)
282 return (NULL);
283 if (savegra->gra_passwd && *savegra->gra_passwd)
284 gra->gra_passwd = savegra->gra_passwd;
285 return (gra);
286 }
287
288 static int
onminuslist(struct group_adjunct * gra)289 onminuslist(struct group_adjunct *gra)
290 {
291 struct gradata *g = _gradata();
292 struct list *ls;
293 char *nm;
294
295 if (g == 0)
296 return (0);
297 nm = gra->gra_name;
298 for (ls = g->minuslist; ls != NULL; ls = ls->nxt)
299 if (strcmp(ls->name, nm) == 0)
300 return (1);
301 return (0);
302 }
303
304 static void
getnextfromyellow(void)305 getnextfromyellow(void)
306 {
307 struct gradata *g = _gradata();
308 int reason;
309 char *key = NULL;
310 int keylen;
311
312 if (g == 0)
313 return;
314 if (reason = yp_next(g->domain, "group.adjunct.byname",
315 g->oldyp, g->oldyplen, &key, &keylen,
316 &g->yp, &g->yplen)) {
317 #ifdef DEBUG
318 fprintf(stderr, "reason yp_next failed is %d\n", reason);
319 #endif
320 g->yp = NULL;
321 }
322 if (g->oldyp)
323 free(g->oldyp);
324 g->oldyp = key;
325 g->oldyplen = keylen;
326 }
327
328 static void
getfirstfromyellow(void)329 getfirstfromyellow(void)
330 {
331 struct gradata *g = _gradata();
332 int reason;
333 char *key = NULL;
334 int keylen;
335
336 if (g == 0)
337 return;
338 if (reason = yp_first(g->domain, "group.adjunct.byname",
339 &key, &keylen, &g->yp, &g->yplen)) {
340 #ifdef DEBUG
341 fprintf(stderr, "reason yp_first failed is %d\n", reason);
342 #endif
343 g->yp = NULL;
344 }
345 if (g->oldyp)
346 free(g->oldyp);
347 g->oldyp = key;
348 g->oldyplen = keylen;
349 }
350
351 static struct group_adjunct *
getnamefromyellow(char * name,struct group_adjunct * savegra)352 getnamefromyellow(char *name, struct group_adjunct *savegra)
353 {
354 struct gradata *g = _gradata();
355 struct group_adjunct *gra;
356 int reason;
357 char *val;
358 int vallen;
359
360 if (g == 0)
361 return (NULL);
362 if (reason = yp_match(g->domain, "group.adjunct.byname",
363 name, strlen(name), &val, &vallen)) {
364 #ifdef DEBUG
365 fprintf(stderr, "reason yp_next failed is %d\n", reason);
366 #endif
367 return (NULL);
368 }
369 else {
370 gra = interpret(val, vallen);
371 free(val);
372 if (gra == NULL)
373 return (NULL);
374 if (savegra->gra_passwd && *savegra->gra_passwd)
375 gra->gra_passwd = savegra->gra_passwd;
376 return (gra);
377 }
378 }
379
380 static void
addtominuslist(char * name)381 addtominuslist(char *name)
382 {
383 struct gradata *g = _gradata();
384 struct list *ls;
385 char *buf;
386
387 if (g == 0)
388 return;
389 ls = (struct list *)malloc(sizeof(struct list));
390 buf = (char *)malloc(strlen(name) + 1);
391 (void) strcpy(buf, name);
392 ls->name = buf;
393 ls->nxt = g->minuslist;
394 g->minuslist = ls;
395 }
396
397 /*
398 * save away psswd field, which is the only
399 * one which can be specified in a local + entry to override the
400 * value in the NIS
401 */
402 static struct group_adjunct *
save(struct group_adjunct * gra)403 save(struct group_adjunct *gra)
404 {
405 struct gradata *g = _gradata();
406
407 if (g == 0)
408 return (0);
409 /*
410 * free up stuff from last time around
411 */
412 if (g->sv) {
413 free(g->sv->gra_passwd);
414 free(g->sv);
415 }
416 g->sv = (struct group_adjunct *)calloc(1, sizeof(struct group_adjunct));
417 g->sv->gra_passwd = (char *)malloc(strlen(gra->gra_passwd) + 1);
418 (void) strcpy(g->sv->gra_passwd, gra->gra_passwd);
419 return (g->sv);
420 }
421
422 static int
matchname(char line1[],struct group_adjunct ** grap,char * name)423 matchname(char line1[], struct group_adjunct **grap, char *name)
424 {
425 struct group_adjunct *savegra;
426 struct group_adjunct *gra = *grap;
427
428 switch (line1[0]) {
429 case '+':
430 if (strcmp(gra->gra_name, "+") == 0) {
431 savegra = save(gra);
432 gra = getnamefromyellow(name, savegra);
433 if (gra) {
434 *grap = gra;
435 return (1);
436 }
437 else
438 return (0);
439 }
440 if (strcmp(gra->gra_name+1, name) == 0) {
441 savegra = save(gra);
442 gra = getnamefromyellow(gra->gra_name+1, savegra);
443 if (gra) {
444 *grap = gra;
445 return (1);
446 }
447 else
448 return (0);
449 }
450 break;
451 case '-':
452 if (strcmp(gra->gra_name+1, name) == 0) {
453 *grap = NULL;
454 return (1);
455 }
456 break;
457 default:
458 if (strcmp(gra->gra_name, name) == 0)
459 return (1);
460 }
461 return (0);
462 }
463