check-cracklib.pl revision 178825
1#!/usr/pkg/bin/perl
2#
3# Sample password verifier for Heimdals external password
4# verifier, see the chapter "Password changing" in the the info
5# documentation for more information about the protocol used.
6#
7# Three checks
8#  1. Check that password is not the principal name
9#  2. Check that the password passes cracklib
10#  3. Check that password isn't repeated for this principal
11#
12# The repeat check must be last because some clients ask
13# twice when getting "no" back and thus the error message
14# would be wrong.
15#
16# Prereqs (example versions):
17#
18# * perl (5.8.5) http://www.perl.org/
19# * cracklib (2.8.5) http://sourceforge.net/projects/cracklib
20# * Crypt-Cracklib perlmodule (0.01) http://search.cpan.org/~daniel/
21#
22# Sample dictionaries:
23#     cracklib-words (1.1) http://sourceforge.net/projects/cracklib
24#     miscfiles (1.4.2) http://directory.fsf.org/miscfiles.html
25#
26# Configuration for krb5.conf or kdc.conf
27#
28#   [password_quality]
29#     	policies = builtin:external-check
30#     	external_program = <your-path>/check-cracklib.pl
31#
32# $Id: check-cracklib.pl 20578 2007-05-07 22:21:51Z lha $
33
34use strict;
35use Crypt::Cracklib;
36use Digest::MD5;
37
38# NEED TO CHANGE THESE TO MATCH YOUR SYSTEM
39my $database = '/usr/lib/cracklib_dict';
40my $historydb = '/var/heimdal/historydb';
41# NEED TO CHANGE THESE TO MATCH YOUR SYSTEM
42
43my %params;
44
45sub check_basic
46{
47    my $principal = shift;
48    my $passwd = shift;
49
50    if ($principal eq $passwd) {
51	return "Principal name as password is not allowed";
52    }
53    return "ok";
54}
55
56sub check_repeat
57{
58    my $principal = shift;
59    my $passwd = shift;
60    my $result  = 'Do not reuse passwords';
61    my %DB;
62    my $md5context = new Digest::MD5;
63
64    $md5context->reset();
65    $md5context->add($principal, ":", $passwd);
66
67    my $key=$md5context->hexdigest();
68
69    dbmopen(%DB,$historydb,0600) or die "Internal: Could not open $historydb";
70    $result = "ok" if (!$DB{$key});
71    $DB{$key}=scalar(time());
72    dbmclose(%DB) or die "Internal: Could not close $historydb";
73    return $result;
74}
75
76sub badpassword
77{
78    my $reason = shift;
79    print "$reason\n";
80    exit 0
81}
82
83while (<>) {
84    last if /^end$/;
85    if (!/^([^:]+): (.+)$/) {
86	die "key value pair not correct: $_";
87    }
88    $params{$1} = $2;
89}
90
91die "missing principal" if (!defined $params{'principal'});
92die "missing password" if (!defined $params{'new-password'});
93
94my $reason;
95
96$reason = check_basic($params{'principal'}, $params{'new-password'});
97badpassword($reason) if ($reason ne "ok");
98
99$reason = fascist_check($params{'new-password'}, $database);
100badpassword($reason) if ($reason ne "ok");
101
102$reason = check_repeat($params{'principal'}, $params{'new-password'});
103badpassword($reason) if ($reason ne "ok");
104
105print "APPROVED\n";
106exit 0
107