date and time created 83/01/01 13:24:54 by sam
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Sun, 2 Jan 1983 05:24:54 +0000 (21:24 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Sun, 2 Jan 1983 05:24:54 +0000 (21:24 -0800)
SCCS-vsn: usr.bin/passwd/passwd.c 4.1

usr/src/usr.bin/passwd/passwd.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/passwd/passwd.c b/usr/src/usr.bin/passwd/passwd.c
new file mode 100644 (file)
index 0000000..7e2ed02
--- /dev/null
@@ -0,0 +1,183 @@
+#ifndef lint
+static char sccsid[] = "@(#)passwd.c   4.1 (Berkeley) %G%";
+#endif
+
+/*
+ * enter a password in the password file
+ * this program should be suid with owner
+ * with an owner with write permission on /etc/passwd
+ */
+#include <sys/file.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+
+char   passwd[] = "/etc/passwd";
+char   temp[]   = "/etc/ptmp";
+struct passwd *pwd;
+struct passwd *getpwent();
+int    endpwent();
+char   *strcpy();
+char   *crypt();
+char   *getpass();
+char   *getlogin();
+char   *pw;
+char   pwbuf[10];
+extern int errno;
+
+main(argc, argv)
+       char *argv[];
+{
+       char *p;
+       int i;
+       char saltc[2];
+       long salt;
+       int u;
+       int insist;
+       int ok, flags;
+       int c, pwlen, fd;
+       FILE *tf;
+       char *uname;
+
+       insist = 0;
+       if (argc < 2) {
+               if ((uname = getlogin()) == NULL) {
+                       printf ("Usage: passwd user\n");
+                       exit(1);
+               }
+               printf("Changing password for %s\n", uname);
+       } else
+               uname = argv[1];
+       while (((pwd = getpwent()) != NULL) && strcmp(pwd->pw_name, uname))
+               ;
+       u = getuid();
+       if (pwd == NULL || (u != 0 && u != pwd->pw_uid)) {
+               printf("Permission denied.\n");
+               exit(1);
+       }
+       endpwent();
+       if (pwd->pw_passwd[0] && u != 0) {
+               strcpy(pwbuf, getpass("Old password:"));
+               pw = crypt(pwbuf, pwd->pw_passwd);
+               if (strcmp(pw, pwd->pw_passwd) != 0) {
+                       printf("Sorry.\n");
+                       exit(1);
+               }
+       }
+tryagain:
+       strcpy(pwbuf, getpass("New password:"));
+       pwlen = strlen(pwbuf);
+       if (pwlen == 0) {
+               printf("Password unchanged.\n");
+               exit(1);
+       }
+       /*
+        * Insure password is of reasonable length and
+        * composition.  If we really wanted to make things
+        * sticky, we could check the dictionary for common
+        * words, but then things would really be slow.
+        */
+       ok = 0;
+       flags = 0;
+       p = pwbuf;
+       while (c = *p++) {
+               if (c >= 'a' && c <= 'z')
+                       flags |= 2;
+               else if (c >= 'A' && c <= 'Z')
+                       flags |= 4;
+               else if (c >= '0' && c <= '9')
+                       flags |= 1;
+               else
+                       flags |= 8;
+       }
+       if (flags >= 7 && pwlen >= 4)
+               ok = 1;
+       if ((flags == 2 || flags == 4) && pwlen >= 6)
+               ok = 1;
+       if ((flags == 3 || flags == 5 || flags == 6) && pwlen >= 5)
+               ok = 1;
+       if (!ok && insist < 2) {
+               if (flags == 1)
+               printf("Please use %s.\n", flags == 1 ?
+                       "at least one non-numeric character" :
+                       "a longer password");
+               insist++;
+               goto tryagain;
+       }
+       if (strcmp(pwbuf, getpass("Retype new password:")) != 0) {
+               printf("Mismatch - password unchanged.\n");
+               exit(1);
+       }
+       time(&salt);
+       salt = 9 * getpid();
+       saltc[0] = salt & 077;
+       saltc[1] = (salt>>6) & 077;
+       for (i = 0; i < 2; i++) {
+               c = saltc[i] + '.';
+               if (c > '9')
+                       c += 7;
+               if (c > 'Z')
+                       c += 6;
+               saltc[i] = c;
+       }
+       pw = crypt(pwbuf, saltc);
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       /*
+        * The mode here could be 644 except then old versions
+        * of passwd that don't honor the advisory locks might
+        * sneak in and mess things up.  If we could believe the
+        * locking were honored, then we could also eliminate the
+        * chmod below after the rename.
+        */
+       fd = open(temp, FWRONLY|FCREATE|FEXLOCK|FNBLOCK, 0600);
+       if (fd < 0) {
+               fprintf(stderr, "passwd: ");
+               if (errno == EBUSY)
+                       fprintf(stderr, "password file busy - try again.\n");
+               else
+                       perror(temp);
+               exit(1);
+       }
+       signal(SIGTSTP, SIG_IGN);
+       if ((tf = fdopen(fd, "w")) == NULL) {
+               fprintf(stderr, "passwd: fdopen failed?\n");
+               exit(1);
+       }
+       /*
+        * Copy passwd to temp, replacing matching lines
+        * with new password.
+        */
+       while ((pwd = getpwent()) != NULL) {
+               if (strcmp(pwd->pw_name,uname) == 0) {
+                       u = getuid();
+                       if (u && u != pwd->pw_uid) {
+                               fprintf(stderr, "passwd: permission denied.\n");
+                               unlink(temp);
+                               exit(1);
+                       }
+                       pwd->pw_passwd = pw;
+                       if (pwd->pw_gecos[0] == '*')
+                               pwd->pw_gecos++;
+               }
+               fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
+                       pwd->pw_name,
+                       pwd->pw_passwd,
+                       pwd->pw_uid,
+                       pwd->pw_gid,
+                       pwd->pw_gecos,
+                       pwd->pw_dir,
+                       pwd->pw_shell);
+       }
+       endpwent();
+       if (rename(temp, passwd) < 0) {
+               fprintf(stderr, "passwd: "); perror("rename");
+               unlink(temp);
+               exit(1);
+       }
+       chmod(passwd, 0644);
+       fclose(tf);
+}