124 lines
4.3 KiB

from ConfigParser import RawConfigParser
import email, os, smtplib, sys, traceback, markdown, syslog, requests
from M2Crypto import BIO, Rand, SMIME, X509
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# Read configuration from /etc/gpg-mailgate.conf
_cfg = RawConfigParser()'/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
def log(msg):
if cfg.has_key('logging') and cfg['logging'].has_key('file'):
if cfg['logging']['file'] == "syslog":
syslog.syslog(syslog.LOG_INFO | syslog.LOG_MAIL, msg)
logfile = open(cfg['logging']['file'], 'a')
logfile.write(msg + "\n")
CERT_PATH = cfg['smime']['cert_path']+"/"
def send_msg( message, from_addr, recipients = None ):
relay = ("", 10028)
smtp = smtplib.SMTP(relay[0], relay[1])
smtp.sendmail( from_addr, recipients, message.as_string() )
if __name__ == "__main__":
# try:
# Read e-mail from stdin
raw =
register_msg = email.message_from_string( raw )
from_addr = email.utils.parseaddr(register_msg['From'])[1]
sign_part = None
for msg_part in register_msg.walk():
if msg_part.get_content_type().lower() == "application/pkcs7-signature" or msg_part.get_content_type().lower() == "application/x-pkcs7-signature":
sign_type = 'smime'
sign_part = msg_part
# This may cause that a non ASCII-armored key will be seen as valid. Other solution is not that efficient though
#elif msg_part.get_content_type().lower() == "application/pgp-keys":
# sign_type = 'pgp'
# sign_part = msg_part.get_payload()
# break
elif "-----BEGIN PGP PUBLIC KEY BLOCK-----" in msg_part.get_payload() and "-----END PGP PUBLIC KEY BLOCK-----" in msg_part.get_payload():
msg_content = msg_part.get_payload()
start = msg_content.find("-----BEGIN PGP PUBLIC KEY BLOCK-----")
end = msg_content.find("-----END PGP PUBLIC KEY BLOCK-----")
sign_type = 'pgp'
sign_part = msg_content[start:end + 34]
if sign_part == None:
log("Unable to find PKCS7 signature or public PGP key in registration email")
failure_msg = file( cfg['mailregister']['mail_templates'] + "/").read()
msg = MIMEMultipart("alternative")
msg["From"] = cfg['mailregister']['register_email']
msg["To"] = from_addr
msg["Subject"] = "S/MIME / OpenPGP registration failed"
msg.attach(MIMEText(failure_msg, 'plain'))
msg.attach(MIMEText(markdown.markdown(failure_msg), 'html'))
send_msg(msg, cfg['mailregister']['register_email'], [from_addr])
if sign_type == 'smime':
raw_sig = sign_part.get_payload().replace("\n","")
# re-wrap signature so that it fits base64 standards
cooked_sig = '\n'.join(raw_sig[pos:pos+76] for pos in xrange(0, len(raw_sig), 76))
# now, wrap the signature in a PKCS7 block
sig = """
-----BEGIN PKCS7-----
-----END PKCS7-----
""" % cooked_sig
# and load it into an SMIME p7 object through the BIO I/O buffer:
buf = BIO.MemoryBuffer(sig)
p7 = SMIME.load_pkcs7_bio(buf)
sk = X509.X509_Stack()
signers = p7.get0_signers(sk)
signing_cert = signers[0], from_addr))
# format in user-specific data
# sending success mail only for S/MIME as GPGMW handles this on its own
success_msg = file(cfg['mailregister']['mail_templates']+"/").read()
success_msg = success_msg.replace("[:FROMADDRESS:]",from_addr)
msg = MIMEMultipart("alternative")
msg["From"] = cfg['mailregister']['register_email']
msg["To"] = from_addr
msg["Subject"] = "S/MIME certificate registration succeeded"
msg.attach(MIMEText(success_msg, 'plain'))
msg.attach(MIMEText(markdown.markdown(success_msg), 'html'))
send_msg(msg, cfg['mailregister']['register_email'], [from_addr])
log("S/MIME Registration succeeded")
elif sign_type == 'pgp':
# send POST to gpg-mailgate webpanel
sig = sign_part
payload = {'email': from_addr, 'key': sig}
r =['mailregister']['webpanel_url'], data=payload)
log("PGP registration is handed over to GPGMW")
# except:
# log("Registration exception")
# sys.exit(0)