[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