diff options
-rw-r--r-- | rpkid/rpki/left_right.py | 37 | ||||
-rw-r--r-- | rpkid/rpki/pubproto.py | 117 | ||||
-rwxr-xr-x | rpkid/xml-parse-test.py | 13 |
3 files changed, 149 insertions, 18 deletions
diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py index 46c1c908..d7dd75ef 100644 --- a/rpkid/rpki/left_right.py +++ b/rpkid/rpki/left_right.py @@ -20,9 +20,8 @@ import base64, lxml.etree, time, traceback, os import rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.sax_utils import rpki.https, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log, rpki.roa -xmlns = "http://www.hactrn.net/uris/rpki/left-right-spec/" - -nsmap = { None : xmlns } +left_right_xmlns = "http://www.hactrn.net/uris/rpki/left-right-spec/" +left_right_nsmap = { None : left_right_xmlns } # Enforce strict checking of XML "sender" field in up-down protocol enforce_strict_up_down_xml_sender = False @@ -34,6 +33,9 @@ class base_elt(object): elements = () booleans = () + xmlns = left_right_xmlns + nsmap = left_right_nsmap + def startElement(self, stack, name, attrs): """Default startElement() handler: just process attributes.""" self.read_attrs(attrs) @@ -54,7 +56,7 @@ class base_elt(object): def make_elt(self): """XML element constructor.""" - elt = lxml.etree.Element("{%s}%s" % (xmlns, self.element_name), nsmap = nsmap) + elt = lxml.etree.Element("{%s}%s" % (self.xmlns, self.element_name), nsmap = self.nsmap) for key in self.attributes: val = getattr(self, key, None) if val is not None: @@ -69,12 +71,22 @@ class base_elt(object): if value is None: value = getattr(self, name, None) if value is not None: - lxml.etree.SubElement(elt, "{%s}%s" % (xmlns, name), nsmap = nsmap).text = base64.b64encode(value) + lxml.etree.SubElement(elt, "{%s}%s" % (self.xmlns, name), nsmap = self.nsmap).text = base64.b64encode(value) def __str__(self): """Convert a base_elt object to string format.""" lxml.etree.tostring(self.toXML(), pretty_print = True, encoding = "us-ascii") + @classmethod + def make_pdu(cls, **kargs): + """Generic left-right PDU constructor.""" + self = cls() + for k,v in kargs.items(): + if isinstance(v, bool): + v = 1 if v else 0 + setattr(self, k, v) + return self + class data_elt(base_elt, rpki.sql.sql_persistant): """Virtual class for top-level left-right protocol data elements.""" @@ -86,16 +98,6 @@ class data_elt(base_elt, rpki.sql.sql_persistant): """Return BSC object to which this object links.""" return bsc_elt.sql_fetch(self.gctx, self.bsc_id) - @classmethod - def make_pdu(cls, **kargs): - """Generic left-right PDU constructor.""" - self = cls() - for k,v in kargs.items(): - if isinstance(v, bool): - v = 1 if v else 0 - setattr(self, k, v) - return self - def make_reply(self, r_pdu = None): """Construct a reply PDU.""" if r_pdu is None: @@ -1025,6 +1027,9 @@ class report_error_elt(base_elt): class msg(list): """Left-right PDU.""" + xmlns = left_right_xmlns + nsmap = left_right_nsmap + ## @var version # Protocol version version = 1 @@ -1058,7 +1063,7 @@ class msg(list): def toXML(self): """Generate left-right PDU.""" - elt = lxml.etree.Element("{%s}msg" % (xmlns), nsmap = nsmap, version = str(self.version), type = self.type) + elt = lxml.etree.Element("{%s}msg" % (self.xmlns), nsmap = self.nsmap, version = str(self.version), type = self.type) elt.extend([i.toXML() for i in self]) return elt diff --git a/rpkid/rpki/pubproto.py b/rpkid/rpki/pubproto.py new file mode 100644 index 00000000..39373f5a --- /dev/null +++ b/rpkid/rpki/pubproto.py @@ -0,0 +1,117 @@ +# $Id$ + +# Copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ARIN 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. + +"""RPKI "publication" protocol. + +At the moment this module imports and tweaks classes from +rpki.left_right. The code in question should be refactored at some +point to make the imports cleaner, but it's faster to write it this +way and see which things I end up using before spending time on +refactoring stuff I don't really need.... +""" + +import base64, lxml.etree, time, traceback, os +import rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.sax_utils +import rpki.https, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log, rpki.roa +import rpki.left_right + +pubproto_xmlns = "http://www.hactrn.net/uris/rpki/publication-spec/" +pubproto_nsmap = { None : pubproto_xmlns } + +class data_elt(rpki.left_right.base_elt): + """Virtual class for top-level publication protocol data elements. + + This is a placeholder. It will probably end up being a mixin that + uses rpki.sql.sql_persistant, just like its counterpart in + rpki.left_right, but wait and see. + """ + + xmlns = pubproto_xmlns + nsmap = pubproto_nsmap + +class client_elt(data_elt): + """<client/> element.""" + + element_name = "client" + attributes = ("action", "tag", "client_id", "base_uri") + elements = ("bpki_cert", "bpki_glue") + + bpki_cert = None + bpki_glue = None + + def startElement(self, stack, name, attrs): + """Handle <client/> element.""" + if name not in ("bpki_cert", "bpki_glue"): + assert name == self.element_name, "Unexpected name %s, stack %s" % (name, stack) + self.read_attrs(attrs) + + def endElement(self, stack, name, text): + """Handle <client/> element.""" + if name == "bpki_cert": + self.bpki_cert = rpki.x509.X509(Base64 = text) + self.clear_https_ta_cache = True + elif name == "bpki_glue": + self.bpki_glue = rpki.x509.X509(Base64 = text) + self.clear_https_ta_cache = True + else: + assert name == self.element_name, "Unexpected name %s, stack %s" % (name, stack) + stack.pop() + + def toXML(self): + """Generate <client/> element.""" + elt = self.make_elt() + if self.bpki_cert and not self.bpki_cert.empty(): + self.make_b64elt(elt, "bpki_cert", self.bpki_cert.get_DER()) + if self.bpki_glue and not self.bpki_glue.empty(): + self.make_b64elt(elt, "bpki_glue", self.bpki_glue.get_DER()) + return elt + +class report_error_elt(rpki.left_right.report_error_elt): + """<report_error/> element. + + For now this is identical to its left_right equivilent. + """ + + pass + +class msg(rpki.left_right.msg): + """Publication PDU.""" + + xmlns = pubproto_xmlns + nsmap = pubproto_nsmap + + ## @var version + # Protocol version + version = 1 + + ## @var pdus + # Dispatch table of PDUs for this protocol. + pdus = dict((x.element_name, x) + for x in (client_elt, report_error_elt)) + +class sax_handler(rpki.sax_utils.handler): + """SAX handler for publication protocol.""" + + pdu = msg + name = "msg" + version = "1" + +class cms_msg(rpki.x509.XML_CMS_object): + """Class to hold a CMS-signed publication PDU.""" + + encoding = "us-ascii" + schema = rpki.relaxng.publication + saxify = sax_handler.saxify diff --git a/rpkid/xml-parse-test.py b/rpkid/xml-parse-test.py index 15e787da..e8747f65 100755 --- a/rpkid/xml-parse-test.py +++ b/rpkid/xml-parse-test.py @@ -15,9 +15,9 @@ # PERFORMANCE OF THIS SOFTWARE. import glob, xml.sax, lxml.etree, lxml.sax, POW, POW.pkix -import rpki.up_down, rpki.left_right, rpki.relaxng +import rpki.up_down, rpki.left_right, rpki.pubproto, rpki.relaxng -verbose = False +verbose = True def test(fileglob, rng, sax_handler, encoding, tester = None): files = glob.glob(fileglob) @@ -73,6 +73,9 @@ def lr_tester(elt_in, elt_out, msg): pprint(((obj.bpki_cert, "Certificate"), (obj.bpki_glue, "Glue"))) +def pp_tester(elt_in, elt_out, msg): + assert isinstance(msg, rpki.pubproto.msg) + test(fileglob = "up-down-protocol-samples/*.xml", rng = rpki.relaxng.up_down, sax_handler = rpki.up_down.sax_handler, @@ -84,3 +87,9 @@ test(fileglob = "left-right-protocol-samples/*.xml", sax_handler = rpki.left_right.sax_handler, encoding = "us-ascii", tester = lr_tester) + +test(fileglob = "publication-protocol-samples/*.xml", + rng = rpki.relaxng.publication, + sax_handler = rpki.pubproto.sax_handler, + encoding = "us-ascii", + tester = pp_tester) |