dslreports logo
site
 
    All Forums Hot Topics Gallery
spc

spacer




how-to block ads


Search Topic:
uniqs
4380
share rss forum feed


CryptyBits

@zoomvps.com

Brainstorm: PGP encrypted ~/Maildir

Preface: Read entirely or assumptions will be made.

This is not the same thread that pops up time and time again on mailing lists about an encrypted ~/Maildir. I *trust* the server. Those threads are about not trusting the server. In this case client-side only encryption makes sense coupled with disk encryption. This is not that thread.

Allow me to craft the following scenario:

1) Dovecot/Postfix IMAPs/POP3s only, Dovecot SASL.
2) Apache SSL WebMail access
3) Mail-enabled limited user-account PAM authenticated to Dovecot/Postfix
4) Only console-access is SSH via RSA keypair with strong password on private key or direct physical access.
5) Strict clearly defined AppArmor rules on each daemon
6) Defense-in-depth security (chroot, AppArmor, ingress/egress firewall, auditing, etc)

Desires: Secure ~/Maildir while allowing disparate clients (Webmail, mobile devices, laptop) access.

Concerns:

1) Single-factor authentication for Dovecot/Postfix leading to mailbox (!SERVER) access.
a) Sensitive data stored in ~/Maildir
b) Password reset vulnerability -- if attacker owns the mailbox online sites/banking/etc passwords can be arbitrarily reset.
c) SSL MiTM allows messages/passwords to be read in cleartext. See the wonderful Dutch CA fiasco and Iran playing SSL MiTM with GMail.

2) Two-factor key-based authentication to SSH deems direct console access to ~/Maildir as reasonably secure.
a) Far more secure than single auth username/password combination.
b) Two-factor

Solution:

1) Use Procmail with GPG to encrypt incoming messages with a private 4096 bit RSA key generated on the server, constrained to the limited user mail account, for the pubkey used by the client user account. The private key is separate/different from the user's private key.
a) Addresses two-factor concerns, Dovecot access to ~/Maildir does not grant access to real mail content, it is encrypted.
b) Addresses SSL MiTM concerns, private key of client or server required to decrypt messages.
c) Server being owned results in messages being read via decryption.
d) SSH private key for limited user + private key password results in likely decryption of ~/Maildir, see item c.

2) Convulated PAM/ecryptfs setup
a) Does not address MiTM situation
b) Does not address single-factor authentication.
c) Server being owned results in messages being read via decryption.

3) Come up with some multi-client two-factor out of band authentication scheme.
a) Does not address MiTM situation
b) Either pricey or convoluted.
c) Server being owned results in messages being read via decryption.

Thoughts? In this particular use-case it seems that GPG is the way to go.



EpicFail

@zoomvps.com

Well that was an epic failure. Here, if anyone stumbles along on this, this is how far I got.

#PGP/GPG encrypt all incoming messages.
#:0 B
#* ! ^-----BEGIN PGP MESSAGE-----
#{
#	#MIME headers
#	PGP_TXT="\n\n--PROCMAIL_GPG_DAEMON-2011\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain; charset=us-ascii\n\n"
#	PGP_ATT="\n\n--PROCMAIL_GPG_DAEMON-2011\nContent-Disposition: attachment; filename="encrypted.pgp\nContent-Type:" application/octet-stream; name="encrypted.pgp\nContent-Transfer-Encoding:" 7bit\n\n"
#	PGP_END="\n\n--PROCMAIL_GPG_DAEMON-2011\n"
#
#	#Feed the header to a pipe, treat pipe as a filter.
#	:0fh
#	|{ /usr/bin/formail -f -XTo: -XFrom: -XDate: -XSubject: -XMessage-ID: | /usr/bin/formail -I"Content-Type: multipart/mixed; boundary=PROCMAIL_GPG_DAEMON-2011" -I"Content-Transfer-Encoding: 7bit" -I"MIME-Version: 1.0"; }
#
#	#Feed the body to a pipe, treat pipe as a filter.
#	:0fb
#	|{ /bin/echo -e "$PGP_TXT"; /bin/cat -|/usr/bin/gpg --trust-model always --batch --quiet -a -e -r 37085D70; /bin/echo -e "$PGP_END"; /bin/echo -e "$PGP_ATT"; /bin/cat -|/usr/bin/gpg --trust-model always --batch --quiet -a -e -r 37085D70; /bin/echo -e "$PGP_END"; }
#}
 


