Your IP : 216.73.217.17


Current Path : /usr/local/assp/
Upload File :
Current File : //usr/local/assp/getpdfsha.pl

#!/usr/local/bin/perl

=head

           ************************************************
           *                A   S   S   P                 *
           ************************************************
           *   perl AntiSpam SMTP Proxy professional V2   *
           ************************************************
           * Auxiliary Support and Service Proxy for SMTP *
           ************************************************

          (c) Thomas Eckardt since 2008 under the terms of the GPL

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation;

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License (http://www.gnu.org/licenses/) for more details.

 ASSP founded and developed to Version 1.0.12 by John Hanna
 ASSP development since 1.0.12 to 1.2.0 by John Calvi
 ASSP development since 1.2.0 to 1.9.9 by Fritz Borgstedt (passed away in 2014 - we will remember you for a long time!)
 ASSP development since 1.4.5 to 1.10.0 by Thomas Eckardt (version 1.x is outdated and is no longer supported)

 ASSP V2 pro development since 2.0.0 by Thomas Eckardt

 The latest released version is available at:
 http://downloads.sourceforge.net/projects/assp/files/ASSP%20V2%20multithreading/autoupdate/assp.pl.gz

 The latest development version is available at:
 http://sourceforge.net/p/assp/svn/HEAD/tree/assp2/trunk/assp.pl.gz?format=raw

 getpdfsha.pl - calculate the SHA256_HEX HASH for all Certificates, Signatures and JavaScripts and write them to STDOUT
 The output can be used in assp (ASSP_AFC.pm) to skip attachment processing for well known good PDF files (origins).
 So you'll be able to block all PDF attachment, which contains executable code - except those are well known good.
 
 (c) Thomas Eckardt since 2019 under the terms of the GPL
 
 usage:
 perl getpdfsha.pl FILENAME

=cut

package main;

use strict;
use CAM::PDF();
use Digest::SHA();
use Getopt::Long;

our $VERSION = '1.00';

our @PDFsum;
our %PDFtags = (          # PDF objects to analyze
#  'StreamData' => '4-StreamData ',
    'JS' =>         '3-JavaScript ',
    'Sig' =>        '2-Signature  ',
    'Cert' =>       '1-Certificate',
);

if (@ARGV != 1) {  # the file name is needed
   usage();
   exit;
}

getPDFSum($ARGV[0]) || (usage() && exit);


sub usage {
    print "usage:\nperl getpdfsha filename\n";
    return 1;
}

sub getPDFSum {
   my $pdf = shift;

   my $doc = CAM::PDF->new($pdf , {'prompt_for_password' => 0, 'fault_tolerant' => 1}) || do {print "$CAM::PDF::errstr\n\n"; return 0;};

   foreach my $objnum (keys %{$doc->{xref}}) {
       my $objnode = $doc->dereference($objnum);
       denode($objnode);
   }
   @PDFsum = sort {$PDFtags{$a->[0]} cmp $PDFtags{$b->[0]}} @PDFsum;
   print "\n";
   for (@PDFsum) {
       print "$_->[1] # $pdf, $PDFtags{$_->[0]}, $_->[2]\n";
   }
   return 1;
}

sub denode {
    my $node = shift;
    if (ref($node) eq 'HASH') {
        while( my ($k,$v) = each(%{$node})) {
            next if (! exists $PDFtags{$k});
            my @val = denode($v);
            push @PDFsum, [ $k, @val] if $val[1];
        }
    } elsif (ref($node) eq 'ARRAY') {
        my @res;
        my $l = 0;
        for (@$node) {
            my @val = denode($_);
            next unless $val[0] && $val[1];
            push @res, $val[0];
            $l += $val[1];
        }
        return if $l == 0 || length("@res") == 0;
        return (uc(Digest::SHA::sha256_hex(join('',@res))) , $l);
    } elsif (ref($node)) {
        if (exists $node->{value}) {
#            $doc->decodeOne($node->{value}) if (ref($node->{value}) ne 'ARRAY' && $node->{value}->{type} eq 'dictionary');
            return denode($node->{value});
        } else {
            return;
        }
    } else {
        return (uc(Digest::SHA::sha256_hex($node)) , length($node));
    }
    return;
}