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