Annotation of loncom/lcnfson, revision 1.6

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.