Annotation of coherent/d/bin/passwd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Rec'd from Lauren Weinstein, 7-16-84.
                      3:  * Passwd - set login password
                      4:  * for a user.
                      5:  */
                      6: 
                      7: #include <stdio.h>
                      8: #include <ctype.h>
                      9: #include <sys/types.h>
                     10: #include <pwd.h>
                     11: #include <signal.h>
                     12: #include <errno.h>
                     13: 
                     14: #define        NSALT   64              /* Size of salt character set */
                     15: #define        NSALTC  2               /* Number of characters in salt */
                     16: #define        NPASSC  32              /* Maximum characters copied into pass. buf */
                     17: #define        AWRITE  2               /* Access for write */
                     18: #define        NLOKOUT 7               /* Maximum number of lockout attempts */
                     19: #define        NPWCHAR 256             /* Number of characters in passwd file line */
                     20: 
                     21: char   notrich[] = "\
                     22: Password is too easily broken\n\
                     23: Try again: \
                     24: ";
                     25: char   pfile[] = "/etc/passwd";
                     26: char   tmpfile[] = "/tmp/passwd";
                     27: 
                     28: char   salttab[NSALT] =
                     29:        "./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                     30: 
                     31: char   pwline[NPWCHAR];
                     32: 
                     33: FILE   *lockopen();
                     34: char   *crypt();
                     35: int    cleanup();
                     36: time_t time();
                     37: 
                     38: int    tmpflag;                /* Says tempfile is open */
                     39: 
                     40: main(argc, argv)
                     41: char *argv[];
                     42: {
                     43:        register struct passwd *pwp;
                     44:        register char *pass, *name;
                     45:        char passbuf[NPASSC+1];
                     46:        int myuid;
                     47:        char *myname;
                     48:        extern char *getpass();
                     49:        extern char *getlogin();
                     50: 
                     51:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                     52:                signal(SIGINT, cleanup);
                     53:        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
                     54:                signal(SIGHUP, cleanup);
                     55:        myuid = getuid();
                     56: 
                     57:        umask(077);  /* mask out file access by other users */
                     58: 
                     59:        if (argc > 1) { /* By supplied argument */
                     60:                if (argc != 2)
                     61:                        usage();
                     62:                if ((pwp = getpwnam(argv[1])) == NULL)
                     63:                        perr("%s: bad user name\n", argv[1]);
                     64:                if (myuid!=0 && pwp->pw_uid!=myuid)
                     65:                        perr("%s: not allowed to change password\n", argv[1]);
                     66:                name = argv[1];  /* get name for change */
                     67:        } else          /* By getlogin from /etc/utmp */
                     68:        if ((myname = getlogin()) != NULL) {
                     69:                if ((pwp = getpwnam(myname)) == NULL)
                     70:                        perr("%s: bad login name\n", argv[1]);
                     71:                if (myuid != 0 && pwp->pw_uid != myuid)
                     72:                        perr("%s: not allowed to change password\n", argv[1]);
                     73:                name = myname;  /* get name for change */
                     74:        } else {        /* By user id */
                     75:                if ((pwp = getpwuid(myuid)) == NULL)
                     76:                        perr("Error on /etc/passwd\n");
                     77:                while ((pwp = getpwent()) != NULL)
                     78:                        if (pwp->pw_uid == myuid)
                     79:                                perr("user id is not unique\n");
                     80:                pwp = getpwuid(myuid);
                     81:                name = pwp->pw_name;  /* changing our own name */
                     82:        }
                     83:        if (myuid!=0 && pwp->pw_passwd[0]!='\0') {
                     84:                if ((pass = getpass("Old password: ")) == NULL)
                     85:                        exit(1);
                     86:                if (!checkpass(pwp->pw_passwd, pass))
                     87:                        perr("Sorry\n");
                     88:        }
                     89:        if ((pass = getpass("New password: ")) == NULL)
                     90:           exit(1);
                     91:        if (pass[0] != 0 || (pass[0] == 0 && getuid() != 0))
                     92:           while (!richenough(pass) || !strcmp(pass, pwp->pw_name))
                     93:              if ((pass = getpass(notrich)) == NULL)
                     94:                 exit(1);
                     95:        strncpy(passbuf, pass, NPASSC);
                     96:        if ((pass = getpass("Verification: ")) == NULL) 
                     97:           exit(1);
                     98:        if (strncmp(pass, passbuf, NPASSC) != 0)
                     99:           perr("No match: password not changed\n");
                    100:        setpass(name, pass);
                    101: }
                    102: 
                    103: /*
                    104:  * Tests to see if a password is rich enough
                    105:  * (i.e. not too easy to break by exhaustion).
                    106:  * A password must be 4 characters if the alphabet
                    107:  * is rich enough and 6 characters if it is in a
                    108:  * single case.  Perhaps the dictionary should
                    109:  * be searched as well for more security-conscious
                    110:  * systems.  We also check (above) to make sure
                    111:  * that the selected password is not the same as the username!
                    112:  */
                    113: richenough(passwd)
                    114: char *passwd;
                    115: {
                    116:        register char *cp;
                    117:        register int uflag=0, lflag=0, oflag=0;
                    118:        register int l;
                    119: 
                    120:        for (cp = passwd; *cp != '\0'; cp++) {
                    121:                if (islower(*cp))
                    122:                        lflag = 1;
                    123:                else if (isupper(*cp))
                    124:                        uflag = 1;
                    125:                else
                    126:                        oflag = 1;
                    127:        }
                    128:        l = cp-passwd;
                    129:        if (l < 4)
                    130:                return (0);
                    131:        if (oflag==0 && lflag^uflag && l<6)
                    132:                return (0);
                    133:        return (1);
                    134: }
                    135: 
                    136: /*
                    137:  * Check the passwd in the password file (`rpass')
                    138:  * against the typed-in (`tpass') password.
                    139:  */
                    140: checkpass(rpass, tpass)
                    141: register char *rpass, *tpass;
                    142: {
                    143:        char salt[3];
                    144: 
                    145:        salt[0] = rpass[0];
                    146:        salt[1] = rpass[1];
                    147:        return (strcmp(crypt(tpass, salt), rpass) == 0);
                    148: }
                    149: 
                    150: /*
                    151:  * Set password for specified name.
                    152:  */
                    153: setpass(name, passwd)
                    154: char *name, *passwd;
                    155: {
                    156:        char salt[NSALTC+1];
                    157:        char namebuff[NPWCHAR];  /* name buffer */
                    158:        time_t xtime;
                    159:        register char *p1, *p2;
                    160:        register int c;
                    161:        register FILE *pwf;
                    162:        register FILE *tf;
                    163: 
                    164:        /*
                    165:         * Generate the salt for crypt.
                    166:         */
                    167:        time(&xtime);
                    168:        srand((int)xtime);
                    169:        salt[0] = salttab[rand()%NSALT];
                    170:        salt[1] = salttab[rand()%NSALT];
                    171:        salt[2] = '\0';
                    172:        if (*passwd != '\0')
                    173:                passwd = crypt(passwd, salt);
                    174:        /*
                    175:         * Copy password file to tempfile
                    176:         * looking for slot to change.
                    177:         * The format of a passwd entry is:
                    178:         * name:password:uid:...
                    179:         */
                    180:        if ((pwf = fopen(pfile, "r")) == NULL)
                    181:                perr("Cannot open %s\n", pfile);
                    182:        tf = lockopen(tmpfile);
                    183:        while (fgets(pwline, NPWCHAR, pwf) != NULL) {
                    184:                strcpy(namebuff, pwline);  /* copy line */
                    185:                p1 = namebuff;          
                    186:                while (*p1 != '\0')
                    187:                        if (*p1++ == ':')
                    188:                                break;  
                    189:                *--p1 = '\0';  /* null terminate user name */
                    190:                                        
                    191:                p1 = pwline;
                    192:                while (*p1 != '\0')
                    193:                        if (*p1++ == ':')
                    194:                                break;
                    195:                p2 = p1;
                    196:                while (*p2 != '\0')
                    197:                        if (*p2++ == ':')
                    198:                                break;
                    199: 
                    200:                if (!strcmp(namebuff, name)) {  /* check for name match */
                    201:                        *p1 = '\0';
                    202:                        fputs(pwline, tf);
                    203:                        fputs(passwd, tf);
                    204:                        putc(':', tf);
                    205:                        fputs(p2, tf);
                    206:                        break;
                    207:                }
                    208:                fputs(pwline, tf);
                    209:        }
                    210:        while ((c = getc(pwf)) != EOF)  /* copy rest of file */
                    211:                putc(c, tf);
                    212:        fclose(pwf);
                    213:        /*
                    214:         * Copy tempfile back to password
                    215:         * file -- this runs protected
                    216:         * from interrupts.
                    217:         */
                    218:        signal(SIGINT, SIG_IGN);
                    219:        signal(SIGHUP, SIG_IGN);
                    220:        signal(SIGQUIT, SIG_IGN);
                    221:        if ((pwf = fopen(pfile, "w")) == NULL)
                    222:                perr("Cannot create %s\n", pfile);
                    223:        fflush(tf);
                    224:        rewind(tf);
                    225:        while ((c = getc(tf)) != EOF)
                    226:                putc(c, pwf);
                    227:        fflush(pwf);
                    228:        unlink(tmpfile);  
                    229: }
                    230: 
                    231: /*
                    232:  * Open the tempfile waiting
                    233:  * for the tempfile to come free.
                    234:  */
                    235: FILE *
                    236: lockopen(file)
                    237: char *file;
                    238: {
                    239:        register int n;
                    240:        register FILE *fp;
                    241:        extern int errno;
                    242: 
                    243:        for (n=NLOKOUT; n>0; n--)
                    244:                if (access(file, AWRITE)<0 && errno==ENOENT) {
                    245:                        if ((fp=fopen(file, "w")) == NULL
                    246:                        ||  (fp=freopen(file, "r+w", fp)) == NULL)
                    247:                                perr("Cannot create tempfile\n");
                    248:                        tmpflag = 1;
                    249:                        return (fp);
                    250:                }
                    251:        perr("Tempfile busy, try again later\n");
                    252: }
                    253: 
                    254: /*
                    255:  * Cleanup the tempfile.
                    256:  */
                    257: cleanup()
                    258: {
                    259:        if (tmpflag)
                    260:                unlink(tmpfile);
                    261:        exit (1);
                    262: }
                    263: 
                    264: /*
                    265:  * Error routines
                    266:  */
                    267: usage()
                    268: {
                    269:        perr("Usage: passwd [name]\n");
                    270: }
                    271: 
                    272: perr(x)
                    273: {
                    274:        fprintf(stderr, "%r", &x);
                    275:        exit(1);
                    276: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.