#!/usr/bin/perl #
# # 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] [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 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 # 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 " # to make it cooperative with my script, which is able # to "remember" a given passphrase. This option reads # the cleartext passphrase from (yuck!) # You can always get Rolands Original # at http://www.rhein.de/~roland/ # aldo@rhein.de; 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: Ronald.Wahl@Informatik.TU-Chemnitz.DE # 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, ") { 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 ( ) { print "| $_"; } close(PGPERR); unlink $pgperr; open(PGPOUT, "<$pgpout") || &abort("Can't read $pgpout"); while ( ) { 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 ( ) { print "| $_"; } close(PGPERR); unlink $pgperr; print "|\n| $pgpheader|\n"; open(PGPOUT, "<$pgpout") || &abort("Can't read $pgpout"); while ( ) { 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 = ; 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,"; 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;}