#!/usr/bin/perl use FileHandle; use Time::Local; use strict; my $file = shift || \*STDIN; if (!ref($file)) { $file = new FileHandle("<$file") or die("Failed to open file $file for read: $!\n"); } my $errors = 0; my $index = 0; my %MonMap = map { ($_,$index++); } qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); # # Sessions are by IP and user # the pid is used to reference the account # my %sessions; my $year = (localtime())[5]; LINE: while (<$file>) { next LINE if !m/^(\S+)\s+(\d+)\s+(\d\d):(\d\d):(\d\d) \S+ (.*)$/; my ($Month,$Day,$Hour,$Min,$Second,$line) = ($1,$2,$3,$4,$5,$6); # # Convert to a sensible time... # my $time = getTimeFromFields($Second,$Min,$Hour,$Day,$Month); # # Look for a new session opening # May 19 09:30:54 myserver internal-sftp[25373]: session opened for local user test1 from [83.104.225.197] # if ($line =~ s/internal-sftp\[(\d+)\]: //) { my $PID = $1; if ($line =~ m/^session opened for local user (\S+) from \[(\S+)\]/) { # # New session opened use pid to reference user and IP # $sessions{$PID} = { User => $1, IP => $2, File => {}, }; next LINE; } if ($line =~ m/^session closed for/) { # # Sessioned closed - delete store.... # delete $sessions{$PID}; next LINE; } # # Stuff a dummy record if not there # my $record = $sessions{$PID} ||= { User => 'unknown', IP => '0.0.0.0', File => { Name => 'unknown', StartTime=> time(), }, }; if ($line =~ m/open \"(.*)\"/) { # # File opened - store the time so can calc xfer time # $sessions{$PID}{File} = { Name => $1, StartTime => $time, }; next LINE; } # # forced close "/in/RoadKill-QuickTime H.264.flv" bytes read 0 written 2129920 # close "/in/RoadKill-QuickTime H.264.flv" bytes read 0 written 2129920 # if ($line =~ m/close \"(.*)\" bytes read (\d+) written (\d+)/) { my ($File,$Read,$Write) = ($1,$2,$3); my $Forced = 0; $Forced = 1 if $line =~ m/forced close /; # # Check filename matched # if ($record->{File}{Name} ne $File) { print STDERR "Error: File $File closed but $record->{File} opened\n"; $errors++; $record->{File}{StartTime} = time(); } if ($Read) { print join(' ', scalar(localtime($time)), # Date $time - $record->{File}{StartTime}, # Time Seconds $record->{IP}, # IP address $Read, # Bytes transfered $File, # Filename 'b', # Binary mode '_', # No specials in sftp 'o', # Outgoing 'r', # Real user $record->{User}, # Username 'ftp', # Service name - ftp I hope 1, # Well it's secure '*', # Odd ? ($Forced)?'i':'c', # Complete or incomplete xfer ),"\n"; } if ($Write) { print join(' ', scalar(localtime($time)), # Date $time - $record->{File}{StartTime}, # Time Seconds $record->{IP}, # IP address $Write, # Bytes transfered $File, # Filename 'b', # Binary mode '_', # No specials in sftp 'i', # Incomming 'r', # Real user $record->{User}, # Username 'ftp', # Service name - ftp I hope 1, # Well it's secure '*', # Odd ? ($Forced)?'i':'c', # Complete or incomplete xfer ),"\n"; } next LINE; } } } exit 1 if $errors; exit 0; sub getTimeFromFields { my ($Second,$Min,$Hour,$Day,$Month) = @_; my $time = timelocal($Second,$Min,$Hour,$Day,$MonMap{$Month},$year); $time = timelocal($Second,$Min,$Hour,$Day,$MonMap{$Month},$year-1) if $time > time(); return $time; }