
Run our Perl script to report any changes in the
system password file since the last time the script was run
By Becca Thomas
Often users must be able to change particular password-file
fields, such as their shell, information in the comment (fifth)
field, and, of course, their encrypted password.
There are ways to monitor password file changes and prevent
being surprised by unexpected changes. One way is to run this
month's Perl script periodically, say using cron, to watch for
any unauthorized changes that might compromise your system's
security.
Small Change
Dear Dr. Thomas:
The passwdchng Perl program [Part A of the Listing] reports any
changes to the system password file (/etc/passwd)
since the last time the passwdchng program was run.
I've found this report helpful when coordinating other services,
such as an internal telephone directory that relies on the
password file for information. I have cron run
passwdchng regularly and mail any output to the
administrative account (root).
First, the program stores a copy of the current password file
in the directory specified by the $logdir
configuration variable. This directory should not be generally
accessible because it will contain a copy of the password file
with encrypted password.
You should place the command that displays your password file
in the $display passwd_configuration variable.
Generally, cat /etc/passwd is used, but systems
running NIS (Network Information Services, formerly Yellow Pages)
would use ypcat passwd instead.
If you don't use a shadow password file, anyone can read
encrypted passwords. The ypcat command used before
NIS+ will include encrypted passwords even if you do use
a shadowed password file. The $old variable names
the file to contain the previous copy, whereas $new
names the file to contain the current copy of the password file.
Both these names can be changed at configuration time. The
program first checks that $logdir names a directory
that is writable. If a previous copy of the password file
doesn't exist, a reference copy is saved and the program exits.
You can run passswdchng again when you're ready to
detect any changes. Otherwise, the current copy of the password
file is saved.
The program runs the external Unix diff utility
to compare the previous and current password files. Only changed
output lines, which are prefixed by angle brackets, are examined
further. The old and new lines are placed in different
associative arrays indexed by account name. Each array is
scanned: any entry in the ``old'' array that doesn't have a
corresponding ``new'' array entry is considered ``removed''; then
the ``new'' array is examined for changed or new entries.
Finally, the new password file overwrites the old one to ready
the program for the next run.
Two subroutines are defined: &show() simply
reports the account name then how the entry was changed (new,
removed, or changed); the &get_changes() function
displays the field that was changed.
This program was developed under both Solaris 2.0 and SunOS
4.1.2. It should be quite portable to any system that has Perl
installed. You can also use Perl library routines, like
getpwent() to obtain password file entries, but I've
had enough difficulties with these routines that I chose my
current approach as detailed above.
I've included some sample output [Part B]. These results tell me that
someone has changed the Gecos (fifth) field for the ``dept''
account, that ``dmv'' is now an active user (we deactivate an
account by specifying /bin/false as the shell), that
``tbaker'' has removed their phone number from the Gecos field,
and new account ``picasso'' was created since the last time
passwdchng was run.
Chris Wharton / Jingili, Darwin, Australia
Tester's Comments
- As long as the password file is intact, the script functions
correctly: It shows all added, changed, or deleted entries as
expected. However, if I corrupt a copy of the password file,
passwdchng displays the changes but doesn't detect
that the file is corrupted. Even worse, the next run shows no
output! It's arguable that this script should also check
password-file integrity, although the pwck utility
does just that. [Editor's note: Pwck is
available for AT&T-derived Unix systems starting with System III
and pwcheck was introduced in Xenix 3.0/5.0.]
Although SCO Xenix keeps the encrypted password in
/etc/passwd, SCO Unix uses a ``shadow'' password
file (/etc/shadow) so password changes aren't
recorded by passwdchng.--Kees Hendrikse, Echelon Consultancy,
Enschede, The Netherlands
- The program runs as expected under Unixware Application
Server 1.0 with Perl 4.0.36 and under 386 BSD with Perl 4.0.19.
I did a quick comparison of getpwent() calls under these
environments: they were the same except that the 386 BSD version
didn't return the Gecos field entry. This call can detect some
password-file corruption.
I found passwdchng useful for tracking the user database: its
output can be used to semiautomate propagation of changed user
status in a local-area network. However, implementors should be
careful in modifying /etc/passwd directly. It's
safer to use any available ``add, change, or delete user''
utilities for updating the user database.
Besides the password file, you might consider comparing these
files in these environments: /etc/shadow (SVR3.2,
SVR4), /etc/security/ia/index and
/etc/security/ia/master (SVR4.2), and
/tcb/files/auth/?/* (SCO 3.2.2). Of course, failure
of the getpwent() call won't detect whether these
files are corrupt.--Endre Bálint Nagy, Walton Networking
Ltd., Budapest, Hungary
- Other testers report that the script works as advertised
using Perl 4.0.35 under AIX 3.2, Perl 4.0.19 under Ultrix 3.2,
Perl 4.0.35 under Linux 1.03, and Perl 4.0.36 under ISC 3.2.2.
Wanted: getpwent() Version
We're looking for an implementation of passwdchng
that uses the password-file access routines, such as
getpwent(). Suggestion: Save the current
password file entries from one invocation in an associative array
indexed by account name and store the array in a ``DBM'' file on
your disk. The next program invocation reads the DBM file into
one associative array and the current password information into a
second array. The last step compares the two arrays, field by
field, reporting any differences.
|