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