diff --git a/lib/kadm5/check-cracklib.pl b/lib/kadm5/check-cracklib.pl index 61a2c51ab..8bfa1329e 100755 --- a/lib/kadm5/check-cracklib.pl +++ b/lib/kadm5/check-cracklib.pl @@ -1,18 +1,83 @@ #!/usr/pkg/bin/perl # -# Sample cracklib password verifier for Heimdals external password +# Sample password verifier for Heimdals external password # verifier, see the chapter "Password changing" in the the info # documentation for more information about the protocol used. # +# Three checks +# 1. Check that password is not the principal name +# 2. Check that the password passes cracklib +# 3. Check that password isn't repeated for this principal +# +# The repeat check must be last because some clients ask +# twice when getting "no" back and thus the error message +# would be wrong. +# +# Prereqs (example versions): +# +# * perl (5.8.5) http://www.perl.org/ +# * cracklib (2.8.5) http://sourceforge.net/projects/cracklib +# * Crypt-Cracklib perlmodule (0.01) http://search.cpan.org/~daniel/ +# +# Samaple dictionaries: +# cracklib-words (1.1) http://sourceforge.net/projects/cracklib +# miscfiles (1.4.2) http://directory.fsf.org/miscfiles.html +# +# Configuration for krb5.conf or kdc.conf +# +# [password_quality] +# policies = builtin:external-check +# external_program = /check-cracklib.pl +# # $Id$ use strict; use Crypt::Cracklib; +use Digest::MD5; -my $database = '/usr/pkg/libdata/pw_dict'; +my $database = '/usr/lib/cracklib_dict'; +my $repeatdb = '/var/heimdal/repeatdb'; my %params; +sub check_basic +{ + my $principal = shift; + my $passwd = shift; + + if ($principal eq $passwd) { + return "Principal name as password is not allowed"; + } + return "ok"; +} + +sub check_repeat +{ + my $principal = shift; + my $passwd = shift; + my $result = 'Do not reuse passwords'; + my %DB; + my $md5context = new Digest::MD5; + + $md5context->reset(); + $md5context->add($principal, ":", $passwd); + + my $key=$md5context->hexdigest(); + + dbmopen(%DB,$repeatdb,0600) or die "Internal: Could not open $db"; + $result = "ok" if (!$DB{$key}); + $DB{$key}=scalar(time()); + dbmclose(%DB) or die "Internal: Could not close $db"; + return $result; +} + +sub badpassword +{ + my $reason = shift; + print "$reason\n"; + exit 0 +} + while (<>) { last if /^end$/; if (!/^([^:]+): (.+)$/) { @@ -21,15 +86,19 @@ while (<>) { $params{$1} = $2; } +die "missing principal" if (!defined $params{'principal'}); die "missing password" if (!defined $params{'new-password'}); -my $reason = fascist_check($params{'new-password'}, $database); +my $reason; -if ($reason eq "ok") { - print "APPROVED\n"; -} else { - print "$reason\n"; -} +$reason = check_basic($params{'principal'}, $params{'new-password'}); +badpassword($reason) if ($reason ne "ok"); +$reason = fascist_check($params{'new-password'}, $database); +badpassword($reason) if ($reason ne "ok"); + +$reason = check_repeat($params{'principal'}, $params{'new-password'}); +badpassword($reason) if ($reason ne "ok"); + +print "APPROVED\n"; exit 0 -