#!/usr/bin/perl
#
# SAINT main start-up script.
# Portions Copyright 1995, Dan Farmer and Wietse Venema.
# Portions Copyright 1998-2002, SAINT Corporation.
# All rights reserved. 

$running_under_saint = 1;
$system = "saint";

do "express" if (-f "express");

require 'config/version.pl';
require 'config/saint.cf';
require 'perl/saint-data.pl';
require 'perl/run-saint.pl';
require 'perl/misc.pl';
require 'perl/text-output.pl';
require 'perl/passwd.pl';
require 'perl/exclusions.pl';
require 'perl/morehtml.pl';
require 'perllib/getopts.pl';	# IRIX needs it at the end.

&init_exclusions();

#
# Defaults are taken from the config file. There are three ways to control
# operation: from the command line, from the saint.cf file, and from the
# HTML user interface. That's a bit much.
#
$opt_a = $attack_level;
$opt_A = $proximity_descent;
$opt_d = $saint_data;
$opt_g = $password_guesses;
$opt_h = $allow_hosts;
$opt_l = $max_proximity_level;
$opt_L = $domain_user;
$opt_m = $maximum_threads;
$opt_n = $target_netmask;
$opt_o = $only_attack_these;
$opt_O = $dont_attack_these;
$opt_s = $attack_proximate_subnets;
$opt_S = $status_file;
$opt_t = $timeout;
$opt_u = $untrusted_host;
$opt_v = 0;
$opt_w = $web_server;
$opt_x = $extreme;
$opt_y = 0;
$opt_z = $sub_zero_proximity;

#
# Parse JCL.
#
$usage = "usage: $0 [options] [targets...]

Enters interactive mode when no target host is specified.

-a level	attack level (0-3:light-heavy+,4:top20,5:custom default $opt_a)
-A descent	proximity descent (default $opt_A)
-c list		change variables (list format: \"name=value; name=value; ...\")
-C level	custom attack level
-d database	data directory (default $opt_d)
-f 		Enable firewall analysis
-F target_file	scan targets listed in target_file
-g guesses	number of passwords to guess (default $opt_g)
-h hosts	IP addresses that are allowed to connect using remote mode
-i		ignore existing results
-k		kill saint server in remote mode
-l proximity	maximal proximity level (default $opt_l)
-L login%passwd	domain administrator login and password
-m threads	max. number of threads, 1 = disable multitasking (default $opt_m)
-n netmask	netmask(s) of targets
-o list		scan only these (default '$opt_o')
-O list		stay away from these (default '$opt_O')
-p port		server port for remote mode
-q		quiet mode -- suppress command-line output
-r		remote mode
-R		remote mode without password prompt
-s		expand primary hosts to subnets
-S status_file	pathname with scanning status file (default $opt_S)
-t level	timeout (0 = short, 1 = medium, 2 = long, default $opt_t)
-u		running from an untrusted host (for rsh/nfs tests)
-U		running from a trusted host (for rsh/nfs tests)
-v		turn on debugging output
-V		print version number
-w		interface with existing web server (implies -r)
-x		extreme -- perform dangerous tests (Caution!)
-X		don't perform dangerous tests
-z		when attack level becomes negative, continue at level 0
-Z		stop at attack level 0
";

&Getopts("a:A:c:C:d:e:fF:g:h:ikl:L:m:n:o:O:p:qrRsS:t:uUvVwxXyzZ") || die $usage;

if ($opt_V) {
	print "$saint_version\n";
	exit 0;
}
if ($opt_k) {
	require 'perl/html.pl';
	&stop_html_server($opt_p);
	exit 0;
}

# The power of PERL never stops to amaze me - Wietse
for (split(/\s*;\s*/, $opt_c)) {
	${$name} = $value if ($name, $value) = split(/\s*=\s*/, $_, 2);
}
#print "SAINT is starting up....\n" if $#ARGV < 0;
if ($#ARGV < 0 && !defined($opt_F)) {
   print "Security Administrator's Integrated Network Tool\n";
   print "Portions copyright (C) 1998-2002 SAINT Corporation.\n";
   print "Portions copyright (C) 1995 by Dan Farmer and Wietse Venema.\n";
   print "SAINT is starting up...\n";
}

$debug = $opt_v;

$attack_level = $opt_a;
if ($opt_C) {
  $custom_level = $opt_C;
  $attack_level = 5;
}
@all_attacks = (\@light, \@normal, \@heavy, \@heavyplus, \@top20, \@$custom_level);
die "bad attack level: $opt_a\n" unless $all_attacks[$opt_a];

$saint_data = $opt_d;
$use_target_file = 1 if defined($opt_F);
$target_file = $opt_F if defined($opt_F);

$firewall_flag = 1 if defined($opt_f);
$password_guesses = $opt_g;
$allow_hosts = $opt_h;
$target_netmask = $opt_n;
$server_port = $opt_p if $opt_p;

$max_proximity_level = $opt_l;
$proximity_descent = $opt_A;
$sub_zero_proximity = $opt_z;
$sub_zero_proximity = 0 if $opt_Z;

$only_attack_these = $opt_o;
$dont_attack_these = $opt_O;

if (defined($opt_R)) {
    $remote_mode = 1;
    $skip_passwd = 1;
} elsif (defined($opt_r)) {
    $remote_mode = 1;
    $skip_passwd = 0;
}
$web_server = $opt_w;
$remote_mode = 1 if $web_server;

$attack_proximate_subnets = $opt_s;
$status_file = $opt_S;

@all_timeouts = ($short_timeout, $med_timeout, $long_timeout);
die "bad timeout: $opt_t\n" unless $all_timeouts[$opt_t];
$timeout = $opt_t;
$maximum_threads = $opt_m;
$quiet = $opt_q;

$untrusted_host = $opt_u;
$untrusted_host = 0 if $opt_U;
$extreme = $opt_x;
$extreme = 0 if $opt_X;
if ($opt_L =~ /(.*)%(.*)/) {
    $domain_user = $1;
    $domain_pass = $2;
}
else {
    $domain_user = $opt_L;
}

umask 077;	# DON'T TAKE THIS OUT!!!

&change_passwd() if ($remote_mode && !$skip_passwd);

if ($#ARGV < 0 && !defined($opt_F)) {
	#
	# The HTML driver will eventually invoke init_saint() and run_saint().
	#
	require 'perl/html.pl';
	&html();
} else {
	&init_saint_data();
	&read_saint_data() unless defined($opt_i);
	if ($use_target_file) {
	  die "cannot open $target_file\n" unless open(TARGET_FILE, $target_file);
	  $primary_target = "";
	  while (<TARGET_FILE>) {
	    chop;
	    $primary_target = $primary_target . $_ . " " if $_;
	    $primary_target =~ s/\s+-\s+/-/g;
	  }
	  close(TARGET_FILE);
	  &run_saint($primary_target);
	} else {
	  &run_saint(join(' ', @ARGV));
	}
	&text_output("$facts_file") if (!$quiet);
}

