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