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