#!/usr/bin/perl # The Learning Online Network with CAPA # # lcpasswd - LON-CAPA setuid script to synchronously change all # filesystem-related passwords (samba, unix, etc) # # YEAR=2002 # 02/19 Matthew Hall # # $Id: lcpasswd,v 1.22 2010/10/12 10:33:47 foxr Exp $ ### ############################################################################### ## ## ## ORGANIZATION OF THIS PERL SCRIPT ## ## ## ## 1. Description of script ## ## 2. Invoking script (standard input only) ## ## 3. Example usage inside another piece of code ## ## 4. Description of functions ## ## 5. Exit codes ## ## ## ############################################################################### use strict; # ------------------------------------------------------- Description of script # # This script is a setuid script that should # be run by user 'www'. This script allows # for synchronous entry of passwords into # both the /etc/passwd and the /etc/smbpasswd # files. # # This script works under the same process control mechanism # as lcuseradd and lcpasswd, to make sure that only one of these # processes is running at any one time on the system. # --------------------------------------- Invoking script (standard input only) # # Standard input usage # First line is USERNAME # Second line is NEW PASSWORD # Third line is NEW PASSWORD # # Valid passwords must consist of the # ascii characters within the inclusive # range of 0x20 (32) to 0x7E (126). # These characters are: # SPACE and # !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO # PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ # # Valid user names must consist of ascii # characters that are alphabetical characters # (A-Z,a-z), numeric (0-9), or the underscore # mark (_). (Essentially, the perl regex \w). # User names must begin with an alphabetical character # (A-Z,a-z). # ---------------------------------------------------- Description of functions # enable_root_capability() : have setuid script run as root # disable_root_capability() : have setuid script run as www # try_to_lock() : make sure that another lcpasswd process isn't running # ------------------------------------------------------------------ Exit codes # These are the exit codes. # ( (0,"ok"), # (1,"User ID mismatch. This program must be run as user 'www'"), # (2,"Error. This program needs 3 command-line arguments (username, old ". # password, new password)."), # (3,"Error. Three lines need to be entered into standard input."), # (4,"Error. Too many other simultaneous password change requests being ". # made."), # (5,"Error. User $username does not exist."), # (6,"Error. Invalid entry of current password."), # (7,"Error. Root was not successfully enabled."), # (8,"Error. Cannot set password."), # (9,"Error. The user name specified has invalid characters."), # (10,"Error. A password entry had an invalid character.") ) # ------------------------------------------------------------- Initializations # Security $ENV{'PATH'}='/bin:/usr/bin:/usr/local/sbin:/home/httpd/perl'; # Nullify path # information delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # nullify potential taints # Do not print error messages my $noprint=1; print "In lcpasswd" unless $noprint; # ----------------------------- Make sure this process is running from user=www my $wwwid=getpwnam('www'); if ($wwwid!=$<) { print("User ID mismatch. This program must be run as user 'www'\n") unless $noprint; exit 1; } # ----------------------------------- Start running script with www permissions # --------------------------- Handle case of another lcpasswd process (locking) unless (&try_to_lock('/tmp/lock_lcpasswd')) { print "Error. Too many other simultaneous password change requests being ". "made.\n" unless $noprint; exit 4; } # ------- Error-check input, need 3 values (user name, password 1, password 2). my @input; @input=<>; if (@input!=3) { print("Error. Three lines need to be entered into standard input.\n") unless $noprint; unlink('/tmp/lock_lcpasswd'); exit 3; } foreach (@input) {chomp;} my ($username,$password1,$password2)=@input; $username=~/^(\w+)$/; my $safeusername=$1; if (($username ne $safeusername) or ($safeusername!~/^[A-Za-z]/)) { print "Error. The user name specified has invalid characters.\n"; unlink('/tmp/lock_lcpasswd'); exit 9; } my $pbad=0; foreach (split(//,$password1)) {if ((ord($_)<32)||(ord($_)>126)){$pbad=1;}} foreach (split(//,$password2)) {if ((ord($_)<32)||(ord($_)>126)){$pbad=1;}} if ($pbad) { print "Error. A password entry had an invalid character.\n"; unlink('/tmp/lock_lcpasswd'); exit 10; } # -- Only add user if the two password arguments match. if ($password1 ne $password2) { print "Error. Password mismatch.\n" unless $noprint; unlink('/tmp/lock_lcpasswd'); exit 13; } # Verify existence of user unless(getpwnam($safeusername)) { print "Error. User $username does not exist.\n" unless $noprint; unlink('/tmp/lock_lcpasswd'); exit 5; } &enable_root_capability; ($>,$<)=(0,0); print "Now $> , $< , -invoking pwchange with $safeusername $password1" unless $noprint; open OUT,"|pwchange $safeusername"; print OUT $password1; print OUT "\n"; close OUT; ($>,$<)=(0,$wwwid); print "pwchange done, back to uid $wwwid" unless $noprint; if ($?) { exit 8; } my $userid=getpwnam($safeusername); if (-e '/usr/bin/smbpasswd') { ($>,$<)=(0,0); # fool smbpasswd here to think this is not a setuid # environment # If the -a switch is put on the smbpasswd # command line, either a new entry will be created or the old one # will be used. # Therefore the old strategy of looking for and adding a dummy entry is # not needed... Finally, the smbpasswd file is in /etc/samba not # /etc/smbpasswd as older versions of the script implied. print "Running smbpasswd" unless $noprint; open(OUT,"|/usr/bin/smbpasswd -s -a $safeusername>/dev/null") or die('cannot run smbpasswd'); print OUT $password2; print OUT "\n"; print OUT $password2; print OUT "\n"; close OUT; $<=$wwwid; # unfool the program print "smbpasswd done" unless $noprint; } unlink('/tmp/lock_lcpasswd'); exit 0; # ---------------------------------------------- have setuid script run as root sub enable_root_capability { if ($wwwid==$>) { ($<,$>)=($>,0); ($(,$))=($),0); } else { # root capability is already enabled } return $>; } # ----------------------------------------------- have setuid script run as www sub disable_root_capability { if ($wwwid==$<) { ($<,$>)=($>,$<); ($(,$))=($),$(); } else { # root capability is already disabled } } # ----------------------- make sure that another lcpasswd process isn't running sub try_to_lock { my ($lockfile)=@_; my $currentpid; my $lastpid; # Try to generate lock file. # Wait 3 seconds. If same process id is in # lock file, then assume lock file is stale, and # go ahead. If process id's fluctuate, try # for a maximum of 10 times. for (0..10) { if (-e $lockfile) { open(LOCK,"<$lockfile"); $currentpid=; close LOCK; if ($currentpid==$lastpid) { last; } sleep 3; $lastpid=$currentpid; } else { last; } if ($_==10) { return 0; } } open(LOCK,">$lockfile"); print LOCK $$; close LOCK; return 1; } =head1 NAME lcpasswd - LON-CAPA setuid script to synchronously change all filesystem-related passwords (samba, unix, etc) =head1 DESCRIPTION LON-CAPA setuid script to synchronously change all filesystem-related passwords (samba, unix, etc) =head1 README LON-CAPA setuid script to synchronously change all filesystem-related passwords (samba, unix, etc) =head1 PREREQUISITES =head1 COREQUISITES =pod OSNAMES linux =pod SCRIPT CATEGORIES LONCAPA/Administrative =cut 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.