On a BSD Unix system, three files keep track of user logins.
/etc/utmp
records which users are on which lines, and when
they logged in (or, for unused lines, logged out). To put it differently,
utmp
records the most recent start or stop time of the latest
session on each line, and which user owns or owned that session. utmp also
records the first 16 characters of the remote hostname for any network
connection.
A parallel file /usr/adm/wtmp
records all changes to utmp.
The last wtmp
entry for line xx is the current utmp entry for
line xx. wtmp
also uses special codes to indicate reboots
and other unusual events. Typically wtmp
is "rotated" every
month: /usr/adm/wtmp
is cleared, with a copy of the old
information saved in /usr/adm/wtmp.0
. Any previous
wtmp.0
is saved in wtmp.1
, and so on up to
wtmp.7
, which is thrown away.
The third file is /usr/adm/lastlog
, a flat database indexed
by uid showing the most recent login entry for each user.
lastlog
and utmp
have different formats but
carry essentially the same information.
utmp
provides only 16 characters for hostnames which are
often much too long to fit. Once utmp
(and wtmp
and lastlog
) truncate a name, any extra characters are lost
permanently. Other information — the remote TCP port, the remote
user as seen by rlogind
or via RFC 931, etc. — isn't
recorded at all. This makes it very difficult to trace network attacks.
Furthermore, when users take advantage of session management (as
described in
An introduction to session management),
utmp
and wtmp
lose even more information. A
user may start a session at work, disconnect it without logging out, go
home, and reconnect to the session from an entirely different location.
It makes sense to talk about the start and stop time of the session, each
connect and disconnect time, and each connect location. utmp
and wtmp
record none of this.
Another problem with utmp
is that it has never been clear
whether utmp
should record all connections (see []) or only
interactive connections. Given that the programs which depend most
heavily on utmp
— to wit, user communication programs
such as talk
and write
— should only see
interactive connections, it makes sense to omit windows and subshells, but
then window information is lost.
lastlog
is mainly an optimization: login
and
finger
both report the last login time for a particular user,
and it would be wasteful to search through wtmp
each time.
But lastlog
only keeps track of the very latest login, with
no indication of any previous logins. It does not record logout time.
Even worse, users and administrators cannot find out when their accounts
are being attacked, because lastlog only records successful logins.
One "solution" is to add more and more fields to utmp
,
recording more and more information. But this is the wrong strategy.
Consider the parallel wtmp
file. If utmp
has
(for instance) fields for the latest connection, then every time a user
connects or disconnects, the basic session fields will be repeated in
wtmp
for no good reason. This wastes disk space but also
indicates a fundamental failure in the model.
The right solution is to give each file a specific purpose.
utmp
should only keep track of sessions; the host field
should be removed. Complete connection information, including connect and
disconnect times, remote host as both IP address and name, remote port,
and remote user if known, can go into a separate file.
To solve the problem of interactive versus non-interactive sessions, utmp
should be split in two. The original utmp
should be
preserved for interactive, user-to-user communication. A separate file
should record all sessions.
lastlog
can be improved in many ways, which we will not
discuss in detail here. Various vendors (e.g., DEC) have already added
features along these lines.
The author's pseudo-tty session manager, pty 4.0 ([]), maintains several
user login files. utmp
and wtmp
record
interactive sessions as above. The user can specify at session startup
whether the session is interactive or not. For maximum flexibility, pty
lets the user choose his host field in utmp
. This way the
user can configure his sessions to work properly with various
utmp-processing programs. (The system administrator may disable these
features.)
All disconnectable sessions are recorded in sessnow
, which
has fields for username, uid, start/stop time, session master process id,
and line. sesslog
keeps a permanent record of changes to
sessnow
. Lines are specified by two characters (e.g.,
p0
for /dev/ttyp0
).
The relation between sessions and connections is recorded in
scnow
. scnow
lists each session by line, the
latest connection start/stop time, and complete remote host information.
All changes to scnow
are listed in sclog
.
Note that it makes sense to record connections separately, even those not
connected to any particular session. The connection managers
(getty
, telnetd
, etc.) might keep
connnow
and connlog
files listing current
connections. In the meantime pty maintains sessnow
,
sesslog
, scnow
, sclog
,
utmp
, and wtmp
. This finally makes a logical
set of records for which user was using what session from where.
Notice the clean distinction between connection information and session
information. All session information is maintained by one program, pty.
The utmp
handling can be completely removed from
init
, getty
, telnetd
,
login
, rlogind
, screen
,
xterm
, sunview
, and dozens of other programs.
It is worth noting that Sun destroyed any credibility it might have had in
its user login files by making /etc/utmp
mode 666. This is
what the author calls a SCINUP: Security Compromise Introduced in the
Name of User Power. Sun found so many programs in its toolset that wanted
to update utmp
that it removed all utmp
protection rather than implement a proper security mechanism. Years
later, security experts (and system crackers) are still finding
devastating holes caused by Sun's incredibly poor judgment.
Needless to say, the author does not approve of unprotected login files.
A single program — pty — can provide safe utmp
service for all programs which need it.
© Copyright 1991 Daniel J. Bernstein. Presumably.