Skip to content

Commit

Permalink
Fixed wrapped message parsing and generation, enabled CRL check
Browse files Browse the repository at this point in the history
  • Loading branch information
catalinb committed Oct 9, 2017
1 parent ce29e5b commit fac152e
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 31 deletions.
10 changes: 6 additions & 4 deletions src/smime/certvld.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@ def verify_cert(cert, local_domain, addr):
import subprocess, os, glob
ca_path = os.path.join(CADIR, 'trust', local_domain)
logging.debug('Verifying certificate expiration, signature, revocation and path: %s', addr)
command = ('/usr/bin/env', 'openssl', 'verify', '-CApath', ca_path)
command = ('/usr/bin/env', 'openssl', 'verify', '-crl_check', '-CApath', ca_path)

issuer_hash = hex(cert.get_issuer().as_hash())[2:-1]
if len(glob.glob(os.path.join(ca_path, issuer_hash, '.r*'))):
command.append('-crl_check')
#issuer_hash = hex(cert.get_issuer().as_hash())[2:-1]
#logging.debug('Issuer hash: %s', str(issuer_hash))
#if len(glob.glob(os.path.join(ca_path, issuer_hash, '.r*'))):
# command.append('-crl_check')
# logging.debug('Verifing CRL too')
proc = subprocess.Popen(command, stdin = subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc.stdin.write(cert.as_pem())
stdout, stderr = proc.communicate()
Expand Down
4 changes: 3 additions & 1 deletion src/smime/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
limitations under the License.
"""

send_dispatched_mdn = True
send_dispatched_mdn = False
log_mdn = True
mdn_log_file = "/tmp/mdn.log"
14 changes: 10 additions & 4 deletions src/smime/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@
from M2Crypto import BIO, SMIME, X509
import subprocess, threading, logging

RFC822 = """content-type: message/rfc822
%s
"""

def writer(proc, message):
proc.stdin.write(message)
proc.stdin.close()

def to_smime(message, sender_key, sender_cert, recipient_cert, cipher = 'aes_128_cbc'):
try:
message = RFC822 % message
smime = SMIME.SMIME()
#smime.pkey = sender_key
#smime.x509 = sender_cert
signature = ''
logging.debug('Signing outgoing message')
command = ('/usr/bin/env', 'openssl', 'cms', '-sign', '-signer', sender_cert , '-inkey', sender_key)
command = ('/usr/bin/env', 'openssl', 'cms', '-sign', '-signer', sender_cert , '-inkey', sender_key, '-md', 'sha256')
proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=-1)
#proc.stdin.write(message)
#signature, stderr = proc.communicate()
Expand All @@ -38,7 +44,7 @@ def to_smime(message, sender_key, sender_cert, recipient_cert, cipher = 'aes_128
signature += line
thread.join()
logging.debug('Message signed')

logging.debug('Encrypting message')

#signature = smime.sign(BIO.MemoryBuffer(message), flags=SMIME.PKCS7_DETACHED)
Expand All @@ -50,8 +56,8 @@ def to_smime(message, sender_key, sender_cert, recipient_cert, cipher = 'aes_128
cert_stack.push(X509.load_cert_der_string(recipient_cert))

smime.set_x509_stack(cert_stack)
smime.set_cipher(SMIME.Cipher(cipher))
smime.set_cipher(SMIME.Cipher(cipher))

message_encrypted = smime.encrypt(message_signed)

out = BIO.MemoryBuffer()
Expand Down
14 changes: 7 additions & 7 deletions src/smime/mdn.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import email.utils, time, random

NOTIFICATION_PROCESSED = """
Reporting-UA: %s; Abelian\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: %s\r\nDisposition: automatic-action/MDN-sent-automatically;processed
Reporting-UA: %s; Abelian\r\nFinal-Recipient: rfc822; %s\r\nOriginal-Message-ID: %s\r\nDisposition: automatic-action/MDN-sent-automatically;processed
"""
NOTIFICATION_DISPATCHED = """
Reporting-UA: %s; Abelian\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: %s\r\nX-DIRECT-FINAL-DESTINATION-DELIVERY: \r\nDisposition: automatic-action/MDN-sent-automatically;dispatched
Expand All @@ -33,7 +33,7 @@ def make_mdn(sender, recipient, orig_message_id, subject, disposition_type):
msg['Content-Type'] = 'multipart/report; report-type=disposition-notification'
msg['From'] = '<%s>' % sender
msg['To'] = '<%s>' % recipient
msg['Date'] = email.utils.formatdate()
msg['Date'] = email.utils.formatdate().replace('-0000','+0000 (UTC)')
msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain)
msg['Message-ID'] = msg_id
if (disposition_type == 'processed'):
Expand All @@ -42,8 +42,8 @@ def make_mdn(sender, recipient, orig_message_id, subject, disposition_type):
msg['Subject'] = 'Delivered: %s' % subject

txt = Message()
txt['Content-Type'] = 'text/plain;charset=us-ascii'
txt['Content-Transfer-Encoding'] = '7bit'
#txt['Content-Type'] = 'text/plain;charset=us-ascii'
#txt['Content-Transfer-Encoding'] = '7bit'
if (disposition_type == 'processed'):
txt.set_payload('Your message was successfully processed.')
else:
Expand All @@ -52,11 +52,11 @@ def make_mdn(sender, recipient, orig_message_id, subject, disposition_type):

