]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - crypto/heimdal/tools/kdc-log-analyze.pl
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / crypto / heimdal / tools / kdc-log-analyze.pl
1 #! /usr/pkg/bin/perl
2 # -*- mode: perl; perl-indent-level: 8 -*-
3
4 # Copyright (c) 2003 Kungliga Tekniska Högskolan
5 # (Royal Institute of Technology, Stockholm, Sweden). 
6 # All rights reserved. 
7
8 # Redistribution and use in source and binary forms, with or without 
9 # modification, are permitted provided that the following conditions 
10 # are met: 
11
12 # 1. Redistributions of source code must retain the above copyright 
13 #    notice, this list of conditions and the following disclaimer. 
14
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. 
18
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. 
22
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 
33 # SUCH DAMAGE. 
34 #
35 # $Id$
36 #
37 # kdc-log-analyze - Analyze a KDC log file and give a report on the contents
38 #
39 # Note: The parts you want likely want to customize are the variable $notlocal,
40 # the array @local_network_re and the array @local_realms.
41 #
42 # Idea and implemetion for MIT Kerberos was done first by 
43 # Ken Hornstein <kenh@cmf.nrl.navy.mil>, this program wouldn't exists
44 # without his help.
45 #
46
47 use strict;
48 use Sys::Hostname;
49
50 my $notlocal = 'not SU';
51 my @local_realms = ( "SU.SE" );
52 my @local_networks_re = 
53     ( 
54       "130\.237",
55       "193\.11\.3[0-9]\.",
56       "130.242.128",
57       "2001:6b0:5:"
58       );
59
60 my $as_req = 0;
61 my %as_req_addr;
62 my %as_req_addr_nonlocal;
63 my %as_req_client;
64 my %as_req_server;
65 my %addr_uses_des;
66 my %princ_uses_des;
67 my $five24_req = 0;
68 my %five24_req_addr;
69 my %five24_req_addr_nonlocal;
70 my %five24_req_server;
71 my %five24_req_client;
72 my $as_req_successful = 0;
73 my $as_req_error = 0;
74 my $no_such_princ = 0;
75 my %no_such_princ_princ;
76 my %no_such_princ_addr;
77 my %no_such_princ_addr_nonlocal;
78 my $as_req_etype_odd = 0;
79 my %bw_addr;
80 my $pa_alt_princ_request = 0;
81 my $pa_alt_princ_verify = 0;
82 my $tgs_req = 0;
83 my %tgs_req_addr;
84 my %tgs_req_addr_nonlocal;
85 my %tgs_req_client;
86 my %tgs_req_server;
87 my $tgs_xrealm_out = 0;
88 my %tgs_xrealm_out_realm;
89 my %tgs_xrealm_out_princ;
90 my $tgs_xrealm_in = 0;
91 my %tgs_xrealm_in_realm;
92 my %tgs_xrealm_in_princ;
93 my %enctype_session;
94 my %enctype_ticket;
95 my $restarts = 0;
96 my $forward_non_forward = 0;
97 my $v4_req = 0;
98 my %v4_req_addr;
99 my %v4_req_addr_nonlocal;
100 my $v4_cross = 0;
101 my %v4_cross_realm;
102 my $v5_cross = 0;
103 my %v5_cross_realm;
104 my $referrals = 0;
105 my %referral_princ;
106 my %referral_realm;
107 my %strange_tcp_data;
108 my $http_malformed = 0;
109 my %http_malformed_addr;
110 my $http_non_kdc = 0;
111 my %http_non_kdc_addr;
112 my $tcp_conn_timeout = 0;
113 my %tcp_conn_timeout_addr;
114 my $failed_processing = 0;
115 my %failed_processing_addr;
116 my $connection_closed = 0;
117 my %connection_closed_addr;
118 my $pa_failed = 0;
119 my %pa_failed_princ;
120 my %pa_failed_addr;
121 my %ip;
122
123 $ip{'4'} = $ip{'6'} = 0;
124
125 while (<>) {
126         process_line($_);
127 }
128
129 print "Kerberos KDC Log Report for ", 
130     hostname, " on ", scalar localtime, "\n\n";
131
132 print "General Statistics\n\n";
133
134 print "\tNumber of IPv4 requests: $ip{'4'}\n";
135 print "\tNumber of IPv6 requests: $ip{'6'}\n\n";
136
137 print "\tNumber of restarts: $restarts\n";
138 print "\tNumber of V4 requests: $v4_req\n";
139 if ($v4_req > 0) {
140         print "\tTop ten IP addresses performing V4 requests:\n";
141         topten(\%v4_req_addr);
142 }
143 if (int(keys %v4_req_addr_nonlocal) > 0) {
144         print "\tTop ten $notlocal IP addresses performing V4 requests:\n";
145         topten(\%v4_req_addr_nonlocal);
146
147 }
148 print "\n";
149
150 print "\tNumber of V4 cross realms (krb4 and 524) requests: $v4_cross\n";
151 if ($v4_cross > 0) {
152         print "\tTop ten realms performing V4 cross requests:\n";
153         topten(\%v4_cross_realm);
154 }
155 print "\n";
156
157 print "\tNumber of V45 cross realms requests: $v5_cross\n";
158 if ($v5_cross > 0) {
159         print "\tTop ten realms performing V4 cross requests:\n";
160         topten(\%v5_cross_realm);
161 }
162 print "\n";
163
164 print "\tNumber of failed lookups: $no_such_princ\n";
165 if ($no_such_princ > 0) {
166         print "\tTop ten IP addresses failing to find principal:\n";
167         topten(\%no_such_princ_addr);
168         print "\tTop ten $notlocal IP addresses failing find principal:\n";
169         topten(\%no_such_princ_addr_nonlocal);
170         print "\tTop ten failed to find principals\n";
171         topten(\%no_such_princ_princ);
172 }
173 print "\n";
174
175 print "\tBandwidth pigs:\n";
176 topten(\%bw_addr);
177 print "\n";
178
179 print "\tStrange TCP data clients: ", int(keys %strange_tcp_data),"\n";
180 topten(\%strange_tcp_data);
181 print "\n";
182
183 print "\tTimeout waiting on TCP requests: ", $tcp_conn_timeout,"\n";
184 if ($tcp_conn_timeout > 0) {
185         print "\tTop ten TCP timeout request clients\n";
186         topten(\%tcp_conn_timeout_addr);
187 }
188 print "\n";
189
190 print "\tFailed processing requests: ", $failed_processing,"\n";
191 if ($failed_processing > 0) {
192         print "\tTop ten failed processing request clients\n";
193         topten(\%failed_processing_addr);
194 }
195 print "\n";
196
197 print "\tConnection closed requests: ", $connection_closed,"\n";
198 if ($connection_closed > 0) {
199         print "\tTop ten connection closed request clients\n";
200         topten(\%connection_closed_addr);
201 }
202 print "\n";
203
204 print "\tMalformed HTTP requests: ", $http_malformed,"\n";
205 if ($http_malformed > 0) {
206         print "\tTop ten malformed HTTP request clients\n";
207         topten(\%http_malformed_addr);
208 }
209 print "\n";
210
211 print "\tHTTP non kdc requests: ", $http_non_kdc,"\n";
212 if ($http_non_kdc > 0) {
213         print "\tTop ten HTTP non KDC request clients\n";
214         topten(\%http_non_kdc_addr);
215 }
216 print "\n";
217
218 print "Report on AS_REQ requests\n\n";
219 print "Overall AS_REQ statistics\n\n";
220
221 print "\tTotal number: $as_req\n";
222
223 print "\nAS_REQ client/server statistics\n\n";
224
225 print "\tDistinct IP Addresses performing requests: ", 
226     int(keys %as_req_addr),"\n";
227 print "\tOverall top ten IP addresses\n";
228 topten(\%as_req_addr);
229
230 print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
231                                         int(keys %as_req_addr_nonlocal), "\n";
232 print "\tTop ten non-local ($notlocal) IP address:\n";
233 topten(\%as_req_addr_nonlocal);
234
235 print "\n\tPreauth failed for for: ", $pa_failed, " requests\n";
236 if ($pa_failed) {
237         print "\tPreauth failed top ten IP addresses:\n";
238         topten(\%pa_failed_addr);
239         print "\tPreauth failed top ten principals:\n";
240         topten(\%pa_failed_princ);
241 }
242
243 print "\n\tDistinct clients performing requests: ", 
244     int(keys %as_req_client), "\n";
245 print "\tTop ten clients:\n";
246 topten(\%as_req_client);
247
248 print "\tDistinct services requested: ", int(keys %as_req_server), "\n";
249 print "\tTop ten requested services:\n";
250 topten(\%as_req_server);
251
252 print "\n\n\nReport on TGS_REQ requests:\n\n";
253 print "Overall TGS_REQ statistics\n\n";
254 print "\tTotal number: $tgs_req\n";
255
256 print "\nTGS_REQ client/server statistics\n\n";
257 print "\tDistinct IP addresses performing requests: ",
258                                 int(keys %tgs_req_addr), "\n";
259 print "\tOverall top ten IP addresses\n";
260 topten(\%tgs_req_addr);
261
262 print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
263                                 int(keys %tgs_req_addr_nonlocal), "\n";
264 print "\tTop ten non-local ($notlocal) IP address:\n";
265 topten(\%tgs_req_addr_nonlocal);
266
267 print "\tDistinct clients performing requests: ",
268                                 int(keys %tgs_req_client), "\n";
269 print "\tTop ten clients:\n";
270 topten(\%tgs_req_client);
271
272 print "\tDistinct services requested: ", int(keys %tgs_req_server), "\n";
273 print "\tTop ten requested services:\n";
274 topten(\%tgs_req_server);
275
276 print "\n\n\nReport on 524_REQ requests:\n\n";
277
278 print "\t524_REQ client/server statistics\n\n";
279
280 print "\tDistinct IP Addresses performing requests: ", 
281     int(keys %five24_req_addr),"\n";
282 print "\tOverall top ten IP addresses\n";
283 topten(\%five24_req_addr);
284
285 print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
286                                         int(keys %five24_req_addr_nonlocal), "\n";
287 print "\tTop ten non-local ($notlocal) IP address:\n";
288 topten(\%five24_req_addr_nonlocal);
289
290 print "\tDistinct clients performing requests: ", int(keys %five24_req_client), "\n";
291 print "\tTop ten clients:\n";
292 topten(\%five24_req_client);
293
294 print "\tDistinct services requested: ", int(keys %five24_req_server), "\n";
295 print "\tTop ten requested services:\n";
296 topten(\%five24_req_server);
297 print "\n";
298
299 print "Cross realm statistics\n\n";
300
301 print "\tNumber of cross-realm tgs out: $tgs_xrealm_out\n";
302 if ($tgs_xrealm_out > 0) {
303         print "\tTop ten realms used for out cross-realm:\n";
304         topten(\%tgs_xrealm_out_realm);
305         print "\tTop ten principals use out cross-realm:\n";
306         topten(\%tgs_xrealm_out_princ);
307 }
308 print "\tNumber of cross-realm tgs in: $tgs_xrealm_in\n";
309 if ($tgs_xrealm_in > 0) {
310         print "\tTop ten realms used for in cross-realm:\n";
311         topten(\%tgs_xrealm_in_realm);
312         print "\tTop ten principals use in cross-realm:\n";
313         topten(\%tgs_xrealm_in_princ);
314 }
315
316 print "\n\nReport on referral:\n\n";
317
318 print "\tNumber of referrals: $referrals\n";
319 if ($referrals > 0) {
320         print "\tTop ten referral-ed principals:\n";
321         topten(\%referral_princ);
322         print "\tTop ten to realm referrals:\n";
323         topten(\%referral_realm);
324 }
325
326 print "\n\nEnctype Statistics:\n\n";
327 print "\tTop ten session enctypes:\n";
328 topten(\%enctype_session);
329 print "\tTop ten ticket enctypes:\n";
330 topten(\%enctype_ticket);
331
332 print "\tDistinct IP addresses using DES: ", int(keys %addr_uses_des), "\n";
333 print "\tTop IP addresses using DES:\n";
334 topten(\%addr_uses_des);
335 print "\tDistinct principals using DES: ", int(keys %princ_uses_des), "\n";
336 print "\tTop ten principals using DES:\n";
337 topten(\%princ_uses_des);
338
339 print "\n";
340
341 printf("Requests to forward non-forwardable ticket: $forward_non_forward\n");
342
343
344 exit 0;
345
346 my $last_addr = "";
347 my $last_principal = "";
348
349 sub process_line {
350         local($_) = @_;
351         #
352         # Eat these lines that are output as a result of startup (but
353         # log the number of restarts)
354         #
355         if (/AS-REQ \(krb4\) (.*) from IPv([46]):([0-9\.:a-fA-F]+) for krbtgt.*$/){
356                 $v4_req++;
357                 $v4_req_addr{$3}++;
358                 $v4_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
359                 $last_addr = $3;
360                 $last_principal = $1;
361                 $ip{$2}++;
362         } elsif (/AS-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) {
363                 $as_req++;
364                 $as_req_client{$1}++;
365                 $as_req_server{$4}++;
366                 $as_req_addr{$3}++;
367                 $as_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
368                 $last_addr = $3;
369                 $last_principal = $1;
370                 $ip{$2}++;
371         } elsif (/TGS-REQ \(krb4\)/) {
372                 #Nothing
373         } elsif (/TGS-REQ (.+) from IPv([46]):([0-9\.:a-fA-F]+) for (.*?)( \[.*\]){0,1}$/) {
374                 $tgs_req++;
375                 $tgs_req_client{$1}++;
376                 $tgs_req_server{$4}++;
377                 $tgs_req_addr{$3}++;
378                 $tgs_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
379                 $last_addr = $3;
380                 $last_principal = $1;
381                 $ip{$2}++;
382
383                 my $source = $1;
384                 my $dest = $4;
385                 
386                 if (!islocalrealm($source)) {
387                         $tgs_xrealm_in++;
388                         $tgs_xrealm_in_princ{$source}++;
389                         if ($source =~ /[^@]+@([^@]+)/ ) {
390                                 $tgs_xrealm_in_realm{$1}++;
391                         }
392                 }
393                 if ($dest =~ /krbtgt\/([^@]+)@[^@]+/) {
394                         if (!islocalrealm($1)) {
395                                 $tgs_xrealm_out++;
396                                 $tgs_xrealm_out_realm{$1}++;
397                                 $tgs_xrealm_out_princ{$source}++;
398                         }
399                 }
400         } elsif (/524-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) {
401                 $five24_req++;
402                 $five24_req_client{$1}++;
403                 $five24_req_server{$4}++;
404                 $five24_req_addr{$3}++;
405                 $five24_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
406                 $last_addr = $3;
407                 $last_principal = $1;
408                 $ip{$2}++;
409         } elsif (/TCP data of strange type from IPv[46]:([0-9\.:a-fA-F]+)/) {
410                 $strange_tcp_data{$1}++;
411         } elsif (/Lookup (.*) failed: No such entry in the database/) {
412                 $no_such_princ++;
413                 $no_such_princ_addr{$last_addr}++;
414                 $no_such_princ_addr_nonlocal{$last_addr}++ if (!islocaladdr($last_addr));
415                 $no_such_princ_princ{$1}++;
416         } elsif (/Lookup .* succeeded$/) {
417                 # Nothing
418         } elsif (/Malformed HTTP request from IPv[46]:([0-9\.:a-fA-F]+)$/) {
419                 $http_malformed++;
420                 $http_malformed_addr{$1}++;
421         } elsif (/TCP-connection from IPv[46]:([0-9\.:a-fA-F]+) expired after [0-9]+ bytes/) {
422                 $tcp_conn_timeout++;
423                 $tcp_conn_timeout_addr{$1}++;
424         } elsif (/Failed processing [0-9]+ byte request from IPv[46]:([0-9\.:a-fA-F]+)/) {
425                 $failed_processing++;
426                 $failed_processing_addr{$1}++;
427         } elsif (/connection closed before end of data after [0-9]+ bytes from IPv[46]:([0-9\.:a-fA-F]+)/) {
428                 $connection_closed++;
429                 $connection_closed_addr{$1}++;
430         } elsif (/HTTP request from IPv[46]:([0-9\.:a-fA-F]+) is non KDC request/) {
431                 $http_non_kdc++;
432                 $http_non_kdc_addr{$1}++;
433         } elsif (/returning a referral to realm (.*) for server (.*) that was not found/) {
434                 $referrals++;
435                 $referral_princ{$2}++;
436                 $referral_realm{$1}++;
437         } elsif (/krb4 Cross-realm (.*) -> (.*) disabled/) {
438                 $v4_cross++;
439                 $v4_cross_realm{$1."->".$2}++;
440         } elsif (/524 cross-realm (.*) -> (.*) disabled/) {
441                 $v4_cross++;
442                 $v4_cross_realm{$1."->".$2}++;
443         } elsif (/cross-realm (.*) -> (.*): no transit through realm (.*)/) {
444         } elsif (/cross-realm (.*) -> (.*) via \[([^\]]+)\]/) {
445                 $v5_cross++;
446                 $v5_cross_realm{$1."->".$2}++;
447         } elsif (/cross-realm (.*) -> (.*)/) {
448                 $v5_cross++;
449                 $v5_cross_realm{$1."->".$2}++;
450         } elsif (/sending ([0-9]+) bytes to IPv[46]:([0-9\.:a-fA-F]+)/) {
451                 $bw_addr{$2} += $1;
452         } elsif (/Using ([-a-z0-9]+)\/([-a-z0-9]+)/) {
453                 $enctype_ticket{$1}++;
454                 $enctype_session{$2}++;
455
456                 my $ticket = $1;
457                 my $session = $2;
458
459                 if ($ticket =~ /des-cbc-(crc|md4|md5)/) {
460                         $addr_uses_des{$last_addr}++;
461                         $princ_uses_des{$last_principal}++;
462                 }
463
464         } elsif (/Failed to decrypt PA-DATA -- (.+)$/) {
465                 $pa_failed++;
466                 $pa_failed_princ{$last_principal}++;
467                 $pa_failed_addr{$last_addr}++;
468
469         } elsif (/Request to forward non-forwardable ticket/) {
470                 $forward_non_forward++;
471         } elsif (/HTTP request:/) {
472         } elsif (/krb_rd_req: Incorrect network address/) {
473         } elsif (/krb_rd_req: Ticket expired \(krb_rd_req\)/) {
474         } elsif (/Ticket expired \(.*\)/) {
475         } elsif (/krb_rd_req: Can't decode authenticator \(krb_rd_req\)/) {
476         } elsif (/Request from wrong address/) {
477                 # XXX
478         } elsif (/UNKNOWN --/) {
479                 # XXX
480         } elsif (/Too large time skew -- (.*)$/) {
481                 # XXX
482         } elsif (/No PA-ENC-TIMESTAMP --/) {
483                 # XXX
484         } elsif (/Looking for pa-data --/) {
485                 # XXX
486         } elsif (/Pre-authentication succeded -- (.+)$/) {
487                 # XXX
488         } elsif (/Bad request for ([,a-zA-Z0-9]+) ticket/) {
489                 # XXX
490         } elsif (/Failed to verify AP-REQ: Ticket expired/) {
491                 # XXX 
492         } elsif (/Client not found in database:/) {
493                 # XXX
494         } elsif (/Server not found in database \(krb4\)/) {
495         } elsif (/Server not found in database:/) {
496                 # XXX
497         } elsif (/newsyslog.*logfile turned over/) {
498                 # Nothing
499         } elsif (/Requested flags:/) {
500                 # Nothing
501         } elsif (/shutting down/) {
502                 # Nothing
503         } elsif (/listening on IP/) {
504                 # Nothing
505         } elsif (/commencing operation/) {
506                 $restarts++;
507         }
508         #
509         # Log it if we didn't parse the line
510         #
511         else {
512                 print "Unknown log file line: $_";
513         }
514 }
515
516 sub topten {
517         my ($list) = @_;
518         my @keys;
519
520         my $key;
521
522         @keys = (sort {$$list{$b} <=> $$list{$a}} (keys %{$list}));
523         splice @keys, 10;
524
525         foreach $key (@keys) {
526                 print "\t\t$key - $$list{$key}\n";
527         }
528 }
529
530 sub islocaladdr (\$) {
531         my ($addr) = @_;
532         my $net;
533
534         foreach $net (@local_networks_re) {
535                 return 1 if ($addr =~ /$net/);
536         }
537         return 0;
538 }
539
540 sub islocalrealm (\$) {
541         my ($princ) = @_;
542         my $realm;
543
544         foreach $realm (@local_realms) {
545                 return 1 if ($princ eq $realm);
546                 return 1 if ($princ =~ /[^@]+\@${realm}/);
547         }
548         return 0;
549 }