%% LyX 1.1 created this file.  For more info, see http://www.lyx.org/.
%% Do not edit unless you really know what you are doing.
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}

\makeatletter


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
\providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@}
\newenvironment{LyXParagraphIndent}[1]%
{
  \begin{list}{}{%
    \setlength\topsep{0pt}%
    \addtolength{\leftmargin}{#1}
    \setlength\parsep{0pt plus 1pt}%
  }
  \item[]
}
{\end{list}}

\makeatother

\begin{document}


\title{An encrypted mailing list with Mailman, Exim and Gnupg on Debian GNU/Linux}

\maketitle

\section{Concept}

The mailing list user (list) has a GPG key pair. Mails sent to the mailing list
have to be encrypted with the list's public key. The mail is then decrypted
on the server, and reencypted for sending to each member of the mailing list.
To do that, the public key of each member has to be present in the keyring of
the mailing list user (list).


\section{Configuration}


\subsection{Mailman}

No tweaking needed


\subsection{GnuPG}

Generate the key pair of the mail list user (see MAILMAN\_UID in exim.conf)
with gpg --gen-key. Share the public key of the list with members (gpg --armor
--export)

Import the key of each member and sign it. This is necessary to use gpg in batch
mode.


\subsection{Exim}

Modify the list\_transport so that it looks like this: 

\begin{LyXParagraphIndent}{0.10\columnwidth}
\texttt{\small list\_transport:} 

\texttt{\small driver = pipe }{\small \par}

\texttt{\small command = \char`\"{}/usr/bin/decrypt.py | MAILMAN\_WRAP post
\$\{lc:\$local\_part\}\char`\"{} }{\small \par}

\texttt{\small current\_directory = MAILMAN\_HOME }{\small \par}

\texttt{\small home\_directory = MAILMAN\_HOME }{\small \par}

\texttt{\small user = MAILMAN\_UID }{\small \par}

\texttt{\small group = MAILMAN\_GID }{\small \par}

\texttt{\small use\_shell}{\small \par}

\end{LyXParagraphIndent}

add a crypt\_transport:

\begin{LyXParagraphIndent}{0.10\columnwidth}
\texttt{\small crypt\_transport:}{\small \par}

\texttt{\small driver = pipe}{\small \par}

\texttt{\small command = \char`\"{}/usr/bin/recrypt.py \$local\_part@\$domain\char`\"{}
\#command = \char`\"{}/bin/cat > /tmp/mailoutput\char`\"{}}{\small \par}

\texttt{\small current\_directory = /var/lib/mailman }{\small \par}

\texttt{\small home\_directory = /var/lib/mailman }{\small \par}

\texttt{\small user = list }{\small \par}

\texttt{\small group = daemon}{\small \par}

\end{LyXParagraphIndent}

Dont touch the directors, but add a crypt\_router before the smarthoste one:

\begin{LyXParagraphIndent}{0.10\columnwidth}
\texttt{\small crypt\_router: }{\small \par}

\texttt{\small driver = domainlist }{\small \par}

\texttt{\small senders = list-admin@smailman}{\small \par}

\texttt{\small transport = crypt\_transport }{\small \par}

\texttt{\small route\_list = \char`\"{}{*} mailadm bydns\_a\char`\"{}}{\small \par}

\end{LyXParagraphIndent}

As senders, put the mail of the list admin of the lists that has to be encrypted
(I didn't test it with several lists yet).


\subsection{Scripts}

I wrote two Python scripts (these are my first python script ever, thanks your
forgiveness if the code could have been better). The first is used for decryption
of the mail received:

\begin{LyXParagraphIndent}{0.10\columnwidth}
\texttt{\small \#!/usr/bin/python2}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Importing modules}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small import os}{\small \par}

\texttt{\small import sys}{\small \par}

\texttt{\small import tempfile}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Temporary files (decrypted mail body)}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small tempfilename = tempfile.mktemp()}{\small \par}

\texttt{\small tempfile = open(tempfilename, 'w')}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small po=os.popen(\char`\"{}\char`\"{}.join( \char`\"{}\%s \%s\char`\"{}
\% (\char`\"{}/usr/bin/gpg -{}-batch -{}-armor -{}-decrypt > \char`\"{}, tempfilename
)),'w')}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small firstline = sys.stdin.readline()~~~~~~~~\#Remove first
line because it's not relevant for SMTP}{\small \par}

\texttt{\small data = sys.stdin.readline()}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Extraction of the headers}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small headers=\char`\"{}\char`\"{}}{\small \par}

\texttt{\small while data !='\textbackslash{}n':}{\small \par}

\texttt{\small ~~~~~~~~headers+=data}{\small \par}

\texttt{\small ~~~~~~~~data = sys.stdin.readline()}{\small \par}

\texttt{\small headers+=\char`\"{}\textbackslash{}n\char`\"{}}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#The rest of the input is the message body}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small data = sys.stdin.read()}{\small \par}

\texttt{\small po.write(data)}{\small \par}

\texttt{\small po.close()}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Print the decrypted mail to the standard output mail and remove
tempfiles}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small body=open(tempfilename,'r')}{\small \par}

