aboutsummaryrefslogtreecommitdiff
path: root/potpourri/format-application-x-rpki.py
diff options
context:
space:
mode:
Diffstat (limited to 'potpourri/format-application-x-rpki.py')
-rw-r--r--potpourri/format-application-x-rpki.py132
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()