dn = Message()
dn['Content-Type'] = 'message/disposition-notification'
dn['Content-Transfer-Encoding'] = '7bit'
#dn['Content-Transfer-Encoding'] = '7bit'
if (disposition_type == 'processed'):
dn.set_payload(NOTIFICATION_PROCESSED % (sender.split('@',1)[1],sender,orig_message_id))
dn.set_payload(NOTIFICATION_PROCESSED % (domain,sender,orig_message_id))
else:
dn.set_payload(NOTIFICATION_DISPATCHED % (sender.split('@',1)[1],sender,orig_message_id))
dn.set_payload(NOTIFICATION_DISPATCHED % (domain,sender,orig_message_id))
msg.attach(dn)
msg_string = msg.as_string()
msg_string = msg_string.replace('\r\n', '\n')
Expand Down
36 changes: 21 additions & 15 deletions src/smime/smimercv.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
TEMPDIR = '/var/spool/direct/tmp/'
CADIR = '/var/spool/direct/ca'

TEMPLATE = """
-----BEGIN PKCS7-----
TEMPLATE = """-----BEGIN PKCS7-----
%s
-----END PKCS7-----
"""
Expand All @@ -43,10 +42,7 @@ def process_message(queue_id, recipient, sender, message):
subject = None

mail = Parser().parsestr(message, True)
if mail['message-id'] != None:
message_id = mail['message-id']
if mail['subject'] != None:
subject = mail['subject']


logging.debug('Decrypting incoming message: %s', queue_id)
command = ('/usr/bin/env', 'openssl', 'cms', '-decrypt', '-recip', recipient_cert , '-inkey', recipient_key)
Expand All @@ -56,8 +52,6 @@ def process_message(queue_id, recipient, sender, message):

mail = Parser().parsestr(msg_sign)

if (subject == None) and (mail['subject'] != None):
subject = mail['subject']
is_mdn = False
sig = None
dispatch_mdn_request = False
Expand Down Expand Up @@ -94,9 +88,11 @@ def process_message(queue_id, recipient, sender, message):
sig = TEMPLATE % sig
break
if sig == None:
logging.debug('Missing signature. Exiting')
return None

if not verify_sig_cert(sig, sender, recipient_domain):
logging.debug('Invalid signing certificate. Exiting')
return None

command = ('/usr/bin/env', 'openssl', 'cms', '-verify', '-CApath', ca_path)
Expand All @@ -117,7 +113,7 @@ def save_message(queue_id, recipient, sender, msg_orig, msg_plain):
guid = str(uuid.uuid4())
cur.execute("INSERT INTO messages(queue_id,recipient,sender,original,msg,domain,guid) VALUES(%s,%s,%s,%s,%s,%s,%s);",(queue_id,recipient,sender,msg_orig,msg_plain,domain,guid))
logging.debug('Inserted new mail with guid ' + guid);

logging.debug('%s: from=<%s>, to=<%s>, status=received (stored as %s)',queue_id,sender,recipient,guid)
conn.commit()

def send_mdn(sender, recipient, orig_message_id, subject, msg_plain, disposition_type):
Expand All @@ -133,11 +129,15 @@ def verify_sig_cert(sig, sender, local_domain):
certs = p7.get0_signers(X509.X509_Stack())
if len(certs) == 0:
return False
if not certvld.verify_cert(certs[0], local_domain, sender):
return False
if not certvld.verify_binding(certs[0], sender, sender.partition('@')[2], True):
return False
return True
for cert in certs:
if certvld.verify_cert(cert, local_domain, sender) and certvld.verify_binding(cert, sender, sender.partition('@')[2], True):
return True
return False
#if not certvld.verify_cert(certs[0], local_domain, sender):
# return False
#if not certvld.verify_binding(certs[0], sender, sender.partition('@')[2], True):
# return False
#return True

if __name__ == "__main__":
import logging.handlers,platform
Expand All @@ -162,10 +162,16 @@ def verify_sig_cert(sig, sender, local_domain):

plain = retval[0]
is_mdn = retval[1]
message_id = retval[2]
message_id = None
subject = retval[3]
dispatch_mdn_request = retval[4]

mail = Parser().parsestr(plain, True)
logging.debug('Content-type: %s', mail.get_content_type())
if mail.get_content_type() == 'message/rfc822':
mail = Parser().parsestr(mail.get_payload(), True)
message_id = mail['message-id']
logging.debug('MDN message-id: %s', message_id)

if not is_mdn: #not MDN
mdn_rc = send_mdn(recip, sender, message_id, subject, plain, 'processed')
Expand Down
1 change: 1 addition & 0 deletions src/smime/smimesend.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def send_message(sender, recipient, message_id, message):
err = send_message(sender, recipient[1], message_id, eml)
if err != 0:
retval += recipient[1] + '; '
logging.warning('0: from=<%s>, to=<%s>, message-id=%s, status=failed (failure)', sender, recipient[1], message_id)
if retval != '':
retval = '[smime_errors] Could not send DIRECT mail to the following recipient(s): ' + retval
exit(retval)
Expand Down

0 comments on commit fac152e

Please sign in to comment.