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