summaryrefslogtreecommitdiffstats
path: root/perl-install/tinyfirewall.pm
blob: 8827e358f198c7d25f576aa184480a32346f705a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
Diffstat (limited to 'tools/ppc/mkINSTALLCD')
0 files changed, 0 insertions, 0 deletions
d='n131' href='#n131'>131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
package tinyfirewall;
use diagnostics;
use strict;
use common qw(:common :functional :system :file);
use commands;
use run_program;
use netconnect;
use network;
use POSIX qw(tmpnam);
my @messages = (_("tinyfirewall configurator

This configures a personal firewall for this Linux Mandrake machine.
For a powerful dedicated firewall solution, please look to the
specialized MandrakeSecurity Firewall distribution."),
_("We'll now ask you questions about which services you'd like to allow
the Internet to connect to.  Please think carefully about these
questions, as your computer's security is important.

Please, if you're not currently using one of these services, firewall
it off.  You can change this configuration anytime you like by
re-running this application!"),
_("Are you running a web server on this machine that you need the whole
Internet to see? If you are running a webserver that only needs to be
accessed by this machine, you can safely answer NO here."),
_("Are you running a name server on this machine? If you didn't set one
up to give away IP and zone information to the whole Internet, please
answer no."),
_("Do you want to allow incoming Secure Shell (ssh) connections? This
is a telnet-replacement that you might use to login. If you're using
telnet now, you should definitely switch to ssh. telnet is not
encrypted -- so some attackers can steal your password if you use
it. ssh is encrypted and doesn't allow for this eavesdropping."),
_("Do you want to allow incoming telnet connections?
This is horribly unsafe, as we explained in the previous screen. We
strongly recommend answering No here and using ssh in place of
telnet."),
_("Are you running an FTP server here that you need accessible to the
Internet? If you are, we strongly recommend that you only use it for
Anonymous transfers. Any passwords sent by FTP can be stolen by some
attackers, since FTP also uses no encryption for transferring passwords."),
_("Are you running a mail server here? If you're sending you 
messages through pine, mutt or any other text-based mail client,
you probably are.  Otherwise, you should firewall this off."),
_("Are you running a POP or IMAP server here? This would
be used to host non-web-based mail accounts for people via 
this machine."),
_("You appear to be running a 2.2 kernel.  If your network IP
is automatically set by a computer in your home or office 
(dynamically assigned), we need to allow for this.  Is
this the case?"),
_("Is your computer getting time syncronized to another computer?
Mostly, this is used by medium-large Unix/Linux organizations
to synchronize time for logging and such.  If you're not part
of a larger office and haven't heard of this, you probably 
aren't."),
_("Configuration complete.  May we write these changes to disk?")
);
my %settings;
my $config_file = "/etc/Bastille/bastille-firewall.cfg";
my $default_config_file = "/usr/share/Bastille/bastille-firewall.cfg"; # set this later
sub ReadConfig {
    -e $config_file or commands::cp($default_config_file, $config_file);
    add2hash(\%settings, { getVarsFromSh("$config_file") });
}
sub SaveConfig {
	my $tmp_file = tmpnam();
	open CONFIGFILE, "$config_file"
		or die "Can't open $config_file: $!\n";
	open TMPFILE, ">$tmp_file"
		or die "Can't open $tmp_file for writing: $!\n";
	while (my $line = <CONFIGFILE>)
	{
		if ($line =~ m/^(.+)\s*\=\s*\"(.*)\"/)
		{
			my ($variable, $value) = ($1, $2);
			my $newvalue = $settings{$variable};
			$line =~ s/\".*\"/\"$newvalue\"/
				if (exists $settings{$variable});
		}
		print TMPFILE $line;
	}
	close CONFIGFILE;
	close TMPFILE;
	rename ($config_file, $config_file . ".orig");
	system ("/bin/cp $tmp_file $config_file");
	system ("/bin/rm $tmp_file");
}
sub DoInterface {
    my ($in)=@_;
    $::isWizard=1;
    my $GetNetworkInfo = sub {
	$settings{DNS_SERVERS} = join(' ', uniq(split(' ', $settings{DNS_SERVERS}),
            @{network::read_resolv_conf("/etc/resolv.conf")}{'dnsServer', 'dnsServer2', 'dnsServer3'}));
	my (undef, undef, @netstat) = `/bin/netstat -in`;
	my @interfaces =  map { /(\S+)/ } @netstat;
	my (@route, undef, undef) = `/sbin/route -n`;
	my $defaultgw;
	my $iface;
	foreach (@route) { my @parts = split /\s+/; $parts[0] eq "0.0.0.0" and $defaultgw = $parts[1], $iface = $parts[7] }
	my $fulliface = $iface;
	$fulliface =~ s/[0-9]+/\\\+/;
	$settings{PUBLIC_INTERFACES} = join(' ', uniq(split(' ', $settings{PUBLIC_INTERFACES}), $iface));
	$settings{PUBLIC_INTERFACES} =~ $fulliface and $settings{PUBLIC_INTERFACES} =~ s/$iface *//;
	$settings{INTERNAL_IFACES} = join(' ', uniq(split(' ', $settings{INTERNAL_IFACES}),
            map { my $i=$_; my $f=$i; $f=~s/[0-9]+/\\\+/;
		  if_(and_( map {$settings{$_} !~ /$i/ and $settings{$_} !~ /$f/ } ('TRUSTED_IFACES', 'PUBLIC_IFACES', 'INTERNAL_IFACES')), $i)
	    } @interfaces ));
    };
#    my $popimap = sub {	$_[0] or return; $settings{FORCE_PASV_FTP} = 11;  mapn {$settings{"$_[0]"} = "$_[1]"; }
#[ qw(FORCE_PASV_FTP TCP_BLOCKED_SERVICES UDP_BLOCKED_SERVICES ICMP_ALLOWED_TYPES ENABLE_SRC_ADDR_VERIFY IP_MASQ_NETWORK IP_MASQ_MODULES REJECT_METHOD) ] ,
#[ "N", "6000:6020", "2049", "destination-unreachable echo-reply time-exceeded" , "Y", "", "", "DENY" ]; };
my $popimap = sub {
    $_[0] or return;
    $settings{'FORCE_PASV_FTP'} = "N";
    $settings{TCP_BLOCKED_SERVICES}= "6000:6020";
    $settings{UDP_BLOCKED_SERVICES}= "2049";
    $settings{ICMP_ALLOWED_TYPES}= "destination-unreachable echo-reply time-exceeded";
    $settings{ENABLE_SRC_ADDR_VEIFY}= "Y";
    $settings{IP_MASQ_NETWORK}= "";
    $settings{IP_MASQ_MODULES}= "";
    $settings{REJECT_METHOD}= "DENY";
};
    #    my $ntp = sub { $_[0] or return; mapn { $settings{$_[0]} = $_[1] } ['ICMP_OUTBOUND_DISABLED_TYPES}', 'LOG_FAILURES'], [ "", "N"] };
    my $ntp = sub { $_[0] or return;
		    $settings{'ICMP_OUTBOUND_DISABLED_TYPES}'} = "";
		    $settings{'LOG_FAILURES'} = "N";
		};
    my $dhcp = sub { if ($_[0]) {
	$settings{DHCP_IFACES} and return;
	my (undef, undef, @netstat) = `/bin/netstat -in`;
	$settings{DHCP_IFACES} = join(' ', split(' ', $settings{DHCP_IFACES}), map { /(\S+)/ } @netstat );
    } else { $settings{DHCP_IFACES} = "" } };
    my $quit = sub {
	$_[0] or $in->exit(0);
	SaveConfig();
	$in->exit(0);
	return;
	$_[0] or $in->exit(0);
	commands::cp("-f", $config_file, $config_file . ".orig");
	substInFile {
	    if(/^(.+)\s*\=/) {
		$a=$settings{$1};
		s/\".*\"/\"$a\"/;
	    }
	} $config_file;
	map { system($_) } ("/bin/cp /usr/share/Bastille/bastille-ipchains /usr/share/Bastille/bastille-netfilter /sbin",
			    "/bin/cp /usr/share/Bastille/bastille-firewall /etc/rc.d/init.d/",
			    "/bin/chmod 0700 /etc/rc.d/init.d/bastille-firewall", "/bin/chmod 0700 /sbin/bastille-ipchains",
			    "/bin/chmod 0700 /sbin/bastille-netfilter", "/sbin/chkconfig bastille-firewall on",
			    "/etc/rc.d/init.d/bastille-firewall stop", "/etc/rc.d/init.d/bastille-firewall start"); };
    my @struct = (
		  [$GetNetworkInfo],
		  [],
		  [undef , undef, undef, undef, ["tcp", "80"], ["tcp", "443"]],
		  [undef , undef, undef, undef, ["tcp", "53"], ["udp", "53"]],
		  [undef , undef, undef, undef, ["tcp", "22"]],
		  [undef , undef, undef, undef, ["tcp", "23"]],
		  [undef , undef, undef, undef, ["tcp", "20"],["tcp", "21"]],
		  [undef , undef, undef, undef, ["tcp", "25"]],
		  [undef , undef, undef, $popimap, ["tcp", "109"], ["tcp", "110"], ["tcp", "143"]],
		  [undef , "No I don't need DHCP", "Yes I need DHCP", $dhcp],
		  [undef , "No I don't need NTP", "Yes I need NTP", $ntp ],
		  [undef , "Don't Save", "Save & Quit", $quit ]
		 );
    !Kernel22() and pop @struct, pop @struct;
    for (my $i=0;$i<@struct;$i++) {
	$::Wizard_no_previous = $i == 0;
	$::Wizard_finished = $i == $#struct;
	my $l = $struct[$i];
	@$l or goto ask;
	if (@$l == 1) {
	    ($l->[0])->();
	  ask:
	    $in->ask_okcancel(_("Firewall Configuration Wizard"), $messages[$i],1) ? next : goto prev;
	}
	my $no = $l->[1] ? $l->[1] : _("No (firewall this off from the internet)");
	my $yes = $l->[2] ? $l->[2] : _("Yes (allow this through the firewall)");
	if (my $e = $in->ask_from_list_(_("Firewall Configuration Wizard"),
				       $messages[$i],
				       [ $yes, $no ], or_( map { $_ && CheckService($_->[0], $_->[1]) } (@$l[4..6])) ? $yes : $no
				      )) {
	    map { $_ and Service($e=~/Yes/, $_->[0], $_->[1]) } (@{$struct[$i]}[4..6]);
	    $struct[$i][3] and $struct[$i][3]->($e=~/Yes/ || $e eq "Save & Quit");
	} else {
	  prev:
	    $i = $i-2 >= -1 ? $i-2 : -1;
	}
    }
}
sub unbox_service {
    split ' ', $settings{uc($_[0]) . "_PUBLIC_SERVICES"}
}
sub Service {
    my ($add, $protocol, $port) = @_;
    my @l = unbox_service($protocol);
    @l = uniq($add ? (@l, $port) : grep { $_ ne $port } @l);
    $settings{uc($protocol) . "_PUBLIC_SERVICES"} = join(' ', @l);
}
sub CheckService { member($_[1], unbox_service($_[0])); }
sub Kernel22 {
    my ($major, $minor, $patchlevel) = (cat_("/proc/version"))[0] =~ m/^Linux version ([0-9]+)\.([0-9]+)\.([0-9]+)/;
    $major eq "2" && $minor eq "2";
}
sub main {
    my ($in)=@_;
    ReadConfig;
    DoInterface($in);
}