
commit
782cda3639
4 changed files with 161 additions and 0 deletions
@ -0,0 +1,43 @@
|
||||
import os |
||||
import subprocess |
||||
|
||||
def public_keys( keyhome ): |
||||
cmd = '/usr/bin/gpg --homedir %s --list-keys --with-colons' % keyhome |
||||
p = subprocess.Popen( cmd.split(' '), stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) |
||||
p.wait() |
||||
keys = list() |
||||
for line in p.stdout.readlines(): |
||||
if line[0:3] == 'uid' or line[0:3] == 'pub': |
||||
key = line.split('<')[1].split('>')[0] |
||||
if keys.count(key) == 0: |
||||
keys.append(key) |
||||
return keys |
||||
|
||||
class GPGEncryptor: |
||||
def __init__(self, keyhome, recipients = None): |
||||
self._keyhome = keyhome |
||||
self._message = '' |
||||
self._recipients = list() |
||||
if recipients != None: |
||||
self._recipients.extend(recipients) |
||||
|
||||
def update(self, message): |
||||
self._message += message |
||||
|
||||
def encrypt(self): |
||||
p = subprocess.Popen( self._command(), stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE ) |
||||
(stdin, stdout, stderr) = (p.stdin, p.stdout, p.stderr) |
||||
|
||||
# Write the data |
||||
stdin.write(self._message) |
||||
stdin.close() |
||||
|
||||
# Read the encrypted data |
||||
p.wait() |
||||
encdata = stdout.read() |
||||
|
||||
return encdata |
||||
|
||||
def _command(self): |
||||
cmd = "/usr/bin/gpg --homedir %s --batch --yes --pgp7 --no-secmem-warning -a -e -r %s" % (self._keyhome, ' -r '.join(self._recipients)) |
||||
return cmd.split() |
@ -0,0 +1,26 @@
|
||||
1) Ensure that GPG is installed and configured. |
||||
a) Make sure public keys for all of your potential recipients are |
||||
available in the GPG home directory you use in step 2 |
||||
2) Configure /etc/gpg-mailgate.conf based on the provided sample config |
||||
3) Place gpg-mailgate.py in /usr/local/bin/ |
||||
4) Place the GnuPG directory in /usr/local/lib/python2.5/site-packages |
||||
5) Add the following to the end of /etc/postfix/master.cf |
||||
|
||||
gpg-mailgate unix - n n - - pipe |
||||
flags= user=nobody argv=/usr/local/bin/gpg-mailgate.py |
||||
|
||||
127.0.0.1:10028 inet n - n - 10 smtpd |
||||
-o content_filter= |
||||
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks |
||||
-o smtpd_helo_restrictions= |
||||
-o smtpd_client_restrictions= |
||||
-o smtpd_sender_restrictions= |
||||
-o smtpd_recipient_restrictions=permit_mynetworks,reject |
||||
-o mynetworks=127.0.0.0/8 |
||||
-o smtpd_authorized_xforward_hosts=127.0.0.0/8 |
||||
|
||||
6) Add the following to /etc/postfix/main.cf |
||||
|
||||
content_filter = gpg-mailgate |
||||
|
||||
7) Restart postfix. |
@ -0,0 +1,23 @@
|
||||
[default] |
||||
add_header = yes |
||||
domains = example.com,corp.org |
||||
|
||||
[gpg] |
||||
keyhome = /var/gpg/.gnupg |
||||
|
||||
[logging] |
||||
file = /tmp/gpg-mailgate.log |
||||
|
||||
[relay] |
||||
host = 127.0.0.1 |
||||
port = 10028 |
||||
|
||||
[keymap] |
||||
# You can find these by running the following command: |
||||
# gpg --list-keys --keyid-format long user@example.com |
||||
# Which will return output similar to: |
||||
# pub 1024D/AAAAAAAAAAAAAAAA 2007-10-22 |
||||
# uid Joe User <user@example.com> |
||||
# sub 2048g/BBBBBBBBBBBBBBBB 2007-10-22 |
||||
# You want the AAAAAAAAAAAAAAAA not BBBBBBBBBBBBBBBB. |
||||
#user@example.com <gpg key id> |
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/python |
||||
|
||||
from ConfigParser import RawConfigParser |
||||
import email |
||||
import GnuPG |
||||
import smtplib |
||||
import sys |
||||
|
||||
# Read configuration from /etc/gpg-mailgate.conf |
||||
_cfg = RawConfigParser() |
||||
_cfg.read('/etc/gpg-mailgate.conf') |
||||
cfg = dict() |
||||
for sect in _cfg.sections(): |
||||
cfg[sect] = dict() |
||||
for (name, value) in _cfg.items(sect): |
||||
cfg[sect][name] = value |
||||
|
||||
# Read e-mail from stdin |
||||
raw = sys.stdin.read() |
||||
raw_message = email.message_from_string( raw ) |
||||
from_addr = raw_message['From'] |
||||
to_addrs = map(lambda x: x.strip(), raw_message['To'].split(',')) |
||||
if raw_message.has_key('Cc'): |
||||
to_addrs.extend( map(lambda x: x.strip(), raw_message['Cc'].split(','))) |
||||
if raw_message.has_key('Bcc'): |
||||
to_addrs.extend( map(lambda x: x.strip(), raw_message['Bcc'].split(','))) |
||||
|
||||
def send_msg( message, recipients = None ): |
||||
if recipients == None: |
||||
recipients = to_addrs |
||||
relay = (cfg['relay']['host'], int(cfg['relay']['port'])) |
||||
smtp = smtplib.SMTP(relay[0], relay[1]) |
||||
smtp.sendmail( from_addr, recipients, message.as_string() ) |
||||
sys.exit(0) |
||||
|
||||
gpg_to = list() |
||||
keys = GnuPG.public_keys( cfg['gpg']['keyhome'] ) |
||||
for to in to_addrs: |
||||
domain = to.split('@')[1] |
||||
if domain in cfg['default']['domains'].split(','): |
||||
if to in keys: |
||||
gpg_to.append( (to, to) ) |
||||
elif cfg.has_key('keymap') and cfg['keymap'].has_key(to): |
||||
gpg_to.append( (to, cfg['keymap'][to]) ) |
||||
|
||||
if gpg_to == list(): |
||||
if cfg['default'].has_key('add_header') and cfg['default']['add_header'] == 'yes': |
||||
raw_message['X-GPG-Mailgate'] = 'Not encrypted, public key not found' |
||||
send_msg( raw_message ) |
||||
|
||||
if raw_message.is_multipart(): |
||||
payload = list() |
||||
for part in raw_message.get_payload(): |
||||
if part.get_content_type() == "text/plain": |
||||
payload.append(part) |
||||
raw_message.set_payload( payload ) |
||||
|
||||
if cfg.has_key('logging') and cfg['logging'].has_key('file'): |
||||
log = open(cfg['logging']['file'], 'a') |
||||
log.write("Encrypting email to: %s\n" % ' '.join( map(lambda x: x[0], gpg_to) )) |
||||
log.close() |
||||
|
||||
if cfg['default'].has_key('add_header') and cfg['default']['add_header'] == 'yes': |
||||
raw_message['X-GPG-Mailgate'] = 'Encrypted by GPG Mailgate 0.1' |
||||
|
||||
gpg = GnuPG.GPGEncryptor( cfg['gpg']['keyhome'], map(lambda x: x[1], gpg_to) ) |
||||
gpg.update( raw_message.get_payload() ) |
||||
raw_message.set_payload( gpg.encrypt() ) |
||||
send_msg( raw_message, map(lambda x: x[0], gpg_to) ) |
Loading…
Reference in new issue