| Mail-SpamCannibal documentation | Contained in the Mail-SpamCannibal distribution. |
Mail::SpamCannibal::GoodPrivacy - PGP for spamcannibal mail
use Mail::SpamCannibal::GoodPrivacy; $plaintext = decrypt(\$hash); or -- defaults shown $plaintext = decrypt( Data => $data, ExeFile => '/usr/local/bin/pgp', KeyPath => '.pgp', Password => 'sometext', UserID => 'default userid', Version => '2.62', ); ($begin,$end) = is_pgp(\@lines,\$err); $nullchar = whiteclean(\@array); $outstrng = whiteclean($instring);
Mail::SpamCannibal::GoodPrivacy is a standardized wrapper around 'pgp2x', 'pgp6x', or 'gnupg' that provides encryption and decryption for IPTable::IPv4::DBTables::SpamCannibal.
Mail::SpamCannibal::GoodPrivacy has been tested using pgp-2.6.2g, pgp-6.5.8, and gpg-1.2.2 on RSA keys generated by pgp-2.6.2g which are included with this distribution.
Utilities to verify that a message has PGP encrypted content prior to decryption so that plain text messages are not inadvertently passed to the decrypt program;
Decrypt an encoded message.
input: a hash or hash pointer
return: plaintext or '' on error
%hash = (
Data => $data,
ExeFile => '/usr/local/bin/gpg',
KeyPath => './',
Password => 'sometext',
UserID => '',
Version => '',
);
Data: data to decrypt
ExeFile: location of executable
i.e. /usr/local/bin/pgp
/usr/local/bin/gpg
WARNING: use appropriate default
keyring names.
KeyPath: directory for keyrings
Password: password for decryption
UserID: Optional default user for decryption.
The user 'name' or keyID
i.e. 'test' or
E56C91B9 as displayed by
pgp -kv ./keyrings/secring.pgp
or
ENVGPGHOME=./keyrings gpg --list-secret-keys
Version: Version compliance (gpg only)
(none) for standard gpg,
2.6x and 6.x for pgp support
Test an array of lines to determine if they represent a valid PGP encrypted message.
input: pointer to array of lines,
[optional] pointer to
error return string
returns: () empty array on failure
or begin = pointer to -----BEGIN PGP
end = pointer to -----END
for the input array
$err will contain and empty string
on success or a text message
indicating the failure reason
not an array ref
signed cleartext
no BEGIN PGP
no blank line
no armor text
invalid armor
no END
i.e. if (@_ = is_pgp(\@lines)) {
($begin,$end) = @_;
} else {
# sorry, not a PGP message
}
See below:
Cleans trailing whitespace from a text string or an array of text lines.
If the input is an array pointer to an array of text lines, cleans the lines of trailing whitespace in place.
If the input is a string, returns a string with trailing whitespace removed.
input: array pointer or string returns: '' if input = ARRAY $outstring if the input was a string
Mail::SpamCannibal::ParseMessage and You must install at least one of the following on your system to use this module.
Recommend versions of freeware from:
http://www.pl.pgpi.org/versions/freeware.shtml
in the US: PGP 2.6.2g, the "rebel" version
ftp://sunsite.smc.univie.ac.at/pub/crypto/cypherpunks/pgp/pgp262/pgp262g.zip
outside US: PGP 2.6.3i
http://www.pgpi.org/
i.e. pgp263is.tar.gz + pgp263i.patch
or
outside US: PGP 6.5.8
http://www.pgpi.org/
i.e. 'pgpsrc658unix-gnu.tar.gz',
PGPcmdln_6.5.8.Lnx_FW.tar.gz,
or PGPcmdln_6.5.8.Lnx_FW.rpm.tar
2.6.2 rebel was the default used to
develop this module.
http://www.gnupg.org/
If you plan to user PGP 2.6x or 6.x compatibility modes and you are in a country where there are not patent restrictions, then you will also need to download:
ftp://ftp.gnupg.dk/pub/contrib-dk/idea.c.gz
and place it in the SRC/gnupg-1.x.x/cipher directory.
PGP 2.6.x pubring.pgp, secring.pgp PGP 6.5.8 pubring.pkr, secring.skr GnuPG pubring.gpg, secring.gpg
decrypt
is_pgp
whiteclean
Michael Robinton <michael@bizsystems.com>
Copyright 2003 - 2004, Michael Robinton <michael@bizsystems.com> 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.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
perl(1)
| Mail-SpamCannibal documentation | Contained in the Mail-SpamCannibal distribution. |
#!/usr/bin/perl package Mail::SpamCannibal::GoodPrivacy; use strict; #use diagnostics; use vars qw($VERSION @ISA @EXPORT_OK); $VERSION = do { my @r = (q$Revision: 0.03 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; use Mail::SpamCannibal::ParseMessage qw( array2string string2array ); require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw( decrypt is_pgp whiteclean );
## test the input array sub _testme { my $me = shift; # Data die "No data present\n" unless exists $me->{Data} && $me->{Data}; # ExeFile die "PGP exe file missing or not executable by effective UID\n" unless exists $me->{ExeFile} && $me->{ExeFile} && -e $me->{ExeFile} && -x $me->{ExeFile}; # KeyPath $_ = $me->{KeyPath} || './'; if ($_ eq '.') { $_ = './'; } elsif ($_ ne './' && $_ ne '/') { chop $_ if $_ =~ m|/$|; $_ = './'.$_ unless $_ =~ m|^\.*/|; } die "Key path $_ does not exist\n" unless -d $_; $me->{KeyPath} = $_; # UserID $me->{UserID} = '' unless $me->{UserID}; # Password $me->{Password} = '' unless $me->{Password}; # Version $me->{Version} = '' unless $me->{Version}; } sub decrypt { my $me = $_[0]; return '' unless $me; $me = {@_} if @_ > 1; _testme($me); my $data = ''; my $pgpcmd = '|'. $me->{ExeFile}; $pgpcmd .= ' -u '. $me->{UserID} if $me->{UserID}; if ($pgpcmd =~ m|/pgp[^/]*$|) { $pgpcmd .= ' -f +batchmode +force 2>/dev/null'; $ENV{PGPPATH} = $me->{KeyPath}; $ENV{PGPPASS} = $me->{Password}; } elsif( $pgpcmd =~ m|/gpg[^/]*$|) { $data .= $me->{Password}."\n"; $pgpcmd .= ' --pgp2' if $me->{Version} =~ /^2\./; $pgpcmd .= ' --pgp6' if $me->{Version} =~ /^6\./; $pgpcmd .= ' --decrypt --batch --passphrase-fd 0 2>/dev/null'; $ENV{GNUPGHOME} = $me->{KeyPath}; } else { die "could not find pgp or gpg executable\n"; } $data .= $me->{Data}; my $rv = ''; my $pid = open(FROMCHILD, '-|'); if($pid) { local $/; $rv = <FROMCHILD>; close FROMCHILD || ($rv = ''); # kid exited } else { # child open(PGP,$pgpcmd) or die "could not exec pgpcmd\n"; $|++; print PGP $data; close PGP; exit; } waitpid $pid,0; $ENV{PGPPASS} = ''; return $rv; }
# # 1) find a begin statement: -----BEGIN PGP # 2) that is not clear signed: -----BEGIN PGP SIGN # 3) ignore any number lines: comment (not case sensitive) # starting like this version (not case sensitive # 4) find one and only one: (blank line) # 5) find 1 or more rad64: lines # 6) find and end statement: -----END sub is_pgp { my($ap,$ep) = @_; if (ref $ep) { $$ep = ''; } else { undef $ep; } unless (ref $ap) { $$ep = 'not an array ref' if $ep; return (); } my $TOPMSG = '-----BEGIN PGP'; # beginning of PGP my $SIGMSG = $TOPMSG . ' SIGNED'; # clear signed my $notRAD64 = "[^a-zA-Z0-9/\+\=]"; my $END = '-----END'; my $noblank = 1; my $noarmor = 1; my $ptr; foreach(0..$#{$ap}) { unless (defined $ptr) { # begin found?? next unless $ap->[$_] =~ /$TOPMSG/o; # if SIGNED message found, this is cleartext, punt! if ($ap->[$_] =~ /$SIGMSG/o) { $ptr = -1; last; } $ptr = $_; # defined, pointer to message start } elsif ($noblank) { # drop comments, check for 1 blank line next if $ap->[$_] =~ /^comment/i || $ap->[$_] =~ /^version/i; # skip comments last if $ap->[$_] =~ /\S/; # PUNT, not blank line $noblank = undef; } elsif ($noarmor) { # must find ascii armor last if $ap->[$_] !~ /\S/ || $ap->[$_] =~ m|$notRAD64|o ; # PUNT, not ascii armor $noarmor = 0; } else { # searching for end return ($ptr,$_) if $ap->[$_] =~ /^$END/o; # FOUND end, GOOD exit if ($ap->[$_] !~ /\S/ || $ap->[$_] =~ m|$notRAD64|o) { # PUNT, not ascii armor; $noarmor = 2; last; } } } if ($ep) { unless (defined $ptr) { $$ep = 'no BEGIN'; } elsif ($ptr < 0) { $$ep = 'signed cleartext'; } elsif ($noblank) { $$ep = 'no blank line'; } elsif ($noarmor == 1) { $$ep = 'no armor text' } elsif ($noarmor == 2) { $$ep = 'invalid armor' } else { $$ep = 'no END'; } } return (); # did not find PGP message }
sub _whiteAcln { my $ap = shift; foreach(0..$#{$ap}) { $ap->[$_] =~ s/\s+$//g; } } sub whiteclean($) { my $thing = shift; my $rv = ''; if (ref $thing eq 'ARRAY') { _whiteAcln($thing); return ''; } @_ = split(/\n/,$thing); _whiteAcln(\@_); array2string(\@_); } 1; __END__
1;