Home | History | Annotate | Line # | Download | only in kadm5
      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
    113