diff options
author | Russ Allbery <rra@stanford.edu> | 2010-08-16 21:01:25 -0700 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2010-08-16 21:01:25 -0700 |
commit | 3799716680711302580b698f6d7c5796df8444b2 (patch) | |
tree | 792b6287772db531dbe29e1feea5f89e429abcdc /contrib | |
parent | 5623ed1520cc916df9c62e137656670c160c7fbb (diff) |
First cut at wallet contrib script to find keytabs for unknown hosts
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/wallet-unknown-hosts | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/contrib/wallet-unknown-hosts b/contrib/wallet-unknown-hosts new file mode 100755 index 0000000..3f94cbe --- /dev/null +++ b/contrib/wallet-unknown-hosts @@ -0,0 +1,116 @@ +#!/usr/bin/perl -w +# +# wallet-unknown-hosts -- Report host keytabs in wallet for unknown hosts. +# +# Written by Russ Allbery <rra@stanford.edu> +# Copyright 2010 Board of Trustees, Leland Stanford Jr. University +# +# See LICENSE for licensing terms. + +############################################################################## +# Site configuration +############################################################################## + +# The path to the supplemental database used to store last seen times and +# counts. Keys are hostnames, and values are the number of times the hostname +# was not seen in DNS, a comma, and the UNIX seconds since epoch of the first +# run during which the host was not found. +# +# This should probably be in the wallet database, but let's try it here first +# and hammer out the data and then add it there later. +our $HISTORY = '/var/lib/wallet/hosts.db'; + +# Set up a Net::DNS resolver that will be used by local_check_keytab. +BEGIN { + use Net::DNS; + our $DNS = Net::DNS::Resolver->new; +} + +# Pre-filter. This is called for all host-based keytabs and is the place to +# apply local exceptions for keytabs that should be retained even though +# there's no corresponding DNS entry. The first argument is the full +# principal name and the second argument is the extracted host. +# +# This function should return 1 if the host is found or if the keytab should +# otherwise not be a candidate for purging, 0 if the keytab should be a +# candidate for purging, and undef if the normal DNS-based check should be +# done. +sub local_check_keytab { + my ($keytab, $host) = @_; + + # Aliases of proxy.best.stanford.edu and www.best.stanford.edu should not + # have host-based keytabs of their own. + my %purge = map { $_ => 1 } + qw(proxy.best.stanford.edu www.best.stanford.edu); + my $query = $DNS->search ($host); + return unless $query; + for my $rr ($query->answer) { + next unless $rr->type eq 'CNAME'; + return 0 if $purge{$rr->cname}; + } + + # Do normal processing by default. + return; +} + +############################################################################## +# Modules and declarations +############################################################################## + +require 5.006; + +use strict; + +use DB_File (); +use Wallet::Report (); + +############################################################################## +# Database queries +############################################################################## + +# Return a list of host-based keytab objects in the wallet database. The +# current heuristic is to look for any keytab object with a principal name +# that includes a slash and at least one period. This may be refined later. +sub list_keytabs { + my $report = Wallet::Report->new; + my @objects = $report->objects ('type', 'keytab'); + if (!@objects and $report->error) { + die $report->error, "\n"; + } + return grep { m%/.+\..+% } map { $$_[1] } @objects; +} + +############################################################################## +# DNS queries +############################################################################## + +# Given a host, look it up in DNS and see if it exists. Returns true if the +# host exists and false otherwise. +sub check_host { + my ($host) = @_; + my $addr = gethostbyname $host; + return defined ($addr) ? 1 : 0; +} + +############################################################################## +# Main routine +############################################################################## + +tie %history, 'DB_File', $HISTORY; +my @keytabs = list_keytabs; +for my $keytab (@keytabs) { + my ($host) = (split '/', $keytab)[1]; + my $result = local_check_keytab ($keytab, $host); + unless (defined $result) { + $result = check_host ($host); + } + if ($result) { + delete $history{$keytab}; + } elsif ($history{$keytab}) { + my ($count, $time) = split (',', $history{$keytab}); + $count++; + $history{$keytab} = "$count,$time"; + } else { + $history{$keytab} = '1,' . time; + } +} |