File:  [LON-CAPA] / loncom / lcnfson
Revision 1.4: download - view: text, annotated - select for diffs
Mon Feb 3 18:03:52 2003 UTC (21 years, 1 month ago) by harris41
Branches: MAIN
CVS tags: version_2_5_X, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, version_1_3_X, version_1_3_3, version_1_3_2, version_1_3_1, version_1_3_0, version_1_2_X, version_1_2_99_1, version_1_2_99_0, version_1_2_1, version_1_2_0, version_1_1_X, version_1_1_99_5, version_1_1_99_4, version_1_1_99_3, version_1_1_99_2, version_1_1_99_1, version_1_1_99_0, version_1_1_3, version_1_1_2, version_1_1_1, version_1_1_0, version_1_0_99_3, version_1_0_99_2, version_1_0_99_1, version_1_0_99, version_1_0_3, version_1_0_2, version_1_0_1, version_1_0_0, version_0_99_5, version_0_99_4, version_0_99_3, version_0_99_2, version_0_99_1, version_0_99_0, conference_2003, HEAD
best wishes to all.

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

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