Cover V03, I02
Article
Figure 1
Figure 2
Listing 1
Listing 2
Listing 3
Table 1

mar94.tar


Listing 3: Changing a user's password

/*****************************************************************************
*                             Listing 3                                     *
*****************************************************************************/

/*
* Program to change a user's password
*/

#include        <stdio.h>
#include        <pwd.h>

extern char *getlogin ();
extern char *getpass ();
extern char *crypt ();
extern char *malloc ();

static int  put_encrypted    ();

main (argc, argv)
int argc;
char *argv [];
{
char encrypted [15];
char password [BUFSIZ];
char *cp;
char *oldpwd;
char *newpwd1;
char *newpwd2;
char *user;
int  isroot;
struct passwd *pe;

user = (char *) NULL;
isroot = (getuid () == 0);

/*
* Find out the name of the user currently logged in
*/
if ((user = getlogin ()) == NULL)
{
/*
* You may or may not want to include this secondary
* method of determining the current user
*/
if ((pe = getpwuid (getuid ())) != NULL)
cp = pe->pw_name;
else
fprintf (stderr, "%s: Who are you ???\n", argv [0]);
}

/*
* We must do this to get root privileges on some systems, although
* we may be already running with setuid root privileges.
*/
setuid (geteuid ());

/*
* Determine the user whose password is to be changed
*/

if (argc > 1)
{
user = (char *) NULL;

/*
* Take user from command line argument
*/
if (argc > 2)
fprintf (stderr, "Usage: %s [username]\n", argv [0]);
else
{
/*
* Only allow the super user to change other user's passwords
*/
if (!isroot && (user == NULL || strcmp (user, argv [1]) != 0))
fprintf (stderr, "%s: Permission denied\n", argv [0]);
else
user = argv [1];
}
}

/*
* Check for validity of user
*/
if (user == (char *) NULL)
exit (1);

if (getpwnam (user) == NULL)
{
fprintf (stderr, "%s: Unknow user %s\n", argv [0], user);
exit (1);
}

/*
* Get old (encrypted) password
*/
if (get_encrypted (user, password) != 0)
{
perror (argv [0]);
exit (1);
}

printf ("Changing password for user %s\n", user);

/*
* If you are super user or if the user had no password,
* then we do not need to verify the old password.
*/
if (!isroot && strlen (password) != 0)
{
if ((oldpwd = getpass ("Old password: ")) == NULL)
{
perror (argv [0]);
exit (1);
}

/*
* The first two letters of the current password are the
* salt used to encrypt the password. Consequently we
* must use it again to encrypt the password that the
* user claims is the current one.
*/
cp = crypt (oldpwd, password);

if (strcmp (cp, password) != 0)
{
/*
* The user was mistaken. The inputed password is not
* the same as the current password.
*/
fprintf (stderr, "Sorry.\n");
exit (1);
}
}

/*
* So far so good. Now lets get the user to input the new password.
* We make the user do it twice to ensure that they did not make
* a typing error while entering it.
*/
if ((newpwd1 = getpass ("New password: ")) == NULL)
{
perror (argv [0]);
exit (1);
}

/*
* getpass() returns pointer to static data. Copy it before we
* call it again.
*/
strcpy (password, newpwd1);

if ((newpwd2 = getpass ("Retype new password: ")) == NULL)
{
perror (argv [0]);
exit (1);
}

/*
* Are they the same ???
*/
if (strcmp (password, newpwd2) != 0)
{
fprintf (stderr, "Mismatch - password unchanged\n");
exit (1);
}

/*
* At this time you may want to implement some rules for
* the password. Some examples:
*
*   - Minimum password length
*   - Password different from username
*   - Password not in dictionary file
*/

/*
* Create a new encrypted password
*/
make_passwd (password, encrypted);

/*
* Save the new password
*/
put_encrypted (user, encrypted);
}

static int
put_encrypted (user, encrypted)
char *user;
char *encrypted;
{
fprintf (stderr, "Encrypted password for user %s is %s\n", user, encrypted);
}