137 lines
5 KiB
Python
137 lines
5 KiB
Python
#!/usr/bin/python
|
|
|
|
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
|
|
|
|
import logging
|
|
|
|
import lacre
|
|
import lacre.config as conf
|
|
|
|
def send_msg( message, from_addr, recipients = None ):
|
|
if conf.config_item_set('relay', 'host') and conf.config_item_set('relay', 'enc_port'):
|
|
relay = (conf.get_item('relay', 'host'), int(conf.get_item('relay', 'enc_port')))
|
|
smtp = smtplib.SMTP(relay[0], relay[1])
|
|
smtp.sendmail( from_addr, recipients, message.as_string() )
|
|
else:
|
|
LOG.info("Could not send mail due to wrong configuration")
|
|
|
|
if __name__ == "__main__":
|
|
# try:
|
|
conf.load_config()
|
|
lacre.init_logging(conf.get_item('logging', 'config'))
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
CERT_PATH = conf.get_item('smime', 'cert_path') + '/'
|
|
|
|
# Read e-mail from stdin
|
|
raw = sys.stdin.read()
|
|
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
|
|
break
|
|
# 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]
|
|
break
|
|
|
|
if sign_part == None:
|
|
LOG.info("Unable to find PKCS7 signature or public PGP key in registration email")
|
|
|
|
failure_msg = file( conf.get_item('mailregister', 'mail_templates') + "/registrationError.md").read()
|
|
msg = MIMEMultipart("alternative")
|
|
msg["From"] = conf.get_item('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, conf.get_item('mailregister', 'register_email'), [from_addr])
|
|
sys.exit(0)
|
|
|
|
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 range(0, len(raw_sig), 76))
|
|
|
|
# now, wrap the signature in a PKCS7 block
|
|
sig = """
|
|
-----BEGIN PKCS7-----
|
|
%s
|
|
-----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]
|
|
|
|
#Save certificate compatible to RFC 2821
|
|
splitted_from_addr = from_addr.split('@')
|
|
processed_from_addr = splitted_from_addr[0] + '@' + splitted_from_addr[1].lower()
|
|
|
|
signing_cert.save(os.path.join(CERT_PATH, processed_from_addr))
|
|
|
|
# format in user-specific data
|
|
# sending success mail only for S/MIME as GPGMW handles this on its own
|
|
success_msg = file(conf.get_item('mailregister', 'mail_templates')+"/registrationSuccess.md").read()
|
|
success_msg = success_msg.replace("[:FROMADDRESS:]", from_addr)
|
|
|
|
msg = MIMEMultipart("alternative")
|
|
msg["From"] = conf.get_item('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, conf.get_item('mailregister', 'register_email'), [from_addr])
|
|
|
|
LOG.info("S/MIME Registration succeeded")
|
|
elif sign_type == 'pgp':
|
|
# send POST to gpg-mailgate webpanel
|
|
sig = sign_part
|
|
payload = {'email': from_addr, 'key': sig}
|
|
r = requests.post(conf.get_item('mailregister', 'webpanel_url'), data=payload)
|
|
|
|
if r.status_code != 200:
|
|
LOG.info("Could not hand registration over to GPGMW. Error: %s" % r.status_code)
|
|
error_msg = open(conf.get_item('mailregister', 'mail_templates')+"/gpgmwFailed.md").read()
|
|
error_msg = error_msg.replace("[:FROMADDRESS:]", from_addr)
|
|
|
|
msg = MIMEMultipart("alternative")
|
|
msg["From"] = conf.get_item('mailregister', 'register_email')
|
|
msg["To"] = from_addr
|
|
msg["Subject"] = "PGP key registration failed"
|
|
|
|
msg.attach(MIMEText(error_msg, 'plain'))
|
|
msg.attach(MIMEText(markdown.markdown(error_msg), 'html'))
|
|
|
|
send_msg(msg, conf.get_item('mailregister', 'register_email'), [from_addr])
|
|
else:
|
|
LOG.info("PGP registration is handed over to GPGMW")
|
|
# except:
|
|
# LOG.info("Registration exception")
|
|
# sys.exit(0)
|