#!/usr/bin/perl
### Copyright (C) 2004 Yves Agostini  
### 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; either version 2 of the License, or
### (at your option) any later version.
###
### 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 for more details.
###
### Contact the copyright holder for commercial licensing terms
### if you wish to incorporate this code into non-GPL software.
###
#
# <agostini@univ-metz.fr>
# $Id: testzip.pl, v1.01 2004-03-10
# 
# Perl plugin for "the great" John D. Hardin impsec sanitizer 
# http://www.impsec.org/email-tools/procmail-security.html
# 
# List files in zip attachement, return DISCARD if one file is include in 
# $POISONED_EXECUTABLES or return MANGLE if there is only files like 
# *.exe, *.scr, ...
#
# CHANGES
# v1.0  : First release
# V1.01 : Only changes in procmailrc
# 	- add "$MANGLE_EXTENSIONS|zip"
# 	- remove attachement test
# 
# NOTES
#  Requires perl, mktemp, MIME::Explode, unzip
# 
# INVOCATION
#
#  With a procmail rule insert before
#  INCLUDERC=/etc/procmail/html-trap.procmail
#
#  Procmail rule :
# ----------uncomment-and--cut-----------
# :0
# * < 600000
# * ^Content-Type:.*multipart/mixed;
# {
# RES=
#
# :0 B
# * ^Content-Transfer-Encoding: base64
# * 9876543210^1 ^Content-(Type|Disposition):.*name *= *"?[-_0-9A-Za-z]+\.zip"?
# {
#  :0 HB W
#  RES=|/etc/procmail/testzip.pl
#
#  :0 hfi
#  * RES ?? ^DISCARD$
#  | formail -A "X-Content-Security: [$HOST] NOTIFY" \
#            -A "X-Content-Security: [$HOST] DISCARD" \
#            -A "X-Content-Security: [$HOST] REPORT: Trapped poisoned document in zip attachement"
#
#  :0
#  * RES ?? ^MANGLE$
#  {
#  MANGLE_EXTENSIONS="$MANGLE_EXTENSIONS|zip"
#  }
#
# }
#}
# -------------cut--------------
#
# Use CPAN to install MIME::Explode
#  perl -MCPAN -e 'install MIME::Explode'
#  apt-get install unzip (for debian)

#use strict;
use MIME::Explode;

my $destd = `mktemp -d /tmp/zipmailchk.XXXXXX`;

chomp($destd);

my $explode = MIME::Explode->new(
    output_dir         => $destd,
    mkdir              => 0755,
    decode_subject     => 0,
    check_content_type => 0,
    exclude_types      => ["image/gif", "image/jpeg", "image/png","text/plain","text/html"],
  );

my $headers = $explode->parse(\*STDIN);

my @res=`cd $destd; ls *.zip 2>/dev/null`;

my @files;
foreach my $l (@res) {
my @unzip=`unzip -l $destd/$l`;
    foreach my $lunzip (@unzip){
            my ($a,$b,$c,$d,$e,$f)=split(' ',$lunzip);
            push (@files,"$d$e$f") if ($d && $d=~/\.(\w+)$/g);
    }
}
#print @files;

`/bin/rm -rf $destd`;
my $RET;
foreach my $filen (@files) {
  if (open(POISONED, $ENV{"POISONED_EXECUTABLES"})) {
    my $psn_spec="";
    warn " Checking document \"$filen\" in zip attachement for poisoning.\n";
    while (chomp($psn_spec = <POISONED>)) {
         $psn_spec =~ s/^\s+//g;
         $psn_spec =~ s/\s.*$//g;
         next unless $psn_spec;
         $psn_spec =~ s/([^\\])\./$1\\./g;
         $psn_spec =~ s/\*/.*/g;
         $psn_spec =~ s/([^\(])\?/$1./g;
         $psn_spec .= "(\\?=)?\$" unless $psn_spec =~ /\$/;
         warn "  Checking against \"$psn_spec\"\n" if $ENV{"DEBUG"};
         if ($filen =~ /^${psn_spec}/i  && $psn_spec!~/^\?\\\.exe/) {
             warn " Trapped poisoned document \"$filen\" in zip attachement.\n";
             $RET= ($psn_spec=~/^\.\*\\\.\w/g) ? "MANGLE":"DISCARD";
             last if ($RET eq "DISCARD");
          }
     }
     close(POISONED);
   }
}
print "$RET";
