#!/usr/bin/perl
# 
# smb.saint attempts to open smb shares and reports those that are public
#
# usage: smb.saint host
# 
# smb.saint requires a preloaded samba configuration in /usr/local/samba.  If
# not found, smb.saint will give a "zwoi" error (pre SAINT-1.3.1 report)
#
# Note:  saint does not provide the samba environment!
# 
# 14 Sep 98
# Aaron Glahe, changed status of Netbios Name to show name if exists
#         5/18/99
# mod 6/20/00 by Sam, fixed some bugs (see CHANGES)
# mod 8/31/00 by Sam, check for unpassworded guest/admininstrator accounts
#		      and writable shares

require 'config/paths.pl';
require 'config/saint.cf';
require 'perl/misc.pl';
require 'perllib/getopts.pl';

print "BEGIN\n";
#
$nmblookup=$NMBLOOKUP;
$smbclient=$SMBCLIENT;
$awk=$AWK;
$target=$ARGV[0];
@accounts = ("sainttest", "guest", "administrator");
#
#  Check for samba programs
#
if ( -e $nmblookup && -e $smbclient )
{
#
# get NetBIOS name
#
open (INBIOS, "$nmblookup -d 1 -A $target |");
while (<INBIOS>) 
{
  chop;
    if ( $_ =~ /<00> -   /)
    {
      @name = split(" ", $_);
      $netbios = "@name[0]\n";
    }
}
close (INBIOS);
# set output buffer to 1 so nothing is lost if there's a timeout
$|=1;
if ($netbios) {
   chomp $netbios;
   $status = "a";
   $service = "netbios-ssn";
   $trustee = "";
   $trusted = "";
   $severity = "i";
   $text = "$netbios";
   $service_output = "Netbios Name";
   &saint_print();
}
#
#  Get a list of shares
#
$open = 1;
LOOP: for $user (@accounts) {
    open (IN, "$smbclient -I $target -L '$netbios' -U '$user' -W Saint -N |");
    @list = <IN>;
    close (IN);

    for ($i = 2; $i <= 30; $i++) {
	if ($list[$i] =~ /Disk/){
	    $list[$i] =~ s/\A\t//;
	    ($list[$i]) = ($list[$i] =~ /(\A.{0,13})/);
	    ($sname, $type, $comment) = split(/   /,$list[$i], 3);
	    if ($user eq $accounts[0]) {
		&smb ($sname);
		$open = 1;
	    } else {
		$status = "a";
		$service = "netbios-ssn";
		if ($user eq $accounts[1]) {
		    # guest account
		    $severity = "ns";
		} elsif ($user eq $accounts[2]) {
		    # administrator account
		    $severity = "rs";
		} else {
		    $severity = "us";
		}
		$trusted = "ANY\@$target";
		$trustee = "ANY\@$target";
		$service_output = "guessed account password";
		$text = "Windows account $user has no password";
		&saint_print();
	    }
	}
	if ($sname=''){ $i=30;}
    }
    last LOOP if $open;
}

# Check for Samba vulnerability
open (SMB, "$smbclient \'//$netbios/saint\' -I $target -c \'quit\' -N -U root -W saint |");
while(<SMB>) {
    if (/Server=\[Samba (\d+\.\d+)(\.?)(\d*)/) {
	if ($1 < 2.0 || ($1==2.0 && $3 < 10)) {
	    $status = "a";
	    $service = "netbios-ssn";
	    $trusted = "ANY\@$target";
	    $trustee = "ANY\@$target";
	    $severity = "zcio";
	    $service_output = "Samba vulnerabilities";
	    $text = "possible vulnerability in Samba $1$2$3";
	    &saint_print;
	}
    }
}
close (SMB);

#
#  Check if shares are public
#

sub smb {
my($dir) = @_;
my($usr);

chomp $netbios;
chomp $dir;
$dir =~ s/\s+$//;
$status = "a";
$service = "netbios-ssn";
$trustee = "ANY\@$target";
$trusted = "ANY\@$target";
$severity = "";

SMBLOOP: for $usr (@accounts) {
  # check if share is readable
  open (SMB, "$smbclient \'//$netbios/$dir\' -I $target -c ls -U '$usr' -N  -W Saint -N|");
  @stuff = <SMB>;
  close (SMB);
  if (grep(/avail/,@stuff)) {

    # check if share is writable
    open (SMBW, "$smbclient \'//$netbios/$dir\' -I $target -c 'put /etc/services saint.xyz;ls saint.xyz;del saint.xyz' -U '$usr' -N  -W Saint -N|");
    @stuff = <SMBW>;
    close (SMBW);
    if (grep(/\d\d:\d\d:\d\d/,@stuff)) {

	# share is writable
	if ($usr eq $accounts[0]) {
	    # share is writable by all
            $severity = "uw";
	    $service_output = "open SMB shares";
            $text = "readable/writable share at $netbios/$dir";
  	    &saint_print();
	    last SMBLOOP;
	} else {
	    # share is not writable by all, so this account
	    # must be open
	    if ($usr eq $accounts[1]) {
		# guest account
		$severity = "ns";
	    } elsif ($usr eq $accounts[2]) {
		# administrator account
		$severity = "rs";
	    } else {
		$severity = "us";
	    }
	    $service_output = "guessed account password";
	    $text = "Windows account $usr has no password";
	    &saint_print();
	}
    } else {

	# share is readable but not writable
	if ($usr eq $accounts[0]) {
	    # share is readable by all
	    $severity = "ur";
	    $service_output = "open SMB shares";
            $text = "readable share at $netbios/$dir";
  	    &saint_print();
	} elsif ($severity ne "ur") {
	    # share is not readable by all, so account
	    # must be open
	    $severity = "us";
	    $service_output = "guessed account password";
	    $text = "Windows account $usr has no password";
	    &saint_print();
	}
    }
  }
}
}
}else {
          $status = "a";
	  $service = "netbios-ssn";
          $trustee = "ANY\@$target";
          $trusted = "ANY\@$target";
          $severity = "zwoi";
          $service_output = "netbios over the internet";
          $text = "Is your Netbios secure";
	  &saint_print();
}
