2 # -*- mode: perl; perl-indent-level: 8 -*-
4 # Copyright (c) 2003 Kungliga Tekniska Högskolan
5 # (Royal Institute of Technology, Stockholm, Sweden).
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
12 # 1. Redistributions of source code must retain the above copyright
13 # notice, this list of conditions and the following disclaimer.
15 # 2. Redistributions in binary form must reproduce the above copyright
16 # notice, this list of conditions and the following disclaimer in the
17 # documentation and/or other materials provided with the distribution.
19 # 3. Neither the name of the Institute nor the names of its contributors
20 # may be used to endorse or promote products derived from this software
21 # without specific prior written permission.
23 # THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 # ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 # $Heimdal: kdc-log-analyze.pl 17173 2006-04-23 13:19:21Z lha $
38 # kdc-log-analyze - Analyze a KDC log file and give a report on the contents
40 # Note: The parts you want likely want to customize are the variable $notlocal,
41 # the array @local_network_re and the array @local_realms.
43 # Idea and implemetion for MIT Kerberos was done first by
44 # Ken Hornstein <kenh@cmf.nrl.navy.mil>, this program wouldn't exists
51 my $notlocal = 'not SU';
52 my @local_realms = ( "SU.SE" );
53 my @local_networks_re =
63 my %as_req_addr_nonlocal;
70 my %five24_req_addr_nonlocal;
71 my %five24_req_server;
72 my %five24_req_client;
73 my $as_req_successful = 0;
75 my $no_such_princ = 0;
76 my %no_such_princ_princ;
77 my %no_such_princ_addr;
78 my %no_such_princ_addr_nonlocal;
79 my $as_req_etype_odd = 0;
81 my $pa_alt_princ_request = 0;
82 my $pa_alt_princ_verify = 0;
85 my %tgs_req_addr_nonlocal;
88 my $tgs_xrealm_out = 0;
89 my %tgs_xrealm_out_realm;
90 my %tgs_xrealm_out_princ;
91 my $tgs_xrealm_in = 0;
92 my %tgs_xrealm_in_realm;
93 my %tgs_xrealm_in_princ;
97 my $forward_non_forward = 0;
100 my %v4_req_addr_nonlocal;
108 my %strange_tcp_data;
109 my $http_malformed = 0;
110 my %http_malformed_addr;
111 my $http_non_kdc = 0;
112 my %http_non_kdc_addr;
113 my $tcp_conn_timeout = 0;
114 my %tcp_conn_timeout_addr;
115 my $failed_processing = 0;
116 my %failed_processing_addr;
117 my $connection_closed = 0;
118 my %connection_closed_addr;
124 $ip{'4'} = $ip{'6'} = 0;
130 print "Kerberos KDC Log Report for ",
131 hostname
, " on ", scalar localtime, "\n\n";
133 print "General Statistics\n\n";
135 print "\tNumber of IPv4 requests: $ip{'4'}\n";
136 print "\tNumber of IPv6 requests: $ip{'6'}\n\n";
138 print "\tNumber of restarts: $restarts\n";
139 print "\tNumber of V4 requests: $v4_req\n";
141 print "\tTop ten IP addresses performing V4 requests:\n";
142 topten
(\
%v4_req_addr);
144 if (int(keys %v4_req_addr_nonlocal) > 0) {
145 print "\tTop ten $notlocal IP addresses performing V4 requests:\n";
146 topten
(\
%v4_req_addr_nonlocal);
151 print "\tNumber of V4 cross realms (krb4 and 524) requests: $v4_cross\n";
153 print "\tTop ten realms performing V4 cross requests:\n";
154 topten
(\
%v4_cross_realm);
158 print "\tNumber of V45 cross realms requests: $v5_cross\n";
160 print "\tTop ten realms performing V4 cross requests:\n";
161 topten
(\
%v5_cross_realm);
165 print "\tNumber of failed lookups: $no_such_princ\n";
166 if ($no_such_princ > 0) {
167 print "\tTop ten IP addresses failing to find principal:\n";
168 topten
(\
%no_such_princ_addr);
169 print "\tTop ten $notlocal IP addresses failing find principal:\n";
170 topten
(\
%no_such_princ_addr_nonlocal);
171 print "\tTop ten failed to find principals\n";
172 topten
(\
%no_such_princ_princ);
176 print "\tBandwidth pigs:\n";
180 print "\tStrange TCP data clients: ", int(keys %strange_tcp_data),"\n";
181 topten
(\
%strange_tcp_data);
184 print "\tTimeout waiting on TCP requests: ", $tcp_conn_timeout,"\n";
185 if ($tcp_conn_timeout > 0) {
186 print "\tTop ten TCP timeout request clients\n";
187 topten
(\
%tcp_conn_timeout_addr);
191 print "\tFailed processing requests: ", $failed_processing,"\n";
192 if ($failed_processing > 0) {
193 print "\tTop ten failed processing request clients\n";
194 topten
(\
%failed_processing_addr);
198 print "\tConnection closed requests: ", $connection_closed,"\n";
199 if ($connection_closed > 0) {
200 print "\tTop ten connection closed request clients\n";
201 topten
(\
%connection_closed_addr);
205 print "\tMalformed HTTP requests: ", $http_malformed,"\n";
206 if ($http_malformed > 0) {
207 print "\tTop ten malformed HTTP request clients\n";
208 topten
(\
%http_malformed_addr);
212 print "\tHTTP non kdc requests: ", $http_non_kdc,"\n";
213 if ($http_non_kdc > 0) {
214 print "\tTop ten HTTP non KDC request clients\n";
215 topten
(\
%http_non_kdc_addr);
219 print "Report on AS_REQ requests\n\n";
220 print "Overall AS_REQ statistics\n\n";
222 print "\tTotal number: $as_req\n";
224 print "\nAS_REQ client/server statistics\n\n";
226 print "\tDistinct IP Addresses performing requests: ",
227 int(keys %as_req_addr),"\n";
228 print "\tOverall top ten IP addresses\n";
229 topten
(\
%as_req_addr);
231 print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
232 int(keys %as_req_addr_nonlocal), "\n";
233 print "\tTop ten non-local ($notlocal) IP address:\n";
234 topten
(\
%as_req_addr_nonlocal);
236 print "\n\tPreauth failed for for: ", $pa_failed, " requests\n";
238 print "\tPreauth failed top ten IP addresses:\n";
239 topten
(\
%pa_failed_addr);
240 print "\tPreauth failed top ten principals:\n";
241 topten
(\
%pa_failed_princ);
244 print "\n\tDistinct clients performing requests: ",
245 int(keys %as_req_client), "\n";
246 print "\tTop ten clients:\n";
247 topten
(\
%as_req_client);
249 print "\tDistinct services requested: ", int(keys %as_req_server), "\n";
250 print "\tTop ten requested services:\n";
251 topten
(\
%as_req_server);
253 print "\n\n\nReport on TGS_REQ requests:\n\n";
254 print "Overall TGS_REQ statistics\n\n";
255 print "\tTotal number: $tgs_req\n";
257 print "\nTGS_REQ client/server statistics\n\n";
258 print "\tDistinct IP addresses performing requests: ",
259 int(keys %tgs_req_addr), "\n";
260 print "\tOverall top ten IP addresses\n";
261 topten
(\
%tgs_req_addr);
263 print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
264 int(keys %tgs_req_addr_nonlocal), "\n";
265 print "\tTop ten non-local ($notlocal) IP address:\n";
266 topten
(\
%tgs_req_addr_nonlocal);
268 print "\tDistinct clients performing requests: ",
269 int(keys %tgs_req_client), "\n";
270 print "\tTop ten clients:\n";
271 topten
(\
%tgs_req_client);
273 print "\tDistinct services requested: ", int(keys %tgs_req_server), "\n";
274 print "\tTop ten requested services:\n";
275 topten
(\
%tgs_req_server);
277 print "\n\n\nReport on 524_REQ requests:\n\n";
279 print "\t524_REQ client/server statistics\n\n";
281 print "\tDistinct IP Addresses performing requests: ",
282 int(keys %five24_req_addr),"\n";
283 print "\tOverall top ten IP addresses\n";
284 topten
(\
%five24_req_addr);
286 print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
287 int(keys %five24_req_addr_nonlocal), "\n";
288 print "\tTop ten non-local ($notlocal) IP address:\n";
289 topten
(\
%five24_req_addr_nonlocal);
291 print "\tDistinct clients performing requests: ", int(keys %five24_req_client), "\n";
292 print "\tTop ten clients:\n";
293 topten
(\
%five24_req_client);
295 print "\tDistinct services requested: ", int(keys %five24_req_server), "\n";
296 print "\tTop ten requested services:\n";
297 topten
(\
%five24_req_server);
300 print "Cross realm statistics\n\n";
302 print "\tNumber of cross-realm tgs out: $tgs_xrealm_out\n";
303 if ($tgs_xrealm_out > 0) {
304 print "\tTop ten realms used for out cross-realm:\n";
305 topten
(\
%tgs_xrealm_out_realm);
306 print "\tTop ten principals use out cross-realm:\n";
307 topten
(\
%tgs_xrealm_out_princ);
309 print "\tNumber of cross-realm tgs in: $tgs_xrealm_in\n";
310 if ($tgs_xrealm_in > 0) {
311 print "\tTop ten realms used for in cross-realm:\n";
312 topten
(\
%tgs_xrealm_in_realm);
313 print "\tTop ten principals use in cross-realm:\n";
314 topten
(\
%tgs_xrealm_in_princ);
317 print "\n\nReport on referral:\n\n";
319 print "\tNumber of referrals: $referrals\n";
320 if ($referrals > 0) {
321 print "\tTop ten referral-ed principals:\n";
322 topten
(\
%referral_princ);
323 print "\tTop ten to realm referrals:\n";
324 topten
(\
%referral_realm);
327 print "\n\nEnctype Statistics:\n\n";
328 print "\tTop ten session enctypes:\n";
329 topten
(\
%enctype_session);
330 print "\tTop ten ticket enctypes:\n";
331 topten
(\
%enctype_ticket);
333 print "\tDistinct IP addresses using DES: ", int(keys %addr_uses_des), "\n";
334 print "\tTop IP addresses using DES:\n";
335 topten
(\
%addr_uses_des);
336 print "\tDistinct principals using DES: ", int(keys %princ_uses_des), "\n";
337 print "\tTop ten principals using DES:\n";
338 topten
(\
%princ_uses_des);
342 printf("Requests to forward non-forwardable ticket: $forward_non_forward\n");
348 my $last_principal = "";
353 # Eat these lines that are output as a result of startup (but
354 # log the number of restarts)
356 if (/AS-REQ \(krb4\) (.*) from IPv([46]):([0-9\.:a-fA-F]+) for krbtgt.*$/){
359 $v4_req_addr_nonlocal{$3}++ if (!islocaladdr
($3));
361 $last_principal = $1;
363 } elsif (/AS-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) {
365 $as_req_client{$1}++;
366 $as_req_server{$4}++;
368 $as_req_addr_nonlocal{$3}++ if (!islocaladdr
($3));
370 $last_principal = $1;
372 } elsif (/TGS-REQ \(krb4\)/) {
374 } elsif (/TGS-REQ (.+) from IPv([46]):([0-9\.:a-fA-F]+) for (.*?)( \[.*\]){0,1}$/) {
376 $tgs_req_client{$1}++;
377 $tgs_req_server{$4}++;
379 $tgs_req_addr_nonlocal{$3}++ if (!islocaladdr
($3));
381 $last_principal = $1;
387 if (!islocalrealm
($source)) {
389 $tgs_xrealm_in_princ{$source}++;
390 if ($source =~ /[^@]+@([^@]+)/ ) {
391 $tgs_xrealm_in_realm{$1}++;
394 if ($dest =~ /krbtgt\/([^@
]+)@
[^@
]+/) {
395 if (!islocalrealm
($1)) {
397 $tgs_xrealm_out_realm{$1}++;
398 $tgs_xrealm_out_princ{$source}++;
401 } elsif (/524-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) {
403 $five24_req_client{$1}++;
404 $five24_req_server{$4}++;
405 $five24_req_addr{$3}++;
406 $five24_req_addr_nonlocal{$3}++ if (!islocaladdr
($3));
408 $last_principal = $1;
410 } elsif (/TCP data of strange type from IPv[46]:([0-9\.:a-fA-F]+)/) {
411 $strange_tcp_data{$1}++;
412 } elsif (/Lookup (.*) failed: No such entry in the database/) {
414 $no_such_princ_addr{$last_addr}++;
415 $no_such_princ_addr_nonlocal{$last_addr}++ if (!islocaladdr
($last_addr));
416 $no_such_princ_princ{$1}++;
417 } elsif (/Lookup .* succeeded$/) {
419 } elsif (/Malformed HTTP request from IPv[46]:([0-9\.:a-fA-F]+)$/) {
421 $http_malformed_addr{$1}++;
422 } elsif (/TCP-connection from IPv[46]:([0-9\.:a-fA-F]+) expired after [0-9]+ bytes/) {
424 $tcp_conn_timeout_addr{$1}++;
425 } elsif (/Failed processing [0-9]+ byte request from IPv[46]:([0-9\.:a-fA-F]+)/) {
426 $failed_processing++;
427 $failed_processing_addr{$1}++;
428 } elsif (/connection closed before end of data after [0-9]+ bytes from IPv[46]:([0-9\.:a-fA-F]+)/) {
429 $connection_closed++;
430 $connection_closed_addr{$1}++;
431 } elsif (/HTTP request from IPv[46]:([0-9\.:a-fA-F]+) is non KDC request/) {
433 $http_non_kdc_addr{$1}++;
434 } elsif (/returning a referral to realm (.*) for server (.*) that was not found/) {
436 $referral_princ{$2}++;
437 $referral_realm{$1}++;
438 } elsif (/krb4 Cross-realm (.*) -> (.*) disabled/) {
440 $v4_cross_realm{$1."->".$2}++;
441 } elsif (/524 cross-realm (.*) -> (.*) disabled/) {
443 $v4_cross_realm{$1."->".$2}++;
444 } elsif (/cross-realm (.*) -> (.*): no transit through realm (.*)/) {
445 } elsif (/cross-realm (.*) -> (.*) via \[([^\]]+)\]/) {
447 $v5_cross_realm{$1."->".$2}++;
448 } elsif (/cross-realm (.*) -> (.*)/) {
450 $v5_cross_realm{$1."->".$2}++;
451 } elsif (/sending ([0-9]+) bytes to IPv[46]:([0-9\.:a-fA-F]+)/) {
453 } elsif (/Using ([-a-z0-9]+)\/([-a
-z0
-9]+)/) {
454 $enctype_ticket{$1}++;
455 $enctype_session{$2}++;
460 if ($ticket =~ /des-cbc-(crc|md4|md5)/) {
461 $addr_uses_des{$last_addr}++;
462 $princ_uses_des{$last_principal}++;
465 } elsif (/Failed to decrypt PA-DATA -- (.+)$/) {
467 $pa_failed_princ{$last_principal}++;
468 $pa_failed_addr{$last_addr}++;
470 } elsif (/Request to forward non-forwardable ticket/) {
471 $forward_non_forward++;
472 } elsif (/HTTP request:/) {
473 } elsif (/krb_rd_req: Incorrect network address/) {
474 } elsif (/krb_rd_req: Ticket expired \(krb_rd_req\)/) {
475 } elsif (/Ticket expired \(.*\)/) {
476 } elsif (/krb_rd_req: Can't decode authenticator \(krb_rd_req\)/) {
477 } elsif (/Request from wrong address/) {
479 } elsif (/UNKNOWN --/) {
481 } elsif (/Too large time skew -- (.*)$/) {
483 } elsif (/No PA-ENC-TIMESTAMP --/) {
485 } elsif (/Looking for pa-data --/) {
487 } elsif (/Pre-authentication succeded -- (.+)$/) {
489 } elsif (/Bad request for ([,a-zA-Z0-9]+) ticket/) {
491 } elsif (/Failed to verify AP-REQ: Ticket expired/) {
493 } elsif (/Client not found in database:/) {
495 } elsif (/Server not found in database \(krb4\)/) {
496 } elsif (/Server not found in database:/) {
498 } elsif (/newsyslog.*logfile turned over/) {
500 } elsif (/Requested flags:/) {
502 } elsif (/shutting down/) {
504 } elsif (/listening on IP/) {
506 } elsif (/commencing operation/) {
510 # Log it if we didn't parse the line
513 print "Unknown log file line: $_";
523 @keys = (sort {$$list{$b} <=> $$list{$a}} (keys %{$list}));
526 foreach $key (@keys) {
527 print "\t\t$key - $$list{$key}\n";
531 sub islocaladdr
(\
$) {
535 foreach $net (@local_networks_re) {
536 return 1 if ($addr =~ /$net/);
541 sub islocalrealm
(\
$) {
545 foreach $realm (@local_realms) {
546 return 1 if ($princ eq $realm);
547 return 1 if ($princ =~ /[^@]+\@${realm}/);