\texttt{\small body\_var=body.read()}{\small \par}

\texttt{\small body.close()}{\small \par}

\texttt{\small print firstline + headers + body\_var}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small os.remove(tempfilename)}{\small \par}

\end{LyXParagraphIndent}

and the second is used to encrypt the mail to send it to each member of the
list:

\begin{LyXParagraphIndent}{0.10\columnwidth}
\texttt{\small \#!/usr/bin/python2}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Importing modules}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small import os}{\small \par}

\texttt{\small import sys}{\small \par}

\texttt{\small import time}{\small \par}

\texttt{\small import tempfile}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Temporary files (file1=headers, file2=mail body)}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small tempfilename = tempfile.mktemp()}{\small \par}

\texttt{\small tempfilename2 = tempfile.mktemp()}{\small \par}

\texttt{\small tempfile = open(tempfilename, 'w')}{\small \par}

\texttt{\small tempfile2 = open(tempfilename2, 'w')}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small po=os.popen(\char`\"{}\char`\"{}.join( \char`\"{}\%s \%s \%s
\%s\char`\"{} \% (\char`\"{}/usr/bin/gpg -{}-batch -{}-armor -{}-encrypt -{}-recipient\char`\"{},
sys.argv{[}1{]}, \char`\"{}>\textcompwordmark{}> \char`\"{}, tempfilename2 )),'w')}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small data = sys.stdin.readline()~~~~~\#Remove first line because
it's not relevant for SMTP}{\small \par}

\texttt{\small data = sys.stdin.readline()}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Extraction of the headers}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small headers=\char`\"{}\char`\"{}}{\small \par}

\texttt{\small while data !='\textbackslash{}n':}{\small \par}

\texttt{\small ~~~~~~~~headers+=data}{\small \par}

\texttt{\small ~~~~~~~~data = sys.stdin.readline()}{\small \par}

\texttt{\small headers+=\char`\"{}\textbackslash{}n\char`\"{}}{\small \par}

\texttt{\small tempfile.writelines(headers)}{\small \par}

\texttt{\small tempfile.close()}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#The rest of the input is the message body}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small data = sys.stdin.readline()}{\small \par}

\texttt{\small po.write(data)}{\small \par}

\texttt{\small po.close()}{\small \par}

\texttt{\small ~}{\small \par}

\texttt{\small \#Send the reencrypted mail and remove tempfiles}{\small \par}

\texttt{\small \#-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-}{\small \par}

\texttt{\small os.system(\char`\"{}\char`\"{}.join( \char`\"{}\%s \%s \%s \%s
\%s \%s\char`\"{} \% ( \char`\"{}/bin/cat \char`\"{}, tempfilename, \char`\"{}
\char`\"{}, tempfilename2, \char`\"{}| /usr/sbin/exim\char`\"{}, sys.argv{[}1{]})))}{\small \par}

\texttt{\small os.remove(tempfilename)}{\small \par}

\texttt{\small os.remove(tempfilename2)}{\small \par}

\end{LyXParagraphIndent}


\section{Problems}

I use temporary files a lot. I didn't find a way to take the ouput of the popen
and put it in a variable. This is especially a problem for the stage where the
mail is not encrypted. I also use os.system to call gpg in the decrypt file.
Maybe it would be better to use a python interface to gnupg?

If the mail received is not encrypted, problem.

Behaviour for mails with Attachments is not garanteed.
\end{document}
