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