aboutsummaryrefslogtreecommitdiff
path: root/rpki
diff options
context:
space:
mode:
Diffstat (limited to 'rpki')
-rw-r--r--rpki/left_right.py142
-rw-r--r--rpki/rpkid.py162
-rw-r--r--rpki/xml_utils.py91
3 files changed, 165 insertions, 230 deletions
diff --git a/rpki/left_right.py b/rpki/left_right.py
index 09d8a5ca..653a2eaf 100644
--- a/rpki/left_right.py
+++ b/rpki/left_right.py
@@ -1373,100 +1373,6 @@ class list_ee_certificate_requests_elt(rpki.xml_utils.base_elt, left_right_names
elt.set("valid_until", self.valid_until.toXMLtime())
return elt
-class list_published_objects_elt(rpki.xml_utils.text_elt, left_right_namespace):
- """
- <list_published_objects/> element.
- """
-
- element_name = "list_published_objects"
- attributes = ("self_handle", "tag", "uri", "child_handle")
- text_attribute = "obj"
-
- obj = None
- child_handle = None
-
- def __repr__(self):
- return rpki.log.log_repr(self, self.self_handle, self.child_handle, self.uri)
-
- def serve_dispatch(self, r_msg, cb, eb):
- """
- Handle a <list_published_objects/> query. The method name is a
- misnomer here, there's no action attribute and no dispatch, we
- just dump every published object for the specified <self/> and return.
- """
-
- for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents:
- for ca in parent.cas:
- ca_detail = ca.active_ca_detail
- if ca_detail is not None:
- r_msg.append(self.make_reply(ca_detail.crl_uri, ca_detail.latest_crl))
- r_msg.append(self.make_reply(ca_detail.manifest_uri, ca_detail.latest_manifest))
- r_msg.extend(self.make_reply(c.uri, c.cert, c.child.child_handle)
- for c in ca_detail.child_certs)
- r_msg.extend(self.make_reply(r.uri, r.roa)
- for r in ca_detail.roas if r.roa is not None)
- r_msg.extend(self.make_reply(g.uri, g.ghostbuster)
- for g in ca_detail.ghostbusters)
- r_msg.extend(self.make_reply(c.uri, c.cert)
- for c in ca_detail.ee_certificates)
- cb()
-
- def make_reply(self, uri, obj, child_handle = None):
- """
- Generate one reply PDU.
- """
-
- r_pdu = self.make_pdu(tag = self.tag, self_handle = self.self_handle,
- uri = uri, child_handle = child_handle)
- r_pdu.obj = obj.get_Base64()
- return r_pdu
-
-class list_received_resources_elt(rpki.xml_utils.base_elt, left_right_namespace):
- """
- <list_received_resources/> element.
- """
-
- element_name = "list_received_resources"
- attributes = ("self_handle", "tag", "parent_handle",
- "notBefore", "notAfter", "uri", "sia_uri", "aia_uri", "asn", "ipv4", "ipv6")
-
- def __repr__(self):
- return rpki.log.log_repr(self, self.self_handle, self.parent_handle, self.uri, self.notAfter)
-
- def serve_dispatch(self, r_msg, cb, eb):
- """
- Handle a <list_received_resources/> query. The method name is a
- misnomer here, there's no action attribute and no dispatch, we
- just dump a bunch of data about every certificate issued to us by
- one of our parents, then return.
- """
-
- for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents:
- for ca in parent.cas:
- ca_detail = ca.active_ca_detail
- if ca_detail is not None and ca_detail.latest_ca_cert is not None:
- r_msg.append(self.make_reply(parent.parent_handle, ca_detail.ca_cert_uri, ca_detail.latest_ca_cert))
- cb()
-
- def make_reply(self, parent_handle, uri, cert):
- """
- Generate one reply PDU.
- """
-
- resources = cert.get_3779resources()
- return self.make_pdu(
- tag = self.tag,
- self_handle = self.self_handle,
- parent_handle = parent_handle,
- notBefore = str(cert.getNotBefore()),
- notAfter = str(cert.getNotAfter()),
- uri = uri,
- sia_uri = cert.get_sia_directory_uri(),
- aia_uri = cert.get_aia_uri(),
- asn = resources.asn,
- ipv4 = resources.v4,
- ipv6 = resources.v6)
-
class report_error_elt(rpki.xml_utils.text_elt, left_right_namespace):
"""
<report_error/> element.
@@ -1494,54 +1400,6 @@ class report_error_elt(rpki.xml_utils.text_elt, left_right_namespace):
self.error_text = str(e)
return self
-class msg(rpki.xml_utils.msg, left_right_namespace):
- """
- Left-right PDU.
- """
-
- ## @var version
- # Protocol version
- version = int(rpki.relaxng.left_right.version)
-
- ## @var pdus
- # Dispatch table of PDUs for this protocol.
- pdus = dict((x.element_name, x)
- for x in (self_elt, child_elt, parent_elt, bsc_elt,
- repository_elt, list_resources_elt,
- list_roa_requests_elt, list_ghostbuster_requests_elt,
- list_ee_certificate_requests_elt,
- list_published_objects_elt,
- list_received_resources_elt, report_error_elt))
-
- def serve_top_level(self, gctx, cb):
- """
- Serve one msg PDU.
- """
-
- r_msg = self.__class__.reply()
-
- def loop(iterator, q_pdu):
-
- def fail(e):
- if not isinstance(e, rpki.exceptions.NotFound):
- logger.exception("Unhandled exception serving left-right PDU %r", q_pdu)
- r_msg.append(report_error_elt.from_exception(
- e, self_handle = q_pdu.self_handle, tag = q_pdu.tag))
- cb(r_msg)
-
- try:
- q_pdu.gctx = gctx
- q_pdu.serve_dispatch(r_msg, iterator, fail)
- except (rpki.async.ExitNow, SystemExit):
- raise
- except Exception, e:
- fail(e)
-
- def done():
- cb(r_msg)
-
- rpki.async.iterator(self, loop, done)
-
class cms_msg(rpki.x509.XML_CMS_object):
"""
diff --git a/rpki/rpkid.py b/rpki/rpkid.py
index f6f8b98f..ce7368df 100644
--- a/rpki/rpkid.py
+++ b/rpki/rpkid.py
@@ -42,7 +42,7 @@ import rpki.async
import rpki.daemonize
import rpki.rpkid_tasks
-from lxml.etree import Element, SubElement
+from lxml.etree import Element, SubElement, tostring as ElementToString
logger = logging.getLogger(__name__)
@@ -104,6 +104,12 @@ class main(object):
if self.profile:
logger.info("Running in profile mode with output to %s", self.profile)
+ import django
+ django.setup()
+
+ global rpki
+ import rpki.rpkidb
+
self.sql = rpki.sql.session(self.cfg)
self.bpki_ta = rpki.x509.X509(Auto_update = self.cfg.get("bpki-ta"))
@@ -273,10 +279,92 @@ class main(object):
return self._left_right_trivial_handlers
except AttributeError:
self._left_right_trivial_handlers = {
- tag_list_published_objects : self.handle_list_published_objects,
- tag_list_received_resources : self.handle_list_received_resources }
+ rpki.left_right.tag_list_published_objects : self.handle_list_published_objects,
+ rpki.left_right.tag_list_received_resources : self.handle_list_received_resources }
return self._left_right_trivial_handlers
+ def handle_list_published_objects(self, q_pdu, r_msg):
+ """
+ <list_published_objects/> server.
+
+ This is written for the old SQL API, will need rewriting once we
+ switch rpkid to Django ORM.
+ """
+
+ logger.debug(".handle_list_published_objects() %s", ElementToString(q_pdu))
+
+ self_handle = q_pdu.get("self_handle")
+ msg_tag = q_pdu.get("tag")
+
+ kw = dict(self_handle = self_handle)
+ if msg_tag is not None:
+ kw.update(tag = msg_tag)
+
+ for parent in rpki.left_right.self_elt.serve_fetch_handle(self, None, self_handle).parents:
+ for ca in parent.cas:
+ ca_detail = ca.active_ca_detail
+ if ca_detail is not None:
+
+ SubElement(r_msg, rpki.left_right.tag_list_published_objects,
+ uri = ca_detail.crl_uri, **kw).text = ca_detail.latest_crl.get_Base64()
+
+ SubElement(r_msg, rpki.left_right.tag_list_published_objects,
+ uri = ca_detail.manifest_uri, **kw).text = ca_detail.latest_manifest.get_Base64()
+
+ for c in ca_detail.child_certs:
+ SubElement(r_msg, rpki.left_right.tag_list_published_objects,
+ uri = c.uri, child_handle = c.child.child_handle, **kw).text = c.cert.get_Base64()
+
+ for r in ca_detail.roas:
+ if r.roa is not None:
+ SubElement(r_msg, rpki.left_right.tag_list_published_objects,
+ uri = r.uri, **kw).text = r.roa.get_Base64()
+
+ for g in ca_detail.ghostbusters:
+ SubElement(r_msg, rpki.left_right.tag_list_published_objects,
+ uri = g.uri, **kw).text = g.ghostbuster.get_Base64()
+
+ for c in ca_detail.ee_certificates:
+ SubElement(r_msg, rpki.left_right.tag_list_published_objects,
+ uri = c.uri, **kw).text = c.cert.get_Base64()
+
+ def handle_list_received_resources(self, q_pdu, r_msg):
+ """
+ <list_received_resources/> server.
+
+ This is written for the old SQL API, will need rewriting once we
+ switch rpkid to Django ORM.
+ """
+
+ logger.debug(".handle_list_received_resources() %s", ElementToString(q_pdu))
+
+ self_handle = q_pdu.get("self_handle")
+ msg_tag = q_pdu.get("tag")
+
+ for parent in rpki.left_right.self_elt.serve_fetch_handle(self, None, self_handle).parents:
+ for ca in parent.cas:
+ ca_detail = ca.active_ca_detail
+ if ca_detail is not None and ca_detail.latest_ca_cert is not None:
+
+ cert = ca_detail.latest_ca_cert
+ resources = cert.get_3779resources()
+
+ r_pdu = SubElement(r_msg, rpki.left_right.tag_list_received_resources,
+ self_handle = self_handle,
+ parent_handle = parent.parent_handle,
+ uri = ca_detail.ca_cert_uri,
+ notBefore = str(cert.getNotBefore()),
+ notAfter = str(cert.getNotAfter()),
+ sia_uri = cert.get_sia_directory_uri(),
+ aia_uri = cert.get_aia_uri(),
+ asn = str(resources.asn),
+ ipv4 = str(resources.v4),
+ ipv6 = str(resources.v6))
+
+ if msg_tag is not None:
+ r_pdu.set("tag", msg_tag)
+
+
def left_right_handler(self, query, path, cb):
"""
Process one left-right PDU.
@@ -289,25 +377,71 @@ class main(object):
# probably just become calls to ordinary methods of this
# (rpki.rpkid.main) class.
#
- # Merge rpki.left_right.msg.serve_top_level() into this method,
- # along with a generalization of rpki.pubd.main.control_handler().
-
- def done(r_msg):
- r_msg = r_msg.toXML()
- reply = rpki.left_right.cms_msg().wrap(r_msg, self.rpkid_key, self.rpkid_cert)
- self.sql.sweep()
- cb(200, body = reply)
+ # Need to clone logic from rpki.pubd.main.control_handler().
try:
q_cms = rpki.left_right.cms_msg(DER = query)
q_msg = q_cms.unwrap((self.bpki_ta, self.irbe_cert))
- q_msg = rpki.left_right.msg.fromXML(q_msg)
+ r_msg = Element(rpki.left_right.tag_msg, nsmap = rpki.left_right.nsmap,
+ type = "reply", version = rpki.left_right.version)
self.irbe_cms_timestamp = q_cms.check_replay(self.irbe_cms_timestamp, path)
- if not q_msg.is_query():
+
+ assert q_msg.tag.startswith(rpki.left_right.xmlns) and all(q_pdu.tag.startswith(rpki.left_right.xmlns) for q_pdu in q_msg)
+
+ if q_msg.get("version") != rpki.left_right.version:
+ raise rpki.exceptions.BadQuery("Unrecognized protocol version")
+
+ if q_msg.get("type") != "query":
raise rpki.exceptions.BadQuery("Message type is not query")
- q_msg.serve_top_level(self, done)
+
+ def done():
+ self.sql.sweep()
+ cb(200, body = rpki.left_right.cms_msg().wrap(r_msg, self.rpkid_key, self.rpkid_cert))
+
+ def loop(iterator, q_pdu):
+
+ def fail(e):
+ if not isinstance(e, rpki.exceptions.NotFound):
+ logger.exception("Unhandled exception serving left-right PDU %r", q_pdu)
+
+ # Compatability kludge
+ if isinstance(q_pdu, rpki.left_right.data_elt):
+ r_msg.append(rpki.left_right.report_error_elt.from_exception(
+ e, self_handle = q_pdu.self_handle, tag = q_pdu.tag).toXML())
+ else:
+ r_pdu = rpki.left_right.report_error_elt.from_exception(e, self_handle = q_pdu.get("self_handle"))
+ tag = q_pdu.get("tag")
+ if tag:
+ r_pdu.set("tag", tag)
+ r_msg.append(r_pdu.toXML())
+
+ self.sql.sweep()
+
+ cb(200, body = rpki.left_right.cms_msg().wrap(r_msg, self.rpkid_key, self.rpkid_cert))
+
+ try:
+ if q_pdu.tag in self.left_right_trivial_handlers:
+ self.left_right_trivial_handlers[q_pdu.tag](q_pdu, r_msg)
+ iterator()
+ else:
+ q_map = { rpki.left_right.tag_self : rpki.left_right.self_elt,
+ rpki.left_right.tag_bsc : rpki.left_right.bsc_elt,
+ rpki.left_right.tag_parent : rpki.left_right.parent_elt,
+ rpki.left_right.tag_child : rpki.left_right.child_elt,
+ rpki.left_right.tag_repository : rpki.left_right.repository_elt }
+ q_pdu = q_map[q_pdu.tag].fromXML(q_pdu)
+ q_pdu.gctx = self
+ q_pdu.serve_dispatch(r_msg, iterator, fail)
+ except (rpki.async.ExitNow, SystemExit):
+ raise
+ except Exception, e:
+ fail(e)
+
+ rpki.async.iterator(q_msg, loop, done)
+
except (rpki.async.ExitNow, SystemExit):
raise
+
except Exception, e:
logger.exception("Unhandled exception serving left-right request")
cb(500, reason = "Unhandled exception %s: %s" % (e.__class__.__name__, e))
diff --git a/rpki/xml_utils.py b/rpki/xml_utils.py
index b85a60c5..da907a0d 100644
--- a/rpki/xml_utils.py
+++ b/rpki/xml_utils.py
@@ -326,10 +326,26 @@ class data_elt(base_elt):
Action dispatch handler.
"""
+ # Transition hack: handle the .toXML() call for old handlers.
+
+ fake_r_msg = []
+
+ def fake_convert():
+ r_msg.extend(r_pdu.toXML() if isinstance(r_pdu, base_elt) else r_pdu
+ for r_pdu in fake_r_msg)
+
+ def fake_cb():
+ fake_convert()
+ cb()
+
+ def fake_eb(e):
+ fake_convert()
+ eb(e)
+
method = getattr(self, "serve_" + self.action, None)
if method is None:
raise rpki.exceptions.BadQuery("Unexpected query: action %s" % self.action)
- method(r_msg, cb, eb)
+ method(fake_r_msg, fake_cb, fake_eb)
def unimplemented_control(self, *controls):
"""
@@ -339,76 +355,3 @@ class data_elt(base_elt):
unimplemented = [x for x in controls if getattr(self, x, False)]
if unimplemented:
raise rpki.exceptions.NotImplementedYet("Unimplemented control %s" % ", ".join(unimplemented))
-
-class msg(list):
- """
- Generic top-level PDU.
- """
-
- def __str__(self):
- """
- Convert msg object to string.
- """
-
- return lxml.etree.tostring(self.toXML(), pretty_print = True, encoding = "us-ascii")
-
- def toXML(self):
- """
- Generate top-level PDU.
- """
-
- elt = lxml.etree.Element(self.xmlns + "msg", nsmap = self.nsmap, version = str(self.version), type = self.type)
- elt.extend(i.toXML() for i in self)
- return elt
-
- @classmethod
- def query(cls, *args):
- """
- Create a query PDU.
- """
-
- self = cls(args)
- self.type = "query"
- return self
-
- @classmethod
- def reply(cls, *args):
- """
- Create a reply PDU.
- """
-
- self = cls(args)
- self.type = "reply"
- return self
-
- def is_query(self):
- """
- Is this msg a query?
- """
-
- return self.type == "query"
-
- def is_reply(self):
- """
- Is this msg a reply?
- """
-
- return self.type == "reply"
-
- @classmethod
- def fromXML(cls, elt):
- """
- First cut at non-SAX message unpacker. This will probably change.
- """
-
- assert cls.version == int(elt.get("version"))
- self = cls()
- self.type = elt.get("type")
-
- # This could be simplified by including the namespace name in the .pdus[] key.
-
- for sub in elt:
- assert sub.tag.startswith(self.xmlns)
- self.append(self.pdus[sub.tag[len(self.xmlns):]].fromXML(sub))
-
- return self