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 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 43# seconds password reuse allowed (to catch retries from clients) 44my $reusetime = 60; 45 46my %params; 47 48sub 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 59sub 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 82sub badpassword 83{ 84 my $reason = shift; 85 print "$reason\n"; 86 exit 0 87} 88 89while (<STDIN>) { 90 last if /^end$/; 91 if (!/^([^:]+): (.+)$/) { 92 die "key value pair not correct: $_"; 93 } 94 $params{$1} = $2; 95} 96 97die "missing principal" if (!defined $params{'principal'}); 98die "missing password" if (!defined $params{'new-password'}); 99 100my $reason; 101 102$reason = check_basic($params{'principal'}, $params{'new-password'}); 103badpassword($reason) if ($reason ne "ok"); 104 105$reason = fascist_check($params{'new-password'}, $database); 106badpassword($reason) if ($reason ne "ok"); 107 108$reason = check_repeat($params{'principal'}, $params{'new-password'}); 109badpassword($reason) if ($reason ne "ok"); 110 111print "APPROVED\n"; 112exit 0 113