use strict;
use warnings;
package Paranoic;
print "Paranoic.pm here..\n";
sub calculate_module_md5{
my $path = shift;
open my $file, '<', $path or die "Impossible to open [$path]";
my $ctx = Digest::MD5->new;
$ctx->addfile ($file);
my $md5 = $ctx->hexdigest;
close $file;
return $md5;
}
sub load_md5_from_file{
my %paranoic_INC;
open my $file, '<', 'md5-check.txt' or die "Unable to load [md5-check.txt]";
while (<$file>){
chomp $_;
next if /^#/;
next unless $_;
my ($name,$path,$md5) = split /\s+/,$_;
$paranoic_INC{ $name } = {
path => $path,
expected_md5 => $md5,
};
}
return \%paranoic_INC;
}
sub traverse_INC{
my $filename = shift;
my @original_INC = @_;
}
BEGIN {
my @original_INC = @INC;
use Digest::MD5 ;
use File::Spec;
#print "BEFORE: ",map {"$_ $INC{$_}\n"} keys %INC;
print "BEFORE any hook I will check md5 of already loaded module:\n";
my $paranoic_inc = load_md5_from_file();
foreach my $module ( keys %INC ){
# SKIP itself while developping it
# next if $module eq 'Paranoic.pm';
#test
#if ($module eq 'Exporter.pm'){$$paranoic_inc{$module}{expected_md5}.='XXXXX'}
my $md5 = calculate_module_md5( $INC{$module} );
# NOT FOUND
if (! exists $$paranoic_inc{$module} ){
# this is a die
print "Cannot find a stored md5 for [$module]";
print "\n-->DEBUG: $module\t$INC{$module}\t$md5\n";
}
# WHITELIST
elsif ( 'ALLOW' eq $$paranoic_inc{$module}{expected_md5} ){
print " WHITELIST for $module at $$paranoic_inc{$module}{path} [$md5]\n";
}
# BLACKLIST
elsif ( 'DENY' eq $$paranoic_inc{$module}{expected_md5} ){
# this is a die
print " DENY for $module at $$paranoic_inc{$module}{path} [$md5]\n";
}
# EXPECTED MD5
elsif ( $md5 eq $$paranoic_inc{$module}{expected_md5} ){
print " OK $module at $$paranoic_inc{$module}{path} has the expected md5: ".
"$$paranoic_inc{$module}{expected_md5}\n";
}
# WRONG MD5
elsif ( $md5 ne $$paranoic_inc{$module}{expected_md5} ){
# this is a die..
print "ERROR: $module at $$paranoic_inc{$module}{path} has [$md5] ".
"insetead of [$$paranoic_inc{$module}{expected_md5}]";
}
# UNKNOWN RESULT
else{
die "UNKNOWN error for $module at $$paranoic_inc{$module}{path} with md5 [$md5]"
}
}
print "\nAFTER I will use some hook to check md5 of modules loaded by the calling program\n";
if ( $^V ge '5.38.0'){
print "====> Perl $^V using \$^HOOK\n";
${^HOOK}{require__before} = sub {
my $filename = shift;
if ( exists $INC{$filename} ){
print " SKIP [$filename] already processed\n";
return;
}
print "Paranoically considering [$filename]\n";
};
}
else{
print "====> Perl $^V using \@INC\n";
unshift @INC, sub {
my ($self,$filename) = @_;
print "Paranoically considering [$filename]\n";
};
}
}
1;
####
warnings.pm /usr/local/lib/perl5/5.36.1/warnings.pm 7167a8489aafb9faddbbe48c6480f47c
strict.pm /usr/local/lib/perl5/5.36.1/strict.pm 31b6105d6dc1cde54154291b86c8b285
Digest/MD5.pm /usr/local/lib/perl5/5.36.1/x86_64-linux/Digest/MD5.pm d75a3d708ce93ad8d99fcbdefa2c8429
Digest/base.pm /usr/local/lib/perl5/5.36.1/Digest/base.pm b5de2696c583dfec247af39b45288735
XSLoader.pm /usr/local/lib/perl5/5.36.1/XSLoader.pm 74a2550b5b0731996c0c825930003013
Exporter.pm /usr/local/lib/perl5/5.36.1/Exporter.pm 9ac6b836ee45f6e08e5c8a84cee5e619
#
Paranoic.pm Paranoic.pm ALLOW
#
Cwd.pm /usr/local/lib/perl5/5.36.1/x86_64-linux/Cwd.pm 8f620379a0649ad32f14f1ce50b88bc0
File/Spec.pm /usr/local/lib/perl5/5.36.1/x86_64-linux/File/Spec.pm 7be482dda6bd364dd65e286b24cd8691
warnings/register.pm /usr/local/lib/perl5/5.36.1/warnings/register.pm 2d8f6ce093a2176b982c0e12c0194b3b
File/Spec/Unix.pm /usr/local/lib/perl5/5.36.1/x86_64-linux/File/Spec/Unix.pm bf252d457a243d20eabbd91292fcf3f4
constant.pm /usr/local/lib/perl5/5.36.1/constant.pm 56cde6eba0f667ab56196613df3933c1
####
use strict;
use warnings;
use List::Util;
####
BEFORE any hook I will check md5 of already loaded module:
OK Exporter.pm at /usr/local/lib/perl5/5.36.1/Exporter.pm has the expected md5: 9ac6b836ee45f6e08e5c8a84cee5e619
OK warnings.pm at /usr/local/lib/perl5/5.36.1/warnings.pm has the expected md5: 7167a8489aafb9faddbbe48c6480f47c
WHITELIST for Paranoic.pm at Paranoic.pm [f929845aba01aa4bf162a15cc254c123]
OK strict.pm at /usr/local/lib/perl5/5.36.1/strict.pm has the expected md5: 31b6105d6dc1cde54154291b86c8b285
OK Cwd.pm at /usr/local/lib/perl5/5.36.1/x86_64-linux/Cwd.pm has the expected md5: 8f620379a0649ad32f14f1ce50b88bc0
OK Digest/base.pm at /usr/local/lib/perl5/5.36.1/Digest/base.pm has the expected md5: b5de2696c583dfec247af39b45288735
OK constant.pm at /usr/local/lib/perl5/5.36.1/constant.pm has the expected md5: 56cde6eba0f667ab56196613df3933c1
OK File/Spec/Unix.pm at /usr/local/lib/perl5/5.36.1/x86_64-linux/File/Spec/Unix.pm has the expected md5: bf252d457a243d20eabbd91292fcf3f4
OK Digest/MD5.pm at /usr/local/lib/perl5/5.36.1/x86_64-linux/Digest/MD5.pm has the expected md5: d75a3d708ce93ad8d99fcbdefa2c8429
OK File/Spec.pm at /usr/local/lib/perl5/5.36.1/x86_64-linux/File/Spec.pm has the expected md5: 7be482dda6bd364dd65e286b24cd8691
OK warnings/register.pm at /usr/local/lib/perl5/5.36.1/warnings/register.pm has the expected md5: 2d8f6ce093a2176b982c0e12c0194b3b
OK XSLoader.pm at /usr/local/lib/perl5/5.36.1/XSLoader.pm has the expected md5: 74a2550b5b0731996c0c825930003013
AFTER I will use some hook to check md5 of modules loaded by the calling program
====> Perl v5.36.1 using @INC
Paranoic.pm here..
Paranoically considering [List/Util.pm]
####
AFTER I will use some hook to check md5 of modules loaded by the calling program
====> Perl v5.38.0 using $^HOOK
Paranoic.pm here..
SKIP [strict.pm] already processed
SKIP [warnings.pm] already processed
Paranoically considering [List/Util.pm]
SKIP [strict.pm] already processed
SKIP [warnings.pm] already processed
SKIP [strict.pm] already processed
SKIP [Exporter.pm] already processed
SKIP [XSLoader.pm] already processed