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 *
_pwajunk(void)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 *
getpwanam(char * name)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
setpwaent(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
endpwaent(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 *
getpwaent(void)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
matchname(char line1[],struct passwd_adjunct ** pwadjp,char * name)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
getnextfromyellow(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
getfirstfromyellow(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 *
getnamefromyellow(char * name,struct passwd_adjunct * savepwadj)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 *
interpretwithsave(char * val,int len,struct passwd_adjunct * savepwadj)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 *
pwskip(char * p)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 *
interpret(char * val,int len)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
freeminuslist(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
addtominuslist(char * name)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 *
save(struct passwd_adjunct * pwadj)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
onminuslist(struct passwd_adjunct * pwadj)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