File:  [LON-CAPA] / loncom / lciptables
Revision 1.1: download - view: text, annotated - select for diffs
Thu Jun 11 00:15:27 2009 UTC (14 years, 9 months ago) by raeburn
Branches: MAIN
CVS tags: version_2_9_99_0, version_2_8_99_0, bz6209-base, bz6209, bz5969, bz2851, HEAD, GCI_3, GCI_2, BZ5971-printing-apage
loncron updates firewall access to lond port (5663) when connections are updated.
- uses lciptables (setuid script which calls routines in LONCAPA::Firewall.pm).
- list of IPs of hosts in cluster stored in temporary file, so
  lciptables does not need to load lonnet.pm
  (contains inadmissable commands in setuid context).

#!/usr/bin/perl
#
# The Learning Online Network with CAPA
#
# $Id: lciptables,v 1.1 2009/06/11 00:15:27 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
#  lciptables - LONC-CAPA setuid script to:
#              o use iptables commands to update Firewall rules for current
#                list of IPs for LON-CAPA hosts in server's cluster.
#

use strict;
use lib '/home/httpd/lib/perl/';
use LONCAPA::Firewall;

# ------------------------------------------------------------------ Exit codes
# Exit codes.
# ( (0,"ok"),
# (1,"User ID mismatch.  This program must be run as user 'www'"),
# (2,"Missing argument: Usage: this script takes one argument - ".
# " the name of a file in /home/httpd/perl/tmp containing IP addresses."),
# (3,"Missing IP addresses file. The file containing IP addresses is missing."),
# (4,"Error. Only one lciptables script can run at any time."),
#
# ------------------------------------------------------------- Initializations
# Security
$ENV{'PATH'}='/bin/:/usr/bin:/usr/local/sbin:/home/httpd/perl'; # Nullify path
                                                                # information
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # nullify potential taints

# Do not print error messages.
my $noprint=1;

print "In lciptables\n" unless $noprint;

# ----------------------------- Make sure this process is running from user=www
my $wwwid=getpwnam('www');
&DisableRoot;
if ($wwwid!=$>) {
    print("User ID mismatch.  This program must be run as user 'www'\n")
        unless $noprint;
    &Exit(1);
}

# ----------------------------------- Retrieve IP addreses for hosts in cluster
&DisableRoot;

my %iphost;
if (@ARGV != 1) {
    print("Error. this script takes one argument - the name of a file in /home/httpd/perl/tmp containing IP addresses.\n") unless $noprint;
    &Exit(2);
}
my $tmpfile = $ARGV[0];
if (-e $tmpfile) {
    if (open(my $fh,"<$tmpfile")) {
        while(<$fh>) {
            chomp();
            $iphost{$_} = 1;
        }
        close($fh);
    } else {
       &Exit(3);  
    }
} else {
    print "Error. File containing IP addresses of hosts in cluster does not exist\n" unless $noprint;
    &Exit(3);
}

# --------------------------- Handle case of another lciptables process (locking)
unless (&try_to_lock("/tmp/lock_lciptables")) {
    print "Error. Too many other simultaneous iptables manipulation requests being ".
        "made.\n" unless $noprint;
    &Exit(4);
}

my $lond_port = &LONCAPA::Firewall::get_lond_port();

($>,$<)=($wwwid,0);
&EnableRoot();

my $fw_chain = &LONCAPA::Firewall::get_fw_chain();
my $iptables = &LONCAPA::Firewall::get_pathto_iptables();
my $firewall_result = 
     &LONCAPA::Firewall::firewall_close_port($iptables,$fw_chain,$lond_port,[$lond_port]);
if ($firewall_result) {
    print "$firewall_result\n";
}
my $firewall_result = &LONCAPA::Firewall::firewall_open_port($iptables,$fw_chain,$lond_port,\%iphost,[$lond_port]);
if ($firewall_result) {
    print "$firewall_result\n";
}

# -------------------------------------------------------- Exit script
print "lciptables Exiting\n" unless $noprint;
&DisableRoot;
unlink('/tmp/lock_lciptables');
&Exit(0);


sub EnableRoot {
    if ($wwwid==$>) {
        ($<,$>)=($>,$<);
        ($(,$))=($),$();
    }
    else {
        # root capability is already enabled
    }
    return $>;
}

sub DisableRoot {
    if ($wwwid==$<) {
        ($<,$>)=($>,$<);
        ($(,$))=($),$();
    }
    else {
        # root capability is already disabled
    }
}

sub try_to_lock {
    my ($lockfile)=@_;
    my $currentpid;
    my $lastpid;
    # Do not manipulate lock file as root
    if ($>==0) {
        return 0;
    }
    # Try to generate lock file.
    # Wait 3 seconds.  If same process id is in
    # lock file, then assume lock file is stale, and
    # go ahead.  If process id's fluctuate, try
    # for a maximum of 10 times.
    for (0..10) {
        if (-e $lockfile) {
            open(LOCK,"<$lockfile");
            $currentpid=<LOCK>;
            close LOCK;
            if ($currentpid==$lastpid) {
                last;
            }
            sleep 3;
            $lastpid=$currentpid;
        } else {
            last;
        }
        if ($_==10) {
            return 0;
        }
    }
    open(LOCK,">$lockfile");
    print LOCK $$;
    close LOCK;
    return 1;
}

sub Exit {
    my ($code) = @_;
    &DisableRoot();
    print "Exiting with status $code\n" unless $noprint;
    exit $code;
}


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>