nwrickert
sand groper
Premium,MVM
join:2004-09-04
Geneva, IL
kudos:7
Reviews:
·AT&T U-Verse
reply to CryptyBits

I am unclear on what you are trying to achieve.

On a quick read, it looks as if you are adding a lot of complexity with no obvious corresponding benefits.
--
AT&T Uverse; Zyxel NBG334W router (behind the 2wire gateway); openSuSE 11.4; firefox 5.0



SecondChance

@zoomvps.com
reply to EpicFail

»github.com/mikecardwell/gpgit looks promising from »grepular.com/Automatically_Encry···ng_Email

The author seems to have the same goals as I.



Brano
I hate Vogons
Premium,MVM
join:2002-06-25
Burlington, ON
kudos:10

1 recommendation

How about encrypted filesystem or home directory?
TrueCrypt or native Linux filesystem encryption? ...it's much simpler to setup, transparent and does not need any special maintenence.



Thx4Reply

@zoomvps.com

Thank you Brano for your reply but I'm not sure how to make this work with the scenario painted above. Can you elaborate? Specifically making it work with IMAPS access to Dovecot from remote clients.

I'm not worried about encrypting ~/Maildir on the server, I trust the server, I am working towards mitigating the issues associated with single-factor authentication and the concerns in #1.



BeesTea
Internet Janitor
Premium,VIP
join:2003-03-08
00000
reply to CryptyBits

EDIT, we posted the same link. For what it's worth, the githib project works well.



happyNdrunk

@zoomvps.com

To all those that replied, thank you. I made no code changes to gpgit.pl other than to rename it to gpgencmail.pl (makes sense in my head).

Here is the procmail recipe I am using.

#GPG encrypt all incoming messages that are not from mailing lists.
#Do not GPG encrypt messags with Subject prefix of "plaintext"
:0
* ! ^List-Id:
* ! ^Subject:[ ]*plaintext
{
	:0f
	|/usr/local/bin/gpgencmail.pl --encrypt-mode prefer-inline myemail@mydomain.net
}
 

Caveats are you must import the pubkey on the server for the recipient, set it as trust, and locally sign it. Then the Perl is so happy. Sadly the iPhone is not very happy, the PGP client iPGMail won't handle PGP/MIME at the moment so HTML or messages with attachments are readable. Oh well ;)


PunchiePets

@zoomvps.com

Everything is working very well, so I cobbled together some BASH code in a alcohol induced stupor to encrypt the older messages since the procmail code above only affects new ingress messages. Figured I'd document the solution here so folks in the future can find it.

Better have a backup of your Maildir before you play with this

Working well. Had to flush the cache on the local IMAP clients including the wonderful iPhone (yay for SSH) and Thunderbird.

Here you go, probably could even improve the code and cron it for encrypting Sent-Items/Sent.

#!/bin/bash
# PunchiePets
# GPG Encrypt a Maildir using gpgencmail.pl, removing any S= or W= virtual flags.
# Sep 02, 2011
# GPLv2
#
 
if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
        echo "Usage is ./encmaildir.sh /path/to/Maildir certificate_user@domain.com file_owner"
        exit 0
fi
 
if [ ! -e "$1" ]; then
        echo "$1 does not exist"
        exit 0
fi
 
if [ $(gpg --list-keys|grep -c "$2") -lt 1 ]; then
	echo "A GPG key for '$2' could not be found!"
	exit 0
fi
 
