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