| 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$
|
|---|
| 33 |
|
|---|
| 34 | use strict;
|
|---|
| 35 | use Crypt::Cracklib;
|
|---|
| 36 | use Digest::MD5;
|
|---|
| 37 |
|
|---|
| 38 | # NEED TO CHANGE THESE TO MATCH YOUR SYSTEM
|
|---|
| 39 | my $database = '/usr/lib/cracklib_dict';
|
|---|
| 40 | my $historydb = '/var/heimdal/historydb';
|
|---|
| 41 | # NEED TO CHANGE THESE TO MATCH YOUR SYSTEM
|
|---|
| 42 |
|
|---|
| 43 | # seconds password reuse allowed (to catch retries from clients)
|
|---|
| 44 | my $reusetime = 60;
|
|---|
| 45 |
|
|---|
| 46 | my %params;
|
|---|
| 47 |
|
|---|
| 48 | sub check_basic
|
|---|
| 49 | {
|
|---|
| 50 | my $principal = shift;
|
|---|
| 51 | my $passwd = shift;
|
|---|
| 52 |
|
|---|
| 53 | if ($principal eq $passwd) {
|
|---|
| 54 | return "Principal name as password is not allowed";
|
|---|
| 55 | }
|
|---|
| 56 | return "ok";
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | sub check_repeat
|
|---|
| 60 | {
|
|---|
| 61 | my $principal = shift;
|
|---|
| 62 | my $passwd = shift;
|
|---|
| 63 | my $result = 'Do not reuse passwords';
|
|---|
| 64 | my %DB;
|
|---|
| 65 | my $md5context = new Digest::MD5;
|
|---|
| 66 | my $timenow = scalar(time());
|
|---|
| 67 |
|
|---|
| 68 | $md5context->reset();
|
|---|
| 69 | $md5context->add($principal, ":", $passwd);
|
|---|
| 70 |
|
|---|
| 71 | my $key=$md5context->hexdigest();
|
|---|
| 72 |
|
|---|
| 73 | dbmopen(%DB,$historydb,0600) or die "Internal: Could not open $historydb";
|
|---|
| 74 | if (!$DB{$key} || ($timenow - $DB{$key} < $reusetime)) {
|
|---|
| 75 | $result = "ok";
|
|---|
| 76 | $DB{$key}=$timenow;
|
|---|
| 77 | }
|
|---|
| 78 | dbmclose(%DB) or die "Internal: Could not close $historydb";
|
|---|
| 79 | return $result;
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | sub badpassword
|
|---|
| 83 | {
|
|---|
| 84 | my $reason = shift;
|
|---|
| 85 | print "$reason\n";
|
|---|
| 86 | exit 0
|
|---|
| 87 | }
|
|---|
| 88 |
|
|---|
| 89 | while (<STDIN>) {
|
|---|
| 90 | last if /^end$/;
|
|---|
| 91 | if (!/^([^:]+): (.+)$/) {
|
|---|
| 92 | die "key value pair not correct: $_";
|
|---|
| 93 | }
|
|---|
| 94 | $params{$1} = $2;
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | die "missing principal" if (!defined $params{'principal'});
|
|---|
| 98 | die "missing password" if (!defined $params{'new-password'});
|
|---|
| 99 |
|
|---|
| 100 | my $reason;
|
|---|
| 101 |
|
|---|
| 102 | $reason = check_basic($params{'principal'}, $params{'new-password'});
|
|---|
| 103 | badpassword($reason) if ($reason ne "ok");
|
|---|
| 104 |
|
|---|
| 105 | $reason = fascist_check($params{'new-password'}, $database);
|
|---|
| 106 | badpassword($reason) if ($reason ne "ok");
|
|---|
| 107 |
|
|---|
| 108 | $reason = check_repeat($params{'principal'}, $params{'new-password'});
|
|---|
| 109 | badpassword($reason) if ($reason ne "ok");
|
|---|
| 110 |
|
|---|
| 111 | print "APPROVED\n";
|
|---|
| 112 | exit 0
|
|---|