[ale] Fun With Linux -- Automating PGP Email On Linux
Jeffrey Thompson
jeffrey at watchman.com
Sun Mar 17 20:29:00 EST 1996
Thoughts and Musings on Automating Encrytion Lists....
by Jeffrey Thompson 3/17/96
(I'll be incorporating this into HOWTO-AUTOMATE-PGP-EMAIL):
1. Here is an email alias to receiving plain-text email into a single
list that later is encrypted and delivered. It uses the majordomo
wrapper:
joe_alias: "|/usr/local/majordomo/wrapper append_note /home/joe/archive_file
append_note looks like this:
#!/bin/sh
#file: append_note
# append_note archive_file : append a note to the outgoing archive file
#
ARCHIVE_MONITOR=the_monitor_man
if [ "$#" -ne 1 ] ; then
echo usage: $0 archive_file
exit 1
fi
ARCHIVE_FILE=$1
/usr/bin/tee -a $ARCHIVE_FILE | \
mailx -s 'Message Placed in $ARCHIVE_FILE' $ARCHIVE_MONITOR
# Delimit the messages with a "\n-----------------------------------\n"
echo >> $ARCHIVE_FILE
echo ------------------------------ >> $ARCHIVE_FILE
echo >> $ARCHIVE_FILE
** Make sure the id that wrapper uses can write to the archive_file
2. The email alias receives encrypted email, auto decrypts it, and mails
a message containing the original sender's 'From: email_address'.
encypted_to_joe: "|/home/joe/wrapper unpgp_with_from | \
/home/joe/remail /bin/mailx joe"
I'll present /home/joe/wrapper, unpgp_with_from (needs to be in /home/joe),
and /home/joe/remail.
- make sure you have /home/joe totally secure
(i.e., recommend 'chmod 700 /home/joe') since /home/joe/wrapper will
be setuid root.
- /home/joe/wrapper is a C program specifically tailored for the user
joe (it contains joe's environment, HOME, BIN, etc. in the program).
To be absolutly safe, I would recommend having a wrapper.c compiled
for each user you plan on auto-decrypting messages to make it safer.
/home/joe/wrapper needs to be setuid root since it needs to
change both the real and effice user and group ids. Use at your own
risk. If anyone can finds any security short-commings with this
C program running setuid root, please let me know (I think it's pretty
safe).
#file: joe_wrapper.c
#include <stdio.h>
#include <unistd.h>
#define JOE_USER_UID 555
#define JOE_USER_GID 121
#ifndef STRCHR
# define STRCHR(s,c) strchr(s,c)
#endif
#ifndef BIN
# define BIN "/home/joe"
#endif
#ifndef PATH
# define PATH "PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/home/joe"
#endif
#ifndef HOME
# define HOME "HOME=/home/joe"
#endif
#ifndef SHELL
# define SHELL "SHELL=/bin/bash"
#endif
char * new_env[] = {
HOME, /* 0 */
PATH, /* 1 */
SHELL, /* 2 */
#ifdef MAJORDOMO_CF
MAJORDOMO_CF, /* 3 */
#endif
0, /* possibly for USER or LOGNAME */
0, /* possible for LOGNAME */
0
};
main(argc, argv, env)
int argc;
char * argv[];
char * env[];
{
char * prog;
int e, i;
if (argc < 2) {
fprintf(stderr, "USAGE: %s program [<arg> ...]\n", argv[0]);
exit(1);
}
/* if the command contains a /, then don't allow it */
if (STRCHR(argv[0][0], '/') != (char) NULL) {
/* this error message is intentionally cryptic */
fprintf(stderr, "%s: error: insecure usage\n", argv[0]);
exit(2);
}
if ((prog = (char *) malloc(strlen(BIN) + strlen(argv[1]) + 2)) == NULL) {
fprintf(stderr, "%s: error: malloc failed\n", argv[0]);
exit(3);
}
sprintf(prog, "%s/%s", BIN, argv[1]);
setgid(JOE_USER_GID);
setuid(JOE_USER_UID);
if ((getuid() != geteuid()) || (getgid() != getegid())) {
fprintf(stderr, "%s: error: recompile with POSIX flags.\n", argv[0]);
exit(4);
}
execve(prog, argv+1, new_env);
/* the exec should never return */
perror(argv[1]);
exit(5);
}
==========================================================
- unpgp_with_from prints the subject: and from: lines from the original
email, and then the decrypted message.
#!/bin/sh
#file: unpgp_with_from
PATH=/bin:/usr/bin:/usr/local/bin
export PGPPASS="a secret private pass-phrase"
# make sure and create private files
umask 77
trap '/bin/rm -f /tmp/unpgp$$' 1 2 15
/bin/cat > /tmp/unpgp$$
SUBJECT=`/usr/bin/grep -i ^Subject: /tmp/unpgp$$ | /usr/bin/sed 1q`
WHOFROM=`/usr/bin/grep -i ^From: /tmp/unpgp$$ | /usr/bin/sed 1q`
echo $WHOFROM
echo $SUBJECT
if [ ! -z "$SUBJECT" ] ; then
echo
fi
/usr/bin/sed -n '/^$/,$p' /usr/tmp/unpgp$$ | /usr/local/bin/pgp -f
/bin/rm -f /usr/tmp/unpgp$$
==========================================================
- /home/joe/remail.c is much like the wrapper program. It needs to be
setuid-root and executable by your mailer userid so it can change
the real and effective IDs to JOE_USER_UID and appear to originate
from the JOE_USER_UID.
#file: remail.c
#include <stdio.h>
#define JOE_USER_UID 555
#define JOE_USER_GID 121
#define MAILPROG "/bin/mailx"
#ifndef STRCHR
# define STRCHR(s,c) strchr(s,c)
#endif
#ifndef BIN
# define BIN "/home/joe"
#endif
#ifndef PATH
# define PATH "PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/home/joe"
#endif
#ifndef HOME
# define HOME "HOME=/home/joe"
#endif
#ifndef SHELL
# define SHELL "SHELL=/bin/bash"
#endif
char * new_env[] = {
HOME, /* 0 */
PATH, /* 1 */
SHELL, /* 2 */
#ifdef MAJORDOMO_CF
MAJORDOMO_CF, /* 3 */
#endif
0, /* possibly for USER or LOGNAME */
0, /* possible for LOGNAME */
0
};
main(argc, argv, env)
int argc;
char * argv[];
char * env[];
{
int e, i;
if (argc < 2) {
fprintf(stderr, "USAGE: %s program [<arg> ...]\n", argv[0]);
exit(1);
}
/* if the command contains a /, then don't allow it */
if (STRCHR(argv[0][0], '/') != (char) NULL) {
/* this error message is intentionally cryptic */
fprintf(stderr, "%s: error: insecure usage\n", argv[0]);
exit(2);
}
setgid(JOE_USER_GID);
setuid(JOE_USER_UID);
if ((getuid() != geteuid()) || (getgid() != getegid())) {
fprintf(stderr, "%s: error: recompile with POSIX flags.\n", argv[0]);
exit(4);
}
execve(MAILPROG, argv+1, new_env);
/* the exec should never return */
perror(argv[1]);
exit(5);
}
3. Here's an email delivery program that takes a plain-text file (possibly
an email archive file), encrypts it, and emails it to a particular address,
and then truncates archive_file. I use append_note to build an email
archive file, and then on regular intervals, have a cron job automatically
deliver the file with deliver_archive_file.
This scheme is useful if you want a level of indirection in the email
list. People can respond with email to an email-alias that collects all
of the messages into a file. Then, one secure email message (containing
all of the other messages) is packaged and delivered to a different
email address.
Usage of deliver_archive_file is:
deliver_archive_file from_user to_user
*** /home/from_user needs to have a /home/from_user/tmp directory
to store copies of the archive files (just in case something goes
wrong)
deliver_archive_file needs to be run from the userid that you want the
PGP file to originate from. Also, the userid that you are sending to
needs to be in your public keyring.
#!/bin/sh
#file: deliver_archive_file
PATH=/bin:/usr/bin:/usr/local/bin
ARCHIVE_MONITOR=the_archive_monitor
if [ $# -ne 2 ] ; then
echo $0 from_user to_user
exit 1;
else
from=$1
to=$2
fi
cd /home/$from
if [ -s ./archive_file ] ; then
# make a backup copy just in case the email gets fried
/bin/cp ./archive_file tmp/archive_file$$
/bin/mailx -s "mailing /home/$from/tmp/archive_file$$ to $to" \
$ARCHIVE_MONITOR < tmp/archive_file$$
# make sure a previous encrypted file isn't here
/bin/rm -f ./archive_file.asc
# this creates ./archive_file.asc
/usr/local/bin/pgp -ea ./archive_file $to
mailx -s "Greetings!" $to < ./archive_file.asc
# wipe out the encrypted copy
/bin/rm -f ./archive_file.asc
# blank out the archive_file (now you know why I made a backup copy)
> ./archive_file
# make sure it is writable by the email program
chmod 666 ./archive_file
fi
4. Receive encrypted email, decrypt it, and remailing it to appear to
have originated from a local id:
joes_friend: "|/home/joe/wrapper unpgp | \
/home/joe/remail /bin/mailx joes_friend at compuserve.com"
Using the above program, joe can send encrypted email to joes_friend
email alias, it is auto-decrypted, and remailed (appearing to be
originally emailed from JOE_USER_ID from /home/joe/wrapper). This
effectively shields joe's original email address.
More information about the Ale
mailing list