File:  [LON-CAPA] / loncom / lcuserdel
Revision 1.15: download - view: text, annotated - select for diffs
Mon Feb 3 18:03:52 2003 UTC (21 years, 1 month ago) by harris41
Branches: MAIN
CVS tags: version_2_5_X, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, 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: #
    3: # lcuserdel
    4: #
    5: 
    6: use strict;
    7: 
    8: # This script is a setuid script (chmod 6755) that should
    9: # be run by user 'www'.  It DOES NOT delete directories.
   10: # All it does is remove a user's entries from
   11: # /etc/passwd, /etc/groups, and /etc/smbpasswd.
   12: # It also disables user directory access by making the directory
   13: # to be owned by user=www (as opposed to the former "username").
   14: # This command only returns an error if it is
   15: # invoked incorrectly (by passing bad command-line arguments, etc).
   16: 
   17: # This script works under the same process control mechanism
   18: # as lcuseradd and lcpasswd, to make sure that only one of these
   19: # processes is running at any one time on the system.
   20: 
   21: # Standard input usage
   22: # First line is USERNAME
   23: 
   24: # Valid user names must consist of ascii
   25: # characters that are alphabetical characters
   26: # (A-Z,a-z), numeric (0-9), or the underscore
   27: # mark (_). (Essentially, the perl regex \w).
   28: 
   29: # Command-line arguments [USERNAME]
   30: # Yes, but be very careful here (don't pass shell commands)
   31: # and this is only supported to allow perl-system calls.
   32: 
   33: # Usage within code
   34: #
   35: # $exitcode=system("/home/httpd/perl/lcuserdel","NAME")/256;
   36: # print "uh-oh" if $exitcode;
   37: 
   38: # These are the exit codes.
   39: # ( (0,"ok"),
   40: #   (1,"User ID mismatch.  This program must be run as user 'www'"),
   41: #   (2,"Error. This program needs just 1 command-line argument (username).") )
   42: #   (3,"Error. Only one line should be entered into standard input."),
   43: #   (4,"Error. Too many other simultaneous password change requests being made."),
   44: #   (5,"Error. The user name specified has invalid characters.") )
   45: 
   46: # Security
   47: $ENV{'PATH'}=""; # Nullify path information.
   48: $ENV{'BASH_ENV'}=""; # Nullify shell environment information.
   49: 
   50: # Do not print error messages if there are command-line arguments
   51: my $noprint=0;
   52: if (@ARGV) {
   53:     $noprint=1;
   54: }
   55: 
   56: # Read in /etc/passwd, and make sure this process is running from user=www
   57: open (IN, "</etc/passwd");
   58: my @lines=<IN>;
   59: close IN;
   60: my $wwwid;
   61: for my $l (@lines) {
   62:     chop $l;
   63:     my @F=split(/\:/,$l);
   64:     if ($F[0] eq 'www') {$wwwid=$F[2];}
   65: }
   66: if ($wwwid!=$<) {
   67:     print("User ID mismatch.  This program must be run as user 'www'\n") unless $noprint;
   68:     exit 1;
   69: }
   70: &disable_root_capability;
   71: 
   72: # Handle case of another lcpasswd process
   73: unless (&try_to_lock("/tmp/lock_lcpasswd")) {
   74:     print "Error. Too many other simultaneous password change requests being made.\n" unless $noprint;
   75:     exit 4;
   76: }
   77: 
   78: # Gather input.  Should only be 1 value (user name).
   79: my @input;
   80: if (@ARGV==1) {
   81:     @input=@ARGV;
   82: }
   83: elsif (@ARGV) {
   84:     print("Error. This program needs just 1 command-line argument (username).\n") unless $noprint;
   85:     unlink('/tmp/lock_lcpasswd');
   86:     exit 2;
   87: }
   88: else {
   89:     @input=<>;
   90:     if (@input!=1) {
   91: 	print("Error. Only one line should be entered into standard input.\n") unless $noprint;
   92: 	unlink('/tmp/lock_lcpasswd');
   93: 	exit 3;
   94:     }
   95:     map {chop} @input;
   96: }
   97: 
   98: my ($username)=@input;
   99: $username=~/^(\w+)$/;
  100: my $safeusername=$1;
  101: if ($username ne $safeusername) {
  102:     print "Error. The user name specified has invalid characters.\n";
  103:     unlink('/tmp/lock_lcpasswd');
  104:     exit 5;
  105: }
  106: 
  107: &enable_root_capability;
  108: 
  109: # By using the system userdel command:
  110: # Remove entry from /etc/passwd if it exists
  111: # Remove entry from /etc/groups if it exists
  112: # I surround with groupdel command to make absolutely sure the group definition disappears.
  113: system('/usr/sbin/groupdel',$safeusername); # ignore error message
  114: system('/usr/sbin/userdel',$safeusername); # ignore error message
  115: system('/usr/sbin/groupdel',$safeusername); # ignore error message
  116: 
  117: # Remove entry from /etc/smbpasswd if it exists
  118: #  the safest way to do this is with smbpasswd -x
  119: #  as that's independent of location of the smbpasswd file.
  120: #
  121: if (-e '/usr/bin/smbpasswd') {
  122:   ($>,$<) = (0,0);		# fool smbpasswd to think this is not setuid.
  123:   system('/usr/bin/smbpasswd -x '.$safeusername);
  124:   $< = $wwwid;
  125: }
  126: 
  127: 
  128: # Change ownership on directory from username:username to www:www
  129: # This prevents subsequently added users from having access.
  130: 
  131: system('/bin/chown','-R','www:www',"/home/$safeusername");
  132: 
  133: &disable_root_capability;
  134: unlink("/tmp/lock_lcpasswd");
  135: exit 0;
  136: 
  137: # ----------------------------------------------------------- have setuid script run as root
  138: sub enable_root_capability {
  139:     if ($wwwid==$>) {
  140: 	($<,$>)=($>,$<);
  141: 	($(,$))=($),$();
  142:     }
  143:     else {
  144: 	# root capability is already enabled
  145:     }
  146:     return $>;
  147: }
  148: 
  149: # ----------------------------------------------------------- have setuid script run as www
  150: sub disable_root_capability {
  151:     if ($wwwid==$<) {
  152: 	($<,$>)=($>,$<);
  153: 	($(,$))=($),$();
  154:     }
  155:     else {
  156: 	# root capability is already disabled
  157:     }
  158: }
  159: 
  160: # ----------------------------------- make sure that another lcpasswd process isn't running
  161: sub try_to_lock {
  162:     my ($lockfile)=@_;
  163:     my $currentpid;
  164:     my $lastpid;
  165:     # Do not manipulate lock file as root
  166:     if ($>==0) {
  167: 	return 0;
  168:     }
  169:     # Try to generate lock file.
  170:     # Wait 3 seconds.  If same process id is in
  171:     # lock file, then assume lock file is stale, and
  172:     # go ahead.  If process id's fluctuate, try
  173:     # for a maximum of 10 times.
  174:     for (0..10) {
  175: 	if (-e $lockfile) {
  176: 	    open(LOCK,"<$lockfile");
  177: 	    $currentpid=<LOCK>;
  178: 	    close LOCK;
  179: 	    if ($currentpid==$lastpid) {
  180: 		last;
  181: 	    }
  182: 	    sleep 3;
  183: 	    $lastpid=$currentpid;
  184: 	}
  185: 	else {
  186: 	    last;
  187: 	}
  188: 	if ($_==10) {
  189: 	    return 0;
  190: 	}
  191:     }
  192:     open(LOCK,">$lockfile");
  193:     print LOCK $$;
  194:     close LOCK;
  195:     return 1;
  196: }
  197: 
  198: 

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