RPKI Engine  1.0
up_down.py (3746)
Go to the documentation of this file.
00001 """
00002 RPKI "up-down" protocol.
00003 
00004 $Id: up_down.py 3746 2011-03-27 01:24:39Z sra $
00005 
00006 Copyright (C) 2009--2011  Internet Systems Consortium ("ISC")
00007 
00008 Permission to use, copy, modify, and distribute this software for any
00009 purpose with or without fee is hereby granted, provided that the above
00010 copyright notice and this permission notice appear in all copies.
00011 
00012 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00013 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00014 AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00015 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00016 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00017 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00018 PERFORMANCE OF THIS SOFTWARE.
00019 
00020 Portions copyright (C) 2007--2008  American Registry for Internet Numbers ("ARIN")
00021 
00022 Permission to use, copy, modify, and distribute this software for any
00023 purpose with or without fee is hereby granted, provided that the above
00024 copyright notice and this permission notice appear in all copies.
00025 
00026 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
00027 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00028 AND FITNESS.  IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,
00029 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00030 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00031 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00032 PERFORMANCE OF THIS SOFTWARE.
00033 """
00034 
00035 import base64, lxml.etree
00036 import rpki.resource_set, rpki.x509, rpki.exceptions, rpki.log
00037 import rpki.xml_utils, rpki.relaxng
00038 
00039 xmlns = "http://www.apnic.net/specs/rescerts/up-down/"
00040 
00041 nsmap = { None : xmlns }
00042 
00043 class base_elt(object):
00044   """
00045   Generic PDU object.
00046 
00047   Virtual class, just provides some default methods.
00048   """
00049 
00050   def startElement(self, stack, name, attrs):
00051     """
00052     Ignore startElement() if there's no specific handler.
00053 
00054     Some elements have no attributes and we only care about their
00055     text content.
00056     """
00057     pass
00058 
00059   def endElement(self, stack, name, text):
00060     """
00061     Ignore endElement() if there's no specific handler.
00062 
00063     If we don't need to do anything else, just pop the stack.
00064     """
00065     stack.pop()
00066 
00067   def make_elt(self, name, *attrs):
00068     """
00069     Construct a element, copying over a set of attributes.
00070     """
00071     elt = lxml.etree.Element("{%s}%s" % (xmlns, name), nsmap=nsmap)
00072     for key in attrs:
00073       val = getattr(self, key, None)
00074       if val is not None:
00075         elt.set(key, str(val))
00076     return elt
00077 
00078   def make_b64elt(self, elt, name, value):
00079     """
00080     Construct a sub-element with Base64 text content.
00081     """
00082     if value is not None and not value.empty():
00083       lxml.etree.SubElement(elt, "{%s}%s" % (xmlns, name), nsmap=nsmap).text = value.get_Base64()
00084 
00085   def serve_pdu(self, q_msg, r_msg, child, callback, errback):
00086     """
00087     Default PDU handler to catch unexpected types.
00088     """
00089     raise rpki.exceptions.BadQuery, "Unexpected query type %s" % q_msg.type
00090 
00091   def check_response(self):
00092     """
00093     Placeholder for response checking.
00094     """
00095     pass
00096 
00097 class multi_uri(list):
00098   """
00099   Container for a set of URIs.
00100   """
00101 
00102   def __init__(self, ini):
00103     """
00104     Initialize a set of URIs, which includes basic some syntax checking.
00105     """
00106     list.__init__(self)
00107     if isinstance(ini, (list, tuple)):
00108       self[:] = ini
00109     elif isinstance(ini, str):
00110       self[:] = ini.split(",")
00111       for s in self:
00112         if s.strip() != s or "://" not in s:
00113           raise rpki.exceptions.BadURISyntax, "Bad URI \"%s\"" % s
00114     else:
00115       raise TypeError
00116 
00117   def __str__(self):
00118     """
00119     Convert a multi_uri back to a string representation.
00120     """
00121     return ",".join(self)
00122 
00123   def rsync(self):
00124     """
00125     Find first rsync://... URI in self.
00126     """
00127     for s in self:
00128       if s.startswith("rsync://"):
00129         return s
00130     return None
00131 
00132 class certificate_elt(base_elt):
00133   """
00134   Up-Down protocol representation of an issued certificate.
00135   """
00136 
00137   def startElement(self, stack, name, attrs):
00138     """
00139     Handle attributes of <certificate/> element.
00140     """
00141     assert name == "certificate", "Unexpected name %s, stack %s" % (name, stack)
00142     self.cert_url = multi_uri(attrs["cert_url"])
00143     self.req_resource_set_as   = rpki.resource_set.resource_set_as(attrs.get("req_resource_set_as"))
00144     self.req_resource_set_ipv4 = rpki.resource_set.resource_set_ipv4(attrs.get("req_resource_set_ipv4"))
00145     self.req_resource_set_ipv6 = rpki.resource_set.resource_set_ipv6(attrs.get("req_resource_set_ipv6"))
00146 
00147   def endElement(self, stack, name, text):
00148     """
00149     Handle text content of a <certificate/> element.
00150     """
00151     assert name == "certificate", "Unexpected name %s, stack %s" % (name, stack)
00152     self.cert = rpki.x509.X509(Base64 = text)
00153     stack.pop()
00154 
00155   def toXML(self):
00156     """
00157     Generate a <certificate/> element.
00158     """
00159     elt = self.make_elt("certificate", "cert_url",
00160                         "req_resource_set_as", "req_resource_set_ipv4", "req_resource_set_ipv6")
00161     elt.text = self.cert.get_Base64()
00162     return elt
00163 
00164 class class_elt(base_elt):
00165   """
00166   Up-Down protocol representation of a resource class.
00167   """
00168 
00169   issuer = None
00170 
00171   def __init__(self):
00172     """
00173     Initialize class_elt.
00174     """
00175     base_elt.__init__(self)
00176     self.certs = []
00177 
00178   def startElement(self, stack, name, attrs):
00179     """
00180     Handle <class/> elements and their children.
00181     """
00182     if name == "certificate":
00183       cert = certificate_elt()
00184       self.certs.append(cert)
00185       stack.append(cert)
00186       cert.startElement(stack, name, attrs)
00187     elif name != "issuer":
00188       assert name == "class", "Unexpected name %s, stack %s" % (name, stack)
00189       self.class_name = attrs["class_name"]
00190       self.cert_url = multi_uri(attrs["cert_url"])
00191       self.suggested_sia_head = attrs.get("suggested_sia_head")
00192       self.resource_set_as   = rpki.resource_set.resource_set_as(attrs["resource_set_as"])
00193       self.resource_set_ipv4 = rpki.resource_set.resource_set_ipv4(attrs["resource_set_ipv4"])
00194       self.resource_set_ipv6 = rpki.resource_set.resource_set_ipv6(attrs["resource_set_ipv6"])
00195       self.resource_set_notafter = rpki.sundial.datetime.fromXMLtime(attrs.get("resource_set_notafter"))
00196 
00197   def endElement(self, stack, name, text):
00198     """
00199     Handle <class/> elements and their children.
00200     """
00201     if name == "issuer":
00202       self.issuer = rpki.x509.X509(Base64 = text)
00203     else:
00204       assert name == "class", "Unexpected name %s, stack %s" % (name, stack)
00205       stack.pop()
00206 
00207   def toXML(self):
00208     """
00209     Generate a <class/> element.
00210     """
00211     elt = self.make_elt("class", "class_name", "cert_url", "resource_set_as",
00212                         "resource_set_ipv4", "resource_set_ipv6",
00213                         "resource_set_notafter", "suggested_sia_head")
00214     elt.extend([i.toXML() for i in self.certs])
00215     self.make_b64elt(elt, "issuer", self.issuer)
00216     return elt
00217 
00218   def to_resource_bag(self):
00219     """
00220     Build a resource_bag from from this <class/> element.
00221     """
00222     return rpki.resource_set.resource_bag(self.resource_set_as,
00223                                           self.resource_set_ipv4,
00224                                           self.resource_set_ipv6,
00225                                           self.resource_set_notafter)
00226 
00227   def from_resource_bag(self, bag):
00228     """
00229     Set resources of this class element from a resource_bag.
00230     """
00231     self.resource_set_as   = bag.asn
00232     self.resource_set_ipv4 = bag.v4
00233     self.resource_set_ipv6 = bag.v6
00234     self.resource_set_notafter = bag.valid_until
00235 
00236 class list_pdu(base_elt):
00237   """
00238   Up-Down protocol "list" PDU.
00239   """
00240 
00241   def toXML(self):
00242     """Generate (empty) payload of "list" PDU."""
00243     return []
00244 
00245   def serve_pdu(self, q_msg, r_msg, child, callback, errback):
00246     """
00247     Serve one "list" PDU.
00248     """
00249 
00250     def handle(irdb_resources):
00251 
00252       r_msg.payload = list_response_pdu()
00253 
00254       if irdb_resources.valid_until > rpki.sundial.now():
00255         for parent in child.parents:
00256           for ca in parent.cas:
00257             ca_detail = ca.active_ca_detail
00258             if not ca_detail:
00259               continue
00260             resources = ca_detail.latest_ca_cert.get_3779resources().intersection(irdb_resources)
00261             if resources.empty():
00262               continue
00263             rc = class_elt()
00264             rc.class_name = str(ca.ca_id)
00265             rc.cert_url = multi_uri(ca_detail.ca_cert_uri)
00266             rc.from_resource_bag(resources)
00267             for child_cert in child.fetch_child_certs(ca_detail = ca_detail):
00268               c = certificate_elt()
00269               c.cert_url = multi_uri(child_cert.uri)
00270               c.cert = child_cert.cert
00271               rc.certs.append(c)
00272             rc.issuer = ca_detail.latest_ca_cert
00273             r_msg.payload.classes.append(rc)
00274 
00275       callback()
00276 
00277     self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, handle, errback)
00278 
00279   @classmethod
00280   def query(cls, parent, cb, eb):
00281     """
00282     Send a "list" query to parent.
00283     """
00284     try:
00285       rpki.log.info('Sending "list" request to parent %s' % parent.parent_handle)
00286       parent.query_up_down(cls(), cb, eb)
00287     except (rpki.async.ExitNow, SystemExit):
00288       raise
00289     except Exception, e:
00290       eb(e)
00291 
00292 class class_response_syntax(base_elt):
00293   """
00294   Syntax for Up-Down protocol "list_response" and "issue_response" PDUs.
00295   """
00296 
00297   def __init__(self):
00298     """
00299     Initialize class_response_syntax.
00300     """
00301     base_elt.__init__(self)
00302     self.classes = []
00303 
00304   def startElement(self, stack, name, attrs):
00305     """
00306     Handle "list_response" and "issue_response" PDUs.
00307     """
00308     assert name == "class", "Unexpected name %s, stack %s" % (name, stack)
00309     c = class_elt()
00310     self.classes.append(c)
00311     stack.append(c)
00312     c.startElement(stack, name, attrs)
00313       
00314   def toXML(self):
00315     """Generate payload of "list_response" and "issue_response" PDUs."""
00316     return [c.toXML() for c in self.classes]
00317 
00318 class list_response_pdu(class_response_syntax):
00319   """
00320   Up-Down protocol "list_response" PDU.
00321   """
00322   pass
00323 
00324 class issue_pdu(base_elt):
00325   """
00326   Up-Down protocol "issue" PDU.
00327   """
00328 
00329   def startElement(self, stack, name, attrs):
00330     """
00331     Handle "issue" PDU.
00332     """
00333     assert name == "request", "Unexpected name %s, stack %s" % (name, stack)
00334     self.class_name = attrs["class_name"]
00335     self.req_resource_set_as   = rpki.resource_set.resource_set_as(attrs.get("req_resource_set_as"))
00336     self.req_resource_set_ipv4 = rpki.resource_set.resource_set_ipv4(attrs.get("req_resource_set_ipv4"))
00337     self.req_resource_set_ipv6 = rpki.resource_set.resource_set_ipv6(attrs.get("req_resource_set_ipv6"))
00338 
00339   def endElement(self, stack, name, text):
00340     """
00341     Handle "issue" PDU.
00342     """
00343     assert name == "request", "Unexpected name %s, stack %s" % (name, stack)
00344     self.pkcs10 = rpki.x509.PKCS10(Base64 = text)
00345     stack.pop()
00346 
00347   def toXML(self):
00348     """
00349     Generate payload of "issue" PDU.
00350     """
00351     elt = self.make_elt("request", "class_name", "req_resource_set_as",
00352                         "req_resource_set_ipv4", "req_resource_set_ipv6")
00353     elt.text = self.pkcs10.get_Base64()
00354     return [elt]
00355 
00356   def serve_pdu(self, q_msg, r_msg, child, callback, errback):
00357     """
00358     Serve one issue request PDU.
00359     """
00360 
00361     # Subsetting not yet implemented, this is the one place where we
00362     # have to handle it, by reporting that we're lame.
00363 
00364     if self.req_resource_set_as or \
00365        self.req_resource_set_ipv4 or \
00366        self.req_resource_set_ipv6:
00367       raise rpki.exceptions.NotImplementedYet, "req_* attributes not implemented yet, sorry"
00368 
00369     # Check the request
00370     self.pkcs10.check_valid_rpki()
00371     ca = child.ca_from_class_name(self.class_name)
00372     ca_detail = ca.active_ca_detail
00373     if ca_detail is None:
00374       raise rpki.exceptions.NoActiveCA, "No active CA for class %r" % self.class_name
00375 
00376     # Check current cert, if any
00377 
00378     def got_resources(irdb_resources):
00379 
00380       if irdb_resources.valid_until < rpki.sundial.now():
00381         raise rpki.exceptions.IRDBExpired, "IRDB entry for child %s expired %s" % (child.child_handle, irdb_resources.valid_until)
00382 
00383       resources = irdb_resources.intersection(ca_detail.latest_ca_cert.get_3779resources())
00384       req_key = self.pkcs10.getPublicKey()
00385       req_sia = self.pkcs10.get_SIA()
00386       child_cert = child.fetch_child_certs(ca_detail = ca_detail, ski = req_key.get_SKI(), unique = True)
00387 
00388       # Generate new cert or regenerate old one if necessary
00389 
00390       publisher = rpki.rpkid.publication_queue()
00391 
00392       if child_cert is None:
00393         child_cert = ca_detail.issue(
00394           ca          = ca,
00395           child       = child,
00396           subject_key = req_key,
00397           sia         = req_sia,
00398           resources   = resources,
00399           publisher   = publisher)
00400       else:
00401         child_cert = child_cert.reissue(
00402           ca_detail = ca_detail,
00403           sia       = req_sia,
00404           resources = resources,
00405           publisher = publisher)
00406 
00407       def done():
00408         c = certificate_elt()
00409         c.cert_url = multi_uri(child_cert.uri)
00410         c.cert = child_cert.cert
00411         rc = class_elt()
00412         rc.class_name = self.class_name
00413         rc.cert_url = multi_uri(ca_detail.ca_cert_uri)
00414         rc.from_resource_bag(resources)
00415         rc.certs.append(c)
00416         rc.issuer = ca_detail.latest_ca_cert
00417         r_msg.payload = issue_response_pdu()
00418         r_msg.payload.classes.append(rc)
00419         callback()
00420 
00421       self.gctx.sql.sweep()
00422       assert child_cert and child_cert.sql_in_db
00423       publisher.call_pubd(done, errback)
00424 
00425     self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, got_resources, errback)
00426 
00427   @classmethod
00428   def query(cls, parent, ca, ca_detail, callback, errback):
00429     """
00430     Send an "issue" request to parent associated with ca.
00431     """
00432     assert ca_detail is not None and ca_detail.state in ("pending", "active")
00433     sia = ((rpki.oids.name2oid["id-ad-caRepository"], ("uri", ca.sia_uri)),
00434            (rpki.oids.name2oid["id-ad-rpkiManifest"], ("uri", ca_detail.manifest_uri)))
00435     self = cls()
00436     self.class_name = ca.parent_resource_class
00437     self.pkcs10 = rpki.x509.PKCS10.create_ca(ca_detail.private_key_id, sia)
00438     rpki.log.info('Sending "issue" request to parent %s' % parent.parent_handle)
00439     parent.query_up_down(self, callback, errback)
00440 
00441 class issue_response_pdu(class_response_syntax):
00442   """
00443   Up-Down protocol "issue_response" PDU.
00444   """
00445 
00446   def check_response(self):
00447     """
00448     Check whether this looks like a reasonable issue_response PDU.
00449     XML schema should be tighter for this response.
00450     """
00451     if len(self.classes) != 1 or len(self.classes[0].certs) != 1:
00452       raise rpki.exceptions.BadIssueResponse
00453 
00454 class revoke_syntax(base_elt):
00455   """
00456   Syntax for Up-Down protocol "revoke" and "revoke_response" PDUs.
00457   """
00458 
00459   def startElement(self, stack, name, attrs):
00460     """Handle "revoke" PDU."""
00461     self.class_name = attrs["class_name"]
00462     self.ski = attrs["ski"]
00463 
00464   def toXML(self):
00465     """Generate payload of "revoke" PDU."""
00466     return [self.make_elt("key", "class_name", "ski")]
00467 
00468 class revoke_pdu(revoke_syntax):
00469   """
00470   Up-Down protocol "revoke" PDU.
00471   """
00472     
00473   def get_SKI(self):
00474     """
00475     Convert g(SKI) encoding from PDU back to raw SKI.
00476     """
00477     return base64.urlsafe_b64decode(self.ski + "=")
00478 
00479   def serve_pdu(self, q_msg, r_msg, child, cb, eb):
00480     """
00481     Serve one revoke request PDU.
00482     """
00483 
00484     def done():
00485       r_msg.payload = revoke_response_pdu()
00486       r_msg.payload.class_name = self.class_name
00487       r_msg.payload.ski = self.ski
00488       cb()
00489 
00490     ca = child.ca_from_class_name(self.class_name)
00491     publisher = rpki.rpkid.publication_queue()
00492     for ca_detail in ca.ca_details:
00493       for child_cert in child.fetch_child_certs(ca_detail = ca_detail, ski = self.get_SKI()):
00494         child_cert.revoke(publisher = publisher)
00495     self.gctx.sql.sweep()
00496     publisher.call_pubd(done, eb)
00497 
00498   @classmethod
00499   def query(cls, ca, gski, cb, eb):
00500     """
00501     Send a "revoke" request for certificate(s) named by gski to parent associated with ca.
00502     """
00503     parent = ca.parent
00504     self = cls()
00505     self.class_name = ca.parent_resource_class
00506     self.ski = gski
00507     rpki.log.info('Sending "revoke" request for SKI %s to parent %s' % (gski, parent.parent_handle))
00508     parent.query_up_down(self, cb, eb)
00509 
00510 class revoke_response_pdu(revoke_syntax):
00511   """
00512   Up-Down protocol "revoke_response" PDU.
00513   """
00514 
00515   pass
00516 
00517 class error_response_pdu(base_elt):
00518   """
00519   Up-Down protocol "error_response" PDU.
00520   """
00521 
00522   codes = {
00523     1101 : "Already processing request",
00524     1102 : "Version number error",
00525     1103 : "Unrecognised request type",
00526     1201 : "Request - no such resource class",
00527     1202 : "Request - no resources allocated in resource class",
00528     1203 : "Request - badly formed certificate request",
00529     1301 : "Revoke - no such resource class",
00530     1302 : "Revoke - no such key",
00531     2001 : "Internal Server Error - Request not performed" }
00532 
00533   exceptions = {
00534     rpki.exceptions.NoActiveCA : 1202 }
00535 
00536   def __init__(self, exception = None):
00537     """
00538     Initialize an error_response PDU from an exception object.
00539     """
00540     base_elt.__init__(self)
00541     if exception is not None:
00542       self.status = self.exceptions.get(type(exception), 2001)
00543       self.description = str(exception)
00544 
00545   def endElement(self, stack, name, text):
00546     """
00547     Handle "error_response" PDU.
00548     """
00549     if name == "status":
00550       code = int(text)
00551       if code not in self.codes:
00552         raise rpki.exceptions.BadStatusCode, "%s is not a known status code" % code
00553       self.status = code
00554     elif name == "description":
00555       self.description = text
00556     else:
00557       assert name == "message", "Unexpected name %s, stack %s" % (name, stack)
00558       stack.pop()
00559       stack[-1].endElement(stack, name, text)
00560 
00561   def toXML(self):
00562     """
00563     Generate payload of "error_response" PDU.
00564     """
00565     assert self.status in self.codes
00566     elt = self.make_elt("status")
00567     elt.text = str(self.status)
00568     payload = [elt]
00569     if self.description:
00570       elt = self.make_elt("description")
00571       elt.text = str(self.description)
00572       elt.set("{http://www.w3.org/XML/1998/namespace}lang", "en-US")
00573       payload.append(elt)
00574     return payload
00575 
00576   def check_response(self):
00577     """
00578     Handle an error response.  For now, just raise an exception,
00579     perhaps figure out something more clever to do later.
00580     """
00581     raise rpki.exceptions.UpstreamError, self.codes[self.status]
00582 
00583 class message_pdu(base_elt):
00584   """
00585   Up-Down protocol message wrapper PDU.
00586   """
00587 
00588   version = 1
00589 
00590   name2type = {
00591     "list"            : list_pdu,
00592     "list_response"   : list_response_pdu,
00593     "issue"           : issue_pdu,
00594     "issue_response"  : issue_response_pdu,
00595     "revoke"          : revoke_pdu,
00596     "revoke_response" : revoke_response_pdu,
00597     "error_response"  : error_response_pdu }
00598 
00599   type2name = dict((v, k) for k, v in name2type.items())
00600 
00601   def toXML(self):
00602     """
00603     Generate payload of message PDU.
00604     """
00605     elt = self.make_elt("message", "version", "sender", "recipient", "type")
00606     elt.extend(self.payload.toXML())
00607     return elt
00608 
00609   def startElement(self, stack, name, attrs):
00610     """
00611     Handle message PDU.
00612 
00613     Payload of the <message/> element varies depending on the "type"
00614     attribute, so after some basic checks we have to instantiate the
00615     right class object to handle whatever kind of PDU this is.
00616     """
00617     assert name == "message", "Unexpected name %s, stack %s" % (name, stack)
00618     assert self.version == int(attrs["version"])
00619     self.sender = attrs["sender"]
00620     self.recipient = attrs["recipient"]
00621     self.type = attrs["type"]
00622     self.payload = self.name2type[attrs["type"]]()
00623     stack.append(self.payload)
00624 
00625   def __str__(self):
00626     """
00627     Convert a message PDU to a string.
00628     """
00629     lxml.etree.tostring(self.toXML(), pretty_print = True, encoding = "UTF-8")
00630 
00631   def serve_top_level(self, child, callback):
00632     """
00633     Serve one message request PDU.
00634     """
00635 
00636     r_msg = message_pdu()
00637     r_msg.sender = self.recipient
00638     r_msg.recipient = self.sender
00639 
00640     def done():
00641       r_msg.type = self.type2name[type(r_msg.payload)]
00642       callback(r_msg)
00643 
00644     def lose(e):
00645       rpki.log.traceback()
00646       callback(self.serve_error(e))
00647 
00648     try:
00649       self.log_query(child)
00650       self.payload.serve_pdu(self, r_msg, child, done, lose)
00651     except (rpki.async.ExitNow, SystemExit):
00652       raise
00653     except Exception, e:
00654       lose(e)
00655 
00656   def log_query(self, child):
00657     """
00658     Log query we're handling.  Separate method so rootd can override.
00659     """
00660     rpki.log.info("Serving %s query from child %s [sender %s, recipient %s]" % (self.type, child.child_handle, self.sender, self.recipient))
00661 
00662   def serve_error(self, exception):
00663     """
00664     Generate an error_response message PDU.
00665     """
00666     r_msg = message_pdu()
00667     r_msg.sender = self.recipient
00668     r_msg.recipient = self.sender
00669     r_msg.payload = error_response_pdu(exception)
00670     r_msg.type = self.type2name[type(r_msg.payload)]
00671     return r_msg
00672 
00673   @classmethod
00674   def make_query(cls, payload, sender, recipient):
00675     """
00676     Construct one message PDU.
00677     """
00678     assert not cls.type2name[type(payload)].endswith("_response")
00679     if sender is None:
00680       sender = "tweedledee"
00681     if recipient is None:
00682       recipient = "tweedledum"
00683     self = cls()
00684     self.sender = sender
00685     self.recipient = recipient
00686     self.payload = payload
00687     self.type = self.type2name[type(payload)]
00688     return self
00689 
00690 class sax_handler(rpki.xml_utils.sax_handler):
00691   """
00692   SAX handler for Up-Down protocol.
00693   """
00694 
00695   pdu = message_pdu
00696   name = "message"
00697   version = "1"
00698 
00699 class cms_msg(rpki.x509.XML_CMS_object):
00700   """
00701   Class to hold a CMS-signed up-down PDU.
00702   """
00703 
00704   encoding = "UTF-8"
00705   schema = rpki.relaxng.up_down
00706   saxify = sax_handler.saxify
 All Classes Namespaces Files Functions Variables Properties