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
17: $ENV{'PATH'}=""; # Nullify path information.
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: }
33: if (@ARGV) {
34: print("Error. This program does not accept command-line arguments.\n");
35: exit 0;
36: }
37:
38: # Gather input from standard input. Should only be 3 lines.
39: my @input=<>;
40: if (@input!=3) {
41: print("Error. Three lines need to be entered into standard input.\n");
42: exit 0;
43: }
44:
45: # Handle case of another lcpasswd process
46: unless (&try_to_lock("/tmp/lock_lcpasswd")) {
47: print "Error. Too many other simultaneous password change requests being made.\n";
48: exit 0;
49: }
50:
51: my ($username,$oldpwd,$newpwd)=map {chop; $_} @input;
52:
53: # Grab the line corresponding to username
54: my ($userid,$useroldcryptpwd);
55: my @F; my @U;
56: for my $l (@lines) {
57: @F=split(/\:/,$l);
58: if ($F[0] eq $username) {($userid,$useroldcryptpwd)=($F[2],$F[1]); @U=@F;}
59: }
60:
61: # Verify existence of user
62: if (!defined($userid)) {
63: print "Error. User $username does not exist.\n";
64: exit 0;
65: }
66:
67: # Verify password entry
68: if (crypt($oldpwd,$useroldcryptpwd) ne $useroldcryptpwd) {
69: print "Error. Invalid entry of current password.\n";
70: exit 0;
71: }
72:
73: # Construct new password entry
74: my $newcryptpwd=crypt($newpwd,$newpwd);
75: $U[1]=$newcryptpwd;
76: my $userline=join(":",@U);
77: print $newcryptpwd;
78: print $userline;
79: #my $rootid=&enable_root_capability;
80: #if ($rootid!=0) {
81: # print "Error. Root was not successfully enabled.\n";
82: # exit 0;
83: #}
84: # open SAMBAPASSWORDFILE, ">/etc/smbpasswd";
85: ($<,$>)=($>,$<);
86: ($(,$))=($),$();
87: open PASSWORDFILE, "/tmp/passwd2" or die("Cannot open /etc/passwd!");
88: for my $l (@lines) {
89: @F=split(/\:/,$l);
90: if ($F[0] eq $username) {print PASSWORDFILE "$userline\n";}
91: else {print PASSWORDFILE "$l\n";}
92: }
93: close PASSWORDFILE;
94: # close SAMBAPASSWORDFILE;
95: &disable_root_capability;
96: unlink("/tmp/lock_lcpasswd");
97:
98: sub enable_root_capability {
99: if ($wwwid==$<) {
100: ($<,$>)=($>,$<);
101: ($(,$))=($),$();
102: }
103: else {
104: # root capability is already enabled
105: }
106: return $<;
107: }
108:
109: sub disable_root_capability {
110: if ($wwwid==$>) {
111: ($<,$>)=($>,$<);
112: ($(,$))=($),$();
113: }
114: else {
115: # root capability is already disabled
116: }
117: }
118:
119: sub try_to_lock {
120: my ($lockfile)=@_;
121: my $currentpid;
122: my $lastpid;
123: for (0..10) {
124: if (-e $lockfile) {
125: open(LOCK,"<$lockfile");
126: $currentpid=<LOCK>;
127: close LOCK;
128: if ($currentpid==$lastpid) {
129: last;
130: }
131: sleep 3;
132: $lastpid=$currentpid;
133: }
134: else {
135: last;
136: }
137: if ($_==10) {
138: return 0;
139: }
140: }
141: open(LOCK,">$lockfile");
142: print LOCK $$;
143: close LOCK;
144: return 1;
145: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>