#!/usr/bin/perl

use Win32::Lanman;
use Win32::TieRegistry( Delimiter=>"/", ArrayValues=>0 );
use Win32::FileSecurity qw(Get EnumerateRights);
use Win32::NetAdmin;
use Win32::NetResource;
use Win32::AdminMisc ;
use Win32::Perms;
use Getopt::Long;




# Print Title
print "\n\n\nINFOSEC Assessment and Vulnerability Windows Scanner version $Version \n\n" ;
# Files needed and can be added to by users

# To print output to screen, set below
$PrintToScreen = 1 ;
# To print Status to screen, set below
$PrintStatus = 1;

#Get the server to run script against.
$server = $ARGV[0] ;

#Uppercase the server name
$server =~ tr/a-z/A-Z/;

@MONTHS=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
# Get the current time/date
($x,$MIN,$HOUR,$MDAY,$MONTH,$YEAR,$x,$x,$x) = localtime(time);
$MNAME = $MONTHS[$MONTH] ; # Give name to month number
$MONTH++;  # Increment for numerical date
$YEAR = 1900 + $YEAR ; # Correct for year > 1999 ;

# Create and bulid the HTML report pages needed

&BuildHead ;    # Start the main report page with headers and structure
$HOSTIP = &GetIP ;

### Check if registry is available remotely
#
$Registry->Delimiter("/");                  # Set delimiter to "/".
$testKey= $Registry->{"//$server/LMachine/"};
$RegConnect = 1 ;
if (!defined $testKey) {
	print "Network connection to registry unavailable.\n\n" ;
	$RegConnect = 0 ; #Failed to connect with current authentication
}
#############################################################################
$ISDC = 0 ;
#Call test sub here
getShareInfo($server) ;

###############


# Close the report html page and finish
&CloseHTML ;
################


####################    TEST SUBS HERE   ##################################
sub getShareInfo {
my ($Server) = @_;
my @shares;
my @enumshare;
if (Win32::Lanman::NetShareEnum("\\\\$Server",\@shares)) {
	&BuildTable(7,"Network Shares Defined and Parameters","Share Name","Path","Remark","Current Users","Max Users","File System Type","Permissions") ;
	foreach my $share (@shares) {
		push(@enumshare,{name => ${$share}{'netname'},path => ${$share}{'path'},
		                 remark => ${$share}{'remark'},max => ${$share}{'max_uses'},
		                 current => ${$share}{'current_uses'}});
	}

	foreach my $share (sort ({lc $a->{name} cmp lc $b->{name}}@enumshare)) {

		my @perms = getPerms("\\\\$Server\\".$share->{name});
		if (@perms) {


			print "\n\n ------------------------------------------------\n\n" ;
			print "Path        :  ".$share->{path}."  ";
			if ($share->{path} =~ m/^\w:\\/) {
				print "(Root share)";
				my $file = "\\\\$Server\\".$share->{name}."\\autorun.inf";
				if (-e $file) {
					print "\nWarning:  Autorun.inf file detected on drive root!!";
				}
			}
			print "\n";
			print "Remark      :  ".$share->{remark}."\n";
			print "Current uses:  ".$share->{current}."\n";
			my $max;
			($share->{max} == -1)?($max = "Max Allowed"):($max = $share->{max});
			print "Max Uses    :  ".$max."\n";
			if (my %hash = Win32::AdminMisc::GetVolumeInfo("\\\\$Server\\".$share->{name})) {
				print "FileSystem  :  ".$hash{FileSystemName}."\n";
				$FileSystem = $hash{FileSystemName} ;
			}
			print "\n";

			#ADDED
			printf "%-15s %-20s %-15s\n","Share","Group/User","Permissions";
			printf "%-15s %-20s %-15s\n","-" x 10,"-" x 10,"-" x 12;
			$ShowPerms = "" ;
			my $elements = @perms;
			my ($group,$permlist) = (split(/:/,$perms[0]))[0,2];
			printf "%-15s %-20s %-15s\n",$share->{name},$group,$permlist;
			$ShowPerms = $ShowPerms . sprintf "%-20s %-15s \<BR\>",$group,$permlist;
			# deal appropriately with
			if ($elements > 1) {
				foreach my $tag (1..$elements-1) {
					my ($group,$permlist) = (split(/:/,$perms[$tag]))[0,2];
					printf "%-15s %-20s %-15s\n","",$group,$permlist;
					$ShowPerms = $ShowPerms . sprintf "%-20s %-15s \<BR\>",$group,$permlist;
				}
			}
			&AddTableData("B","$share->{name}","$share->{path}","$share->{remark}","$share->{current}",
					"$max","$FileSystem","\<PRE\><FONT SIZE=2><B>$ShowPerms</FONT></B>\</PRE\>") ;

		}

		else {
			printf "%-15s %-20s %-15s\n",$share,"","";
			print "\n";
		} # IF ELSE @PERMS
	} # FOREACH

}# IF SHARE CONNECT
else {
	my $err = Win32::FormatMessage Win32::Lanman::GetLastError();
	$err = Win32::Lanman::GetLastError() if ($err eq "");
	$err = "Server service not enabled, no shares available" if ($err == 2114);
	print "NetShareEnum error: ".$err."\n";
}


&CloseTable ;
} #END SUB







