version 1.5, 2000/10/28 18:25:47
|
version 1.9, 2000/10/30 02:31:45
|
Line 3
|
Line 3
|
# lcpasswd |
# lcpasswd |
# |
# |
# Scott Harrison |
# Scott Harrison |
# October 27, 2000 |
# SH: October 27, 2000 |
|
# SH: October 28, 2000 |
|
|
use strict; |
use strict; |
|
|
Line 22 use strict;
|
Line 23 use strict;
|
# Second line is CURRENT PASSWORD |
# Second line is CURRENT PASSWORD |
# Third line is NEW PASSWORD |
# Third line is NEW PASSWORD |
|
|
|
# Valid passwords must consist of the |
|
# ascii characters within the inclusive |
|
# range of 0x20 (32) to 0x7E (126). |
|
# These characters are: |
|
# SPACE and |
|
# !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO |
|
# PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ |
|
|
|
# Valid user names must consist of ascii |
|
# characters that are alphabetical characters |
|
# (A-Z,a-z), numeric (0-9), or the underscore |
|
# mark (_). (Essentially, the perl regex \w). |
|
|
# Command-line arguments |
# Command-line arguments |
# Yes, but be very careful here (don't pass shell commands) |
# Yes, but be very careful here (don't pass shell commands) |
# and this is only supported to allow perl-system calls. |
# and this is only supported to allow perl-system calls. |
Line 34 use strict;
|
Line 48 use strict;
|
|
|
# These are the exit codes. |
# These are the exit codes. |
# ( (0,"ok"), |
# ( (0,"ok"), |
# (1,"User ID mismatch. This program must be run as user 'www'), |
# (1,"User ID mismatch. This program must be run as user 'www'"), |
# (2,"Error. This program does not accept command-line arguments."), |
# (2,"Error. This program does not accept command-line arguments."), |
# (3,"Error. Three lines need to be entered into standard input.\n"), |
# (3,"Error. Three lines need to be entered into standard input."), |
# (4,"Error. Too many other simultaneous password change requests being made.\n"), |
# (4,"Error. Too many other simultaneous password change requests being made."), |
# (5,"Error. User $username does not exist.\n"), |
# (5,"Error. User $username does not exist."), |
# (6,"Error. Invalid entry of current password.\n"), |
# (6,"Error. Invalid entry of current password."), |
# (7,"Error. Root was not successfully enabled.\n") ) |
# (7,"Error. Root was not successfully enabled."), |
|
# (8,"Error. Cannot open /etc/passwd.") ) |
|
|
# Security |
# Security |
$ENV{'PATH'}="/bin:/usr/bin"; # Nullify path information except for what smbpasswd needs |
$ENV{'PATH'}='/bin:/usr/bin'; # Nullify path information except for what smbpasswd needs |
$ENV{'BASH_ENV'}=""; # Nullify shell environment information. |
$ENV{'BASH_ENV'}=''; # Nullify shell environment information. |
|
|
# Do not print error messages if there are command-line arguments |
# Do not print error messages if there are command-line arguments |
my $noprint=0; |
my $noprint=0; |
Line 53 if (@ARGV) {
|
Line 68 if (@ARGV) {
|
} |
} |
|
|
# Read in /etc/passwd, and make sure this process is running from user=www |
# Read in /etc/passwd, and make sure this process is running from user=www |
open (IN, "</etc/passwd"); |
open (IN, '</etc/passwd'); |
my @lines=<IN>; |
my @lines=<IN>; |
close IN; |
close IN; |
my $wwwid; |
my $wwwid; |
Line 64 for my $l (@lines) {
|
Line 79 for my $l (@lines) {
|
} |
} |
if ($wwwid!=$<) { |
if ($wwwid!=$<) { |
print("User ID mismatch. This program must be run as user 'www'\n") unless $noprint; |
print("User ID mismatch. This program must be run as user 'www'\n") unless $noprint; |
unlink("/tmp/lock_lcpasswd"); |
|
exit 1; |
exit 1; |
} |
} |
&disable_root_capability; |
&disable_root_capability; |
|
|
# Handle case of another lcpasswd process |
# Handle case of another lcpasswd process |
unless (&try_to_lock("/tmp/lock_lcpasswd")) { |
unless (&try_to_lock('/tmp/lock_lcpasswd')) { |
print "Error. Too many other simultaneous password change requests being made.\n" unless $noprint; |
print "Error. Too many other simultaneous password change requests being made.\n" unless $noprint; |
exit 4; |
exit 4; |
} |
} |
Line 82 if (@ARGV==3) {
|
Line 96 if (@ARGV==3) {
|
} |
} |
elsif (@ARGV) { |
elsif (@ARGV) { |
print("Error. This program needs 3 command-line arguments (username, old password, new password).\n") unless $noprint; |
print("Error. This program needs 3 command-line arguments (username, old password, new password).\n") unless $noprint; |
unlink("/tmp/lock_lcpasswd"); |
unlink('/tmp/lock_lcpasswd'); |
exit 2; |
exit 2; |
} |
} |
else { |
else { |
@input=<>; |
@input=<>; |
if (@input!=3) { |
if (@input!=3) { |
print("Error. Three lines need to be entered into standard input.\n") unless $noprint; |
print("Error. Three lines need to be entered into standard input.\n") unless $noprint; |
unlink("/tmp/lock_lcpasswd"); |
unlink('/tmp/lock_lcpasswd'); |
exit 3; |
exit 3; |
} |
} |
map {chop} @input; |
map {chop} @input; |
} |
} |
|
|
my ($username,$oldpwd,$newpwd)=@input; |
my ($username,$oldpwd,$newpwd)=@input; |
|
$username=~/^(\w+)$/; |
|
my $safeusername=$1; |
|
if ($username ne $safeusername) { |
|
print "Error. The user name specified has invalid characters.\n"; |
|
unlink('/tmp/lock_lcpasswd'); |
|
exit 9; |
|
} |
|
my $pbad=0; |
|
map {if (($_<32)&&($_>126)){$pbad=1;}} (split(//,$oldpwd)); |
|
map {if (($_<32)&&($_>126)){$pbad=1;}} (split(//,$newpwd)); |
|
if ($pbad) { |
|
print "Error. A password entry had an invalid character.\n"; |
|
unlink('/tmp/lock_lcpasswd'); |
|
exit 10; |
|
} |
|
|
# Grab the line corresponding to username |
# Grab the line corresponding to username |
my ($userid,$useroldcryptpwd); |
my ($userid,$useroldcryptpwd); |
Line 108 for my $l (@lines) {
|
Line 137 for my $l (@lines) {
|
# Verify existence of user |
# Verify existence of user |
if (!defined($userid)) { |
if (!defined($userid)) { |
print "Error. User $username does not exist.\n" unless $noprint; |
print "Error. User $username does not exist.\n" unless $noprint; |
unlink("/tmp/lock_lcpasswd"); |
unlink('/tmp/lock_lcpasswd'); |
exit 5; |
exit 5; |
} |
} |
|
|
# Verify password entry |
# Verify password entry |
if (crypt($oldpwd,$useroldcryptpwd) ne $useroldcryptpwd) { |
if (crypt($oldpwd,$useroldcryptpwd) ne $useroldcryptpwd) { |
print "Error. Invalid entry of current password.\n" unless $noprint; |
print "Error. Invalid entry of current password.\n" unless $noprint; |
unlink("/tmp/lock_lcpasswd"); |
unlink('/tmp/lock_lcpasswd'); |
exit 6; |
exit 6; |
} |
} |
|
|
# Construct new password entry (random salt) |
# Construct new password entry (random salt) |
my $newcryptpwd=crypt($newpwd,(join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64])); |
my $newcryptpwd=crypt($newpwd,(join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64])); |
$U[1]=$newcryptpwd; |
$U[1]=$newcryptpwd; |
my $userline=join(":",@U); |
my $userline=join(':',@U); |
my $rootid=&enable_root_capability; |
my $rootid=&enable_root_capability; |
if ($rootid!=0) { |
if ($rootid!=0) { |
print "Error. Root was not successfully enabled.\n" unless $noprint; |
print "Error. Root was not successfully enabled.\n" unless $noprint; |
unlink("/tmp/lock_lcpasswd"); |
unlink('/tmp/lock_lcpasswd'); |
exit 7; |
exit 7; |
} |
} |
open PASSWORDFILE, ">/etc/passwd" or die("Cannot open /etc/passwd!"); |
open PASSWORDFILE, '>/etc/passwd' or (print("Error. Cannot open /etc/passwd.\n") && unlink('/tmp/lock_lcpasswd') && exit(8)); |
for my $l (@lines) { |
for my $l (@lines) { |
@F=split(/\:/,$l); |
@F=split(/\:/,$l); |
if ($F[0] eq $username) {print PASSWORDFILE "$userline\n";} |
if ($F[0] eq $username) {print PASSWORDFILE "$userline\n";} |
else {print PASSWORDFILE "$l\n";} |
else {print PASSWORDFILE "$l\n";} |
} |
} |
close PASSWORDFILE; |
close PASSWORDFILE; |
$username=~/^(\w+)$/; |
|
my $safeusername=$1; |
|
($>,$<)=(0,0); # fool smbpasswd here to think this is not a setuid environment |
($>,$<)=(0,0); # fool smbpasswd here to think this is not a setuid environment |
unless (-e "/etc/smbpasswd") { |
unless (-e '/etc/smbpasswd') { |
open (OUT,">/etc/smbpasswd"); close OUT; |
open (OUT,'>/etc/smbpasswd'); close OUT; |
} |
} |
my $smbexist=0; |
my $smbexist=0; |
open (IN, "</etc/smbpasswd"); |
open (IN, '</etc/smbpasswd'); |
my @lines=<IN>; |
my @lines=<IN>; |
close IN; |
close IN; |
for my $l (@lines) { |
for my $l (@lines) { |
Line 152 for my $l (@lines) {
|
Line 180 for my $l (@lines) {
|
if ($F[0] eq $username) {$smbexist=1;} |
if ($F[0] eq $username) {$smbexist=1;} |
} |
} |
unless ($smbexist) { |
unless ($smbexist) { |
open(OUT,">>/etc/smbpasswd"); |
open(OUT,'>>/etc/smbpasswd'); |
print OUT join(":",($safeusername,$userid,'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX','','/home/'.$safeusername,'/bin/bash')) . "\n"; |
print OUT join(':',($safeusername,$userid,'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX','','/home/'.$safeusername,'/bin/bash')) . "\n"; |
close OUT; |
close OUT; |
} |
} |
open(OUT,"|/usr/bin/smbpasswd -s $safeusername>/dev/null"); |
open(OUT,"|/usr/bin/smbpasswd -s $safeusername>/dev/null"); |
Line 162 print OUT $newpwd; print OUT "\n";
|
Line 190 print OUT $newpwd; print OUT "\n";
|
close OUT; |
close OUT; |
$<=$wwwid; # unfool the program |
$<=$wwwid; # unfool the program |
&disable_root_capability; |
&disable_root_capability; |
unlink("/tmp/lock_lcpasswd"); |
unlink('/tmp/lock_lcpasswd'); |
exit 0; |
exit 0; |
|
|
# ----------------------------------------------------------- have setuid script run as root |
# ----------------------------------------------------------- have setuid script run as root |