Audit Share Perl Script

Used to audit usage of a network share on a remote server.
Usage: $script /[m]achine <hostname> /[s]hare <share name> /[d]uration <number of hours>
/[i]nterval <number of minutes> /[l]og <file name> /single /domain <domain name>
/[v]erbose
/machine    Hostname of remote server.  Default is localhost.
/share      Name of share (double quoted if it contains a space).
/duration   Number of days for which you want the audit to run.
/interval   Number of minutes between each enumeration. Default is 5 minutes.
/log        File name where results must be stored. Default is
“Date.Server.Share.AuditShare.log” in the current directory. A new
log file is created every day.
/single     Do not create multiple log files (default is one per day).
/domain     Specify the name of a Windows domain against which you want to check
all user names contained in session information.  If the user is found,
then the script will also display the user full name and the user description.
This option only works with /duration.
/verbose    Display entries as they are created in the log file (valid only with /duration).
/help       Displays this help message.

use Getopt::Long;
#use diagnostics;
#use strict;
use Win32::Console;

use Win32::NetAdmin;
use Win32::Lanman;

##################
# main procedure #
##################
my (%config);

p_parsecmdline(%config, @ARGV);
p_checkargs();

# set console codepage
Win32::Console::OutputCP(1252);

# CODE STARTS HERE
if ($config{duration}) {
my $NumberOfPolls = ($config{duration} * 60) / $config{interval};
my $IntervalInSeconds = $config{interval} * 60;
while ($NumberOfPolls) {
p_EnumConnections($config{machine},$config{share});
--$NumberOfPolls;
sleep $IntervalInSeconds;
}
} else {
p_EnumConnections($config{machine},$config{share});
}
# CODE ENDS HERE

exit 0;

##################
# sub-procedures #
##################

# procedure p_help
# displays a help message
sub p_help {
my ($script)=($0=~/([^\/]*?)$/);
my ($header)=$script." v1.5.1 - Authors: suparatuk@gmail.com - August 2007";
my ($line)="-" x length($header);
print <

$header
$line
Used to audit usage of a network share on a remote server.

Usage: $script /[m]achine /[s]hare /[d]uration
/[i]nterval /[l]og /single /domain
/[v]erbose

/machine Hostname of remote server. Default is localhost.
/share Name of share (double quoted if it contains a space).
/duration Number of days for which you want the audit to run.
/interval Number of minutes between each enumeration. Default is 5 minutes.
/log File name where results must be stored. Default is
"Date.Server.Share.AuditShare.log" in the current directory. A new
log file is created every day.
/single Do not create multiple log files (default is one per day).
/domain Specify the name of a Windows domain against which you want to check
all user names contained in session information. If the user is found,
then the script will also display the user full name and the user description.
This option only works with /duration.
/verbose Display entries as they are created in the log file (valid only with /duration).
/help Displays this help message.
EOT

exit 1;
}
# procedure p_parsecmdline
# parses the command line and retrieves arguments values
sub p_parsecmdline {
my ($config) = @_;
Getopt::Long::Configure("prefix_pattern=(-|/)");
GetOptions($config, qw(
machine|m=s
share|s=s
duration|d=i
interval|i=i
log|l=s
single
domain=s
verbose|v
help|?|h));
}
# procedure p_checkargs
# checks the arguments which have been used are a valid combination
sub p_checkargs {
p_help() if defined($config{help});
unless ($config{share}) {
print "nERROR: You MUST specify a share name!nn";
p_help();
}
unless ($config{machine}) {
$config{machine}=Win32::NodeName();
}
unless ($config{interval}) {
$config{interval} = 5;
}
unless ($config{log}) {
my $time = time();
$time = localtime($time);
my @time = split(/s+/,$time);
$config{log} = "$time[4]$time[1]$time[2].AuditShare.$config{machine}.$config{share}.log";
}
}
# procedure p_EnumConnections
# Enumerates connections made to a given share
sub p_EnumConnections {
my ($Server,$Share) = @_;
my (@Connections,$Connection);
$Server = "\\".$Server;

unless (Win32::Lanman::NetConnectionEnum($Server,$Share,@Connections)) {
print "ERROR: Could not enumerate connections: ".Win32::Lanman::GetLastError();
exit 1;
}

if ($config{duration}) {
foreach $Connection (@Connections) {
if (-f $config{log}) {
open (LOG, "$config{log}") or die "nERROR: could not open $config{log}: $^En";
my $Match = 0;
while (defined(my $LogEntry = )) {
my @LogEntryItems = split(",",$LogEntry);
chomp($LogEntryItems[2]);
unless ($Connection->{username}) {
$Connection->{username} = "Not specified";
if ($LogEntryItems[1] and $Connection->{netname}) {
if ($LogEntryItems[1] eq $Connection->{netname}) {
$Match = 1;
}
}
}
if ($LogEntryItems[2] and $Connection->{username}) {
if ($LogEntryItems[2] eq $Connection->{username}) {
$Match = 1;
}
}
}
close (LOG);
unless ($Match) {
p_log($config{log},"$Connection->{netname},$Connection->{username}");
}
} else {
p_log($config{log},"$Connection->{netname},$Connection->{username}");
}
}
} else {
$~ = 'HEADER';
write;
$~ = 'REPORT';

foreach $Connection (@Connections) {
unless ($Connection->{username}) {
$Connection->{username} = "Not Specified";
}
write;
}
}
format HEADER =
Computer Name Username
------------------ ----------------
.
format REPORT =
@||||||||||||||||| @|||||||||||||||
$Connection->{netname},$Connection->{username}
.
}
# procedure p_log
# manages creating log entries
sub p_log {
my ($logfile,$message) = @_;
my ($pdc,$Server,%attribs);
my $time = time();
$time = localtime($time);
unless ($config{single}) {
my @time = split(/s+/,$time);
my $NewLogFile = "$time[4]$time[1]$time[2].AuditShare.$config{machine}.$config{share}.log";
open (LOG, ">>$NewLogFile") or die "nERROR: could not open $NewLogFile: $^En";
} else {
open (LOG, ">>$logfile") or die "nERROR: could not open $logfile: $^En";
}

if ($config{domain}) {
my @Message = split(",",$message);
unless ($Message[1] eq "Not Specified") {
$Server = Win32::NodeName();
if (Win32::NetAdmin::GetDomainController("\\$Server",$config{domain},$pdc)) {
if (Win32::Lanman::NetUserGetInfo($pdc,$Message[1],%attribs)) {
$attribs{'full_name'} =~ s/,+//g;
$attribs{'comment'} =~ s/,+//g;
if ($config{verbose}) {
print "$time,$message,$attribs{'full_name'},$attribs{'comment'}n";
}
print LOG "$time,$message,$attribs{'full_name'},$attribs{'comment'}n";
} else {
if ($config{verbose}) {
print "$time,$messagen";
}
print LOG "$time,$messagen";
}
} else {
if ($config{verbose}) {
print "$time,$messagen";
}
print LOG "$time,$messagen";
}
}
} else {
if ($config{verbose}) {
print "$time,$messagen";
}
print LOG "$time,$messagen";
}
close (LOG);
}

Leave a Comment