home *** CD-ROM | disk | FTP | other *** search
- /* vi:tabstop=4:shiftwidth=4:smartindent
- *
- * passwd.c - Change password for a user.
- *
- */
- #include <time.h>
- #include "login.h"
-
- #define PASSWD "/etc/passwd"
- #define PASSWD_NEW "/etc/passwd.new"
- #define PASSWD_OLD "/etc/passwd.old"
-
- /* Old and new passwords.
- */
- char pass1[1024], pass2[1024];
-
- /* Run at exit to blank any plaintext password. Running it as
- * an atexit function should protect them in all circumstances.
- */
- void splange(void)
- {
- int i;
- for (i=0; i<1024; i++)
- {
- pass1[i] = pass2[i] = '\0';
- }
- }
-
- /* Characters we allow in the salt.
- */
- char *saltchars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-
- int main(void)
- {
- struct passwd *pw;
- char salt[3], *pass;
- int uid;
- FILE *fp;
-
- #ifdef crypt
- init_des();
- #endif
-
- /* Make sure that any plaintext passwords get zapped.
- */
- atexit(splange);
-
- /* Disable escape.
- */
- signal(SIGINT, SIG_IGN);
-
- /* Find out who is running the program.
- */
- pw = getpwnam(getenv("USER"));
- if (pw == NULL)
- {
- fprintf(stderr, "Can't get your passwd entry\n");
- exit(1);
- }
-
- /* If they have a password, ask them for it.
- */
- if (pw->pw_passwd[0])
- {
- get("Old Password: ", pass1, 0);
-
- /* If they enter the wrong password then don't let them
- * change it.
- */
- strncpy(salt, pw->pw_passwd, 2);
- salt[2] = '\0';
- if (strcmp(pw->pw_passwd, crypt(pass1, salt)))
- {
- fprintf(stderr, "Sorry\n");
- exit(1);
- }
- }
-
- /* OK, they knew their old password. Ask them for a new one.
- */
- get("New Password: ", pass1, 0);
- if (strlen(pass1) < 6)
- {
- fprintf(stderr, "Your password must be six or more characters long\n");
- exit(1);
- }
-
- /* Twice, just to make sure.
- */
- get("Again: ", pass2, 0);
- if (strcmp(pass1, pass2))
- {
- fprintf(stderr, "The new passwords didn't match\n");
- exit(1);
- }
-
- /* Generate a salt for the new password. I don't know the criterion
- * for generating these under Unix, but we should be safe if it's
- * limited to letters and numbers.
- */
- srand(time(NULL));
- salt[0] = saltchars[rand() % strlen(saltchars)];
- salt[1] = saltchars[rand() % strlen(saltchars)];
- strcpy(pass1, crypt(pass2, salt));
-
- /* Copy the password file, making the relevant change.
- */
- fp = fopen(PASSWD_NEW, "w");
- if (fp == NULL)
- {
- fprintf(stderr, "Can't open new password file\n");
- exit(1);
- }
-
- /* Remember the uid for searching.
- */
- uid = pw->pw_uid;
-
- setpwent();
- while (pw = getpwent())
- {
- if ((pw->pw_uid != uid) || (strcmp(pw->pw_name, getenv("USER"))))
- {
- pass = pw->pw_passwd;
- }
- else
- {
- pass = pass1;
- }
-
- /* Output the current record to the new file.
- */
- fprintf(fp, "%s:%s:%d:%d:%s:%s:%s\n", pw->pw_name, pass,
- pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir,
- pw->pw_shell);
- }
- endpwent();
-
- fclose(fp);
-
- /* Finally shuffle the files.
- */
- remove(PASSWD_OLD);
- rename(PASSWD, PASSWD_OLD);
- rename(PASSWD_NEW, PASSWD);
-
- exit(0);
- }
-