Class: MiqLinux::FileWTMP

Inherits:
Object
  • Object
show all
Defined in:
lib/metadata/linux/LinuxUsers.rb

Overview

class Users

Constant Summary collapse

WTMP_RECORD =

From www.hcidata.info/wtmp.htm

The wtmp log file is usually found in /var/log/wtmp and contains the following information:

    * Activity code (e.g. login, logout, boot)
    * PID
    * Date and time of last login
    * Terminal line name
    * Host user came from

The following one line PERL program will format and print /var/log/wtmp but it may need modification to work on your site.

perl -we '@type=("Empty","Run Lvl","Boot","New Time","Old Time","Init","Login","Normal","Term","Account");$recs = ""; while (<>) {$recs .= $_};foreach (split(/(.{384})/s,$recs)) {next if length($_) == 0;my ($type,$pid,$line,$inittab,$user,$host,$t1,$t2,$t3,$t4,$t5) = $_ =~/(.{4})(.{4})(.{32})(.{4})(.{32})(.{256})(.{4})(.{4})(.{4})(.{4})(.{4})/s;if (defined $line && $line =~ /\w/) {$line =~ s/\x00+//g;$host =~ s/\x00+//g;$user =~ s/\x00+//g;printf("%s %-8s %-12s %10s %-45s \n",scalar(gmtime(unpack("I4",$t3))),$type[unpack("I4",$type)],$user,$line,$host)}}print"\n"' < /var/log/wtmp

The items that may need modification in order to format and print your lastlog file are:

    * 384 - this should be changed to the length of each record on /var/log/wtmp.
    * 32 - this should be changed to the value of UT_LINESIZE (probably 32) in /usr/include/bits/utmp.h
    * 32 - this should be changed to the value of UT_NAMESIZE](probably 32) in /usr/include/bits/utmp.h
    * 256 - this should be changed to the value of UT_HOSTSIZE (probably 256) in /usr/include/bits/utmp.h
    * /var/log/wtmp - this should be the name of the lastlog file on your system - probably /var/log/wtmp
BinaryStruct.new([
  'V',        'type',          # type of login
  'V',        'pid',           # PID of login process
  'a32',      'line',          # device name of tty - "/dev/"
  'V',        'inittab',       # init id or abbrev. ttyname
  'a32',      'user',          # user name
  'a256',     'host',          # hostname for remote login
  'v',        'e_termination', # process termination status
  'v',        'e_exit',        # process exit status
  'V',        'session',       # Session ID, used for windowing
  'V',        'seconds',       # Time, in seconds
  'V',        'useconds',      #     microseconds
  'V4',       'addr_v6',       # * Internet address of remote host; IPv4 address uses just ut_addr_v6[0] */
  'a20',      'extra'
])
WTMP_RECORD_LEN =
WTMP_RECORD.size
WTMP_TYPE_UT_UNKNOWN =

WTMP Account Types

0
WTMP_TYPE_RUN_LVL =
1
WTMP_TYPE_BOOT_TIME =
2
WTMP_TYPE_NEW_TIME =
3
WTMP_TYPE_OLD_TIME =
4
WTMP_TYPE_INIT_PROCESS =
5
WTMP_TYPE_LOGIN_PROCESS =
6
WTMP_TYPE_USER_PROCESS =
7
WTMP_TYPE_DEAD_PROCESS =
8
WTMP_TYPE_ACCOUNTING =
9
WTMP_TYPES =
{
  WTMP_TYPE_UT_UNKNOWN    => "Unknown",
  WTMP_TYPE_RUN_LVL       => "Run Level",
  WTMP_TYPE_BOOT_TIME     => "Boot Time",
  WTMP_TYPE_NEW_TIME      => "New Time",
  WTMP_TYPE_OLD_TIME      => "Old Time",
  WTMP_TYPE_INIT_PROCESS  => "Init Process",
  WTMP_TYPE_LOGIN_PROCESS => "Login Process",
  WTMP_TYPE_USER_PROCESS  => "User Process",
  WTMP_TYPE_DEAD_PROCESS  => "Dead Process",
  WTMP_TYPE_ACCOUNTING    => "Accounting"
}

Instance Method Summary collapse

Constructor Details

#initialize(fs, path = "/var/log/wtmp") ⇒ FileWTMP

Returns a new instance of FileWTMP.



192
193
194
195
196
197
198
199
# File 'lib/metadata/linux/LinuxUsers.rb', line 192

def initialize(fs, path = "/var/log/wtmp")
  @contents = nil
  @records  = nil
  begin
    fs.fileOpen(path, "rb") { |fo| @contents = fo.read }
  rescue
  end
end

Instance Method Details

#dump(rec) ⇒ Object



214
215
216
217
218
219
220
221
222
223
# File 'lib/metadata/linux/LinuxUsers.rb', line 214

def dump(rec)
  puts "WTMP Record:"
  #      puts "WTMP Record: #{rec.inspect}"
  puts "\ttype: #{WTMP_TYPES[rec["type"]]}"
  puts "\tuser: #{rec["user"]}"
  puts "\thost: #{rec["host"]}"
  puts "\tline: #{rec["line"]}"
  puts "\tpid:  #{rec["pid"]}"
  puts "\ttime: #{Time.at(rec["seconds"])}"
end

#last_logon(username) ⇒ Object



201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/metadata/linux/LinuxUsers.rb', line 201

def last_logon(username)
  return nil if @contents.nil?
  last = nil

  begin
    last = records[username]
    last = Time.at(last).getutc unless last.nil?
  rescue => err
    $log.error("Error processing WTMP file because <#{err.message}>") if $log
  end
  last
end

#recordsObject



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/metadata/linux/LinuxUsers.rb', line 225

def records
  return @records unless @records.nil?
  @records = {}
  recnum = 0
  nrecs  = @contents.length / WTMP_RECORD_LEN
  # TODO(lsmola) limiting log file size and logging warning when it's over it?
  # Cause this can potentily go through milions of records
  while recnum < nrecs
    offset  = recnum * WTMP_RECORD_LEN
    recnum += 1
    buf     = @contents[offset, WTMP_RECORD_LEN]
    break unless buf.length == WTMP_RECORD_LEN
    rec = WTMP_RECORD.decode(buf)
    ['host', 'user', 'line'].each { |k| rec[k].strip! if rec[k] }
    next if rec["user"].blank?
    next unless rec["type"] == WTMP_TYPE_USER_PROCESS

    current = rec["seconds"]
    user    = rec["user"]
    # Get the latest logon timestamp for each user
    @records[user] = current if @records[user].blank? || current > @records[user]
  end
  @records
end