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