Annotation of loncom/lcnfson, revision 1.2

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

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