#
# perl/config.pl
#
# rewrite saint.cf after the user changes it.
#
# suck in the changes, then just cycle through each line of the .cf file.
# if there is a match, put the new value in there.
#

sub write_config_file {
local($new_values) = @_;
local(%new_values, $variable, $old_variable, $old_value);

#
# split the strings into something easier to handle
for ( split(/\n/, $new_values) ) {
	next if !$_;

	($variable, $value) = split(/=/, $_);

	# need to stick a dollar sign in front of var
	$variable = "\$" . "$variable";
	# and quotes around non-numbers
	if ($value !~ /^\d+$/) { $value = "\"$value\""; }

	$new_values{$variable} = $value;
	}

#
# open the config and the scratch file
#
die "Can't read $SAINT_CF file!\n" unless open(CF, "$SAINT_CF");
die "Can't write $SAINT_CF.new file!\n" unless open(CFN, ">$SAINT_CF.new");

while (<CF>) {
	# punt if the going gets too tough...
	if (!/^\$/) {
		print CFN $_;
		next;
		}
	
	chop;
	($old_variable, $old_value) = split(/\s*=\s*/, $_);

	# kill spaces and semicolons
	$old_variable =~ s/\s//g;
	$old_value =~ s/;//g;

	# suck in the lines, compare them to each of the vars gotten from user
	for $variable (keys %new_values) {
		if ($variable eq $old_variable) {
			$old_value = $new_values{$variable};
			}
		}

	print "CF: $_ ($old_variable, $old_value)\n";
	print CFN "$old_variable = $old_value;\n";
	}

close(CF);
close(CFN);

# move the evidence to where it belongs... old to .old, new to .cf:
system("mv $SAINT_CF $SAINT_CF.old");
system("mv $SAINT_CF.new $SAINT_CF");

}

# rewrite the config file after changing the custom scan
# s.k. 10/00

sub process_custom {

    my($variables) = @_;
    my($i);
    local($tcp_ports, $udp_ports);

    @$custom_level = ();
    for (split /\n/, $variables) {
	if (/(tcp|udp)_ports=(.*)/) {
	    $i = "${1}_ports";
	    ($$i = $2) =~ s/(\s|\n)//g;
	}
	if (/(.*)_saint(q?)/) {
	    if ($2) {
	        push @$custom_level, $1 . ".saint?";
	    } else {
		push @$custom_level, $1 . ".saint";
	    }
	}
    }
    for (@$custom_level) {
	$_ .= " $tcp_ports" if /tcpscan\.saint/;
	$_ .= " $udp_ports" if /udpscan\.saint/;
    }
    &write_custom();
}

sub write_custom {

    die "Can't read $SAINT_CF file!\n" unless open(CF, "$SAINT_CF");
    die "Can't write $SAINT_CF.new file!\n" unless open(CFN, ">$SAINT_CF.new");

    while(<CF>) {
	if (/\@$custom_level\b/) {
	    # skip over the old custom_level definition
	    until (/\)/) { $_ = <CF>; }

	    # skip to the next line
	    $_ = <CF>;
	    until (/\S+/) { $_ = <CF>; }
	}
	if (/^#\s*Custom attack levels/i) {
	    print CFN;

	    # put the new attack level definition here
	    print CFN "\@$custom_level = (\n";
	    for $probe (@$custom_level) {
		print CFN "\t\'$probe\',\n";
	    }
	    print CFN "\t);\n\n";
	}
	elsif (/^\$attack_level\s*=\s*\d+\s*;/) {
	    # set the attack level to 5 (custom)
	    print CFN "\$attack_level = 5;\n";
	}
	elsif (/^\$custom_level\s*=\s*\"(\w+)\"\s*;/) {
	    # reset the custom level
	    print CFN "\$custom_level = \"$custom_level\";\n";
	}
	elsif (/^\@custom_levels\s*=\s*\((.*)\)\s*;/
			&& $1 !~ /\b$custom_level\b/) {
	    # add this level to the list if it's not there
	    push @custom_levels, $custom_level;
	    print CFN "\@custom_levels = ($1, \"$custom_level\");\n";
	}
	else {
	    print CFN;
	}
    }
    close(CF);
    close(CFN);

    system("mv $SAINT_CF $SAINT_CF.old");
    system("mv $SAINT_CF.new $SAINT_CF");

    $attack_level = 5;
}
1;
