1#!/usr/local/bin/perl
2#
3# potcheck.pl   This script is used to upgrade john's .pot file, to find
4#               problems, and 'fix' them, and other things.
5#
6# 2016 by JimF for use in JohnRipper project.  Code placed in public domain.
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted, as long an unmodified copy of this
9# license/disclaimer accompanies the source.
10#
11# There's ABSOLUTELY NO WARRANTY, express or implied.
12#
13
14use warnings;
15use strict;
16use Getopt::Long;
17use Digest::MD5 qw(md5_hex);
18
19# NOTE, if this is changed in params.h, we need to update it here!
20my $LINE_BUFFER_SIZE = 0x400;
21my $PLAINTEXT_BUFFER_SIZE = 0x80;
22my $MAX_CIPHERTEXT_SIZE = ($LINE_BUFFER_SIZE - $PLAINTEXT_BUFFER_SIZE);
23my $POT_BUFFER_CT_TRIM_SIZE = ($MAX_CIPHERTEXT_SIZE - 13 - 32);
24
25# options:
26my $help = 0; my $quiet = 0; my $verbosity = 0; my $stop_on_error = 0;
27my $canonize_fix = 0;   # canonize .pot lines, (i.e. $dyna_33$ -> $NT$ type stuff)
28my $encode_fix  = 0;    # normalize to utf8 ?  (NOTE, this may be harder than hell)
29my $longline_fix = 0;   # this will be done by default is ANY other 'fix' is selected.
30my $validate = 0;       # silent. Only returns 0 or 1 (1 if there are ANY invalid lines).
31
32my $line_buffer_size = 0x400;
33my $plaintext_buffer_size = 0x100;
34my $max_ciphertext_size = ($line_buffer_size - $plaintext_buffer_size);
35my $pot_buffer_ct_trim_size = ($max_ciphertext_size - 13 - 32);
36
37my $cato = 0;       # cato error.  If seen, return 1 and print explanation.
38                    # Then ./configure will stop telling the user to first
39                    # 'fix' his .pot file.
40my $fix = 0;        # this will cause output in .pot format, fixing lines.
41                    # if ANY of the *_fix vars get set, then we set this to true
42my $line_no = 0;
43
44parseArgs();
45
46while (my $line = <STDIN>) {
47	$line_no++;
48	chomp $line;
49	minimize($line);
50}
51exit (!!$cato);
52
53
54sub usage {
55	print "usage:  $0 [args]\n";
56	print "\targs:\n";
57	print "\t -? | -help    Provide this help screen\n";
58#	print "\t -quiet        Less output (multiple -q allowed)\n";
59	print "\t -verbose      More output\n";
60	print "\t -validate     Returns 0 if .pot valid, or 1 if any lines are problems\n";
61#	print "\t -stoponerror  If there is any fatal problem, stop\n";
62#	print "\t -canonize_fix Apply canonizaton rules to convert formats\n";
63#	print "\t -encode_fix   Fix encoding issues (cannonize to utf8)\n";
64	print "\t -longline_fix Overlong lines are converted to short .pot format\n";
65	print "\nThe program is a filter. stdin/stdout are used for input and output\n";
66	exit (0);
67}
68
69sub parseArgs {
70	my @passthru=();
71	my $help = 0;
72	my $err = GetOptions(
73		'help|?'            => \$help,
74	#	'quiet+'            => \$quiet,
75		'verbose+'          => \$verbosity,
76	#	'stoponerror!'      => \$stop_on_error,
77		'validate!'         => \$validate,
78	#	'canonize_fix!'     => \$canonize_fix,
79	#	'encode_fix!'       => \$encode_fix,
80		'longline_fix!'     => \$longline_fix,
81		);
82	if ($err == 0) { usage("exiting, due to invalid option"); }
83	if ($help) { usage(); }
84	#if ($canonize_fix || $encode_fix) { $longline_fix = 1; }
85	$fix = $canonize_fix + $encode_fix + $longline_fix;
86	if ($fix) { $verbosity += 1; }
87	$verbosity -= $quiet;
88	die "validate can not be used with some fixing function" if ($validate and $fix);
89	die "validate or some fixing function(s) must be specified" if (!$validate and !$fix);
90}
91
92sub minimize {
93	my $line = $_[0];
94	$line=fixcanon($line)     if ($canonize_fix);
95	$line=fixencode($line)    if ($encode_fix);
96	$line=fixlongline($line)  if ($longline_fix or $validate);
97	if ($validate == 0) { print "$line\n"; }
98}
99
100sub fixcanon {
101	return 'canon '.$_[0];
102}
103sub fixencode {
104	require Encode;
105	return 'encode '.$_[0];
106}
107sub fixlongline {
108	my $pos = index($_[0], ':');
109	if ($pos <= $MAX_CIPHERTEXT_SIZE) { return $_[0]; }
110	if ($verbosity > 1) {
111		print STDERR sprintf("Long line %d: '%.50s(...)'\n", $line_no, $_[0])
112	}
113	$cato++;
114	my $line = $_[0];
115	my $pass = substr($line, $pos);
116	my $hash = substr($line, 0, $pos);
117	$line = substr($line, 0, $POT_BUFFER_CT_TRIM_SIZE) . '$SOURCE_HASH$';
118	$line .= md5_hex($hash).$pass;
119	return $line;
120}
121