Annotation of 42BSD/bin/passwd.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)passwd.c   4.4 (Berkeley) 7/10/83";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Enter a password in the password file.
                      7:  * This program should be suid with an owner
                      8:  * with write permission on /etc/passwd.
                      9:  */
                     10: #include <sys/file.h>
                     11: 
                     12: #include <stdio.h>
                     13: #include <signal.h>
                     14: #include <pwd.h>
                     15: #include <errno.h>
                     16: 
                     17: char   passwd[] = "/etc/passwd";
                     18: char   temp[]   = "/etc/ptmp";
                     19: struct passwd *pwd;
                     20: struct passwd *getpwent();
                     21: int    endpwent();
                     22: char   *strcpy();
                     23: char   *crypt();
                     24: char   *getpass();
                     25: char   *getlogin();
                     26: char   *pw;
                     27: char   pwbuf[10];
                     28: extern int errno;
                     29: 
                     30: main(argc, argv)
                     31:        char *argv[];
                     32: {
                     33:        char *p;
                     34:        int i;
                     35:        char saltc[2];
                     36:        long salt;
                     37:        int u;
                     38:        int insist;
                     39:        int ok, flags;
                     40:        int c, pwlen, fd;
                     41:        FILE *tf;
                     42:        char *uname;
                     43: 
                     44:        insist = 0;
                     45:        if (argc < 2) {
                     46:                if ((uname = getlogin()) == NULL) {
                     47:                        printf ("Usage: passwd user\n");
                     48:                        exit(1);
                     49:                }
                     50:                printf("Changing password for %s\n", uname);
                     51:        } else
                     52:                uname = argv[1];
                     53:        while (((pwd = getpwent()) != NULL) && strcmp(pwd->pw_name, uname))
                     54:                ;
                     55:        u = getuid();
                     56:        if (pwd == NULL || (u != 0 && u != pwd->pw_uid)) {
                     57:                printf("Permission denied.\n");
                     58:                exit(1);
                     59:        }
                     60:        endpwent();
                     61:        if (pwd->pw_passwd[0] && u != 0) {
                     62:                strcpy(pwbuf, getpass("Old password:"));
                     63:                pw = crypt(pwbuf, pwd->pw_passwd);
                     64:                if (strcmp(pw, pwd->pw_passwd) != 0) {
                     65:                        printf("Sorry.\n");
                     66:                        exit(1);
                     67:                }
                     68:        }
                     69: tryagain:
                     70:        strcpy(pwbuf, getpass("New password:"));
                     71:        pwlen = strlen(pwbuf);
                     72:        if (pwlen == 0) {
                     73:                printf("Password unchanged.\n");
                     74:                exit(1);
                     75:        }
                     76:        /*
                     77:         * Insure password is of reasonable length and
                     78:         * composition.  If we really wanted to make things
                     79:         * sticky, we could check the dictionary for common
                     80:         * words, but then things would really be slow.
                     81:         */
                     82:        ok = 0;
                     83:        flags = 0;
                     84:        p = pwbuf;
                     85:        while (c = *p++) {
                     86:                if (c >= 'a' && c <= 'z')
                     87:                        flags |= 2;
                     88:                else if (c >= 'A' && c <= 'Z')
                     89:                        flags |= 4;
                     90:                else if (c >= '0' && c <= '9')
                     91:                        flags |= 1;
                     92:                else
                     93:                        flags |= 8;
                     94:        }
                     95:        if (flags >= 7 && pwlen >= 4)
                     96:                ok = 1;
                     97:        if ((flags == 2 || flags == 4) && pwlen >= 6)
                     98:                ok = 1;
                     99:        if ((flags == 3 || flags == 5 || flags == 6) && pwlen >= 5)
                    100:                ok = 1;
                    101:        if (!ok && insist < 2) {
                    102:                printf("Please use %s.\n", flags == 1 ?
                    103:                        "at least one non-numeric character" :
                    104:                        "a longer password");
                    105:                insist++;
                    106:                goto tryagain;
                    107:        }
                    108:        if (strcmp(pwbuf, getpass("Retype new password:")) != 0) {
                    109:                printf("Mismatch - password unchanged.\n");
                    110:                exit(1);
                    111:        }
                    112:        time(&salt);
                    113:        salt = 9 * getpid();
                    114:        saltc[0] = salt & 077;
                    115:        saltc[1] = (salt>>6) & 077;
                    116:        for (i = 0; i < 2; i++) {
                    117:                c = saltc[i] + '.';
                    118:                if (c > '9')
                    119:                        c += 7;
                    120:                if (c > 'Z')
                    121:                        c += 6;
                    122:                saltc[i] = c;
                    123:        }
                    124:        pw = crypt(pwbuf, saltc);
                    125:        signal(SIGHUP, SIG_IGN);
                    126:        signal(SIGINT, SIG_IGN);
                    127:        signal(SIGQUIT, SIG_IGN);
                    128:        (void) umask(0);
                    129:        fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
                    130:        if (fd < 0) {
                    131:                fprintf(stderr, "passwd: ");
                    132:                if (errno == EEXIST)
                    133:                        fprintf(stderr, "password file busy - try again.\n");
                    134:                else
                    135:                        perror(temp);
                    136:                exit(1);
                    137:        }
                    138:        signal(SIGTSTP, SIG_IGN);
                    139:        if ((tf = fdopen(fd, "w")) == NULL) {
                    140:                fprintf(stderr, "passwd: fdopen failed?\n");
                    141:                exit(1);
                    142:        }
                    143:        /*
                    144:         * Copy passwd to temp, replacing matching lines
                    145:         * with new password.
                    146:         */
                    147:        while ((pwd = getpwent()) != NULL) {
                    148:                if (strcmp(pwd->pw_name,uname) == 0) {
                    149:                        u = getuid();
                    150:                        if (u && u != pwd->pw_uid) {
                    151:                                fprintf(stderr, "passwd: permission denied.\n");
                    152:                                unlink(temp);
                    153:                                exit(1);
                    154:                        }
                    155:                        pwd->pw_passwd = pw;
                    156:                        if (pwd->pw_gecos[0] == '*')
                    157:                                pwd->pw_gecos++;
                    158:                }
                    159:                fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
                    160:                        pwd->pw_name,
                    161:                        pwd->pw_passwd,
                    162:                        pwd->pw_uid,
                    163:                        pwd->pw_gid,
                    164:                        pwd->pw_gecos,
                    165:                        pwd->pw_dir,
                    166:                        pwd->pw_shell);
                    167:        }
                    168:        endpwent();
                    169:        if (rename(temp, passwd) < 0) {
                    170:                fprintf(stderr, "passwd: "); perror("rename");
                    171:                unlink(temp);
                    172:                exit(1);
                    173:        }
                    174:        fclose(tf);
                    175: }

unix.superglobalmegacorp.com

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