find "$1" -type f|grep '/cur/'|while read line; do
        cat "$line"|/usr/local/bin/gpgencmail.pl --encrypt-mode prefer-inline "$2" > /tmp/msg
 
	chown $3:$3 /tmp/msg
	chmod 600 /tmp/msg
        touch /tmp/msg --reference="$line"
 
	#Unlink the original Maildir message
	unlink "$line"
 
	#Strip message sizes, retain experimental flags.
	STRIPSIZES=$(echo "$line"|sed -e 's/W=[[:digit:]]*//' -e 's/S=[[:digit:]]*//' -e 's/,,//' -e 's/,:2/:2/')
	cp -av /tmp/msg "$STRIPSIZES"
done
 
find "$1" -type f|grep "dovecot-\|dovecot\.\|\.uidvalidity"|while read line; do
	echo "Removing file $line"
	unlink "$line"
done
 


PGPAllGood

@pnap.net

Here is a final summary of this thread.

As each user, you should generate a RSA certificate pair, on the server.

gpg --gen-key
 

Select an RSA keypair, tune to your fit, and generate the certificate. Import the public key of the intended recipient, which has likely been generated on a separate computer. Import this into your GPG keyring.

gpg --import /path/to/pubkey
 

Now you must set this pubkey as trusted and locally sign it.
gpg --edit-key user@mydomain.net
Command> trust
Your decision? 4
Command> lsign
Really sign? (y/N) Y
quit
Save Changes (y/N) Y
 

The procmail recipe I am using for users to be PGP/GPG encrypted:
#GPG encrypt all incoming messages that are not from mailing lists.
#Do not GPG encrypt messages with Subject prefix of "plaintext"
:0
* ! ^List-Id:
* ! ^Subject:[ ]*plaintext
{
  :0f
  |/usr/local/bin/gpgencmail.pl --encrypt-mode prefer-inline user@mydomain.net
}
 
#GPG encrypt all messages with passwords in the body.
:0B
* ^.*pass
{
  :0f
  |/usr/local/bin/gpgencmail.pl --encrypt-mode prefer-inline user@mydomain.net
}
 

Here is the script I am using to PGP/GPG encrypt the contents of existing Maildir, it has been cleaned up. Before playing with this script or the contents of your ~/Maildir ensure you have good backups. What works for me may be catastrophic to your ~/Maildir. You are responsible for the contents of your ~/Maildir.

To encrypt User1's maildir, you would use '/usr/local/bin/encmaildir.sh /home/user1/Maildir user1@mydomain.net user1'
#!/bin/bash
# GPLv2
# GPG Encrypt a Maildir using gpgencmail.pl, removing any S= or W= size flags.
# Sep 02, 2011
#
# Change log:
#  Sep 03, 2011
#      - Temporary file is based on file_owner to avoid issues with permission differences.
#      - Temporary file is removed after run.
#      - Optional arguments passed to 'find'.
#      - Full paths to binaries.
#      - Removed unnecessary need of 'cat', 'grep', etc.
 
if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
  /bin/echo "Usage is ./encmaildir.sh    {optional arguments passed to 'find' for messages such as '-mtime 0'}"
  exit 0
fi
 
if [ ! -e "$1" ]; then
  /bin/echo "Fatal: Key for $1 does not exist"
  exit 0
fi
 
#Does this key exist?
/usr/bin/gpg --list-keys "$2" > /dev/null 2>&1
if [ $? -gt 0 ]; then
  /bin/echo "A GPG key for '$2' could not be found!"
  exit 0
fi
 
#Find all files in the Maildir specified.
/bin/echo "Calling /usr/bin/find \"$1\" -type f -regex '.*/\(cur\|new\)/.*' $4"
/usr/bin/find "$1" -type f -regex '.*/\(cur\|new\)/.*' $4|while read line; do
  /usr/local/bin/gpgencmail.pl --encrypt-mode prefer-inline "$2"  /tmp/msg_$3
 
  #Preserve timestamps, set ownership.
  /bin/chown $3:$3 /tmp/msg_$3
  /bin/chmod 600 /tmp/msg_$3
  /usr/bin/touch /tmp/msg_$3 --reference="$line"
 
  #Unlink the original Maildir message
  /usr/bin/unlink "$line"
 
  #Strip message sizes, retain experimental flags and status flags.
  STRIPSIZES=$(/bin/echo "$line"|/bin/sed -e 's/W=[[:digit:]]*//' -e 's/S=[[:digit:]]*//' -e 's/,,//' -e 's/,:2/:2/')
  /bin/cp -av /tmp/msg_$3 "$STRIPSIZES"
