diff options
Diffstat (limited to 'potpourri/format-application-x-rpki.py')
-rw-r--r-- | potpourri/format-application-x-rpki.py | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/potpourri/format-application-x-rpki.py b/potpourri/format-application-x-rpki.py new file mode 100644 index 00000000..184103f9 --- /dev/null +++ b/potpourri/format-application-x-rpki.py @@ -0,0 +1,132 @@ +# $Id$ +# +# Copyright (C) 2014 Dragon Research Labs ("DRL") +# Portions copyright (C) 2010--2012 Internet Systems Consortium ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notices and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND DRL AND ISC DISCLAIM ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR +# ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +""" +Take the basic application/x-rpki messages that rpkid and friends +log and translate them into a text version that's easier to search, +without losing any of the original data. We use MH for the output +format because nmh makes a handy viewer. +""" + +import email.mime +import email.mime.application +import email.mime.text +import email.mime.multipart +import email.utils +import email.encoders +import mailbox +import rpki.POW +import lxml.etree +import argparse +import sys +import base64 + +parser = argparse.ArgumentParser(description = __doc__) +parser.add_argument("-i", "--input", required = True, + help = "input Maildir") +parser.add_argument("-m", "--mark", action = "store_true", + help = "mark seen messages") +parser.add_argument("-k", "--kill", action = "store_true", + help = "kill seen messages") +parser.add_argument("-o", "--output", required = True, + help = "output MH folder") +parser.add_argument("-t", "--tag", + default = "{http://www.apnic.net/specs/rescerts/up-down/}message", + help = "XML namespace tag for an input message") +parser.add_argument("-u", "--unseen", action = "store_true", + help = "only process unseen messages") +args = parser.parse_args() + +def pprint_cert(b64): + return rpki.POW.X509.derRead(base64.b64decode(b64)).pprint() + +def up_down(): + msg["X-RPKI-Up-Down-Type"] = xml.get("type") + msg["X-RPKI-Up-Down-Sender"] = xml.get("sender") + msg["X-RPKI-Up-Down-Recipient"] = xml.get("recipient") + msg["Subject"] = "Up-down %s %s => %s" % (xml.get("type"), xml.get("sender"), xml.get("recipient")) + for x in xml: + if x.tag.endswith("class"): + for y in x: + if y.tag.endswith("certificate") or y.tag.endswith("issuer"): + msg.attach(email.mime.text.MIMEText(pprint_cert(y.text))) + +def left_right(): + msg["X-RPKI-Left-Right-Type"] = xml.get("type") + msg["Subject"] = "Left-right %s" % xml.get("type") + +def publication(): + msg["X-RPKI-Left-Right-Type"] = xml.get("type") + msg["Subject"] = "Publication %s" % xml.get("type") + +dispatch = { "{http://www.apnic.net/specs/rescerts/up-down/}message" : up_down, + "{http://www.hactrn.net/uris/rpki/left-right-spec/}msg" : left_right, + "{http://www.hactrn.net/uris/rpki/publication-spec/}msg" : publication } + +def fix_headers(): + if "X-RPKI-PID" in srcmsg or "X-RPKI-Object" in srcmsg: + msg["X-RPKI-PID"] = srcmsg["X-RPKI-PID"] + msg["X-RPKI-Object"] = srcmsg["X-RPKI-Object"] + else: + words = srcmsg["Subject"].split() + msg["X-RPKI-PID"] = words[1] + msg["X-RPKI-Object"] = " ".join(words[4:]) + +destination = None +source = None +try: + destination = mailbox.MH(args.output, factory = None, create = True) + source = mailbox.Maildir(args.input, factory = None) + + for srckey, srcmsg in source.iteritems(): + if args.unseen and "S" in srcmsg.get_flags(): + continue + assert not srcmsg.is_multipart() and srcmsg.get_content_type() == "application/x-rpki" + payload = srcmsg.get_payload(decode = True) + cms = rpki.POW.CMS.derRead(payload) + txt = cms.verify(rpki.POW.X509Store(), None, rpki.POW.CMS_NOCRL | rpki.POW.CMS_NO_SIGNER_CERT_VERIFY | rpki.POW.CMS_NO_ATTR_VERIFY | rpki.POW.CMS_NO_CONTENT_VERIFY) + xml = lxml.etree.fromstring(txt) + tag = xml.tag + if args.tag and tag != args.tag: + continue + msg = email.mime.multipart.MIMEMultipart("related") + msg["X-RPKI-Tag"] = tag + for i in ("Date", "Message-ID", "X-RPKI-Timestamp"): + msg[i] = srcmsg[i] + fix_headers() + if tag in dispatch: + dispatch[tag]() + if "Subject" not in msg: + msg["Subject"] = srcmsg["Subject"] + msg.attach(email.mime.text.MIMEText(txt)) + msg.attach(email.mime.application.MIMEApplication(payload, "x-rpki")) + msg.epilogue = "\n" # Force trailing newline + key = destination.add(msg) + print "Added", key + if args.kill: + del source[srckey] + elif args.mark: + srcmsg.set_subdir("cur") + srcmsg.add_flag("S") + source[srckey] = srcmsg + +finally: + if destination: + destination.close() + if source: + source.close() |