1994-11-30 - Elm and premail (long)

Header Data

From: “John A. Perry” <perry@jpunix.com>
To: cypherpunks@toad.com
Message Hash: 9057f3b233f473cad3371656c841fa05f79346caa4ef1eca4f361983e776d245
Message ID: <199411300324.VAA14320@jpunix.com>
Reply To: N/A
UTC Datetime: 1994-11-30 03:24:54 UTC
Raw Date: Tue, 29 Nov 94 19:24:54 PST

Raw message

From: "John A. Perry" <perry@jpunix.com>
Date: Tue, 29 Nov 94 19:24:54 PST
To: cypherpunks@toad.com
Subject: Elm and premail (long)
Message-ID: <199411300324.VAA14320@jpunix.com>
MIME-Version: 1.0
Content-Type: text/plain


-----BEGIN PGP SIGNED MESSAGE-----


	I have just finished integrating premail 0.30 with Elm on
jpunix.com. Since there have been some questions about how to do this type
of thing, I thought I'd give a blow-by-blow description of what I did and
the pro's, con's and alternatives to what I did. 

1) I installed premail as a wedge to the sendmail daemon. In other words,
per Raph Levin's instructions in his README file, I renamed sendmail to
something else and then renamed premail to sendmail and have it pointing
to the renamed sendmail. I realize this requires system admin privs and is
a big step to take, but I have testing premail working as the sendmail
program with great success and at this point I have no qualms about
premail/sendmail being one in the same. 

2) I created the ~/.premailrc file in my home directory per Raph's README
file. There is an option at the bottom to create aliases and that is what
I did at first. Then, I discovered that the alias database created by Elm
is compatible with premail!! 

3) I edited ~/.elm/aliases.text to make changes similar to the following: 

The alias 
raph = Levin; Raph = raph@kiwi.cs.berkeley.edu
to
raph = Levin; Raph = raph@kiwi.cs.berkeley.edu^key=raph@cs.berkeley.edu

	Elm doesn't seem to mind this new alias structure and premail
parses it just fine!  I could have added a ^chain=3 also, but I decided
that I may not want to email Raph through a set of remailers every time. I
decided I would add the extra header during message creation. More on this
later. 

	What this does is that from now on, whenever I send email to 
Raph, it will automatically be encrypted with his public key with no 
further intervention on my part! When I want to chain the message through 
some remailers, I just take the H)eaders option from the Elm pre-send 
menu and add a header line:

Chain: 3

	This causes the message to be chaine through three random 
remailers before it gets to Raph.

	I also added two addition Perl scripts to Elm to help in the 
creation of encrypted messages for people NOT in my alias file, signing 
messages, and reading PGP encrypted messages that are not MIME compliant.
These scripts are mailpgp and morepgp. These Perl scripts were published 
with version 2.3 of PGP but work fine with 2.4 and up. In Elm, I went to 
the options menu and replaced the default editor with mailpgp as well as 
the visual editor. I also replaced the default builtin+ display parameter 
with morepgp. These two Perl scripts are listed at the end of this 
message. The mailpgp script will allow you to encrypt and sign messages 
right before they are sent. The morepgp script will decrypt/verify 
incoming messages on the fly. The really nice benefit of these scripts is 
that you can reply to cleartext version of PGP encrypted messages.

	With the combination of these Perl scripts, Elm (or Pine for that 
matter) can be turned into an encrypted mail handler with a minimum of fuss.

morepgp:

#!/usr/local/bin/perl
# -*- Perl -*-

# written by jason steiner, jsteiner@anwsun.phya.utoledo.edu, Jan 1993
#
# if you use or make improvements to this program i would appreciate
# copies of your modifications & your PGP public key.
#

# Modified by Greg Spencer, greg@graphics.cornell.edu, May 1994
# Mostly just cleaned up things and added stuff like automatic
# addition and detection (and ignoring) of keys to be added to keyring,
# and signal catching, as well as environment variable control of
# most site-specific stuff.
# 
# Must set the following environment variable:
# 
# PGPCOMMAND set to the pgp decryption command
# 
# PAGER set to the desired pager command
#
# NOTE that this program NEVER writes sensitive data to a disk file.
# it will only slurp it into memory, so if you have a HUGE file, you might
# have problems.

# setup some variables
($pgpcommand = $ENV{'PGPCOMMAND'}) || ($pgpcommand = "/usr/local/bin/pgp");

