skeyprune.pl revision 1.7
1#!/usr/bin/perl -w
2#
3# Copyright (c) 1996, 2001, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4#
5# Permission to use, copy, modify, and distribute this software for any
6# purpose with or without fee is hereby granted, provided that the above
7# copyright notice and this permission notice appear in all copies.
8#
9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16#
17# Sponsored in part by the Defense Advanced Research Projects
18# Agency (DARPA) and Air Force Research Laboratory, Air Force
19# Materiel Command, USAF, under agreement number F39502-99-1-0512.
20#
21# Prune commented out, bogus, and crufty entries from /etc/skey
22# usage: skeyprune [days]
23#
24# $OpenBSD: skeyprune.pl,v 1.7 2015/10/06 15:06:29 tim Exp $
25#
26
27use POSIX qw(S_ISREG);
28use Fcntl qw(:DEFAULT :flock);
29
30# Keep out the stupid
31die "Only root may run $0.\n" if $>;
32die "usage: $0 [days]\n" if $#ARGV > 0;
33
34# Pathnames
35$skeydir = '/etc/skey';
36
37# Remove entries that haven't been modified in this many days.
38$days_old = $ARGV[0] || -1;
39
40# Safe umask
41umask(077);
42
43# Current time
44$now = time();
45
46# Slurp mode
47undef $/;
48
49chdir($skeydir) || die "$0: Can't cd to $skeydir: $!\n";
50opendir(SKEYDIR, ".") || die "$0: Can't open $skeydir: $!\n";
51while (defined($user = readdir(SKEYDIR))) {
52	next if $user =~ /^\./;
53	if (!sysopen(SKEY, $user, 0, O_RDWR | O_NONBLOCK | O_NOFOLLOW)) {
54	    warn "$0: Can't open $user: $!\n";
55	    next;
56	}
57	if (!flock(SKEY, LOCK_EX)) {
58		warn "$0: Can't lock $user: $!\n";
59		close(SKEY);
60		next;
61	}
62
63	if (!stat(SKEY)) {
64		warn "$0: Can't stat $user: $!\n";
65		close(SKEY);
66		next;
67	}
68
69	# Sanity checks.
70	if (!S_ISREG((stat(_))[2])) {
71		warn "$0: $user is not a regular file\n";
72		close(SKEY);
73		next;
74	}
75	if (((stat(_))[2] & 07777) != 0600) {
76		printf STDERR ("%s: Bad mode for %s: 0%o\n", $0, $user,
77		    (stat(_))[2]);
78		close(SKEY);
79		next;
80	}
81	if ((stat(_))[3] != 1) {
82		printf STDERR ("%s: Bad link count for %s: %d\n", $0, $user,
83		    (stat(_))[3]);
84		close(SKEY);
85		next;
86	}
87
88	# Remove zero size entries
89	if (-z _) {
90		unlink($user) || warn "$0: Can't unlink $user: $!\n";
91		close(SKEY);
92		next;
93	}
94
95	# Prune out old entries if asked to
96	if ($days_old > 0) {
97		$then = (stat(_))[9];
98		if (($now - $then) / (60 * 60 * 24) - 1 > $days_old) {
99			unlink($user) || warn "$0: Can't unlink $user: $!\n";
100			close(SKEY);
101			next;
102		}
103	}
104
105	# Read in the entry and check its contents.
106	$entry = <SKEY>;
107	if ($entry !~ /^\S+[\r\n]+\S+[\r\n]+\d+[\r\n]+[A-z0-9]+[\r\n]+[a-f0-9]+[\r\n]+$/) {
108		warn "$0: Invalid entry for $user:\n$entry";
109	}
110
111	close(SKEY);
112}
113exit(0);
114