#!/usr/bin/perl
# <pre>
#
# filter for pine 3.93 and newer for de/encoding pgp mails
# This use a feature in Pine, the _DATAFILE_, a file which is
# created by pine for storing information by filters between
# two runs. papp stores the cleartext Passphrase (!) if You
# decide so. The _DATAFILE_ is mode 600, but this is only
# a small protection. But You get asked to give away your passphrase
# only once per pine session. And of course, You can always decide
# again, without loosing the ability of reading/sending pgp-enhanced
# mail
sub usage {
die "USAGE: $0 [-metoo] [-dontask] [encode] [-passfile <file>] [recipients]
OPTIONS: -metoo Enables +EncryptToSelf=on
-dontask Default is ask every time if You want to use PGP
-encode Default is encoding of mail from STDIN
-passfile <file> <file> is normally the _DATAFILE_
simply, don't use this Option, if you don't want it...
Everything else is taken as a list of recipients
";
}
# use this with the following in your .pinerc:
# display-filters=_BEGINNING("-----BEGIN PGP")_ /path/to/papp
# sending-filters = /path/to/papp encode _RECIPIENTS_
#
# Or similar, if you are crazy enough to store the passphrase:
#
# display-filters=_BEGINNING("-----BEGIN PGP")_ /path/to/papp -passfile _DATAFILE_
# sending-filters = /path/to/papp -encode -passfile _DATAFILE_ _RECIPIENTS_
#
# And DONT Forget to have a look at the source!
#
# History:
#
# $Id: papp,v 1.3 1997/03/16 08:19:43 aldo Exp $
#
# 21.03.96 Roland Rosenfeld <
[email protected]>
# 23.03.96 $TMPFILE moved to $PGPPATH.
# 17.05.96 total rewrite in perl; many new features
# 27.08.96 corrected code for adding new keys
# 19.11.96 ask whether to run pgp before running it
# 25.11.96 some compatibility fixes
# x-mas '96 Aldo Valente: Added option "-passfile <file>"
# to make it cooperative with my script, which is able
# to "remember" a given passphrase. This option reads
# the cleartext passphrase from <file> (yuck!)
# You can always get Rolands Original
# at
http://www.rhein.de/~roland/
#
[email protected];
http://www.rhein.de/~aldo/
#
# feb '97 Aldo: moving my bash-script to /dev/null and merging
# functionality into Rolands perlscript, which was
# a display-filter before.
# So the new features are sending of pgpified mails
# and the option to "remember" a passphrase.
# changed the Name from pgpdecode to papp (Pine And PgP)
# Mar '97 Aldo:BUGFIX:
[email protected]
# told me that PAPP would not work if the recipients List
# contains a '-'. PAPP thinks of such mailaddresses as an
# (unrecognized) option ans complains. Stupid me. Fixed.
umask 077;
$stty="/bin/stty"; # where to find a stty, which supports -cbreak
$tmpdir = $ENV{'PGPPATH'} || ""; # this offers more security than /tmp
if ($tmpdir =~ /^$/) {
$tmpdir = $ENV{'HOME'}; # if not set $PGPPATH try $HOME as tmp-dir
}
# just to make some things really clear
$PASS="";
$dontask=undef;
$encode=undef;
$zaphod='zaphod beeblebrox for president'; # taken from pgpdoc2.txt
$metoo=undef;
# Processing of Arguments
while ($ARG = shift(@ARGV)) {
if ($ARG =~ /^-metoo$/i) { $metoo='+EncryptToSelf=on';next;}
if ($ARG =~ /^-dontask$/i) { $dontask='true'; next; }
if ($ARG =~ /^-passfile$/i) { &read_pass(shift(@ARGV)) || &get_pass; next;}
if ($ARG =~ /^-encode$/) { $encode='true';next;}
if (($ARG =~ /^--?h(elp)?$/) or ($ARG =~ /^-\?$/)) {&usage}
# The above now matches a rather minimalistic set of Users cry for help
# The code under this lines is false and stupid.
# Thank you, Ronald for submitting the bug .
# if ($ARG =~ /-.*/) {&usage}
$recipients .= $ARG;
}
$pgpout = "$tmpdir/pgpout$$";
$pgperr = "$tmpdir/pgperr$$";
sub ask_if {
# this is a comfortable way to ask random Yes or No questions
print STDERR $_[0];
system("$stty cbreak < /dev/tty"); # read char without pressing RETURN
open (IN, "</dev/tty");
$return=getc(IN); # read exactly one keystroke from tty
close IN;
system("$stty -cbreak < /dev/tty"); # reset tty to normal
print STDERR "\n";
return 1 if $return =~ /y/i;
undef;
}
sub decode {
if (! $dontask) { # option -dontask given?
if (! ask_if('Message uses PGP, do you wish to run PGP on it? [N/y]')) {
# do not run pgp but print mail to stdout
while (<>) {
print;
}
exit;
}
# when we did not exit, user wants to run pgp now.
}
#
# Now let us start the real decoder
#
$pgpfound=1;
while ($pgpfound) {
while (($_=<>) && !(/^-----BEGIN PGP/)) {
print $_;
}
if (/^-----BEGIN PGP/) {
$pgpfound=1;
} else {
$pgpfound=0;
}
if (/^-----BEGIN PGP PUBLIC KEY BLOCK-----$/) {
$pgpkeyblock .= $_;
while (($_=<>) && !(/^-----END PGP PUBLIC KEY BLOCK-----$/)) {
$pgpkeyblock .= $_;
}
$pgpkeyblock .= $_;
open(SAVEOUT, ">&STDOUT");
open(SAVEERR, ">&STDERR");
open(STDOUT, ">$pgpout") || &abort("Can't redirect stdout to $pgpout");
open(STDERR, "| tee $pgperr 1>&2") || &abort("Can't redirect stderr");
open(PGP, "|pgp -kaf") || &abort("Can't execute pgp");
print PGP $pgpkeyblock;
close(PGP);
close(STDOUT);
close(STDERR);
open(STDOUT, ">&SAVEOUT");
open(STDERR, ">&SAVEERR");
open(PGPERR, "<$pgperr") || &abort("Can't read $pgperr");
while (<PGPERR>) {
print "| $_";
}
close(PGPERR);
unlink $pgperr;
open(PGPOUT, "<$pgpout") || &abort("Can't read $pgpout");
while (<PGPOUT>) {
print ": $_";
}
close(PGPOUT);
unlink $pgpout;
} elsif (/^-----BEGIN PGP( SIGNED)? MESSAGE-----$/) {
$pgpmessage .= $_;
$pgpheader = $_;
while (($_=<>) && !(/^-----END PGP (MESSAGE|SIGNATURE)-----$/)) {
$pgpmessage .= $_;
}
$pgpmessage .= $_;
open(SAVEOUT, ">&STDOUT");
open(SAVEERR, ">&STDERR");
open(STDOUT, ">$pgpout") || &abort("Can't redirect stdout");
open(STDERR, "| tee $pgperr 1>&2") || &abort("Can't redirect stderr");
open(PGP, "|pgp -z \"$PASS\"") || &abort("Can't execute pgp");
print PGP $pgpmessage;
close(PGP);
close(STDOUT);
close(STDERR);
open(STDOUT, ">&SAVEOUT");
open(STDERR, ">&SAVEERR");
open(PGPERR, "<$pgperr") || &abort("Can't read $pgperr");
while (<PGPERR>) {
print "| $_";
}
close(PGPERR);
unlink $pgperr;
print "|\n| $pgpheader|\n";
open(PGPOUT, "<$pgpout") || &abort("Can't read $pgpout");
while (<PGPOUT>) {
print $_;
}
close(PGPOUT);
unlink $pgpout;
$pgpheader =~ s/BEGIN/END/;
print "\n|\n| $pgpheader|\n\n";
}
}
}
sub abort {
local ($message) = @_;
unlink $pgpout;
unlink $pgperr;
die $message
}
sub encode {
$options='fat';
ask_if("Encryption ? [N/y] ") and $options .='e';
ask_if("Signing ? [N/y] ") and $options .='s';
open(PGP,"|pgp $recipients +clearsig=on -$options -z \"$PASS\" \"$metoo\"");
while (<>) {
print PGP;
}
close PGP;
}
sub check_pass {
# As the name of the sub says
`echo a |pgp -saft +batchmode -z "$_[0]" >/dev/null 2>&1`;
if ($?) { return 0}
1;
}
sub read_pass {
# We're trying to read a given passphrase
$passfile = $_[0];
# perhaps in the Environment ?
return 1 if check_pass("$ENV{'PGPPASS'}");
# Some paranoia checks
# We refuse to work if the file given on the commandline isn't a normal file
return 2 unless -f $passfile;
# either if the mode is different from 600
return 3 unless 600 == sprintf "%lo", (stat _)[2] & 07777 ;
# or has not the right owner
return 4 unless -o $passfile;
# or has another link
return 5 unless (stat _)[3] == 1;
open(PASS,"<$passfile");
$PASS = <PASS>;
close (PASS);
chomp $PASS;
# if this occur, we already asked for the phrase
return 6 if $PASS eq $zaphod;
return 7 unless $PASS eq '';
# We may only ask for a phrase, if nothing is in this file
return 0;
}
sub get_pass {
# Only once per run, we ask to save a passphrase
$PASS=$zaphod;
open(PASS,">$passfile");
if (ask_if('You really want to give Your Passphrase [N/y] ')) {
print STDERR "Cursor will not move. Hit [RETURN] after the passphrase";
# quiet...
system("$stty -echo < /dev/tty");
open(IN,"</dev/tty");
$PASS = <IN>;
chomp ($PASS);
system("$stty echo < /dev/tty");
print STDERR "\n";
$PASS=$zaphod unless (check_pass("$PASS"));
}
print PASS "$PASS";
close PASS;
}
# Main ;-)
if ("$encode") {&encode;}
else {&decode;}