aboutsummaryrefslogtreecommitdiff
path: root/rpki/up_down.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpki/up_down.py')
-rw-r--r--rpki/up_down.py79
1 files changed, 65 insertions, 14 deletions
diff --git a/rpki/up_down.py b/rpki/up_down.py
index 73a0ae99..a145ed28 100644
--- a/rpki/up_down.py
+++ b/rpki/up_down.py
@@ -50,6 +50,7 @@ class base_elt(object):
Some elements have no attributes and we only care about their
text content.
"""
+
pass
def endElement(self, stack, name, text):
@@ -58,12 +59,14 @@ class base_elt(object):
If we don't need to do anything else, just pop the stack.
"""
+
stack.pop()
def make_elt(self, name, *attrs):
"""
Construct a element, copying over a set of attributes.
"""
+
elt = lxml.etree.Element(xmlns + name, nsmap = nsmap)
for key in attrs:
val = getattr(self, key, None)
@@ -75,6 +78,7 @@ class base_elt(object):
"""
Construct a sub-element with Base64 text content.
"""
+
if value is not None and not value.empty():
lxml.etree.SubElement(elt, xmlns + name, nsmap = nsmap).text = value.get_Base64()
@@ -82,12 +86,14 @@ class base_elt(object):
"""
Default PDU handler to catch unexpected types.
"""
+
raise rpki.exceptions.BadQuery("Unexpected query type %s" % q_msg.type)
def check_response(self):
"""
Placeholder for response checking.
"""
+
pass
class multi_uri(list):
@@ -99,6 +105,7 @@ class multi_uri(list):
"""
Initialize a set of URIs, which includes basic some syntax checking.
"""
+
list.__init__(self)
if isinstance(ini, (list, tuple)):
self[:] = ini
@@ -114,12 +121,14 @@ class multi_uri(list):
"""
Convert a multi_uri back to a string representation.
"""
+
return ",".join(self)
def rsync(self):
"""
Find first rsync://... URI in self.
"""
+
for s in self:
if s.startswith("rsync://"):
return s
@@ -134,6 +143,7 @@ class certificate_elt(base_elt):
"""
Handle attributes of <certificate/> element.
"""
+
assert name == "certificate", "Unexpected name %s, stack %s" % (name, stack)
self.cert_url = multi_uri(attrs["cert_url"])
self.req_resource_set_as = rpki.resource_set.resource_set_as(attrs.get("req_resource_set_as"))
@@ -144,6 +154,7 @@ class certificate_elt(base_elt):
"""
Handle text content of a <certificate/> element.
"""
+
assert name == "certificate", "Unexpected name %s, stack %s" % (name, stack)
self.cert = rpki.x509.X509(Base64 = text)
stack.pop()
@@ -152,6 +163,7 @@ class certificate_elt(base_elt):
"""
Generate a <certificate/> element.
"""
+
elt = self.make_elt("certificate", "cert_url",
"req_resource_set_as", "req_resource_set_ipv4", "req_resource_set_ipv6")
elt.text = self.cert.get_Base64()
@@ -168,6 +180,7 @@ class class_elt(base_elt):
"""
Initialize class_elt.
"""
+
base_elt.__init__(self)
self.certs = []
@@ -175,6 +188,7 @@ class class_elt(base_elt):
"""
Handle <class/> elements and their children.
"""
+
if name == "certificate":
cert = certificate_elt()
self.certs.append(cert)
@@ -194,6 +208,7 @@ class class_elt(base_elt):
"""
Handle <class/> elements and their children.
"""
+
if name == "issuer":
self.issuer = rpki.x509.X509(Base64 = text)
else:
@@ -204,10 +219,11 @@ class class_elt(base_elt):
"""
Generate a <class/> element.
"""
+
elt = self.make_elt("class", "class_name", "cert_url", "resource_set_as",
"resource_set_ipv4", "resource_set_ipv6",
"resource_set_notafter", "suggested_sia_head")
- elt.extend([i.toXML() for i in self.certs])
+ elt.extend(i.toXML() for i in self.certs)
self.make_b64elt(elt, "issuer", self.issuer)
return elt
@@ -215,6 +231,7 @@ class class_elt(base_elt):
"""
Build a resource_bag from from this <class/> element.
"""
+
return rpki.resource_set.resource_bag(self.resource_set_as,
self.resource_set_ipv4,
self.resource_set_ipv6,
@@ -224,6 +241,7 @@ class class_elt(base_elt):
"""
Set resources of this class element from a resource_bag.
"""
+
self.resource_set_as = bag.asn
self.resource_set_ipv4 = bag.v4
self.resource_set_ipv6 = bag.v6
@@ -235,7 +253,10 @@ class list_pdu(base_elt):
"""
def toXML(self):
- """Generate (empty) payload of "list" PDU."""
+ """
+ Generate (empty) payload of "list" PDU.
+ """
+
return []
def serve_pdu(self, q_msg, r_msg, child, callback, errback):
@@ -282,6 +303,7 @@ class list_pdu(base_elt):
"""
Send a "list" query to parent.
"""
+
try:
logger.info('Sending "list" request to parent %s', parent.parent_handle)
parent.query_up_down(cls(), cb, eb)
@@ -299,6 +321,7 @@ class class_response_syntax(base_elt):
"""
Initialize class_response_syntax.
"""
+
base_elt.__init__(self)
self.classes = []
@@ -306,6 +329,7 @@ class class_response_syntax(base_elt):
"""
Handle "list_response" and "issue_response" PDUs.
"""
+
assert name == "class", "Unexpected name %s, stack %s" % (name, stack)
c = class_elt()
self.classes.append(c)
@@ -313,13 +337,17 @@ class class_response_syntax(base_elt):
c.startElement(stack, name, attrs)
def toXML(self):
- """Generate payload of "list_response" and "issue_response" PDUs."""
+ """
+ Generate payload of "list_response" and "issue_response" PDUs.
+ """
+
return [c.toXML() for c in self.classes]
class list_response_pdu(class_response_syntax):
"""
Up-Down protocol "list_response" PDU.
"""
+
pass
class issue_pdu(base_elt):
@@ -331,6 +359,7 @@ class issue_pdu(base_elt):
"""
Handle "issue" PDU.
"""
+
assert name == "request", "Unexpected name %s, stack %s" % (name, stack)
self.class_name = attrs["class_name"]
self.req_resource_set_as = rpki.resource_set.resource_set_as(attrs.get("req_resource_set_as"))
@@ -341,6 +370,7 @@ class issue_pdu(base_elt):
"""
Handle "issue" PDU.
"""
+
assert name == "request", "Unexpected name %s, stack %s" % (name, stack)
self.pkcs10 = rpki.x509.PKCS10(Base64 = text)
stack.pop()
@@ -349,6 +379,7 @@ class issue_pdu(base_elt):
"""
Generate payload of "issue" PDU.
"""
+
elt = self.make_elt("request", "class_name", "req_resource_set_as",
"req_resource_set_ipv4", "req_resource_set_ipv6")
elt.text = self.pkcs10.get_Base64()
@@ -432,6 +463,7 @@ class issue_pdu(base_elt):
"""
Send an "issue" request to parent associated with ca.
"""
+
assert ca_detail is not None and ca_detail.state in ("pending", "active")
self = cls()
self.class_name = ca.parent_resource_class
@@ -453,6 +485,7 @@ class issue_response_pdu(class_response_syntax):
Check whether this looks like a reasonable issue_response PDU.
XML schema should be tighter for this response.
"""
+
if len(self.classes) != 1 or len(self.classes[0].certs) != 1:
raise rpki.exceptions.BadIssueResponse
@@ -462,12 +495,18 @@ class revoke_syntax(base_elt):
"""
def startElement(self, stack, name, attrs):
- """Handle "revoke" PDU."""
+ """
+ Handle "revoke" PDU.
+ """
+
self.class_name = attrs["class_name"]
self.ski = attrs["ski"]
def toXML(self):
- """Generate payload of "revoke" PDU."""
+ """
+ Generate payload of "revoke" PDU.
+ """
+
return [self.make_elt("key", "class_name", "ski")]
class revoke_pdu(revoke_syntax):
@@ -479,6 +518,7 @@ class revoke_pdu(revoke_syntax):
"""
Convert g(SKI) encoding from PDU back to raw SKI.
"""
+
return base64.urlsafe_b64decode(self.ski + "=")
def serve_pdu(self, q_msg, r_msg, child, cb, eb):
@@ -505,6 +545,7 @@ class revoke_pdu(revoke_syntax):
"""
Send a "revoke" request for certificate(s) named by gski to parent associated with ca.
"""
+
parent = ca.parent
self = cls()
self.class_name = ca.parent_resource_class
@@ -545,6 +586,7 @@ class error_response_pdu(base_elt):
"""
Initialize an error_response PDU from an exception object.
"""
+
base_elt.__init__(self)
if exception is not None:
logger.debug("Constructing up-down error response from exception %s", exception)
@@ -570,6 +612,7 @@ class error_response_pdu(base_elt):
"""
Handle "error_response" PDU.
"""
+
if name == "status":
code = int(text)
if code not in self.codes:
@@ -586,6 +629,7 @@ class error_response_pdu(base_elt):
"""
Generate payload of "error_response" PDU.
"""
+
assert self.status in self.codes
elt = self.make_elt("status")
elt.text = str(self.status)
@@ -602,6 +646,7 @@ class error_response_pdu(base_elt):
Handle an error response. For now, just raise an exception,
perhaps figure out something more clever to do later.
"""
+
raise rpki.exceptions.UpstreamError(self.codes[self.status])
class message_pdu(base_elt):
@@ -611,16 +656,16 @@ class message_pdu(base_elt):
version = 1
- name2type = {
- "list" : list_pdu,
- "list_response" : list_response_pdu,
- "issue" : issue_pdu,
- "issue_response" : issue_response_pdu,
- "revoke" : revoke_pdu,
- "revoke_response" : revoke_response_pdu,
- "error_response" : error_response_pdu }
+ name2type = dict(
+ list = list_pdu,
+ list_response = list_response_pdu,
+ issue = issue_pdu,
+ issue_response = issue_response_pdu,
+ revoke = revoke_pdu,
+ revoke_response = revoke_response_pdu,
+ error_response = error_response_pdu)
- type2name = dict((v, k) for k, v in name2type.items())
+ type2name = dict((v, k) for k, v in name2type.iteritems())
error_pdu_type = error_response_pdu
@@ -628,6 +673,7 @@ class message_pdu(base_elt):
"""
Generate payload of message PDU.
"""
+
elt = self.make_elt("message", "version", "sender", "recipient", "type")
elt.extend(self.payload.toXML())
return elt
@@ -640,6 +686,7 @@ class message_pdu(base_elt):
attribute, so after some basic checks we have to instantiate the
right class object to handle whatever kind of PDU this is.
"""
+
assert name == "message", "Unexpected name %s, stack %s" % (name, stack)
assert self.version == int(attrs["version"])
self.sender = attrs["sender"]
@@ -652,6 +699,7 @@ class message_pdu(base_elt):
"""
Convert a message PDU to a string.
"""
+
return lxml.etree.tostring(self.toXML(), pretty_print = True, encoding = "UTF-8")
def serve_top_level(self, child, callback):
@@ -683,12 +731,14 @@ class message_pdu(base_elt):
"""
Log query we're handling. Separate method so rootd can override.
"""
+
logger.info("Serving %s query from child %s [sender %s, recipient %s]", self.type, child.child_handle, self.sender, self.recipient)
def serve_error(self, exception):
"""
Generate an error_response message PDU.
"""
+
r_msg = message_pdu()
r_msg.sender = self.recipient
r_msg.recipient = self.sender
@@ -701,6 +751,7 @@ class message_pdu(base_elt):
"""
Construct one message PDU.
"""
+
assert not cls.type2name[type(payload)].endswith("_response")
if sender is None:
sender = "tweedledee"