source: trunk/server/fedora/config/etc/syslog-ng/d_zroot.pl @ 2093

Last change on this file since 2093 was 2093, checked in by geofft, 12 years ago
d_zroot: Don't accidentally let @recipients be empty d_zroot.pl fails to notice when the .k5login is nonexistent/empty, and when it runs ("zwrite", "-c", "scripts-spew", @k5login), it ends up giving zwrite no recipients, which causes the message to go to <scripts-spew,*,*>. This has the potential to leak sensitive logs on a misconfigured server. Fix this by redacting messages and also warning at startup if the .k5login is empty.
  • Property svn:executable set to *
File size: 4.8 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5use Sys::Hostname;
6use Time::HiRes qw(ualarm);
7use File::Temp;
8
9our $ZCLASS = "scripts-auto";
10our @USERS = qw/root logview/;
11my $k5login;
12open $k5login, '/root/.k5login';
13our @RECIPIENTS = map {chomp; m|([^/@]*)| && $1} <$k5login>;
14close $k5login;
15
16our %USERS;
17@USERS{@USERS} = undef;
18
19sub zwrite($;$$\@) {
20    my ($message, $class, $instance, $recipref) = @_;
21    my @recipients = ();
22    if (defined($recipref)) {
23        if (@$recipref) {
24            @recipients = @$recipref;
25        } else {
26            $message = '@b(Empty recipient list specified, message redacted)';
27        }
28    }
29    $class ||= $ZCLASS;
30    $instance ||= 'root.'.hostname;
31    open(ZWRITE, "|-", qw|/usr/bin/zwrite -d -n -O log -c|, $class, '-i', $instance, '-s', hostname, @recipients) or die "Couldn't open zwrite";
32    print ZWRITE $message;
33    close(ZWRITE);
34}
35
36unless (@RECIPIENTS) {
37    zwrite('@b(No .k5login found, sensitive logs will not be zephyred)', $ZCLASS);
38}
39
40my %toclass;
41
42my %sshkeys;
43
44sub buildKeyMap($) {
45    my ($file) = @_;
46    open (KEYS, $file) or (warn "Couldn't open $file: $!\n" and return);
47    while (<KEYS>) {
48        chomp;
49        my ($fingerprint, $comment) = parseKey($_);
50        $sshkeys{$fingerprint} = $comment;
51    }
52    close(KEYS);
53}
54
55sub parseKey($) {
56    my ($key) = @_;
57    my $tmp = new File::Temp;
58    print $tmp $key;
59    close $tmp;
60    open (KEYGEN, "-|", qw(/usr/bin/ssh-keygen -l -f), $tmp) or die "Couldn't call ssh-keygen: $!";
61    my ($line) = <KEYGEN>;
62    close(KEYGEN);
63    my (undef, $fingerprint, undef) = split(' ', $line, 3);
64    my (undef, undef, $comment) = split(' ', $key, 3);
65    #print "$fingerprint $comment";
66    return ($fingerprint, $comment);
67}
68
69buildKeyMap("/root/.ssh/authorized_keys");
70buildKeyMap("/root/.ssh/authorized_keys2");
71
72my @message;
73
74while (my $line = <>) {
75    @message = $line;
76    eval {
77        local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
78        ualarm(500*1000);
79        while (<>) { push @message, $_; }
80    };
81    chomp @message;
82    map { s/^(.*?): // } @message;
83    %toclass = ();
84    foreach my $message (@message) {
85        sub sendmsg ($;$) {
86            my ($message, $class) = @_;
87            $class ||= $ZCLASS;
88            $toclass{$class} .= $message."\n";
89        }
90        if ($message =~ m|Accepted (\S+) for (\S+)|) {
91            sendmsg($message) if exists $USERS{$2}
92        } elsif ($message =~ m|Authorized to (\S+),|) {
93            sendmsg($message) if exists $USERS{$1};
94        } elsif ($message =~ m|Root (\S+) shell|) {
95            sendmsg($message);
96        } elsif ($message =~ m|pam_unix\(([^:]+):session\): session \S+ for user (\S+)|) {
97            sendmsg($message) if $1 ne "cron" and exists $USERS{$2};
98        } elsif ($message =~ m|^Found matching (\w+) key: (\S+)|) {
99            if ($sshkeys{$2}) {
100                sendmsg($message." (".$sshkeys{$2}.")");
101            } else {
102                sendmsg($message." (UNKNOWN KEY)");
103            }
104        } elsif ($message =~ m|^Out of memory:|) {
105            sendmsg($message);
106        } elsif ($message =~ m|^giving \S+ admin rights|) {
107            sendmsg($message);
108        } elsif ($message =~ m|^Connection closed|) {
109            # Do nothing
110        } elsif ($message =~ m|^Closing connection to |) {
111        } elsif ($message =~ m|^Connection from (\S+) port (\S+)|) {
112        } elsif ($message =~ m|^Invalid user|) {
113        } elsif ($message =~ m|^input_userauth_request: invalid user|) {
114        } elsif ($message =~ m|^Received disconnect from|) {
115        } elsif ($message =~ m|^Postponed keyboard-interactive|) {
116        } elsif ($message =~ m|^Failed keyboard-interactive/pam|) {
117        } elsif ($message =~ m|^fatal: Read from socket failed: Connection reset by peer$|) {
118        } elsif ($message =~ m|^reverse mapping checking getaddrinfo|) {
119        } elsif ($message =~ m|^pam_succeed_if\(sshd\:auth\)\:|) {
120        } elsif ($message =~ m|^error: PAM: Authentication failure|) {
121        } elsif ($message =~ m|^pam_unix\(sshd:auth\): authentication failure|) {
122        } elsif ($message =~ m|^Postponed keyboard-interactive for invalid user |) {
123        } elsif ($message =~ m|^Failed keyboard-interactive/pam for invalid user |) {
124        } elsif ($message =~ m|^Postponed gssapi-with-mic for |) {
125        } elsif ($message =~ m|^Address \S+ maps to \S+, but this does not map back to the address|) {
126        } elsif ($message =~ m|^Nasty PTR record .* is set up for .*, ignoring|) {
127        } elsif ($message =~ m|^User child is on pid \d+$|) {
128        } elsif ($message =~ m|^Transferred: sent \d+, received \d+ bytes$|) {
129        } elsif ($message =~ m|^Setting tty modes failed: Invalid argument$|) {
130        } elsif ($message =~ m|^ *nrpe .* COMMAND=/etc/nagios/check_ldap_mmr.real$|) {
131        } elsif ($message =~ m|^ *root : TTY=|) {
132        } elsif ($message =~ m|^Set /proc/self/oom_adj to |) {
133        } elsif ($message =~ m|^fatal: mm_request_receive: read: Connection reset by peer$|) {
134        } else {
135            sendmsg($message, "scripts-spew");
136        }
137    }
138
139    foreach my $class (keys %toclass) {
140        if ($class eq $ZCLASS) {
141            zwrite($toclass{$class}, $class);
142        } else {
143            zwrite($toclass{$class}, $class, undef, @RECIPIENTS);
144        }
145    }
146}
Note: See TracBrowser for help on using the repository browser.