File:  [LON-CAPA] / loncom / lcpasswd
Revision 1.19: download - view: text, annotated - select for diffs
Mon Feb 3 18:03:52 2003 UTC (21 years, 4 months ago) by harris41
Branches: MAIN
CVS tags: 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: # The Learning Online Network with CAPA
    3: #
    4: # lcpasswd - LON-CAPA setuid script to synchronously change all
    5: #            filesystem-related passwords (samba, unix, etc)
    6: #
    7: # YEAR=2002
    8: # 02/19 Matthew Hall
    9: #
   10: # $Id: lcpasswd,v 1.19 2003/02/03 18:03:52 harris41 Exp $
   11: ###
   12: 
   13: ###############################################################################
   14: ##                                                                           ##
   15: ## ORGANIZATION OF THIS PERL SCRIPT                                          ##
   16: ##                                                                           ##
   17: ## 1. Description of script                                                  ##
   18: ## 2. Invoking script (standard input only)                                  ##
   19: ## 3. Example usage inside another piece of code                             ##
   20: ## 4. Description of functions                                               ##
   21: ## 5. Exit codes                                                             ##
   22: ##                                                                           ##
   23: ###############################################################################
   24: 
   25: use strict;
   26: 
   27: # ------------------------------------------------------- Description of script
   28: #
   29: # This script is a setuid script that should
   30: # be run by user 'www'.  This script allows
   31: # for synchronous entry of passwords into
   32: # both the /etc/passwd and the /etc/smbpasswd
   33: # files.
   34: #
   35: # This script works under the same process control mechanism
   36: # as lcuseradd and lcpasswd, to make sure that only one of these
   37: # processes is running at any one time on the system.
   38: 
   39: # --------------------------------------- Invoking script (standard input only)
   40: #
   41: # Standard input usage
   42: # First line is USERNAME
   43: # Second line is NEW PASSWORD
   44: # Third line is NEW PASSWORD
   45: #
   46: # Valid passwords must consist of the
   47: # ascii characters within the inclusive
   48: # range of 0x20 (32) to 0x7E (126).
   49: # These characters are:
   50: # SPACE and
   51: # !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO
   52: # PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
   53: #
   54: # Valid user names must consist of ascii
   55: # characters that are alphabetical characters
   56: # (A-Z,a-z), numeric (0-9), or the underscore
   57: # mark (_). (Essentially, the perl regex \w).
   58: # User names must begin with an alphabetical character
   59: # (A-Z,a-z).
   60: 
   61: # ---------------------------------------------------- Description of functions
   62: # enable_root_capability() : have setuid script run as root
   63: # disable_root_capability() : have setuid script run as www
   64: # try_to_lock() : make sure that another lcpasswd process isn't running
   65: 
   66: # ------------------------------------------------------------------ Exit codes
   67: # These are the exit codes.
   68: # ( (0,"ok"),
   69: #   (1,"User ID mismatch.  This program must be run as user 'www'"),
   70: #   (2,"Error. This program needs 3 command-line arguments (username, old ".
   71: #       password, new password)."),
   72: #   (3,"Error. Three lines need to be entered into standard input."),
   73: #   (4,"Error. Too many other simultaneous password change requests being ".
   74: #       made."),
   75: #   (5,"Error. User $username does not exist."),
   76: #   (6,"Error. Invalid entry of current password."),
   77: #   (7,"Error. Root was not successfully enabled."),
   78: #   (8,"Error. Cannot set password."),
   79: #   (9,"Error. The user name specified has invalid characters."),
   80: #   (10,"Error. A password entry had an invalid character.") )
   81: 
   82: # ------------------------------------------------------------- Initializations
   83: # Security
   84: $ENV{'PATH'}='/bin:/usr/bin:/usr/local/sbin:/home/httpd/perl'; # Nullify path
   85:                                                                # information
   86: delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # nullify potential taints
   87: 
   88: # Do not print error messages
   89: my $noprint=1;
   90: 
   91: print "In lcpasswd" unless $noprint;
   92: 
   93: # ----------------------------- Make sure this process is running from user=www
   94: my $wwwid=getpwnam('www');
   95: &disable_root_capability;
   96: if ($wwwid!=$>) {
   97:     print("User ID mismatch.  This program must be run as user 'www'\n")
   98: 	unless $noprint;
   99:     exit 1;
  100: }
  101: 
  102: # ----------------------------------- Start running script with www permissions
  103: &disable_root_capability;
  104: 
  105: # --------------------------- Handle case of another lcpasswd process (locking)
  106: unless (&try_to_lock('/tmp/lock_lcpasswd')) {
  107:     print "Error. Too many other simultaneous password change requests being ".
  108: 	"made.\n" unless $noprint;
  109:     exit 4;
  110: }
  111: 
  112: # ------- Error-check input, need 3 values (user name, password 1, password 2).
  113: my @input;
  114: @input=<>;
  115: if (@input!=3) {
  116:     print("Error. Three lines need to be entered into standard input.\n")
  117: 	unless $noprint;
  118:     unlink('/tmp/lock_lcpasswd');
  119:     exit 3;
  120: }
  121: foreach (@input) {chomp;}
  122: 
  123: my ($username,$password1,$password2)=@input;
  124: $username=~/^(\w+)$/;
  125: my $safeusername=$1;
  126: if (($username ne $safeusername) or ($safeusername!~/^[A-Za-z]/)) {
  127:     print "Error. The user name specified has invalid characters.\n";
  128:     unlink('/tmp/lock_lcpasswd');
  129:     exit 9;
  130: }
  131: my $pbad=0;
  132: foreach (split(//,$password1)) {if ((ord($_)<32)||(ord($_)>126)){$pbad=1;}}
  133: foreach (split(//,$password2)) {if ((ord($_)<32)||(ord($_)>126)){$pbad=1;}}
  134: if ($pbad) {
  135:     print "Error. A password entry had an invalid character.\n";
  136:     unlink('/tmp/lock_lcpasswd');
  137:     exit 10;
  138: }
  139: 
  140: # -- Only add user if the two password arguments match.
  141: if ($password1 ne $password2) {
  142:     print "Error. Password mismatch.\n" unless $noprint;
  143:     unlink('/tmp/lock_lcpasswd');
  144:     exit 13;
  145: }
  146: 
  147: # Verify existence of user
  148: unless(getpwnam($safeusername)) {
  149:     print "Error. User $username does not exist.\n" unless $noprint;
  150:     unlink('/tmp/lock_lcpasswd');
  151:     exit 5;
  152: }
  153: &enable_root_capability;
  154: ($>,$<)=(0,0);
  155: 
  156: print "Now $> , $< , -invoking pwchange with $safeusername $password1"
  157:     unless $noprint;
  158: open OUT,"|pwchange $safeusername";
  159: print OUT $password1;
  160: print OUT "\n";
  161: close OUT;
  162: ($>,$<)=(0,500);
  163: 
  164: print "pwchange done, back to uid 500" unless $noprint;
  165: 
  166: if ($?) {
  167:     exit 8;
  168: }
  169: my $userid=getpwnam($safeusername);
  170: 
  171: if (-e '/usr/bin/smbpasswd') {
  172: 
  173:     ($>,$<)=(0,0); # fool smbpasswd here to think this is not a setuid
  174:                    # environment
  175: 
  176: #   If the -a swithc is put on the smbpasswd
  177: # command line, either a new entry will be created or the old one
  178: # will be used. 
  179: # Therefore the old strategy of looking for and adding a dummy entry is 
  180: # not needed... Finally, the smbpasswd file is in /etc/samba not 
  181: # /etc/smbpasswd as older versions of the script implied.
  182: 
  183:     print "Running smbpasswd" unless $noprint;
  184:     open(OUT,"|/usr/bin/smbpasswd -s -a $safeusername>/dev/null") or
  185: 	die('cannot run smbpasswd');
  186:     print OUT $password2; print OUT "\n";
  187:     print OUT $password2; print OUT "\n";
  188:     close OUT;
  189:     $<=$wwwid; # unfool the program
  190:     print "smbpasswd done" unless $noprint;
  191: }
  192: 
  193: &disable_root_capability;
  194: unlink('/tmp/lock_lcpasswd');
  195: exit 0;
  196: 
  197: # ---------------------------------------------- have setuid script run as root
  198: sub enable_root_capability {
  199:     if ($wwwid==$>) {
  200: 	($<,$>)=($>,0);
  201: 	($(,$))=($),0);
  202:     }
  203:     else {
  204: 	# root capability is already enabled
  205:     }
  206:     return $>;
  207: }
  208: 
  209: # ----------------------------------------------- have setuid script run as www
  210: sub disable_root_capability {
  211:     if ($wwwid==$<) {
  212: 	($<,$>)=($>,$<);
  213: 	($(,$))=($),$();
  214:     }
  215:     else {
  216: 	# root capability is already disabled
  217:     }
  218: }
  219: 
  220: # ----------------------- make sure that another lcpasswd process isn't running
  221: sub try_to_lock {
  222:     my ($lockfile)=@_;
  223:     my $currentpid;
  224:     my $lastpid;
  225:     # Do not manipulate lock file as root
  226:     if ($>==0) {
  227: 	return 0;
  228:     }
  229:     # Try to generate lock file.
  230:     # Wait 3 seconds.  If same process id is in
  231:     # lock file, then assume lock file is stale, and
  232:     # go ahead.  If process id's fluctuate, try
  233:     # for a maximum of 10 times.
  234:     for (0..10) {
  235: 	if (-e $lockfile) {
  236: 	    open(LOCK,"<$lockfile");
  237: 	    $currentpid=<LOCK>;
  238: 	    close LOCK;
  239: 	    if ($currentpid==$lastpid) {
  240: 		last;
  241: 	    }
  242: 	    sleep 3;
  243: 	    $lastpid=$currentpid;
  244: 	}
  245: 	else {
  246: 	    last;
  247: 	}
  248: 	if ($_==10) {
  249: 	    return 0;
  250: 	}
  251:     }
  252:     open(LOCK,">$lockfile");
  253:     print LOCK $$;
  254:     close LOCK;
  255:     return 1;
  256: }
  257: 
  258: =head1 NAME
  259: 
  260: lcpasswd - LON-CAPA setuid script to synchronously change all
  261:            filesystem-related passwords (samba, unix, etc)
  262: 
  263: =head1 DESCRIPTION
  264: 
  265: LON-CAPA setuid script to synchronously change all
  266: filesystem-related passwords (samba, unix, etc)
  267: 
  268: =head1 README
  269: 
  270: LON-CAPA setuid script to synchronously change all
  271: filesystem-related passwords (samba, unix, etc)
  272: 
  273: =head1 PREREQUISITES
  274: 
  275: =head1 COREQUISITES
  276: 
  277: =pod OSNAMES
  278: 
  279: linux
  280: 
  281: =pod SCRIPT CATEGORIES
  282: 
  283: LONCAPA/Administrative
  284: 
  285: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
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.