xref: /titanic_52/usr/src/lib/libbc/libc/gen/common/getpwaent.c (revision b02e9a2d4d2071d770e5aa9ae8f83f2bbe1f2ced)
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 1991 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 
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/label.h>
33 #include <sys/audit.h>
34 #include <pwdadj.h>
35 #include <pwd.h>
36 #include <rpcsvc/ypclnt.h>
37 #include <string.h>
38 #include <malloc.h>
39 
40 extern void rewind();
41 extern long strtol();
42 extern int fclose();
43 
44 void	setpwaent(void);
45 void	endpwaent(void);
46 
47 static struct _pwajunk {
48 	struct passwd _NULLPW;
49 	FILE *_pwfadj;
50 	char *_yp;
51 	int _yplen;
52 	char *_oldyp;
53 	int _oldyplen;
54 	struct list {
55 		char *name;
56 		struct list *nxt;
57 	} *_minuslist;
58 	struct passwd _interppasswd;
59 	struct passwd_adjunct _apwadj;
60 	char _interpline[BUFSIZ+1];
61 	char *_domain;
62 } *__pwajunk, *_pwajunk(void);
63 
64 #define	NULLPW (_pwa->_NULLPW)
65 #define pwfadj (_pwa->_pwfadj)
66 #define yp (_pwa->_yp)
67 #define yplen (_pwa->_yplen)
68 #define oldyp (_pwa->_oldyp)
69 #define oldyplen (_pwa->_oldyplen)
70 #define minuslist (_pwa->_minuslist)
71 #define interppasswd (_pwa->_interppasswd)
72 #define apwadj (_pwa->_apwadj)
73 #define interpline (_pwa->_interpline)
74 #define domain (_pwa->_domain)
75 
76 static char *PASSWDADJ	= "/etc/security/passwd.adjunct";
77 
78 static struct passwd_adjunct	*interpret(char *, int);
79 static struct passwd_adjunct	*interpretwithsave(char *, int,
80     struct passwd_adjunct *);
81 static struct passwd_adjunct	*save(struct passwd_adjunct *);
82 static struct passwd_adjunct	*getnamefromyellow(char *,
83     struct passwd_adjunct *);
84 static int	matchname(char [], struct passwd_adjunct **, char *);
85 static int	onminuslist(struct passwd_adjunct *);
86 static void	getnextfromyellow(void);
87 static void	getfirstfromyellow(void);
88 static void	freeminuslist(void);
89 static void	addtominuslist(char *);
90 
91 
92 
93 static struct _pwajunk *
94 _pwajunk(void)
95 {
96 
97 	if (__pwajunk == 0)
98 		__pwajunk = (struct _pwajunk *)calloc(1, sizeof (*__pwajunk));
99 	return (__pwajunk);
100 }
101 
102 struct passwd_adjunct *
103 getpwanam(char *name)
104 {
105 	struct _pwajunk *_pwa = _pwajunk();
106 	struct passwd_adjunct *pwadj;
107 	char line[BUFSIZ+1];
108 
109 	if (_pwa == 0)
110 		return (NULL);
111 	setpwaent();
112 	if (!pwfadj)
113 		return (NULL);
114 	while (fgets(line, BUFSIZ, pwfadj) != NULL) {
115 		if ((pwadj = interpret(line, strlen(line))) == NULL)
116 			continue;
117 		if (matchname(line, &pwadj, name)) {
118 			endpwaent();
119 			return (pwadj);
120 		}
121 	}
122 	endpwaent();
123 	return (NULL);
124 }
125 
126 
127 void
128 setpwaent(void)
129 {
130 	struct _pwajunk *_pwa = _pwajunk();
131 
132 	if (_pwa == 0)
133 		return;
134 	if (domain == NULL) {
135 		(void) yp_get_default_domain(&domain );
136 	}
137 	if (pwfadj == NULL)
138 		pwfadj = fopen(PASSWDADJ, "r");
139 	else
140 		rewind(pwfadj);
141 	if (yp)
142 		free(yp);
143 	yp = NULL;
144 	freeminuslist();
145 }
146 
147 
148 
149 void
150 endpwaent(void)
151 {
152 	struct _pwajunk *_pwa = _pwajunk();
153 
154 	if (_pwa == 0)
155 		return;
156 	if (pwfadj != NULL) {
157 		(void) fclose(pwfadj);
158 		pwfadj = NULL;
159 	}
160 	if (yp)
161 		free(yp);
162 	yp = NULL;
163 	freeminuslist();
164 	endnetgrent();
165 }
166 
167 
168 
169 struct passwd_adjunct *
170 getpwaent(void)
171 {
172 	struct _pwajunk *_pwa = _pwajunk();
173 	char line[BUFSIZ+1];
174 	static struct passwd_adjunct *savepwadj;
175 	struct passwd_adjunct *pwadj;
176 	char *user;
177 	char *mach;
178 	char *dom;
179 
180 	if (_pwa == 0)
181 		return (NULL);
182 	if (domain == NULL) {
183 		(void) yp_get_default_domain(&domain );
184 	}
185 	if (pwfadj == NULL && (pwfadj = fopen(PASSWDADJ, "r")) == NULL) {
186 		return (NULL);
187 	}
188 
189 	for (;;) {
190 		if (yp) {
191 			pwadj = interpretwithsave(yp, yplen, savepwadj);
192 			free(yp);
193 			if (pwadj == NULL)
194 				return (NULL);
195 			getnextfromyellow();
196 			if (!onminuslist(pwadj)) {
197 				return (pwadj);
198 			}
199 		} else if (getnetgrent(&mach,&user,&dom)) {
200 			if (user) {
201 				pwadj = getnamefromyellow(user, savepwadj);
202 				if (pwadj != NULL && !onminuslist(pwadj)) {
203 					return (pwadj);
204 				}
205 			}
206 		} else {
207 			endnetgrent();
208 			if (fgets(line, BUFSIZ, pwfadj) == NULL)  {
209 				return (NULL);
210 			}
211 			if ((pwadj = interpret(line, strlen(line))) == NULL)
212 				return (NULL);
213 			switch(line[0]) {
214 			case '+':
215 				if (strcmp(pwadj->pwa_name, "+") == 0) {
216 					getfirstfromyellow();
217 					savepwadj = save(pwadj);
218 				} else if (line[1] == '@') {
219 					savepwadj = save(pwadj);
220 					if (innetgr(pwadj->pwa_name+2,(char *) NULL,"*",domain)) {
221 						/* include the whole NIS database */
222 						getfirstfromyellow();
223 					} else {
224 						setnetgrent(pwadj->pwa_name+2);
225 					}
226 				} else {
227 					/*
228 					 * else look up this entry in NIS
229 				 	 */
230 					savepwadj = save(pwadj);
231 					pwadj = getnamefromyellow(pwadj->pwa_name+1, savepwadj);
232 					if (pwadj != NULL && !onminuslist(pwadj)) {
233 						return (pwadj);
234 					}
235 				}
236 				break;
237 			case '-':
238 				if (line[1] == '@') {
239 					if (innetgr(pwadj->pwa_name+2,(char *) NULL,"*",domain)) {
240 						/* everybody was subtracted */
241 						return (NULL);
242 					}
243 					setnetgrent(pwadj->pwa_name+2);
244 					while (getnetgrent(&mach,&user,&dom)) {
245 						if (user) {
246 							addtominuslist(user);
247 						}
248 					}
249 					endnetgrent();
250 				} else {
251 					addtominuslist(pwadj->pwa_name+1);
252 				}
253 				break;
254 			default:
255 				if (!onminuslist(pwadj)) {
256 					return (pwadj);
257 				}
258 				break;
259 			}
260 		}
261 	}
262 }
263 
264 static int
265 matchname(char line1[], struct passwd_adjunct **pwadjp, char *name)
266 {
267 	struct _pwajunk *_pwa = _pwajunk();
268 	struct passwd_adjunct *savepwadj;
269 	struct passwd_adjunct *pwadj = *pwadjp;
270 
271 	if (_pwa == 0)
272 		return (0);
273 	switch(line1[0]) {
274 		case '+':
275 			if (strcmp(pwadj->pwa_name, "+") == 0) {
276 				savepwadj = save(pwadj);
277 				pwadj = getnamefromyellow(name, savepwadj);
278 				if (pwadj) {
279 					*pwadjp = pwadj;
280 					return (1);
281 				}
282 				else
283 					return (0);
284 			}
285 			if (line1[1] == '@') {
286 				if (innetgr(pwadj->pwa_name+2,(char *) NULL,name,domain)) {
287 					savepwadj = save(pwadj);
288 					pwadj = getnamefromyellow(name,savepwadj);
289 					if (pwadj) {
290 						*pwadjp = pwadj;
291 						return (1);
292 					}
293 				}
294 				return (0);
295 			}
296 			if (strcmp(pwadj->pwa_name+1, name) == 0) {
297 				savepwadj = save(pwadj);
298 				pwadj = getnamefromyellow(pwadj->pwa_name+1, savepwadj);
299 				if (pwadj) {
300 					*pwadjp = pwadj;
301 					return (1);
302 				}
303 				else
304 					return (0);
305 			}
306 			break;
307 		case '-':
308 			if (line1[1] == '@') {
309 				if (innetgr(pwadj->pwa_name+2,(char *) NULL,name,domain)) {
310 					*pwadjp = NULL;
311 					return (1);
312 				}
313 			}
314 			else if (strcmp(pwadj->pwa_name+1, name) == 0) {
315 				*pwadjp = NULL;
316 				return (1);
317 			}
318 			break;
319 		default:
320 			if (strcmp(pwadj->pwa_name, name) == 0)
321 				return (1);
322 	}
323 	return (0);
324 }
325 
326 static void
327 getnextfromyellow(void)
328 {
329 	struct _pwajunk *_pwa = _pwajunk();
330 	int reason;
331 	char *key;
332 	int keylen;
333 
334 	if (_pwa == 0)
335 		return;
336 	reason = yp_next(domain, "passwd_adjunct",oldyp, oldyplen, &key
337 	    ,&keylen,&yp,&yplen);
338 	if (reason) {
339 #ifdef DEBUG
340 fprintf(stderr, "reason yp_next failed is %d\n", reason);
341 #endif
342 		yp = NULL;
343 	}
344 	if (oldyp)
345 		free(oldyp);
346 	oldyp = key;
347 	oldyplen = keylen;
348 }
349 
350 static void
351 getfirstfromyellow(void)
352 {
353 	struct _pwajunk *_pwa = _pwajunk();
354 	int reason;
355 	char *key;
356 	int keylen;
357 
358 	if (_pwa == 0)
359 		return;
360 	reason =  yp_first(domain, "passwd_adjunct", &key, &keylen, &yp, &yplen);
361 	if (reason) {
362 #ifdef DEBUG
363 fprintf(stderr, "reason yp_first failed is %d\n", reason);
364 #endif
365 		yp = NULL;
366 	}
367 	if (oldyp)
368 		free(oldyp);
369 	oldyp = key;
370 	oldyplen = keylen;
371 }
372 
373 static struct passwd_adjunct *
374 getnamefromyellow(char *name, struct passwd_adjunct *savepwadj)
375 {
376 	struct _pwajunk *_pwa = _pwajunk();
377 	struct passwd_adjunct *pwadj;
378 	int reason;
379 	char *val;
380 	int vallen;
381 
382 	if (_pwa == 0)
383 		return (NULL);
384 	reason = yp_match(domain, "passwd.adjunct.byname", name, strlen(name)
385 		, &val, &vallen);
386 	if (reason) {
387 #ifdef DEBUG
388 fprintf(stderr, "reason yp_match failed is %d\n", reason);
389 #endif
390 		return (NULL);
391 	} else {
392 		pwadj = interpret(val, vallen);
393 		free(val);
394 		if (pwadj == NULL)
395 			return (NULL);
396 		if (savepwadj->pwa_passwd && *savepwadj->pwa_passwd)
397 			pwadj->pwa_passwd =  savepwadj->pwa_passwd;
398 		return (pwadj);
399 	}
400 }
401 
402 static struct passwd_adjunct *
403 interpretwithsave(char *val, int len, struct passwd_adjunct *savepwadj)
404 {
405 	struct _pwajunk *_pwa = _pwajunk();
406 	struct passwd_adjunct *pwadj;
407 
408 	if (_pwa == 0)
409 		return (NULL);
410 	if ((pwadj = interpret(val, len)) == NULL)
411 		return (NULL);
412 	if (savepwadj->pwa_passwd && *savepwadj->pwa_passwd)
413 		pwadj->pwa_passwd =  savepwadj->pwa_passwd;
414 	return (pwadj);
415 }
416 
417 static char *
418 pwskip(char *p)
419 {
420 	while(*p && *p != ':' && *p != '\n')
421 		++p;
422 	if (*p == '\n')
423 		*p = '\0';
424 	else if (*p != '\0')
425 		*p++ = '\0';
426 	return (p);
427 }
428 
429 static struct passwd_adjunct *
430 interpret(char *val, int len)
431 {
432 	struct _pwajunk *_pwa = _pwajunk();
433 	char *p;
434 	char *field;
435 
436 	if (_pwa == 0)
437 		return (NULL);
438 	(void) strncpy(interpline, val, len);
439 	p = interpline;
440 	interpline[len] = '\n';
441 	interpline[len+1] = 0;
442 
443 	apwadj.pwa_name = p;
444 	p = pwskip(p);
445 	if (strcmp(apwadj.pwa_name, "+") == 0) {
446 		/* we are going to the NIS - fix the
447 		 * rest of the struct as much as is needed
448 		 */
449 		apwadj.pwa_passwd = "";
450 		return (&apwadj);
451 	}
452 	apwadj.pwa_passwd = p;
453 	p = pwskip(p);
454 	field = p;
455 	p = pwskip(p);
456 	labelfromstring(0, field, &apwadj.pwa_minimum);
457 	field = p;
458 	p = pwskip(p);
459 	labelfromstring(0, field, &apwadj.pwa_maximum);
460 	field = p;
461 	p = pwskip(p);
462 	labelfromstring(0, field, &apwadj.pwa_def);
463 	field = p;
464 	p = pwskip(p);
465 	apwadj.pwa_au_always.as_success = 0;
466 	apwadj.pwa_au_always.as_failure = 0;
467 	if (getauditflagsbin(field, &apwadj.pwa_au_always) != 0)
468 		return (NULL);
469 	field = p;
470 	(void) pwskip(p);
471 	p = apwadj.pwa_passwd;
472 	while (*p && *p != ',')
473 		p++;
474 	if (*p)
475 		*p = '\0';
476 	apwadj.pwa_age = p;
477 	apwadj.pwa_au_never.as_success = 0;
478 	apwadj.pwa_au_never.as_failure = 0;
479 	if (getauditflagsbin(field, &apwadj.pwa_au_never) != 0)
480 		return (NULL);
481 	return (&apwadj);
482 }
483 
484 static void
485 freeminuslist(void) {
486 	struct _pwajunk *_pwa = _pwajunk();
487 	struct list *ls;
488 
489 	if (_pwa == 0)
490 		return;
491 	for (ls = minuslist; ls != NULL; ls = ls->nxt) {
492 		free(ls->name);
493 		free((char *) ls);
494 	}
495 	minuslist = NULL;
496 }
497 
498 static void
499 addtominuslist(char *name)
500 {
501 	struct _pwajunk *_pwa = _pwajunk();
502 	struct list *ls;
503 	char *buf;
504 
505 	if (_pwa == 0)
506 		return;
507 	ls = (struct list *) malloc(sizeof(struct list));
508 	buf = malloc((unsigned) strlen(name) + 1);
509 	(void) strcpy(buf, name);
510 	ls->name = buf;
511 	ls->nxt = minuslist;
512 	minuslist = ls;
513 }
514 
515 /*
516  * save away the psswd field, which is the only one which can be
517  * specified in a local + entry to override the value in the NIS
518  * for passwd.adjunct
519  */
520 static struct passwd_adjunct *
521 save(struct passwd_adjunct *pwadj)
522 {
523 	struct _pwajunk *_pwa = _pwajunk();
524 	static struct passwd_adjunct *sv;
525 
526 	if (_pwa == 0)
527 		return (NULL);
528 	/* free up stuff from last call */
529 	if (sv) {
530 		free(sv->pwa_passwd);
531 		free((char *) sv);
532 	}
533 	sv = (struct passwd_adjunct *) malloc(sizeof(struct passwd_adjunct));
534 
535 	sv->pwa_passwd = malloc((unsigned) strlen(pwadj->pwa_passwd) + 1);
536 	(void) strcpy(sv->pwa_passwd, pwadj->pwa_passwd);
537 
538 	return (sv);
539 }
540 
541 static int
542 onminuslist(struct passwd_adjunct *pwadj)
543 {
544 	struct _pwajunk *_pwa = _pwajunk();
545 	struct list *ls;
546 	char *nm;
547 
548 	if (_pwa == 0)
549 		return (0);
550 	nm = pwadj->pwa_name;
551 	for (ls = minuslist; ls != NULL; ls = ls->nxt) {
552 		if (strcmp(ls->name,nm) == 0) {
553 			return (1);
554 		}
555 	}
556 	return (0);
557 }
558