Hiho,
ich habe hier ein wundervolles und hoffentlich auch sicheres Skript zur Änderung und zum Prüfen der Passwörter von best. Unix-Benutzern.
Zur Kommentierung: Ich weiss, dass es nicht sicher ist, ein Perl Skript "willkührlich" Passwörter ändern zu lassen, aber eine andere Möglichkeit sehe ich im Moment nicht.
Hier das Skript.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/perl -w
use Getopt::Long;
use Unix::PasswdFile;
use Authen::PAM;
use POSIX qw(ttyname);
### SETTINGS
my $pathid = "/usr/bin/id";
my $pathpasswd = "/etc/passwd";
my @allowed = (qr/^mail_/, qr/^web_/);
### SCRIPT BEGIN
my ($match, $exp);
my ($user, $pass, $newpass, $help);
# Turn off warnings
$SIG{} = sub { $help = 1; };
# Read Options
my $args = GetOptions(
"user=s"=>\$user,
"pass=s"=>\$pass,
"newpass=s"=>\$newpass,
"help"=>\$help
);
# Turn warning on again
$SIG{} = sub { warn $_[0] };
# Show Help
if ($help or not $args) { &showHelp(); }
if (not @ARGV or not $ARGV[0] =~ /^(check|change)$/i) { &showHelp(); }
# Check ID, stop if not root
if (not isRoot()) { openErr("Please run this script as root."); }
# Check Strings: User/Pass
if (not checkUser($user)) { openErr("The Username is not valid or not allowed."); }
if (not checkStr($pass)) { openErr("Please enter a valid User/Password"); }
# Validate User/Pass (from ex. cpan)
ref($pamh = new Authen::PAM("passwd", $user, \&convFunc)) or openErr("Error code $pamh during PAM init!");
$res = $pamh->pam_set_item(PAM_TTY(),ttyname(fileno(STDIN))); $res = $pamh->pam_authenticate;
&openErr($pamh->pam_strerror($res)) unless $res == PAM_SUCCESS();
# Mode CHANGE
if ($ARGV[0] =~ /^change$/i) {
if (not checkStr($newpass)) { openErr("The new password is invalid."); }
$pw = new Unix::PasswdFile $pathpasswd;
$pw->passwd($user,$pw->encpass($newpass));
$pw->commit(); undef $pw;
# Password changed
print "SUCCESS: Password changed\n";
exit 0;
}
# Mode CHECK
elsif ($ARGV[0] =~ /^check$/i) {
print "SUCCESS: Password correct!\n";
exit 0;
}
# Mode HELP
else {
&showHelp();
}
### FUNCTIONS
sub showHelp {
print "Usage:\n";
print " pc.pl [options] check\n";
print " pc.pl [options] change\n";
print "\n";
print "Options:\n";
print " --user=s Unix username (required)\n";
print " --pass=s Current password (required)\n";
print " --newpass=s New password (only for mode change)\n";
print "\n";
exit 0;
}
sub openErr {
print "ERROR: $_[0]\n";
exit 1;
}
sub checkStr {
return ($_[0] and $_[0] =~ /^[0-9a-z_]+$/i)?1:0;
}
sub checkUser {
my @allow = grep($_[0] =~ /$_/,@allowed);
return (checkStr($_[0]) and @allow)?1:0;
}
sub isRoot {
return `$pathid` =~ /^uid=0\(root\)/ and $ENV{USER} eq "root";
}
sub convFunc {
my @res;
while ( @_ ) {
my $code = shift;
my $msg = shift;
my $ans = "";
$ans = $user if ($code == PAM_PROMPT_ECHO_ON() );
$ans = $pass if ($code == PAM_PROMPT_ECHO_OFF() );
push @res, (PAM_SUCCESS(),$ans);
}
push @res, PAM_SUCCESS();
return @res;
}
Siehe "Usage" für Bedienung. Meine Frage nun: Findet hier jmd einen Fehler, der SIcherheitstehcnische Folgen haben könnte? Gibt es Schwachstellen, die man ausnutzen könnte?
Bitte helft mir. Danke.
Gruß, Felix