1#!/usr/bin/perl -w 2# 3# Copyright (c) 1996, 2001 Todd C. Miller <Todd.Miller@courtesan.com> 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 3. The name of the author may not be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 19# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 20# THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# Prune commented out, bogus, and crufty entries from /etc/skeykeys 29# Usage: skeyprune [days] 30# 31# $OpenBSD: skeyprune.pl,v 1.2 2001/06/20 22:19:58 millert Exp $ 32# 33 34use File::Temp qw(:mktemp); 35use Fcntl qw(:DEFAULT :flock); 36use Time::Local; 37 38# Keep out the stupid 39die "Only root may run $0.\n" if $>; 40die "Usage: $0 [days]\n" if $#ARGV > 0; 41 42# Pathnames 43$keyfile = '/etc/skeykeys'; 44$template = "$keyfile.XXXXXXXX"; 45 46# Quick mapping of month name -> number 47%months = ('Jan', 0, 'Feb', 1, 'Mar', 2, 'Apr', 3, 'May', 4, 'Jun', 5, 48 'Jul', 6, 'Aug', 7, 'Sep', 8, 'Oct', 9, 'Nov', 10, 'Dec', 11); 49 50# Remove entries that haven't been modified in this many days. 51$days_old = $ARGV[0] || -1; 52 53# Safe umask 54umask(077); 55 56# Open and lock the current key file 57open(OLD, $keyfile) || die "$0: Can't open $keyfile: $!\n"; 58flock(OLD, LOCK_EX) || die "$0: Can't lock $keyfile: $!\n"; 59 60# Safely open temp file 61($NEW, $temp) = mkstemp($template); 62die "$0: Can't open tempfile $template: $!\n" unless $temp; 63 64# Run at a high priority so we don't keep things locked for too long 65setpriority(0, 0, -4); 66 67while (<OLD>) { 68 chomp(); 69 70 # Valid entry: 'username hash seq seed key date" 71 if ( /^[^\s#]+\s+(\S+\s+)?[0-9]+\s+[A-z0-9]+\s+[a-f0-9]+\s+(Jan|Feb|Mar|Apr|May|Ju[nl]|Aug|Sep|Oct|Nov|Dec)\s+[0-9]+,\s*[0-9]+\s+[0-9]+:[0-9]+:[0-9]+$/ ) { 72 73 @entry = split(/[\s,:]+/, $_); 74 # Prune out old entries if asked to 75 if ($days_old > 0) { 76 # build up time based on date string 77 $sec = $date[10]; 78 $min = $date[9]; 79 $hours = $date[8]; 80 $mday = $date[6] - 1; 81 $mon = $months{$date[5]}; 82 $year = $date[7] - 1900; 83 84 $now = time(); 85 $then = timelocal($sec,$min,$hours,$mday,$mon,$year); 86 if (($now - $then) / (60 * 60 * 24) - 1 > $days_old) { 87 next; # too old 88 } 89 } 90 91 # Missing hash type? Must be md4... 92 if ($entry[1] =~ /^\d/) { 93 splice(@entry, 1, 0, "md4"); 94 } 95 96 printf $NEW "%s %s %04d %-16s %s %4s %02d,%-4d %02d:%02d:%02d\n", 97 $entry[0], $entry[1], $entry[2], $entry[3], $entry[4], 98 $entry[5], $entry[6], $entry[7], $entry[8], $entry[9], 99 $entry[10] || do { 100 warn "Can't write to $temp: $!\n"; 101 unlink($temp); 102 exit(1); 103 }; 104 } 105} 106close(OLD); 107close($NEW); 108 109# Set owner/group/mode on tempfile and move to real location. 110($mode, $nlink, $uid, $gid) = (stat($keyfile))[2..5]; 111if (!defined($mode)) { 112 unlink($temp); 113 die "$0: Unable to stat $keyfile: $!\n"; 114} 115if (!chmod($mode, $temp)) { 116 unlink($temp); 117 die "$0: Unable to set mode of $temp to $mode: $!\n"; 118} 119if (!chown($uid, $gid, $temp)) { 120 unlink($temp); 121 die "$0: Unable to set owner of $temp to ($uid, $gid): $!\n"; 122} 123if ($nlink != 1) { 124 $nlink--; 125 warn "$0: Old $keyfile had $nlink hard links, those will be broken\n"; 126} 127# Leave temp file in place if rename fails. Might help in debugging. 128rename($temp, $keyfile) || die "$0: Unable to rename $temp to $keyfile: $!\n"; 129 130exit(0); 131