#!/usr/bin/perl -w # MHOnArc plugin for managing PKCS#7 signed data. # ©-IDEALX 2001. May be freely used and distributed under the # terms of the GNU General Public License v2. package IDX::MHOnArcAddOns; use strict; use Fcntl qw(O_WRONLY O_CREAT O_EXCL); use Errno; sub filter_pkcs7_mime { my (undef, undef, $bodysymbol, $isdecoded, $args)=@_; local *FULLSIG; local *OPENSSL; my $bodyref=*{$bodysymbol}{SCALAR}; # We keep the signature around my $sigfilepfx=$mhonarc::OUTDIR; # Fixes silly warning $sigfilepfx="pkcs7sig-$$-".time(); my ($sigfile,$fullsigfile); for(my $i=0; $i<1000; $i++) { # FIXME: not NFS resistant. $!=0; $fullsigfile=$mhonarc::OUTDIR."/$sigfilepfx-$i.bin"; sysopen(FULLSIG,$fullsigfile, O_WRONLY|O_CREAT|O_EXCL); $! && do { next if $!{EEXIST}; last; }; $sigfile="$sigfilepfx-$i.bin"; last; }; die "Could not open a file beginning with name $sigfilepfx" if (!defined $sigfile); print FULLSIG $$bodyref; close(FULLSIG); my $ispem=scalar( $$bodyref =~ m/^-*BEGIN PKCS7/ ); # FIXME: configurable path for openssl ? open(OPENSSL,"openssl smime -verify -noverify ". ($ispem? "-inform pem ": "-inform der "). "-in $fullsigfile 2>/dev/null |"); my $body=join('',); close(OPENSSL); # FIXME: should check return code of openssl so as to do something # with non-extractible messages. # OK now we have some kind of bogus MIME document in $headersandtext. # We must recurse through MHOnArc's innards (which are quite well # thought, fortunately) to get an HTML vision of same. my %headfields; my %junk; my $header=readmail::MAILread_header(\$body,\%headfields, {}); my ($text,@files)=readmail::MAILread_body ($header,$body, ($headfields{"content-type"} || "text/plain"), ($headfields{"content-transfer-encoding"} || "US-ASCII")); return ( ("$text\n"."
".# $$bodyref."
". Data::Dumper::Dumper(\@_). qq{
Original signed message (PKCS#7, }. ($ispem ? "PEM format": "DER format").")"), $fullsigfile,@files); # FIXME: shall we not return relative path ($sigfile instead of # $fullsigfile)? } ######################## TEST SUITE ############################# eval join('',) || die "$@" unless caller(); __END__ use Test; BEGIN { plan tests => 4 }; #### FIRST TEST: openssl availability, DER recoding use vars qw($pkcs7pem $pkcs7der); $pkcs7pem=<); close(RECODED); unlink($tmpfile); open(OPENSSL,"| openssl pkcs7 -inform der -out $tmpfile"); print OPENSSL $pkcs7der; close(OPENSSL); open(RECODED,"<$tmpfile"); my $pkcs7pemagain=join('',); close(RECODED); unlink($tmpfile); ok($pkcs7pemagain eq $pkcs7pem); ########## Test 2: actually doing something # Copy-pasted from MHOnArc 2.4.9 no strict; sub readmail::MAILread_header { local(*mesg, *fields, *l2o) = @_; local($label, $olabel, $value, $tmp, $header); $header = ''; %fields = (); %l2o = (); $label = ''; ## Read a line at a time. while ($mesg =~ s/^([^\n]*\n)//) { $tmp = $1; # Save off match last if $tmp =~ /^[\r]?$/; # Done if blank line $header .= $tmp; # Store original text $tmp =~ s/[\r\n]//g; # Delete eol characters ## Decode text if requested $tmp = &MAILdecode_1522_str($tmp,1) if $DecodeHeader; ## Check for continuation of a field if ($tmp =~ s/^\s//) { $fields{$label} .= $tmp if $label; next; } ## Separate head from field text if ($tmp =~ /^([^:\s]+):\s*([\s\S]*)$/) { ($olabel, $value) = ($1, $2); ($label = $olabel) =~ tr/A-Z/a-z/; $l2o{$label} = $olabel; if ($fields{$label}) { $fields{$label} .= $FieldSep . $value; } else { $fields{$label} = $value; } } } $header; } use strict; # This one is bogus. sub readmail::MAILread_body { my ($header, $body, $ctypeArg, $encodingArg, $inaltArg) = @_; return ("
$body
"); } $mhonarc::OUTDIR="/tmp"; use vars qw(%header); %header=("from" => [ "me" ], "to" => [ "you" ]); my ($text,$sigfile)= IDX::MHOnArcAddOns::filter_pkcs7_mime("From: me\nTo: you\n",*header,*pkcs7pem,1,""); die if (!defined $sigfile); ok(`cat $sigfile` eq $pkcs7pem); ok($text =~ m/test/); # This is the original contents of the message. ok($text !~ m/Content/); # Headers should have been wiped off by now my ($text2,$sigfile2)= IDX::MHOnArcAddOns::filter_pkcs7_mime("From: me\nTo: you\n",*header,*pkcs7der,1,""); die if (!defined $sigfile); ok($sigfile ne $sigfile2); ok(`cat $sigfile2` eq $pkcs7der); unlink($sigfile); unlink($sigfile2); ok($text2 =~ m/test/); # This is the original contents of the message. ok($text2 !~ m/Content/); # Headers should have been wiped off by now