summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/lib/kadm5/check-cracklib.pl
blob: a6fbd4c82d494602f6f03ac5c04d3e68787e0b16 (plain)
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
#!/usr/pkg/bin/perl
#
# 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/
#
# Sample 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 = <your-path>/check-cracklib.pl
#
# $Id$

use strict;
use Crypt::Cracklib;
use Digest::MD5;

# NEED TO CHANGE THESE TO MATCH YOUR SYSTEM
my $database = '/usr/lib/cracklib_dict';
my $historydb = '/var/heimdal/historydb';
# NEED TO CHANGE THESE TO MATCH YOUR SYSTEM

# seconds password reuse allowed (to catch retries from clients)
my $reusetime = 60; 

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;
    my $timenow = scalar(time());

    $md5context->reset();
    $md5context->add($principal, ":", $passwd);

    my $key=$md5context->hexdigest();

    dbmopen(%DB,$historydb,0600) or die "Internal: Could not open $historydb";
    if (!$DB{$key} || ($timenow - $DB{$key} < $reusetime)) { 
	$result = "ok";
	$DB{$key}=$timenow;
    }
    dbmclose(%DB) or die "Internal: Could not close $historydb";
    return $result;
}

sub badpassword
{
    my $reason = shift;
    print "$reason\n";
    exit 0
}

while (<STDIN>) {
    last if /^end$/;
    if (!/^([^:]+): (.+)$/) {
	die "key value pair not correct: $_";
    }
    $params{$1} = $2;
}

die "missing principal" if (!defined $params{'principal'});
die "missing password" if (!defined $params{'new-password'});

my $reason;

$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