File:  [LON-CAPA] / loncom / lcpasswd
Revision 1.3: download - view: text, annotated - select for diffs
Fri Oct 27 22:13:40 2000 UTC (23 years, 6 months ago) by harris41
Branches: MAIN
CVS tags: HEAD
minor rearrangement of comments

    1: #!/usr/bin/perl
    2: #
    3: # lcpasswd
    4: #
    5: # Scott Harrison
    6: # October 27, 2000
    7: 
    8: use strict;
    9: 
   10: # This script is a setuid script that should
   11: # be run by user 'www'.
   12: 
   13: # Standard input usage
   14: # First line is USERNAME
   15: # Second line is CURRENT PASSWORD
   16: # Third line is NEW PASSWORD
   17: 
   18: # Security
   19: $ENV{'PATH'}="/bin:/usr/bin"; # Nullify path information except for what smbpasswd needs
   20: $ENV{'BASH_ENV'}=""; # Nullify shell environment information.
   21: 
   22: open (IN, "</etc/passwd");
   23: my @lines=<IN>;
   24: close IN;
   25: my $wwwid;
   26: for my $l (@lines) {
   27:     chop $l;
   28:     my @F=split(/\:/,$l);
   29:     if ($F[0] eq 'www') {$wwwid=$F[2];}
   30: }
   31: if ($wwwid!=$<) {
   32:     print("User ID mismatch.  This program must be run as user 'www'\n");
   33:     exit 0;
   34: }
   35: &disable_root_capability;
   36: if (@ARGV) {
   37:     print("Error. This program does not accept command-line arguments.\n");
   38:     exit 0;
   39: }
   40: 
   41: # Gather input from standard input.  Should only be 3 lines.
   42: my @input=<>;
   43: if (@input!=3) {
   44:     print("Error. Three lines need to be entered into standard input.\n");
   45:     exit 0;
   46: }
   47: 
   48: # Handle case of another lcpasswd process
   49: unless (&try_to_lock("/tmp/lock_lcpasswd")) {
   50:     print "Error. Too many other simultaneous password change requests being made.\n";
   51:     exit 0;
   52: }
   53: 
   54: my ($username,$oldpwd,$newpwd)=map {chop; $_} @input;
   55: 
   56: # Grab the line corresponding to username
   57: my ($userid,$useroldcryptpwd);
   58: my @F; my @U;
   59: for my $l (@lines) {
   60:     @F=split(/\:/,$l);
   61:     if ($F[0] eq $username) {($userid,$useroldcryptpwd)=($F[2],$F[1]); @U=@F;}
   62: }
   63: 
   64: # Verify existence of user
   65: if (!defined($userid)) {
   66:     print "Error. User $username does not exist.\n";
   67:     exit 0;
   68: }
   69: 
   70: # Verify password entry
   71: if (crypt($oldpwd,$useroldcryptpwd) ne $useroldcryptpwd) {
   72:     print "Error. Invalid entry of current password.\n";
   73:     exit 0;
   74: }
   75: 
   76: # Construct new password entry (random salt)
   77: my $newcryptpwd=crypt($newpwd,(join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]));
   78: $U[1]=$newcryptpwd;
   79: my $userline=join(":",@U);
   80: my $rootid=&enable_root_capability;
   81: if ($rootid!=0) {
   82:     print "Error.  Root was not successfully enabled.\n";
   83:     exit 0;
   84: }
   85: open PASSWORDFILE, ">/etc/passwd" or die("Cannot open /etc/passwd!");
   86: for my $l (@lines) {
   87:     @F=split(/\:/,$l);
   88:     if ($F[0] eq $username) {print PASSWORDFILE "$userline\n";}
   89:     else {print PASSWORDFILE "$l\n";}
   90: }
   91: close PASSWORDFILE;
   92: $username=~/^(\w+)$/;
   93: my $safeusername=$1;
   94: ($>,$<)=(0,0); # fool smbpasswd here to think this is not a setuid environment
   95: unless (-e "/etc/smbpasswd") {
   96:     open (OUT,">/etc/smbpasswd"); close OUT;
   97: }
   98: my $smbexist=0;
   99: open (IN, "</etc/smbpasswd");
  100: my @lines=<IN>;
  101: close IN;
  102: for my $l (@lines) {
  103:     chop $l;
  104:     my @F=split(/\:/,$l);
  105:     if ($F[0] eq $username) {$smbexist=1;}
  106: }
  107: unless ($smbexist) {
  108:     open(OUT,">>/etc/smbpasswd");
  109:     print OUT join(":",($safeusername,$userid,'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX','','/home/'.$safeusername,'/bin/bash')) . "\n";
  110:     close OUT;
  111: }
  112: open(OUT,"|/usr/bin/smbpasswd -s $safeusername>/dev/null");
  113: print OUT $newpwd; print OUT "\n";
  114: print OUT $newpwd; print OUT "\n";
  115: close OUT;
  116: $<=$wwwid; # unfool the program
  117: &disable_root_capability;
  118: unlink("/tmp/lock_lcpasswd");
  119: 
  120: sub enable_root_capability {
  121:     if ($wwwid==$>) {
  122: 	($<,$>)=($>,$<);
  123: 	($(,$))=($),$();
  124:     }
  125:     else {
  126: 	# root capability is already enabled
  127:     }
  128:     return $>;
  129: }
  130: 
  131: sub disable_root_capability {
  132:     if ($wwwid==$<) {
  133: 	($<,$>)=($>,$<);
  134: 	($(,$))=($),$();
  135:     }
  136:     else {
  137: 	# root capability is already disabled
  138:     }
  139: }
  140: 
  141: sub try_to_lock {
  142:     my ($lockfile)=@_;
  143:     my $currentpid;
  144:     my $lastpid;
  145:     for (0..10) {
  146: 	if (-e $lockfile) {
  147: 	    open(LOCK,"<$lockfile");
  148: 	    $currentpid=<LOCK>;
  149: 	    close LOCK;
  150: 	    if ($currentpid==$lastpid) {
  151: 		last;
  152: 	    }
  153: 	    sleep 3;
  154: 	    $lastpid=$currentpid;
  155: 	}
  156: 	else {
  157: 	    last;
  158: 	}
  159: 	if ($_==10) {
  160: 	    return 0;
  161: 	}
  162:     }
  163:     open(LOCK,">$lockfile");
  164:     print LOCK $$;
  165:     close LOCK;
  166:     return 1;
  167: }

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