Annotation of loncom/lcnfsoff, revision 1.2

1.1       harris41    1: #!/usr/bin/perl
                      2: 
                      3: use strict;
                      4: 
                      5: # This script is a setuid script (chmod 6755; chown root:root).
                      6: # It disables nfs/portmap services for a specific user at
                      7: # a specific ip address.
                      8: 
                      9: # Exit codes.  0=ok.  Higher than 0 means something went wrong.
                     10: 
                     11: # Usage within code
                     12: #
                     13: # $exitcode=system("/home/httpd/perl/lcnfsoff","NAME","IPADDRESS")/256;
                     14: # print "uh-oh" if $exitcode;
                     15: 
                     16: # Security
                     17: $ENV{'PATH'}=""; # Nullify path information.
                     18: $ENV{'BASH_ENV'}=""; # Nullify shell environment information.
                     19: 
                     20: # Do not print error messages if there are command-line arguments
                     21: my $noprint=0;
                     22: if (@ARGV) {
                     23:     $noprint=1;
                     24: }
                     25: 
                     26: # Read in /etc/passwd, and make sure this process is running from user=www
                     27: open (IN, "</etc/passwd");
                     28: my @lines=<IN>;
                     29: close IN;
                     30: my $wwwid;
                     31: for my $l (@lines) {
                     32:     chop $l;
                     33:     my @F=split(/\:/,$l);
                     34:     if ($F[0] eq 'www') {$wwwid=$F[2];}
                     35: }
                     36: if ($wwwid!=$<) {
                     37:     print("User ID mismatch.  This program must be run as user 'www'\n") unless $noprint;
                     38:     exit 1;
                     39: }
                     40: &disable_root_capability;
                     41: 
                     42: # Handle case of another lcnfs process
                     43: unless (&try_to_lock("/tmp/lock_lcnfs")) {
                     44:     print "Error. Too many other simultaneous nfs change requests being made.\n" unless $noprint;
                     45:     exit 4;
                     46: }
                     47: # Gather input.  Should be 2 values (user name, numeric ip address).
                     48: my @input;
                     49: if (@ARGV==3) {
                     50:     @input=@ARGV;
                     51: }
                     52: elsif (@ARGV) {
                     53:     print("Error. This program needs 2 command-line arguments (username, numeric ip address).\n") unless $noprint;
                     54:     unlink('/tmp/lock_lcnfs');
                     55:     exit 2;
                     56: }
                     57: else {
                     58:     @input=<>;
                     59:     if (@input!=2) {
                     60: 	print("Error. Two lines should be entered into standard input.\n") unless $noprint;
                     61: 	unlink('/tmp/lock_lcnfs');
                     62: 	exit 3;
                     63:     }
                     64:     map {chop} @input;
                     65: }
                     66: 
                     67: my ($username,$ipaddress)=@input;
                     68: $username=~/^(\w+)$/;
                     69: my $safeusername=$1;
                     70: if ($username ne $safeusername) {
                     71:     print "Error. The user name specified has invalid characters.\n";
                     72:     unlink('/tmp/lock_lcnfs');
                     73:     exit 9;
                     74: }
                     75: 
                     76: $ipaddress=~/^([\w|\.]*)$/;
                     77: my $safeipaddress=$1;
                     78: if ($ipaddress ne $safeipaddress) {
                     79:     print "Error. The IP address must be numeric and of the form ##.##.##.##.\n";
                     80:     unlink('/tmp/lock_lcnfs');
                     81:     exit 8;
                     82: }
                     83: 
                     84: &enable_root_capability;
                     85: # Remove entry from /etc/exports
                     86: my $exports=`/bin/cat /etc/exports`;
                     87: $exports=~s/\/home\/${safeusername}\s*${safeipaddress}.*?\n//g;
                     88: # Resynchronize /etc/exports file
                     89: open (OUT,">/etc/exports");
                     90: print OUT $exports;
                     91: close OUT;
                     92: system('/usr/sbin/exportfs','-r');
                     93: 
                     94: # Remove entry from /etc/hosts.allow
                     95: my $hostsallow=`/bin/cat /etc/hosts.allow`;
                     96: $hostsallow=~s/\# $safeusername\nportmap: $safeipaddress\n//g;
                     97: open (OUT,">/etc/hosts.allow");
                     98: print OUT $hostsallow;
                     99: close OUT;
                    100: 
                    101: &disable_root_capability;
                    102: unlink('/tmp/lock_lcnfs');
                    103: exit 0;
                    104: 
                    105: # ----------------------------------------------------------- have setuid script run as root
                    106: sub enable_root_capability {
                    107:     if ($wwwid==$>) {
                    108: 	($<,$>)=($>,$<);
                    109: 	($(,$))=($),$();
                    110:     }
                    111:     else {
                    112: 	# root capability is already enabled
                    113:     }
                    114:     return $>;
                    115: }
                    116: 
                    117: # ----------------------------------------------------------- have setuid script run as www
                    118: sub disable_root_capability {
                    119:     if ($wwwid==$<) {
                    120: 	($<,$>)=($>,$<);
                    121: 	($(,$))=($),$();
                    122:     }
                    123:     else {
                    124: 	# root capability is already disabled
                    125:     }
                    126: }
                    127: 
                    128: # ----------------------------------- make sure that another lcnfs process isn't running
                    129: sub try_to_lock {
                    130:     my ($lockfile)=@_;
                    131:     my $currentpid;
                    132:     my $lastpid;
                    133:     # Do not manipulate lock file as root
                    134:     if ($>==0) {
                    135: 	return 0;
                    136:     }
                    137:     # Try to generate lock file.
                    138:     # Wait 3 seconds.  If same process id is in
                    139:     # lock file, then assume lock file is stale, and
                    140:     # go ahead.  If process id's fluctuate, try
                    141:     # for a maximum of 10 times.
                    142:     for (0..10) {
                    143: 	if (-e $lockfile) {
                    144: 	    open(LOCK,"<$lockfile");
                    145: 	    $currentpid=<LOCK>;
                    146: 	    close LOCK;
                    147: 	    if ($currentpid==$lastpid) {
                    148: 		last;
                    149: 	    }
                    150: 	    sleep 3;
                    151: 	    $lastpid=$currentpid;
                    152: 	}
                    153: 	else {
                    154: 	    last;
                    155: 	}
                    156: 	if ($_==10) {
                    157: 	    return 0;
                    158: 	}
                    159:     }
                    160:     open(LOCK,">$lockfile");
                    161:     print LOCK $$;
                    162:     close LOCK;
                    163:     return 1;
                    164: }
                    165: 
                    166: 

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