diff options
-rwxr-xr-x | contrib/wallet-unknown-hosts | 107 |
1 files changed, 87 insertions, 20 deletions
diff --git a/contrib/wallet-unknown-hosts b/contrib/wallet-unknown-hosts index 3f94cbe..5655aed 100755 --- a/contrib/wallet-unknown-hosts +++ b/contrib/wallet-unknown-hosts @@ -20,6 +20,12 @@ # and hammer out the data and then add it there later. our $HISTORY = '/var/lib/wallet/hosts.db'; +# Default thresholds for reporting or purging. $MIN is the number of times we +# see the keytab in a row eligible for purge, and $THRESHOLD is the newest +# that the first time can be and still be eligible. +our $MIN = 3; +our $THRESHOLD = time - 30 * 24 * 60 * 60; + # Set up a Net::DNS resolver that will be used by local_check_keytab. BEGIN { use Net::DNS; @@ -65,7 +71,7 @@ use DB_File (); use Wallet::Report (); ############################################################################## -# Database queries +# Utility functions ############################################################################## # Return a list of host-based keytab objects in the wallet database. The @@ -80,10 +86,6 @@ sub list_keytabs { 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 { @@ -93,24 +95,89 @@ sub check_host { } ############################################################################## -# Main routine +# Main functions ############################################################################## -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); +# Do a scan of all host-based keytabs in wallet and record those that are not +# found in DNS or which should not be used according to site configuration. +sub check { + 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; + } } - if ($result) { - delete $history{$keytab}; - } elsif ($history{$keytab}) { + untie %history; +} + +# Report on all keytabs that are eligible to be deleted. Takes two values: +# the threshold for the number of times the keytab had to show up as eligible +# for purge, and the threshold for how long the keytab must have been on that +# list (given as a threshold time in seconds since epoch). +sub report { + my ($min, $threshold) = @_; + tie %history, 'DB_File', $HISTORY; + for my $keytab (sort keys %history) { my ($count, $time) = split (',', $history{$keytab}); - $count++; - $history{$keytab} = "$count,$time"; - } else { - $history{$keytab} = '1,' . time; + if ($count > $min && $time < $threshold) { + print $keytab, "\n"; + } } + untie %history; +} + +# Purge eligible keytabs. Takes three values: the user to authenticate as, +# the threshold for the number of times the keytab had to show up as eligible +# for purge, and the threshold for the first date when the keytab was seen +# eligible for purge. Rather than listing the keytabs, this deletes them +# immediately. +sub purge { + my ($user, $min, $threshold) = @_; + my $wallet = Wallet::Server->new ($user, 'localhost'); + tie %history, 'DB_File', $HISTORY; + for my $keytab (sort keys %history) { + my ($count, $time) = split (',', $history{$keytab}); + if ($count > $min && $time < $threshold) { + unless ($wallet->destroy ('keytab', $keytab)) { + warn "$0: cannot destroy keytab $keytab: ", + $wallet->error, "\n"; + } + } + } + untie %history; +} + +############################################################################## +# Main routine +############################################################################## + +my $command = shift or die "Usage: $0 (check | report | purge)\n"; +if ($command eq 'check') { + check; +} elsif ($command eq 'report') { + my ($min, $threshold) = @_; + $min = $MIN unless defined ($min); + die "$0: minimum count must be at least 1\n" if $min < 1; + $threshold = $THRESHOLD unless defined ($threshold); + report ($min, $threshold); +} elsif ($command eq 'purge') { + my $user = $ENV{REMOTE_USER} or die "$0: REMOTE_USER must be set\n"; + $min = $MIN unless defined ($min); + die "$0: minimum count must be at least 1\n" if $min < 1; + $threshold = $THRESHOLD unless defined ($threshold); + purge ($min, $threshold); +} else { + die "$0: unknown command $command\n"; } |