skeyprune.pl revision 1.2
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