Annotation of loncom/lcuserdel, revision 1.16

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

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.