/*
* Copyright (c) 2000 Andre Lucas. All rights reserved.
* Portions copyright (c) 1998 Todd C. Miller
* Portions copyright (c) 1996 Jason Downs
* Portions copyright (c) 1996 Theo de Raadt
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Markus Friedl.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
** loginrec.c: platform-independent login recording and lastlog retrieval
**/
/*
The new login code explained
============================
This code attempts to provide a common interface to login recording
(utmp and friends) and last login time retrieval.
Its primary means of achieving this is to use 'struct logininfo', a
union of all the useful fields in the various different types of
system login record structures one finds on UNIX variants.
We depend on autoconf to define which recording methods are to be
used, and which fields are contained in the relevant data structures
on the local system. Many C preprocessor symbols affect which code
gets compiled here.
The code is designed to make it easy to modify a particular
recording method, without affecting other methods nor requiring so
many nested conditional compilation blocks as were commonplace in
the old code.
For login recording, we try to use the local system's libraries as
these are clearly most likely to work correctly. For utmp systems
this usually means login() and logout() or setutent() etc., probably
in libutil, along with logwtmp() etc. On these systems, we fall back
to writing the files directly if we have to, though this method
requires very thorough testing so we do not corrupt local auditing
information. These files and their access methods are very system
specific indeed.
For utmpx systems, the corresponding library functions are
setutxent() etc. To the author's knowledge, all utmpx systems have
these library functions and so no direct write is attempted. If such
a system exists and needs support, direct analogues of the [uw]tmp
code should suffice.
Retrieving the time of last login ('lastlog') is in some ways even
more problemmatic than login recording. Some systems provide a
simple table of all users which we seek based on uid and retrieve a
relatively standard structure. Others record the same information in
a directory with a separate file, and others don't record the
information separately at all. For systems in the latter category,
we look backwards in the wtmp or wtmpx file for the last login entry
for our user. Naturally this is slower and on busy systems could
incur a significant performance penalty.
Calling the new code
--------------------
In OpenSSH all login recording and retrieval is performed in
login.c. Here you'll find working examples. Also, in the logintest.c
program there are more examples.
Internal handler calling method
-------------------------------
When a call is made to login_login() or login_logout(), both
routines set a struct logininfo flag defining which action (log in,
or log out) is to be taken. They both then call login_write(), which
calls whichever of the many structure-specific handlers autoconf
selects for the local system.
The handlers themselves handle system data structure specifics. Both
struct utmp and struct utmpx have utility functions (see
construct_utmp*()) to try to make it simpler to add extra systems
that introduce new features to either structure.
While it may seem terribly wasteful to replicate so much similar
code for each method, experience has shown that maintaining code to
write both struct utmp and utmpx in one function, whilst maintaining
support for all systems whether they have library support or not, is
a difficult and time-consuming task.
Lastlog support proceeds similarly. Functions login_get_lastlog()
(and its OpenSSH-tuned friend login_get_lastlog_time()) call
getlast_entry(), which tries one of three methods to find the last
login time. It uses local system lastlog support if it can,
otherwise it tries wtmp or wtmpx before giving up and returning 0,
meaning "