done
 
#Remove Dovecot index and uids for regeneration.
/bin/echo "Removing Dovecot indexes and uids"
/usr/bin/find "$1" -type f -regex '.*\(dovecot-\|dovecot\.\|\.uidvalidity\).*' -delete
 
#Remove the temporary file
if [ -e /tmp/msg_$3 ]; then /usr/bin/unlink /tmp/msg_$3; fi
 

I am using gpgit.pl, as-is, renamed to gpgencmail.pl, and stored at /usr/local/bin/gpgencmail.pl. gpgit.pl is located at »github.com/mikecardwell/gpgit

To handle Sent and Sent-Items, which are not processed by procmail, and therefor not encrypted, I use a Cron script to call encmaildir.sh to handle Sent-Items and Sent.

#GPG Encrypt Sent folders for GPG enabled users.
00 23 * * *  user1  /usr/local/bin/encmaildir.sh /home/user1/Maildir/.Sent user1@mydomain.net user1 "-mtime 0"
00 23 * * *  user1  /usr/local/bin/encmaildir.sh /home/user1/Maildir/.Sent\ Items user1@mydomain.net user1 "-mtime 0"
00 23 * * *  user2  /usr/local/bin/encmaildir.sh /home/user2/Maildir/.Sent user2@mydomain.net user2 "-mtime 0"
00 23 * * *  user2  /usr/local/bin/encmaildir.sh /home/user2/Maildir/.Sent\ Items user2@mydomain.net user2 "-mtime 0"
 

I have documented this here in it's entirety for the benefit of future users who wish to do the same. This entire process is working quite well and I am fully happy with the results.

Enigmail for Thunderbird handles decryption, including attachments, multipart advanced E-mails, etc without issue.

I am also using SecuMail for the iPhone to PGP decrypt these messages and it is working great with the same functionality similar to Enigmail. One caveat is that the PGP/MIME inline body appears as 'mime-attachment' as is not viewable by the Mail Application. I have notified the developers of SecuMail and as a work-around I am using AttachmentSaver and opening 'mime-attachment' in iFile, copying the contents to clipboard, and decrypting using SecuMail. AttachmentSaver and iFile are available from Cydia for Jailbroken iPhones. SecuMail is available from the Apple App Store.

I have not tried Android PGP clients yet.

To those that have participated in this thread thank you. I hope this thread will assist someone in the future with the same goals as I.


PatchMePlz

@pnap.net

It seems that the handling of multipart or PGP/MIME is not compatible with all PGP clients. The below patch resolves this issue and allows these clients to work as expected. I also believe this format to be closer to what traditional OpenPGP and PGP clients produce.

--- /usr/share/perl5/Mail/GnuPG.pm 2008-05-20 06:37:01.000000000 -0600
+++ /usr/share/perl5/Mail/GnuPG.pm 2011-09-07 14:29:28.000000000 -0600
@@ -901,13 +901,14 @@
 
   $entity->attach(Type => "application/pgp-encrypted",
 		  Disposition => "inline",
-		  Filename => "msg.asc",
+		  Filename => "Version.txt",
 		  Data => ["Version: 1",""],
 		  Encoding => "7bit");
   $entity->attach(Type => "application/octet-stream",
 		  Disposition => "inline",
 		  Data => [@ciphertext],
-		  Encoding => "7bit");
+		  Encoding => "7bit",
+		  Filename => "message.asc");
 
   $entity->head->mime_attr("Content-Type","multipart/encrypted");
   $entity->head->mime_attr("Content-Type.protocol","application/pgp-encrypted");
 


SelfReplyAgn

@pnap.net

