|
|
1.1 ! root 1: /* ! 2: * enter a password in the password file ! 3: * this program should be suid with owner ! 4: * with an owner with write permission on /etc/passwd ! 5: */ ! 6: #include <stdio.h> ! 7: #include <signal.h> ! 8: #include <pwd.h> ! 9: #include <errno.h> ! 10: #include <ctype.h> ! 11: ! 12: char passwd[] = "/etc/passwd"; ! 13: char npasswd[] = "/etc/npasswd"; ! 14: char tpasswd[] = "/etc/pwXXXXXX"; ! 15: char stdprof[] = "/etc/stdprofile"; ! 16: int newmode = 0755; ! 17: char *tempfile; ! 18: struct passwd *pwd; ! 19: long time(); ! 20: char *mktemp(); ! 21: char *readpasswd(); ! 22: struct passwd *getpwent(); ! 23: int endpwent(); ! 24: char *strcpy(); ! 25: char *crypt(); ! 26: char *getpass(); ! 27: char *getlogin(); ! 28: extern int optind; ! 29: extern int errno; ! 30: int newuser; ! 31: int alter; ! 32: char *username; ! 33: struct passwd pw; ! 34: ! 35: char *getstring(); ! 36: char *newstr(); ! 37: int rootid = 0; ! 38: ! 39: main(argc, argv) ! 40: char *argv[]; ! 41: { ! 42: char *pwp; ! 43: int c, u, maxuid; ! 44: FILE *tf; ! 45: ! 46: while ((c = getopt(argc, argv, "na")) != EOF) { ! 47: switch(c) { ! 48: case 'n': ! 49: newuser++; ! 50: break; ! 51: ! 52: case 'a': ! 53: alter++; ! 54: break; ! 55: ! 56: default: ! 57: exit(1); ! 58: } ! 59: } ! 60: if (optind >= argc) { ! 61: if (newuser==0) { ! 62: if ((username = getlogin()) == NULL) { ! 63: printf ("Usage: passwd [-na] [user]\n"); ! 64: exit(1); ! 65: } else ! 66: printf("Changing password for %s\n", username); ! 67: } ! 68: } else ! 69: username = argv[optind]; ! 70: if (username==NULL) { ! 71: username = getstring("User: "); ! 72: if (username==NULL || *username=='\0') { ! 73: printf("Cannot default user\n"); ! 74: exit(1); ! 75: } ! 76: } ! 77: maxuid = -1; ! 78: while ((pwd = getpwent()) != NULL) { ! 79: if (strcmp(pwd->pw_name, username) == 0) { ! 80: pw.pw_name = username; ! 81: pw.pw_passwd = newstr(pwd->pw_passwd); ! 82: pw.pw_uid = pwd->pw_uid; ! 83: pw.pw_gid = pwd->pw_gid; ! 84: pw.pw_gecos = newstr(pwd->pw_gecos); ! 85: pw.pw_dir = newstr(pwd->pw_dir); ! 86: pw.pw_shell = newstr(pwd->pw_shell); ! 87: } ! 88: if (pwd->pw_uid > maxuid) ! 89: maxuid = pwd->pw_uid; ! 90: } ! 91: endpwent(); ! 92: if (pw.pw_name==NULL && newuser==0) { ! 93: printf("Cannot find password entry for %s\n", username); ! 94: exit(1); ! 95: } ! 96: if (newuser) { ! 97: if (pw.pw_name) { ! 98: printf("user %s already exists\n", username); ! 99: exit(1); ! 100: } ! 101: pw.pw_name = username; ! 102: } ! 103: u = getuid(); ! 104: if (u!=rootid && (newuser || pw.pw_uid!=u)) { ! 105: printf("Permission denied.\n"); ! 106: exit(1); ! 107: } ! 108: pwp = readpasswd(u, pw.pw_passwd); ! 109: if (pwp==NULL) { ! 110: if (newuser==0) { ! 111: printf("Password unchanged.\n"); ! 112: if (alter==0) ! 113: exit(0); ! 114: pwp = pw.pw_passwd; ! 115: } else ! 116: pwp = ""; ! 117: } ! 118: pw.pw_passwd = pwp; ! 119: if (alter!=0 || newuser!=0) ! 120: otherfields(maxuid+1); ! 121: signal(SIGHUP, SIG_IGN); ! 122: signal(SIGINT, SIG_IGN); ! 123: signal(SIGQUIT, SIG_IGN); ! 124: tempfile = mktemp(tpasswd); ! 125: if((tf=fopen(tempfile,"w")) == NULL) { ! 126: printf("Cannot create temporary file\n"); ! 127: exit(1); ! 128: } ! 129: chmod(tempfile, 0644); ! 130: while((pwd=getpwent()) != NULL) { ! 131: if(strcmp(pwd->pw_name,username) == 0) ! 132: pwd = &pw; ! 133: fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n", ! 134: pwd->pw_name, ! 135: pwd->pw_passwd, ! 136: pwd->pw_uid, ! 137: pwd->pw_gid, ! 138: pwd->pw_gecos, ! 139: pwd->pw_dir, ! 140: pwd->pw_shell); ! 141: } ! 142: endpwent(); ! 143: if (newuser) { ! 144: pwd = &pw; ! 145: fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n", ! 146: pwd->pw_name, ! 147: pwd->pw_passwd, ! 148: pwd->pw_uid, ! 149: pwd->pw_gid, ! 150: pwd->pw_gecos, ! 151: pwd->pw_dir, ! 152: pwd->pw_shell); ! 153: } ! 154: fclose(tf); ! 155: /* ! 156: * move temp back to passwd file ! 157: * (carefully) ! 158: */ ! 159: while (link(tempfile, npasswd) < 0) { ! 160: if (errno == EEXIST) { ! 161: printf("Password file busy... shall I wait?"); ! 162: if (*getstring() == 'y') ! 163: sleep(5); ! 164: else ! 165: exit(1); ! 166: } else { ! 167: printf("Cannot link to temp\n"); ! 168: exit(1); ! 169: } ! 170: } ! 171: if (unlink(passwd) < 0) { ! 172: printf("Cannot unlink old passwd\n"); ! 173: exit(1); ! 174: } ! 175: if (link(npasswd, passwd) < 0) { ! 176: printf("Cannot link in new passwd.\n"); ! 177: exit(1); ! 178: } ! 179: unlink(npasswd); ! 180: unlink(tempfile); ! 181: return 0; ! 182: } ! 183: ! 184: char * ! 185: readpasswd(uid, opass) ! 186: char *opass; ! 187: { ! 188: static char minlen[] = ! 189: { 8, 8, 6, 5, 6, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4}; ! 190: register char *p, *npass; ! 191: register c, flags; ! 192: int ok, tries, pwlen; ! 193: long salt; ! 194: char saltc[2]; ! 195: char *rev(), *multi(); ! 196: register i; ! 197: ! 198: if (uid!=0 && opass && *opass) { ! 199: npass = getpass("Old password:"); ! 200: if (strcmp(crypt(npass, opass), opass)) { ! 201: printf("Sorry.\n"); ! 202: exit(1); ! 203: } ! 204: } ! 205: opass = NULL; ! 206: for (ok=0, tries=0;;) { ! 207: if (ok==0 && tries) { ! 208: printf("Password too simple. Try again.\n"); ! 209: opass = 0; ! 210: } ! 211: npass = newstr(getpass(ok?"Reconfirm password:":"New password:")); ! 212: if (opass && strcmp(opass, npass)) { ! 213: printf("Password mismatch.\n"); ! 214: exit(1); ! 215: } ! 216: if (strcmp(npass, "sorry")==0 && tries==0) { ! 217: if (*getstring("You want an unusable password, right? ") == 'y') ! 218: return("sorry"); ! 219: } ! 220: if (ok) ! 221: break; ! 222: pwlen = strlen(npass); ! 223: if (pwlen == 0) ! 224: return(NULL); ! 225: flags = 0; ! 226: p = npass; ! 227: while (c = *p++) { ! 228: if (islower(c)) ! 229: flags |= 02; ! 230: else if (isupper(c)) ! 231: flags |= 04; ! 232: else if (isdigit(c)) ! 233: flags |= 01; ! 234: else ! 235: flags |= 010; ! 236: } ! 237: if (tries>2 || pwlen>=minlen[flags]) ! 238: ok++; ! 239: tries++; ! 240: ! 241: if((strcmp(npass, pw.pw_name) == 0) ! 242: || (strcmp(npass, rev(pw.pw_name)) == 0) ! 243: || (strcmp(npass, multi(pw.pw_name)) == 0)){ ! 244: ! 245: ok = 0; ! 246: tries = 1; ! 247: } ! 248: ! 249: ! 250: opass = npass; ! 251: } ! 252: time(&salt); ! 253: salt += getpid(); ! 254: saltc[0] = salt & 077; ! 255: saltc[1] = (salt>>6) & 077; ! 256: for(i=0; i<2; i++) { ! 257: c = saltc[i] + '.'; ! 258: if(c>'9') c += 7; ! 259: if(c>'Z') c += 6; ! 260: saltc[i] = c; ! 261: } ! 262: return(newstr(crypt(npass, saltc))); ! 263: } ! 264: ! 265: char * ! 266: getstring(mesg) ! 267: char *mesg; ! 268: { ! 269: char buf[128], *fgets(); ! 270: ! 271: printf("%s", mesg); ! 272: if (fgets(buf, 128, stdin) == NULL) ! 273: exit(1); ! 274: buf[strlen(buf)-1] = '\0'; ! 275: return(newstr(buf)); ! 276: } ! 277: ! 278: char * ! 279: newstr(s) ! 280: char *s; ! 281: { ! 282: char *strcpy(); ! 283: return(strcpy(malloc(strlen(s)+1), s)); ! 284: } ! 285: ! 286: otherfields(uid) ! 287: { ! 288: char *s; ! 289: int id; ! 290: ! 291: if (newuser) { ! 292: s = getstring("UID: "); ! 293: while (!isnum(s)) { ! 294: printf ("Not numeric\n"); ! 295: s = getstring ("Enter numeric user ID: "); ! 296: } ! 297: if (*s != '\0') ! 298: uid = atoi (s); ! 299: pw.pw_uid = uid; ! 300: pw.pw_gid = 1; ! 301: } ! 302: if (newuser || alter) { ! 303: char defdir[128]; ! 304: ! 305: strcpy (defdir, "/usr/"); ! 306: strcat (defdir, pw.pw_name); ! 307: ! 308: s = getstring("GCOS acct,box: "); ! 309: if (*s) ! 310: pw.pw_gecos = s; ! 311: if (pw.pw_gecos==NULL) ! 312: pw.pw_gecos = ""; ! 313: s = getstring("Directory: "); ! 314: if (*s) ! 315: pw.pw_dir = s; ! 316: if (pw.pw_dir==NULL) ! 317: pw.pw_dir = newstr(defdir); ! 318: if (newuser) { ! 319: char *realdir; ! 320: realdir = pw.pw_dir; ! 321: if (realdir[0] == '*') { ! 322: realdir++; ! 323: if (realdir[0] != '/') { ! 324: char x[256]; ! 325: strcpy (x, "/"); ! 326: strcat (x, realdir); ! 327: strcat (x, "/"); ! 328: strcat (x, pw.pw_name); ! 329: realdir = newstr (x); ! 330: } ! 331: pw.pw_dir = newstr(defdir); ! 332: symlink (realdir, defdir); ! 333: } ! 334: mkdir(realdir); ! 335: chown(realdir, pw.pw_uid, pw.pw_gid); ! 336: chmod(realdir, newmode); ! 337: } ! 338: s = getstring("Shell: "); ! 339: if (*s) ! 340: pw.pw_shell = s; ! 341: if (pw.pw_shell == NULL) ! 342: pw.pw_shell = ""; ! 343: ! 344: /* Create .profile for the new user */ ! 345: if (newuser) { ! 346: FILE *inf, *outf; ! 347: ! 348: for (;;) { ! 349: s = getstring("Profile: "); ! 350: if (*s == '\0') ! 351: s = stdprof; ! 352: inf = fopen (s, "r"); ! 353: if (inf != NULL || s == stdprof) ! 354: break; ! 355: printf ("Can't open %s\n", s); ! 356: } ! 357: if (inf != NULL) { ! 358: char pname[128]; ! 359: register int c; ! 360: ! 361: (void) strcpy (pname, pw.pw_dir); ! 362: (void) strcat (pname, "/.profile"); ! 363: outf = fopen (pname, "w"); ! 364: if (outf == NULL) { ! 365: printf ("can't create %s\n", pname); ! 366: exit(1); ! 367: } ! 368: (void) chown (pname, pw.pw_uid, pw.pw_gid); ! 369: (void) chmod (pname, newmode); ! 370: ! 371: /* ! 372: * copy the profile file to the new ! 373: * user's .profile, transforming \N into ! 374: * the user's name, \D into his home ! 375: * directory, and \\ into \. ! 376: */ ! 377: while ((c = getc (inf)) != EOF) { ! 378: if (c == '\\') { ! 379: c = getc (inf); ! 380: switch (c) { ! 381: ! 382: case 'D': ! 383: fputs (pw.pw_dir, outf); ! 384: break; ! 385: ! 386: case 'N': ! 387: fputs (pw.pw_name,outf); ! 388: break; ! 389: ! 390: case EOF: ! 391: break; ! 392: ! 393: default: ! 394: putc ('\\', outf); ! 395: /* No break */ ! 396: case '\\': ! 397: putc (c, outf); ! 398: break; ! 399: } ! 400: } else ! 401: putc (c, outf); ! 402: } ! 403: if (ferror (inf) || ferror (outf)) ! 404: printf ("I/O error copying %s to %s\n", ! 405: s, pname); ! 406: (void) fclose (inf); ! 407: (void) fclose (outf); ! 408: } ! 409: } ! 410: } ! 411: } ! 412: ! 413: ! 414: int ! 415: mkdir(d) ! 416: register char *d; ! 417: { ! 418: register int pid, w; ! 419: int status; ! 420: ! 421: switch (pid=fork()) { ! 422: ! 423: case 0: ! 424: execl ("/bin/mkdir", "mkdir", d, 0); ! 425: execl ("/usr/bin/mkdir", "mkdir", d, 0); ! 426: /* No break */ ! 427: case -1: ! 428: return 1; ! 429: ! 430: default: ! 431: do w = wait (&status); ! 432: while (w != pid && w > 0); ! 433: if (w == pid) ! 434: return status; ! 435: return w; ! 436: } ! 437: } ! 438: ! 439: int ! 440: isnum(s) ! 441: register char *s; ! 442: { ! 443: while (*s) ! 444: if (!isdigit(*s++)) ! 445: return 0; ! 446: return 1; ! 447: } ! 448: char *rev(s) ! 449: char *s; ! 450: { ! 451: ! 452: static char t[200]; ! 453: char *p, *q; ! 454: ! 455: p = s; ! 456: q = &t[199]; ! 457: *q-- = '\0'; ! 458: ! 459: while(*q-- = *p++); ! 460: ! 461: return q+2; ! 462: } ! 463: char *multi(s) ! 464: char *s; ! 465: { ! 466: ! 467: int i, x; ! 468: char *p=s; ! 469: static char w[9]; ! 470: ! 471: while(*p++); x = p-s-1; ! 472: ! 473: if(x > 4) return "password"; ! 474: ! 475: *w = '\0'; ! 476: ! 477: for(i=0;i<2*x*x-(x*x*x+47*x)/6+12;i++) ! 478: ! 479: strcat(w,s); ! 480: ! 481: return w; ! 482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.