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>