## SUB TO RETURN PERMISSIONS ON AN OBJECT  #####
sub getPerms {
  my($obj) = $_[0];
  my($Acct,@List,$iTotal,$p);
  my(@perms) = ();
  my($Perm) = new Win32::Perms($obj);

  my (%PERM) = (R   =>  0,
  							W   =>  1,
  							X   =>  2,
  							D   =>  3,
   							P   =>  4,
   							O   =>  5,
   							A   =>  6,);

   my(%MAP) = (	'FILE_READ_DATA'    =>  'R',
  							'GENERIC_READ'      =>  'R',
  							'KEY_READ'          =>  'R',
  							'DIR_READ'          =>  'R',
  							'KEY_QUERY_VALUE'   =>  'R',

  							'FILE_WRITE_DATA'   =>  'W',
  							'KEY_WRITE'         =>  'W',
  							'KEY_SET_VALUE'     =>  'W',
  							'GENERIC_WRITE'     =>  'W',
  							'FILE_APPEND_DATA'  =>  'W',
  							'DIR_ADD_SUBDIR'    =>  'W',
  							'DIR_ADD_FILE'      =>  'W',

  							'DELETE'            =>  'D',
  							'FILE_DELETE_CHILD' =>  'D',

  							'FILE_EXECUTE'      =>  'X',
  							'FILE_TRAVERSE'     =>  'X',
  							'GENERIC_EXECUTE'   =>  'X',
  							'DIR_TRAVERSE'      =>  'X',
  							'DIR_EXECUTE'       =>  'X',

  							'CHANGE_PERMISSION' =>  'P',

  							'TAKE_OWNERSHIP'    =>  'O',

  							'FILE_ALL_ACCESS'   =>  'A',
  							'GENERIC_ALL'       =>  'A',
  							'DIR_ALL_ACCESS'    =>  'A',
  							'STANDARD_RIGHTS_ALL' => 'A');

   if(!$Perm) {
#     push(@perms,"Can not obtain permissions for '$obj'");
#     return @perms;
			return undef;
   };

   $Perm->Dump(\@List);

   foreach $Acct (@List) {
     my($Perm);
     my(@String) = split(//, "-" x scalar(keys(%PERM)));
     my($Mask,@M,@F);
     my($DaclType);
     next if($Acct->{Entry} ne "DACL");
     $iTotal++;

     DecodeMask($Acct,\@M,\@F);
     foreach $Mask (@M) {
       $Perm |= 2**$PERM{$MAP{$Mask}};
     }

     foreach $Mask (keys(%PERM)) {
       $String[$PERM{$Mask}] = $Mask if ($Perm & 2**$PERM{$Mask}) ;
     }

     $DaclType = $Acct->{ObjectName};
     if( 2 == $Acct->{ObjectType} ) {
# We have either a file or directory. Therefore we need to figure out if this
# DACL represents an object (file) or a container (dir)...
       ($Acct->{Flag} & DIR) ? ($DaclType = "Directory") : ($DaclType = "File");
     }

     $p = join('',@String);
     push(@perms,"$Acct->{Account}:$DaclType:$p");
  }

  if(!$iTotal) {
    push(@perms,"Everyone::------A");
  }

  return @perms;
}
##########################################################################









###########################################################################



###   DO NOT DELETE OR CHANGE BELOW  ########################333

#########################################################################################
# Get name or IP, return IP address
#########################################################################################
sub GetIP {
  my ($host) = $server;
  eval {
    $ipaddr = inet_ntoa(inet_aton($host));
    print "IP:\t\t$ipaddr\n" unless (! $PrintToScreen) ;
    return $ipaddr;
  }

}
#########################################################################################
####################################################################################
# HTML Routines for building tables and pages.
####################################################################################
sub BuildHead {
	open (H, ">$server.html") ;
	print H <<"EOL";
	<HTML><HEAD><TITLE>Server Information Report for $server</TITLE></HEAD>
	<BODY BGCOLOR="WHITE" TEXT="BLACK">
	<a name="top"><B>&nbsp;</B></a> <BR>
	<CENTER>
	<FONT SIZE=4 COLOR=BLUE><B>INFOSEC Assessment and Vulnerability Windows Scanner version $Version</B></FONT><BR>
	</CENTER><HR>
	<FONT SIZE=4 COLOR=BLUE><B>Server report for $server</B></FONT><BR>
	<B>Produced $MNAME $MDAY, $YEAR  at  $HOUR:$MIN</B><BR>
	<FONT COLOR=RED><B><I>Information is confidential and for internal use only</I></B></FONT>
	<BR><BR>
EOL
}

sub CloseHTML {
	print H <<"EOL";
	</BODY></HTML>
EOL
close H ;
}

sub CloseTable {
	print H <<"EOL";
	</TABLE><BR><HR><BR>
EOL
}

sub BuildTable {
	#Parms recieved are 1- # of columns 2- Table header  rest are column headers
	my (@Parms) = @_ ;

	print H <<"EOL";
	<TABLE COLS=$Parms[0] Border=1 Width=100%>
	<TH COLSPAN=$Parms[0] Align=Center BGCOLOR=BLUE><FONT SIZE=3 COLOR="WHITE">$Parms[1]</FONT></TH>
	<tr>
EOL
	foreach $i (2..($Parms[0]+1)) {
		print H <<"EOL";
		<TD BGCOLOR=BROWN><B><FONT SIZE=3 COLOR="WHITE">$Parms[$i]</FONT></B></TD>

EOL
	}
print H "</TR>" ;
}



sub AddTableData {
	my (@Parms) = @_ ;
	my $i = 1 ;
	$COLOR = "FF3333" if ($Parms[0] eq "R") ;
	$COLOR = "000000" if ($Parms[0] eq "B") ;
	print H "<TR>" ;
	foreach $i (1..$#Parms) {
		print H <<"EOL";
		<TD VALIGN="LEFT" BGCOLOR=WHITE  ><FONT SIZE=2 COLOR="$COLOR"><B>$Parms[$i] &nbsp</FONT></B></TD>
EOL
	}
	print H "<TR>" ;
}

####################################################################################


sub mlocaltime {
    ($_[0] == 0) ? (return "Never") : (return localtime($_[0]));
}

####################################################################################
####################################################################################