# just used for tmpfile names...
($logname = $ENV{'LOGNAME'}) || ($logname = "nobody");

# ($pager = $ENV{'PAGER'}) || ($pager="/usr/local/bin/less -i -n -s -S -c -M");
($pager = $ENV{'PAGER'}) || ($pager="/usr/bin/more -c");

$|=1;
$topgp = 0;
$tokey = 0;
$pgpused = 0;
($tmpdir = $ENV{'TMPDIR'}) || ($tmpdir = "/tmp");

#temporary file name
$tmpfile  = "${tmpdir}/.pgp1.$logname.$$";
$tmpfile2 = "${tmpdir}/.pgp2.$logname.$$";

# trap signals so we do not leave
# garbage around
sub catcher {
	local ($sig) = @_;

	print "Caught a SIG$sig -- exiting\n";
	close (TMPFILE);
	close (OUTPUT);
	close (PAGER);
	unlink ($tmpfile);
	unlink ($tmpfile2);
}

$SIG{'INT'}  = 'catcher';
$SIG{'QUIT'} = 'catcher';
$SIG{'HUP'}  = 'catcher';
$SIG{'KILL'} = 'catcher';

# make sure nobody can read stuff
umask 077;

# prepare a data area
@tmpdata = ();
@newkeys = ();

while (<>) {
	if (!$topgp && m/^-----BEGIN PGP .*-----/ && !m/^-----BEGIN PGP PUBLIC KEY BLOCK-----/) {
		$topgp = 1;
		$pgpused = 1;
		unlink ($tmpfile);
		open (TMPFILE, ">$tmpfile") || (unlink ($tmpfile) && die "Cannot open $tmpfile for output.\n");
	}
	if (!$topgp) {
		push(@tmpdata, $_);
	} 
	if ((!$tokey) && (m/^-----BEGIN PGP PUBLIC KEY BLOCK-----/)) {
		$contains_keys = 1;
		$tokey = 1;
	}
	if ($tokey) {
		push (@newkeys, $_);
		if (m/^-----END PGP PUBLIC KEY BLOCK-----/) {
			$tokey = 0;
		}
	}
	if ($topgp) {
		print TMPFILE $_; # OK to write this to a file -- it is encrypted!
		if (m/^-----END PGP .*-----/ && !m/^-----END PGP PUBLIC KEY BLOCK-----/) {
			$topgp = 0;
			close TMPFILE;
			open (CLEAR, "$pgpcommand -f < $tmpfile |") || 
			(unlink($tmpfile) && die "Cannot open pipe to PGP.\n");
			$blocktype = $_;
			$blocktype =~s/^-----END (PGP .*)-----/$1/;
			$blocktype =~s/PGP MESSAGE/DECRYPTED MESSAGE/;
			$blocktype =~s/PGP SIGNATURE/SIGNED MESSAGE/;
			chop ($blocktype);
			push (@tmpdata, "-----BEGIN $blocktype-----\n");
			while (<CLEAR>) {
				push (@tmpdata, $_);
				if ((!$tokey) && (m/^-----BEGIN PGP PUBLIC KEY BLOCK-----/)) {
					$contains_keys = 1;
					$tokey = 1;
				}
				if ($tokey) {
					push (@newkeys, $_);
					if (m/^-----END PGP PUBLIC KEY BLOCK-----/) {
						$tokey = 0;
					}
				}
			}
			close CLEAR;
			print STDERR "\n";
			unlink ($tmpfile);
			push (@tmpdata, "-----END $blocktype-----\n");
		}
	}
}

select (STDIN);  $|=1;
select (STDERR); $|=1;
select (STDOUT); $|=1;

# This handles things if we found keys that need
# adding to our keyring
# note that we are only writing the KEYS to the file.
if ($contains_keys) { 
	print STDERR "PGP Keys found, attempting to add...\n";

	open (TMPFILE2, ">$tmpfile2");
	foreach $_ (@newkeys) {
		print TMPFILE2;
	}
	close (TMPFILE2);

	# strange things happen if we do not 
	# read/write directly from /dev/tty (perl bug??)
	system ("$pgpcommand -ka $tmpfile2 >/dev/tty </dev/tty 2>&1");
	unlink ($tmpfile2);	# get rid of it asap
	$pgpused = 1;
}

