home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl
-
- =begin comment info
- +-----------------------------------------------------------------------------+
- | Copyright 2001, Guardian Digital Inc.
- | $Id: firewall-lib.pl,v 1.7 2002/05/16 16:28:19 rwm Exp $
- |
- | Ryan W. Maple, <ryan@guardiandigital.com>
- +-----------------------------------------------------------------------------+
- =end comment info
- =cut
-
- require "../Security.pl";
-
- ### ##########################################################################
- ### Global Variables
- ### ##########################################################################
- $CONFIGURATION_FILE = '/etc/firewall/firewall.conf';
- $PORTFW_FILE = '/etc/firewall/include/portfw.sh';
- $IPCHAINS_INIT = '/etc/init.d/iptables';
- $CHKCONFIG_BIN = '/sbin/chkconfig';
- $IPCHAINS_BIN = '/sbin/iptables';
- $IPFWADM_BIN = '/sbin/ipfwadm';
- $IPMASQADM_BIN = '/usr/sbin/ipmasqadm';
- $IPCALC_BIN = '/bin/ipcalc';
- $FIREWALL_HTB_DIR = '/etc/firewall/htb';
-
- @PORTFW_PROTOCOLS = ('tcp', 'udp');
-
- %PORTFW_PORTS = ( 20, 'FTP Data (20)',
- 21, 'FTP (21)',
- 22, 'SSH (22)',
- 23, 'Telnet (23)',
- 25, 'SMTP (25)',
- 53, 'DNS (53)',
- 80, 'HTTP (80)',
- 110, 'POP3 (110)',
- 143, 'IMAP (143)',
- 443, 'HTTPS (443)',
- 993, 'SIMAP (993)',
- 995, 'SPOP3 (995)',
- 8080, 'Web Proxy (8080)' );
-
- @HTB_RATE_TYPES = ('Kbit', 'Mbit');
-
-
- ##############################################################################
- sub firewallHTBGetNextCID() {
- my $PARENT = shift;
- my %CLASS = &firewallHTBReadClasses();
- my $RV = undef;
- my @TMP = undef;
-
- # Build a list of all existing children nodes of this @PARENT in @TMP.
- foreach my $k (sort keys %CLASS) {
- push @TMP, $k if ($CLASS{$k}->{'PARENT'} eq "1:$PARENT");
- }
-
- # This is the first child node of $PARENT. Make it's LSB 0.
- if (! $TMP[0]) { $RV = $PARENT . "0"; }
-
- # Get the largest cid, add one, and return the result.
- else { @TMP = sort { $b <=> $a } @TMP; $RV = ++$TMP[0] }
-
- # Hand it back up.
- return $RV;
- }
-
- ### ##########################################################################
- sub firewallHTBWalkTree() {
- my $BASE_NODE = shift;
- my $FCN = shift;
- my %CLASS = &firewallHTBReadClasses();
- my @CURRENT = ("$BASE_NODE");
- my $DEPTH = 0;
- my $CLASS_SEEN_COUNT = 1;
- my $CLASS_TOUCHED_COUNT = 1;
-
- # Find out how many nodes we have.
- foreach my $k (sort keys %CLASS) { $CLASS_SEEN_COUNT++; }
-
- # Loop until we've hit every node.
- while ($CLASS_TOUCHED_COUNT < $CLASS_SEEN_COUNT) {
- my $NEXT = undef;
-
- # Find any untouched children of this node (run till $NEXT is undef).
- foreach my $k (sort keys %CLASS) {
-
- # Touch this child, bump our touched count, and do SOMETHING with it.
- if (($CLASS{$k}->{'PARENT'} eq $CURRENT[$DEPTH]) &&
- (! $CLASS{$k}->{'TOUCHED'}) && ! $NEXT) {
- $CLASS{$k}->{'TOUCHED'} = 1;
-
- #
- # ($FCN == 1) We want to print this in a table on list_htb.cgi.
- #
- if ($FCN == 1) {
- my $SPACER = "";
- for (my $i = 0; $i < $DEPTH; $i++) { $SPACER .= " "; }
-
- # Print a row.
- print <<EOF;
- <TR $cb>
- <TD WIDTH="10"> </TD>
- <TD><DIV CLASS="nbody">$SPACER<B><A HREF="edit_htb_class.cgi?classid=$k">$CLASS{$k}->{'NAME'} (1:$k)</B></A></DIV></TD>
- <TD><DIV CLASS="nbody">$CLASS{$k}->{'RATE'}</DIV></TD>
- <TD><DIV CLASS="nbody">$CLASS{$k}->{'CEIL'}</DIV></TD>
- </TR>
- EOF
- }
-
- # Bump our touched count and move down to this node next pass.
- $CLASS_TOUCHED_COUNT++;
- $NEXT = "1:$k";
- }
- }
-
- #
- # If $NEXT was not defined thn $CURRENT has no more children. Move up a
- # branch. # Otherwise push our new $NEXT parent onto @CURRENT and move
- # into the new branch.
- #
-
- # If we didn't find any children then move up a node. Otherwise move
- # down to the new child.
- if (! $NEXT) { pop @CURRENT; $DEPTH--; }
- else { push @CURRENT, $NEXT; $DEPTH++; }
- }
-
- }
-
- ### ##########################################################################
- sub firewallHTBReadClasses() {
- my %CLASS;
-
- opendir CLASSES, "$FIREWALL_HTB_DIR";
- foreach my $c (sort readdir CLASSES) {
- next if (($c !~ m/^[0-9]+$/) || (! -f "$FIREWALL_HTB_DIR/$c"));
- $CLASS{$c} = &firewallReadHTBFile($c);
- $CLASS_SEEN_COUNT++;
- }
- closedir CLASSES;
-
- return %CLASS;
- }
-
- ### ############################################################################
- sub firewallReadHTBFile() {
- my $FILE = shift;
- my $RV;
-
- open HTBFILE, "$FIREWALL_HTB_DIR/$FILE";
- while (my $line = <HTBFILE>) {
- chomp $line;
-
- my ($KEY, $VALUE);
- ($KEY, $VALUE) = ($line =~ m/^([A-Z]+)\=\"?([^\"]+)\"?$/);
- $RV->{$KEY} = $VALUE;
- }
- close HTBFILE;
-
- # Break RATE and CEIL apart for edit_htb_class.cgi
- my @tmp = ($RV->{'RATE'} =~ m/^([0-9]+)(.*)$/);
- $RV->{'RATE_n'} = $tmp[0]; $RV->{'RATE_t'} = $tmp[1];
- my @tmp = ($RV->{'CEIL'} =~ m/^([0-9]+)(.*)$/);
- $RV->{'CEIL_n'} = $tmp[0]; $RV->{'CEIL_t'} = $tmp[1];
-
- # Make sure this node isn't touched and hand it back.
- $RV->{'TOUCHED'} = 0;
- return $RV;
- }
-
- ### ##########################################################################
- sub firewallReadConfig() {
- my (%C);
-
- open CONFIG, '/etc/firewall/firewall.conf';
- while (my $line = <CONFIG>)
- {
- my ($key, $value);
- chomp $line;
-
- next if (($line eq "") || ($line =~ m/^#/));
-
- ($key, $value) = split /\=/, $line;
- $C{$key} = $value;
- }
- close CONFIG;
-
-
- # Read our HTB 'defaults' file
- open CONFIG, 'etc/fireall/htb/defaults';
- while (my $line = <CONFIG>) {
- chomp $line;
-
- if ($line =~ /^DEVICE=\"?([^\"]+)\"?$/) {
- $C{'htb_device'} = $1;
- }
- elsif ($line =~ /^DEFAULT=\"?([^\"]+)\"?$/) {
- $C{'htb_defaultclass'} = $1;
- }
- }
- close CONFIG;
-
- return %C;
- }
-
-
- ### ##########################################################################
- sub firewallGetInterfaces() {
- my (@addresses, $IN_IFACE, $IS_VIRT, $tmp_iface);
-
- $IN_IFACE = 0;
- $IS_VIRT = 0;
- $tmp_iface = "";
-
- open IFCONFIG, "/sbin/ifconfig |";
- while (<IFCONFIG>)
- {
- chomp $_;
-
- if (($_ =~ m/^(eth[0-9\:]+)\s+/) || ($_ =~ m/^(ppp[0-9\:]+)\s+/)) {
- $IN_IFACE = 1; $tmp_iface = $1;
- $IS_VIRT = 1 if ($tmp_iface =~ m/\:/);
- }
- elsif ($_ eq "") { $IN_IFACE = 0; $IS_VIRT = 0; $tmp_iface = ""; }
-
- if (($_ =~ m/^\s+inet\ addr\:([0-9\.]+).*Mask\:([0-9\.]+)$/) &&
- $IN_IFACE) {
- my $IF = $1;
- my $MASK = $2;
- my @BYTES = split /\./, $2;
- my $CIDR = 0;
-
- for (@BYTES) {
- my $BITS = unpack( "B*", pack( "C", $_ ) );
- $CIDR += $BITS =~ tr /1/1/;
- }
-
- push @addresses, { 'iface' => $tmp_iface,
- 'address' => $IF,
- 'netmask' => $MASK,
- 'cidr' => $CIDR,
- 'virtual' => $IS_VIRT };
- }
- }
- close IFCONFIG;
-
- return @addresses;
- }
-
-
- ### ##########################################################################
- ### Usage: &firewallBuildIfaceSelect($name, $selected, $novirt, $ifacefirst);
- ### ##########################################################################
- sub firewallBuildIfaceSelect() {
- my ($ret, @INTERFACES); $ret = "";
-
- $ret = "<SELECT NAME=\"$_[0]\">\n";
- $ret .= " <OPTION VALUE=\"NULL\">Please Select</OPTION>\n";
- @INTERFACES = &firewallGetInterfaces();
-
- foreach my $i (sort @INTERFACES) {
- my ($if, $address);
-
- next if ($i->{'virtual'} && $_[2]);
-
- $if = $i->{'iface'};
- $address = $i->{'address'};
-
- $ret .= " <OPTION VALUE=\"$if\" ";
- $ret .= "SELECTED" if ($if eq $_[1]);
-
- if ($_[3]) { $ret .= ">$if ($address)</OPTION>\n"; }
- else { $ret .= ">$address ($if)</OPTION>\n"; }
- }
-
- $ret .= "</SELECT>\n";
-
- return $ret;
- }
-
-
- ### ##########################################################################
- sub firewallListPortfw() {
- my (@PFW, $lineno, %GCONFIG); $lineno = -1;
-
- %GCONFIG = &firewallReadConfig();
-
- open PORTFW, $PORTFW_FILE;
- while (my $line = <PORTFW>)
- {
- my (@tmp); chomp $line; $lineno++;
-
- ### Skip all non-rule lines.
- next if ( ($line !~ m/^\$IPTABLES\ /) ||
- ($line eq "\$IPTABLES -F"));
-
- ### Split the $line apart and populate @PFW.
- @tmp = split /\ /, $line;
- @rtmp = split /:/, $tmp[14];
- $rtmp[0] = $GCONFIG{'UNTRUSTED_IP'} if ($rtmp[0] eq "\$UNTRUSTED_IP");
-
- push @PFW, { 'lineno' => $lineno, 'proto' => $tmp[6],
- 'laddr' => $tmp[8], 'lport' => $tmp[10],
- 'raddr' => $rtmp[0], 'rport' => $rtmp[1] };
- }
- close PORTFW;
-
- return @PFW;
- }
-
-
- ### ##########################################################################
- sub firewallGetNetworkNumber() {
- my ($rv, $tmp); $rv = undef;
-
- $rv = `$IPCALC_BIN --network $_[0] $_[1]`; chomp $rv; $rv =~ s/^NETWORK\=//;
-
- return $rv;
- }
-
-
- ### ##########################################################################
- sub firewallNumInterfaces() {
- my ($rv); $rv = 0;
-
- foreach my $i (&firewallGetInterfaces()) {
- next if ($i->{'virtual'});
- $rv++;
- }
-
- return $rv;
- }
-
-
- ### ##########################################################################
- sub firewallFirewallIsActive() {
- my ($rv);
-
- ($rv) = `chkconfig --list iptables` =~ m/\s+3\:([onf]+)/;
-
- return $rv;
- }
-
-
- ### ##########################################################################
- sub firewallPortFwCtl() {
- my ($rc); $rc = undef;
-
- if ($_[0] eq 'restart') {
- my (%E); %E = %ENV; %ENV = ();
- ## $rc = system ("/etc/firewall/include/portfw.sh");
- $rc = system ("/etc/firewall/include/default.sh");
- %ENV = %E;
- }
-
- return $rc;
- }
-
-
- ### ##########################################################################
- sub firewallPrintError {
- my ($message) = @_;
-
- print <<ErrorEOF;
- Content-type: text/html
-
-
- <HTML>
- <HEAD>
- <TITLE> </TITLE>
-
- <SCRIPT LANGUAGE="JavaScript">
- alert("$message");
- history.go(-1);
- </SCRIPT>
- </HEAD>
- </HTML>
- ErrorEOF
- }
-
-
- ### ##########################################################################
- sub isIP() {
- if ($_[0] =~ (m/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/)) {
- return 1;
- }
-
- return 0;
- }
-
-
-