File:
[LON-CAPA] /
loncom /
lcpasswd
Revision
1.22:
download - view:
text,
annotated -
select for diffs
Tue Oct 12 10:33:47 2010 UTC (14 years, 4 months ago) by
foxr
Branches:
MAIN
CVS tags:
version_2_12_X,
version_2_11_X,
version_2_11_6_msu,
version_2_11_6,
version_2_11_5_msu,
version_2_11_5,
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>