# copy the contents of @tmpdata to the pager we want to use.
open (PAGER, "|$pager") || (unlink ($tmpfile1) && die "Cannot open pipe to $pager.\n");

# do "press any key to continue"
# only if we had some output from PGP
# (like a verified signature)
# again with the /dev/tty thing (weird!)
if ($pgpused) {
	$q='';
	open (TTY, "</dev/tty")	|| (unlink ($tmpfile1) && die "Couldn't open /dev/tty\n");
	select(TTY); $| = 1;
	print STDERR "Press any key to continue...\n";
	$q = getc (TTY);
	select (STDIN);
}

# output the decoded thing to the pager
foreach $_ (@tmpdata) {
	print PAGER;
}
@tmpdata = ();

close OUTPUT;
close PAGER;

# cleanup
unlink ($tmpfile);

mailpgp:

#!/usr/local/bin/perl
# -*- Perl -*-

# written by jason steiner, jsteiner@anwsun.phya.utoledo.edu, Jan 1993
#
# if you use or make improvements to this program i would appreciate
# copies of your modifications & your PGP public key.
#

# Modified by Greg Spencer, greg@graphics.cornell.edu, May 1994
# Mostly just cleaned up things and added stuff like automatic
# addition and detection (and ignoring) of keys to be added to keyring,
# and signal catching, as well as environment variable control of
# most site-specific stuff.
#
# Must set the following environment variables:
#
# EDITOR or VISUAL set to editor of choice
#
# PGPCOMMAND set to the pgp decryption command
#
# PGPID or SIGNATURE set to the id you wish to
# have used for your pgp signatures, etc.
#
# PREFIX set to the forwarded message prefix that you use
#

