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

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