Here is an updated version of /usr/local/bin/encmaildir.sh I don't plan to feature creep, just wanted to finalize a working solution.

I know this thread is mostly me replying to myself but I wanted to fully document for others down the road. Thanks for humoring me. ;)

For some reason the tab character in previous posts shows up as the HTML entity for tab. Ampersand, hash, 9, semi-colon is tab (\x09 or \t) in the above code snippets.

#!/bin/bash
#
# GPLv2
# GPG Encrypt a Maildir using gpgencmail.pl, removing any S= or W= virtual flags.
# Sep 02, 2011
#
# Change log:
#     Sep 03, 2011
#               - Temporary file is based on file_owner to avoid issues with permission differences.
#               - Temporary file is removed after run.
#               - Optional arguments passed to 'find'.
#               - Full paths to binaries.
#               - Removed unneccessary need of 'cat', 'grep', etc.
#     Sep 04, 2011
#               - Don't remove Dovecot index/uid unless messages have been GPG encrypted.
#               - Adjust file tests to not just use -e
#               - Quote all file operations
#     Sep 05, 2011
#               - Don't arbitrarily copy files, only overwrite the file in ~/Maildir if it differs after calling gpgencmail.pl
#               - Only rebuild the index if we have modified ~/Maildir
 
if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
        /bin/echo "Usage is ./encmaildir.sh    {optional arguments passed to 'find' for messages such as '-mtime 0'}"
        exit 0
fi
 
if [ ! -d "$1" ]; then
        /bin/echo "The directory of '$1' does not exist!"
        exit 0
fi
 
#Does this key exist?
/usr/bin/gpg --list-keys "$2" > /dev/null 2>&1
if [ $? -gt 0 ]; then
     /bin/echo "A GPG key for '$2' could not be found!"
     exit 0
fi
 
#Find all files in the Maildir specified.
/bin/echo "Calling /usr/bin/find \"$1\" -type f -regex '.*/\(cur\|new\)/.*' $4"
/usr/bin/find "$1" -type f -regex '.*/\(cur\|new\)/.*' $4|while read line; do
     /usr/local/bin/gpgencmail.pl --encrypt-mode prefer-inline "$2"  "/tmp/msg_$3"
 
     #Check to see if there are differences between the existing Maildir file and what was created by gpgencmail.pl
     /usr/bin/diff -qa "$line" "/tmp/msg_$3" > /dev/null 2>&1;
     if [ $? -gt 0 ]; then
          #Preserve timestamps, set ownership.
          /bin/chown $3:$3 "/tmp/msg_$3"
          /bin/chmod 600   "/tmp/msg_$3"
          /usr/bin/touch   "/tmp/msg_$3" --reference="$line"
 
          #Unlink the original Maildir message
          /usr/bin/unlink "$line"
 
          #Strip message sizes, retain experimental flags and status flags, and copy the file over.
          STRIPSIZES=$(/bin/echo "$line"|/bin/sed -e 's/W=[[:digit:]]*//' -e 's/S=[[:digit:]]*//' -e 's/,,//' -e 's/,:2/:2/')
          /bin/cp -av "/tmp/msg_$3" "$STRIPSIZES"
 
          #Indexes must be rebuilt, we've modified Maildir.
          /usr/bin/touch "/tmp/rebuild_index_$3"
     else
          /bin/echo "Not copying, no differences between '/tmp/msg_$3' and '$line'"
     fi
 
        #Remove the temporary file
        /usr/bin/unlink "/tmp/msg_$3"
done
 
#Remove Dovecot index and uids for regeneration.
if [ -f "/tmp/rebuild_index_$3" ]; then
        /bin/echo "Removing Dovecot indexes and uids"
        /usr/bin/find "$1" -type f -regex '.*\(dovecot-\|dovecot\.\|\.uidvalidity\).*' -delete
 
        #Remove the temporary file
        /usr/bin/unlink "/tmp/rebuild_index_$3"
else
        /bin/echo "No messages found needing GPG encryption, not removing Dovecot indexes and UIDs."
fi