Annotation of loncom/lcuserdel, revision 1.15

1.1       harris41    1: #!/usr/bin/perl
                      2: #
                      3: # lcuserdel
                      4: #
                      5: 
                      6: use strict;
                      7: 
1.2       harris41    8: # This script is a setuid script (chmod 6755) that should
1.1       harris41    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.
1.5       harris41   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).
1.1       harris41   16: 
1.3       harris41   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.
1.1       harris41   20: 
                     21: # Standard input usage
                     22: # First line is USERNAME
                     23: 
1.10      harris41   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: 
1.1       harris41   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: 
1.2       harris41   33: # Usage within code
                     34: #
1.3       harris41   35: # $exitcode=system("/home/httpd/perl/lcuserdel","NAME")/256;
1.2       harris41   36: # print "uh-oh" if $exitcode;
                     37: 
                     38: # These are the exit codes.
1.9       harris41   39: # ( (0,"ok"),
                     40: #   (1,"User ID mismatch.  This program must be run as user 'www'"),
1.11      harris41   41: #   (2,"Error. This program needs just 1 command-line argument (username).") )
1.9       harris41   42: #   (3,"Error. Only one line should be entered into standard input."),
1.11      harris41   43: #   (4,"Error. Too many other simultaneous password change requests being made."),
                     44: #   (5,"Error. The user name specified has invalid characters.") )
1.2       harris41   45: 
1.1       harris41   46: # Security
                     47: $ENV{'PATH'}=""; # Nullify path information.
                     48: $ENV{'BASH_ENV'}=""; # Nullify shell environment information.
1.2       harris41   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: 
1.3       harris41   56: # Read in /etc/passwd, and make sure this process is running from user=www
1.2       harris41   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: 
1.3       harris41   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).
1.2       harris41   79: my @input;
1.3       harris41   80: if (@ARGV==1) {
1.2       harris41   81:     @input=@ARGV;
                     82: }
                     83: elsif (@ARGV) {
1.3       harris41   84:     print("Error. This program needs just 1 command-line argument (username).\n") unless $noprint;
1.9       harris41   85:     unlink('/tmp/lock_lcpasswd');
1.2       harris41   86:     exit 2;
                     87: }
                     88: else {
                     89:     @input=<>;
1.3       harris41   90:     if (@input!=1) {
                     91: 	print("Error. Only one line should be entered into standard input.\n") unless $noprint;
1.9       harris41   92: 	unlink('/tmp/lock_lcpasswd');
1.2       harris41   93: 	exit 3;
                     94:     }
                     95:     map {chop} @input;
                     96: }
1.4       harris41   97: 
                     98: my ($username)=@input;
                     99: $username=~/^(\w+)$/;
                    100: my $safeusername=$1;
1.10      harris41  101: if ($username ne $safeusername) {
                    102:     print "Error. The user name specified has invalid characters.\n";
                    103:     unlink('/tmp/lock_lcpasswd');
1.11      harris41  104:     exit 5;
1.10      harris41  105: }
1.4       harris41  106: 
1.5       harris41  107: &enable_root_capability;
                    108: 
1.4       harris41  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
1.8       harris41  112: # I surround with groupdel command to make absolutely sure the group definition disappears.
1.12      harris41  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
1.4       harris41  116: 
                    117: # Remove entry from /etc/smbpasswd if it exists
1.13      foxr      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);
1.14      foxr      124:   $< = $wwwid;
1.13      foxr      125: }
1.4       harris41  126: 
                    127: 
                    128: # Change ownership on directory from username:username to www:www
                    129: # This prevents subsequently added users from having access.
                    130: 
1.5       harris41  131: system('/bin/chown','-R','www:www',"/home/$safeusername");
1.3       harris41  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:     }
1.2       harris41  158: }
                    159: 
1.3       harris41  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: }
1.2       harris41  197: 
1.1       harris41  198: 

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.