# setup some variables
($visual = $ENV{'EDITOR'}) || ($visual = $ENV{'VISUAL'}) || ($visual = 'pico');
($pgpcommand = $ENV{'PGPCOMMAND'}) || ($pgpcommand = "/usr/local/bin/pgp");
#($myname = $ENV{'PGPID'}) || ($myname = $ENV{'SIGNATURE'});
($prefix = $ENV{'PREFIX'}) || ($prefix = "> ");
$topgp = 0;
$blanks = 0;
$paragraphs = 1;
$blankcompress = 1;
$name=@ARGV[$#ARGV];

#temporary file names
$rplyfile = "$name.rply";
$pgpfile  = "$name.pgp";
$ascfile  = "$name.asc";
$clrfile  = "$name.clr";

# trap signals so we don't leave
# (possibly sensitive!) garbage around
sub catcher {
	local($sig) = @_;

	print "Caught a SIG$sig -- exiting\n";
	close (OUTPUT);
	close (PGPFILE);
	close (CLEAR);
	close (INPUT);
	unlink ("$pgpfile");
	unlink ("$rplyfile");
	unlink ("$clrfile");
	unlink ("$ascfile");
}

$SIG{'INT'}  = 'catcher';
$SIG{'QUIT'} = 'catcher';
$SIG{'HUP'}  = 'catcher';
$SIG{'KILL'} = 'catcher';

# parse the input file to see if we're replying to an encrypted message
# user may need to type in pass phrase to decode
umask (077);
open (INPUT, "<$name");
open (OUTPUT, ">$rplyfile") || die "Cannot open $rplyfile for output.\n";
while (<INPUT>) {
	# make sure to allow printing of key blocks
	if (!$topgp && (!m/^$prefix-----BEGIN PGP .*-----/ || m/^$prefix-----BEGIN PGP PUBLIC KEY BLOCK-----/)) {
		if (m/^$prefix*$/) {
			if ($paragraphs) {
				if ($blankcompress) {
					if ($blanks == 0) {
						print OUTPUT "\n";
						$blanks = 1;
					}
				} else {
					print OUTPUT "\n";
				}
			} else {
				print OUTPUT;
			}
		} elsif (m/^[ \t\r]*$/) {
			if ($blankcompress) {
				if ($blanks == 0) {
					print OUTPUT "\n";
					$blanks = 1;
				}
			} else {
				print OUTPUT;
			}
		} else {
			print OUTPUT;
			if ($. == 1 && !m/^$prefix/) {
				print OUTPUT "\n";
				$blanks = 1;
			} else {
				$blanks = 0;
			}
		}
	}
	# make sure to skip key blocks because we already did 'em in morepgp
	if (!$topgp && m/^$prefix-----BEGIN PGP .*-----/ && !m/^$prefix-----BEGIN PGP PUBLIC KEY BLOCK-----/ ) {
		$topgp = 1;
		unlink ($pgpfile);
		open (PGPFILE, ">$pgpfile") || die "Cannot open $pgpfile for output.\n";
	}
	if ($topgp) {
		$_ =~ s/^$prefix//;
		print PGPFILE $_;
		# make sure to skip key blocks because we already did 'em in morepgp
		if (m/^-----END PGP .*-----/ && !m/^-----END PGP PUBLIC KEY BLOCK-----/) {
			$blocktype = $_;
			$blocktype =~ s/^-----END (PGP .*)-----/$1/;
			$blocktype =~ s/PGP MESSAGE/DECRYPTED MESSAGE/;
			$blocktype =~ s/PGP SIGNATURE/SIGNED MESSAGE/;
			chop ($blocktype);
			$topgp = 0;
			close (PGPFILE);
			system ("$pgpcommand $pgpfile -o $clrfile > /dev/tty 2>&1");
			open (CLEAR, "<$clrfile") || die "Cannot open $clrfile for input.\n";
			print OUTPUT "$prefix-----BEGIN $blocktype-----\n> \n";
			$blanks = 0;
			while (<CLEAR>) {
				if (m/^[ \t\r]*$/) {
					if ($paragraphs) {
						if ($blankcompress) {
							if ($blanks == 0) {
								print OUTPUT "\n";
								$blanks = 1;
							}
						} else {
							print OUTPUT "\n";
						}
					} else {
						print OUTPUT "$prefix\n";
					}
				} else {
					print OUTPUT "$prefix";
					print OUTPUT;
					$blanks = 0;
				}
			}
			close (CLEAR);
			unlink ($clrfile);
			unlink ($pgpfile);
			print OUTPUT "$prefix-----END $blocktype-----\n\n";
		}
	}
}
close OUTPUT;
close INPUT;
unlink ($name);
rename ("$rplyfile", "$name");

system ($visual, @ARGV);

while (!$q) {
	print "\nSign this message? [Y]: ";
	$q = <STDIN>;
	$q =~ s/[ \t\n]//g;
	$q = substr ($q, 0, 1);
	if (($q eq 'Y') || ($q eq 'y') || ($q eq '')) {
		push (@opts, '-st', '+clearsig=on');
		$q = "y";
	} elsif (($q ne 'N') && ($q ne 'n')) {
		$q = '';
	}
}

# note that it is the default to NOT encrypt,
# simply because not everyone has PGP (unfortunately :-)
$q='';
while (!$q) {
	print "Encrypt this message? [N]: ";
	$q = <STDIN>;
	$q =~ s/[ \t\n]//g;
	$q = substr ($q, 0, 1);
	if (($q eq 'Y') || ($q eq 'y')) {
		push (@opts, '-e');
		$q = "y";
	} elsif (($q eq 'N') || ($q eq 'n') || ($q eq '')) {
		$q = "n";
	} else {
		$q = '';
	}
}

if (@opts) {
	if ($q eq 'y') {
		print "Enter receipients, each on a separate line, terminate with EOF or a single `.':\n";
		{
			print "> ";
			if ($_ = <STDIN>) {
				chop;
				last if ("$_" eq '.');
				push (@receipients, "$_");
				redo;
			}
			last;
		}
	}
	system ($pgpcommand, '-a', @opts, "$name", @receipients);
	if ($? == 0) {
		unlink ($name);
		rename ("$ascfile", "$name");
	}
}

- -- 
 John A. Perry - KG5RG - perry@jpunix.com
 WWW - http://jpunix.com
 PGP 2.62 key for perry@jpunix.com is on the keyservers.
 PGP-encrypted e-mail welcome!

 Finger kserver@jpunix.com for PGP keyserver help.
 Finger remailer@jpunix.com for remailer help.

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBLtvwZ1OTpEThrthvAQFwlAP+MxX6olbMempfh6UYdTDGruTngH+WgRsa
BacTB86oNIjlllDfZB55KJyuUs5dpP+gRRDW4BZTK6zyNuzy3tv5iErQnvDiV/Tn
PjSKmJJFs7HnC88aC830eQ+ojGaXzZCE2IbaTm/a7R6SU9nLc/KnJYY5pMHjdVx+
uN0xwmRrBYw=
=SUyb
-----END PGP SIGNATURE-----




Thread