File:  [LON-CAPA] / loncom / lcpasswd
Revision 1.22: download - view: text, annotated - select for diffs
Tue Oct 12 10:33:47 2010 UTC (13 years, 5 months ago) by foxr
Branches: MAIN
CVS tags: version_2_12_X, version_2_11_X, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0_RC2, version_2_10_0, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, HEAD, BZ4492-merge, BZ4492-feature_horizontal_radioresponse, BZ4492-feature_Support_horizontal_radioresponse, BZ4492-Support_horizontal_radioresponse
Make this work on fc13.

    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.22 2010/10/12 10:33:47 foxr 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: 
   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: 
  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,$wwwid);
  163: 
  164: print "pwchange done, back to uid $wwwid" 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 switch 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: 
  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: 
  226:     # Try to generate lock file.
  227:     # Wait 3 seconds.  If same process id is in
  228:     # lock file, then assume lock file is stale, and
  229:     # go ahead.  If process id's fluctuate, try
  230:     # for a maximum of 10 times.
  231:     for (0..10) {
  232: 	if (-e $lockfile) {
  233: 	    open(LOCK,"<$lockfile");
  234: 	    $currentpid=<LOCK>;
  235: 	    close LOCK;
  236: 	    if ($currentpid==$lastpid) {
  237: 		last;
  238: 	    }
  239: 	    sleep 3;
  240: 	    $lastpid=$currentpid;
  241: 	}
  242: 	else {
  243: 	    last;
  244: 	}
  245: 	if ($_==10) {
  246: 	    return 0;
  247: 	}
  248:     }
  249:     open(LOCK,">$lockfile");
  250:     print LOCK $$;
  251:     close LOCK;
  252:     return 1;
  253: }
  254: 
  255: =head1 NAME
  256: 
  257: lcpasswd - LON-CAPA setuid script to synchronously change all
  258:            filesystem-related passwords (samba, unix, etc)
  259: 
  260: =head1 DESCRIPTION
  261: 
  262: LON-CAPA setuid script to synchronously change all
  263: filesystem-related passwords (samba, unix, etc)
  264: 
  265: =head1 README
  266: 
  267: LON-CAPA setuid script to synchronously change all
  268: filesystem-related passwords (samba, unix, etc)
  269: 
  270: =head1 PREREQUISITES
  271: 
  272: =head1 COREQUISITES
  273: 
  274: =pod OSNAMES
  275: 
  276: linux
  277: 
  278: =pod SCRIPT CATEGORIES
  279: 
  280: LONCAPA/Administrative
  281: 
  282: =cut

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