Annotation of loncom/lcpasswd, revision 1.2
1.1 harris41 1: #!/usr/bin/perl
2:
3: use strict;
4:
5: # Scott Harrison
6: # October 27, 2000
7:
8: # This script is a setuid script that should
9: # be run by user 'www'.
10:
11: # Standard input usage
12: # First line is USERNAME
13: # Second line is CURRENT PASSWORD
14: # Third line is NEW PASSWORD
15:
16: # Security
1.2 ! harris41 17: $ENV{'PATH'}="/bin:/usr/bin"; # Nullify path information except for what smbpasswd needs
1.1 harris41 18: $ENV{'BASH_ENV'}=""; # Nullify shell environment information.
19:
20: open (IN, "</etc/passwd");
21: my @lines=<IN>;
22: close IN;
23: my $wwwid;
24: for my $l (@lines) {
25: chop $l;
26: my @F=split(/\:/,$l);
27: if ($F[0] eq 'www') {$wwwid=$F[2];}
28: }
29: if ($wwwid!=$<) {
30: print("User ID mismatch. This program must be run as user 'www'\n");
31: exit 0;
32: }
1.2 ! harris41 33: &disable_root_capability;
1.1 harris41 34: if (@ARGV) {
35: print("Error. This program does not accept command-line arguments.\n");
36: exit 0;
37: }
38:
39: # Gather input from standard input. Should only be 3 lines.
40: my @input=<>;
41: if (@input!=3) {
42: print("Error. Three lines need to be entered into standard input.\n");
43: exit 0;
44: }
45:
46: # Handle case of another lcpasswd process
47: unless (&try_to_lock("/tmp/lock_lcpasswd")) {
48: print "Error. Too many other simultaneous password change requests being made.\n";
49: exit 0;
50: }
51:
52: my ($username,$oldpwd,$newpwd)=map {chop; $_} @input;
53:
54: # Grab the line corresponding to username
55: my ($userid,$useroldcryptpwd);
56: my @F; my @U;
57: for my $l (@lines) {
58: @F=split(/\:/,$l);
59: if ($F[0] eq $username) {($userid,$useroldcryptpwd)=($F[2],$F[1]); @U=@F;}
60: }
61:
62: # Verify existence of user
63: if (!defined($userid)) {
64: print "Error. User $username does not exist.\n";
65: exit 0;
66: }
67:
68: # Verify password entry
69: if (crypt($oldpwd,$useroldcryptpwd) ne $useroldcryptpwd) {
70: print "Error. Invalid entry of current password.\n";
71: exit 0;
72: }
73:
1.2 ! harris41 74: # Construct new password entry (random salt)
! 75: my $newcryptpwd=crypt($newpwd,(join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]));
1.1 harris41 76: $U[1]=$newcryptpwd;
77: my $userline=join(":",@U);
1.2 ! harris41 78: my $rootid=&enable_root_capability;
! 79: if ($rootid!=0) {
! 80: print "Error. Root was not successfully enabled.\n";
! 81: exit 0;
! 82: }
! 83: open PASSWORDFILE, ">/etc/passwd" or die("Cannot open /etc/passwd!");
1.1 harris41 84: for my $l (@lines) {
85: @F=split(/\:/,$l);
86: if ($F[0] eq $username) {print PASSWORDFILE "$userline\n";}
87: else {print PASSWORDFILE "$l\n";}
88: }
89: close PASSWORDFILE;
1.2 ! harris41 90: $username=~/^(\w+)$/;
! 91: my $safeusername=$1;
! 92: ($>,$<)=(0,0); # fool smbpasswd here to think this is not a setuid environment
! 93: unless (-e "/etc/smbpasswd") {
! 94: open (OUT,">/etc/smbpasswd"); close OUT;
! 95: }
! 96: my $smbexist=0;
! 97: open (IN, "</etc/smbpasswd");
! 98: my @lines=<IN>;
! 99: close IN;
! 100: for my $l (@lines) {
! 101: chop $l;
! 102: my @F=split(/\:/,$l);
! 103: if ($F[0] eq $username) {$smbexist=1;}
! 104: }
! 105: unless ($smbexist) {
! 106: open(OUT,">>/etc/smbpasswd");
! 107: print OUT join(":",($safeusername,$userid,'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX','','/home/'.$safeusername,'/bin/bash')) . "\n";
! 108: close OUT;
! 109: }
! 110: open(OUT,"|/usr/bin/smbpasswd -s $safeusername>/dev/null");
! 111: print OUT $newpwd; print OUT "\n";
! 112: print OUT $newpwd; print OUT "\n";
! 113: close OUT;
! 114: $<=$wwwid; # unfool the program
1.1 harris41 115: &disable_root_capability;
116: unlink("/tmp/lock_lcpasswd");
117:
118: sub enable_root_capability {
1.2 ! harris41 119: if ($wwwid==$>) {
1.1 harris41 120: ($<,$>)=($>,$<);
121: ($(,$))=($),$();
122: }
123: else {
124: # root capability is already enabled
125: }
1.2 ! harris41 126: return $>;
1.1 harris41 127: }
128:
129: sub disable_root_capability {
1.2 ! harris41 130: if ($wwwid==$<) {
1.1 harris41 131: ($<,$>)=($>,$<);
132: ($(,$))=($),$();
133: }
134: else {
135: # root capability is already disabled
136: }
137: }
138:
139: sub try_to_lock {
140: my ($lockfile)=@_;
141: my $currentpid;
142: my $lastpid;
143: for (0..10) {
144: if (-e $lockfile) {
145: open(LOCK,"<$lockfile");
146: $currentpid=<LOCK>;
147: close LOCK;
148: if ($currentpid==$lastpid) {
149: last;
150: }
151: sleep 3;
152: $lastpid=$currentpid;
153: }
154: else {
155: last;
156: }
157: if ($_==10) {
158: return 0;
159: }
160: }
161: open(LOCK,">$lockfile");
162: print LOCK $$;
163: close LOCK;
164: return 1;
165: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>