diff options
Diffstat (limited to 'rpkid/rpki')
-rw-r--r-- | rpkid/rpki/exceptions.py | 5 | ||||
-rw-r--r-- | rpkid/rpki/https.py | 4 | ||||
-rw-r--r-- | rpkid/rpki/left_right.py | 254 | ||||
-rw-r--r-- | rpkid/rpki/publication.py | 22 | ||||
-rw-r--r-- | rpkid/rpki/relaxng.py | 306 | ||||
-rw-r--r-- | rpkid/rpki/rpki_engine.py | 20 | ||||
-rw-r--r-- | rpkid/rpki/sql.py | 25 | ||||
-rw-r--r-- | rpkid/rpki/up_down.py | 4 | ||||
-rw-r--r-- | rpkid/rpki/xml_utils.py | 16 |
9 files changed, 373 insertions, 283 deletions
diff --git a/rpkid/rpki/exceptions.py b/rpkid/rpki/exceptions.py index a0aabccc..e98357a0 100644 --- a/rpkid/rpki/exceptions.py +++ b/rpkid/rpki/exceptions.py @@ -258,3 +258,8 @@ class BadPublicationReply(RPKI_Exception): """ Unexpected reply to publication query. """ + +class DuplicateObject(RPKI_Exception): + """ + Attempt to create an object that already exists. + """ diff --git a/rpkid/rpki/https.py b/rpkid/rpki/https.py index 2dabfe50..e7059df2 100644 --- a/rpkid/rpki/https.py +++ b/rpkid/rpki/https.py @@ -46,10 +46,10 @@ rpki_content_type = "application/x-rpki" # ================================================================ # Chatter about TLS certificates -debug_tls_certs = True +debug_tls_certs = False # Verbose chatter about HTTP streams -debug = True +debug = False # Whether we want persistent HTTP streams, when peer also supports them want_persistent_client = True diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py index 41f15e0e..dae834b2 100644 --- a/rpkid/rpki/left_right.py +++ b/rpkid/rpki/left_right.py @@ -53,6 +53,10 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name Virtual class for top-level left-right protocol data elements. """ + handles = () + + self_id = None + def self(self): """Fetch self object to which this object links.""" return self_elt.sql_fetch(self.gctx, self.self_id) @@ -62,25 +66,48 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name return bsc_elt.sql_fetch(self.gctx, self.bsc_id) def make_reply_clone_hook(self, r_pdu): - """Set self_id when cloning.""" - r_pdu.self_id = self.self_id + """Set self_handle when cloning.""" + r_pdu.self_handle = self.self_handle + + @classmethod + def serve_fetch_handle(cls, gctx, self_id, handle): + """ + Find an object based on its handle. + """ + return cls.sql_fetch_where1(gctx, cls.element_name + "_handle = %s AND self_id = %s", (handle, self_id)) - def serve_fetch_one(self): + def serve_fetch_one_maybe(self): """ Find the object on which a get, set, or destroy method should - operate. + operate, or which would conflict with a create method. """ - where = self.sql_template.index + " = %s AND self_id = %s" - args = (getattr(self, self.sql_template.index), self.self_id) - r = self.sql_fetch_where1(self.gctx, where, args) - if r is None: - raise rpki.exceptions.NotFound, "Lookup failed where " + (where % args) - return r + where = "%s.%s_handle = %%s AND %s.self_id = self.self_id AND self.self_handle = %%s" % ((self.element_name,) * 3) + args = (getattr(self, self.element_name + "_handle"), self.self_handle) + return self.sql_fetch_where1(self.gctx, where, args, "self") def serve_fetch_all(self): - """Find the objects on which a list method should operate.""" - return self.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,)) + """ + Find the objects on which a list method should operate. + """ + where = "%s.self_id = self.self_id and self.self_handle = %%s" % self.element_name + return self.sql_fetch_where(self.gctx, where, (self.self_handle,), "self") + def serve_pre_save_hook(self, q_pdu, r_pdu, cb, eb): + """ + Hook to do _handle => _id translation before saving. + """ + for tag, elt in self.handles: + id_name = tag + "_id" + if getattr(r_pdu, id_name, None) is None: + x = elt.serve_fetch_handle(self.gctx, self.self_id, getattr(q_pdu, tag + "_handle")) + if x is None: + raise rpki.exceptions.NotFound + val = getattr(x, id_name) + rpki.log.debug("Setting %r and %r %s = %r" % (self, r_pdu, id_name, val)) + setattr(self, id_name, val) + setattr(r_pdu, id_name, val) + cb() + def unimplemented_control(self, *controls): """ Uniform handling for unimplemented control operations. @@ -95,14 +122,15 @@ class self_elt(data_elt): """ element_name = "self" - attributes = ("action", "tag", "self_id", "crl_interval", "regen_margin") + attributes = ("action", "tag", "self_handle", "crl_interval", "regen_margin") elements = ("bpki_cert", "bpki_glue") booleans = ("rekey", "reissue", "revoke", "run_now", "publish_world_now") - sql_template = rpki.sql.template("self", "self_id", "use_hsm", "crl_interval", "regen_margin", + sql_template = rpki.sql.template("self", "self_id", "self_handle", + "use_hsm", "crl_interval", "regen_margin", ("bpki_cert", rpki.x509.X509), ("bpki_glue", rpki.x509.X509)) + handles = () - self_id = None use_hsm = False crl_interval = None regen_margin = None @@ -164,15 +192,19 @@ class self_elt(data_elt): rpki.async.iterator(self.parents(), loop, cb) - def serve_fetch_one(self): + def serve_fetch_one_maybe(self): """ Find the self object upon which a get, set, or destroy action - should operate. + should operate, or which would conflict with a create method. + """ + return self.serve_fetch_handle(self.gctx, None, self.self_handle) + + @classmethod + def serve_fetch_handle(cls, gctx, self_id, self_handle): + """ + Find a self object based on its self_handle. """ - r = self.sql_fetch(self.gctx, self.self_id) - if r is None: - raise rpki.exceptions.NotFound - return r + return cls.sql_fetch_where1(gctx, "self_handle = %s", self_handle) def serve_fetch_all(self): """ @@ -310,7 +342,7 @@ class self_elt(data_elt): child_certs = child.child_certs() if child_certs: - self.gctx.irdb_query(child.self_id, child.child_id, got_resources, irdb_lookup_failed) + self.gctx.irdb_query(child.self().self_handle, child.child_handle, got_resources, irdb_lookup_failed) else: iterator1() @@ -385,15 +417,17 @@ class bsc_elt(data_elt): """ element_name = "bsc" - attributes = ("action", "tag", "self_id", "bsc_id", "key_type", "hash_alg", "key_length") + attributes = ("action", "tag", "self_handle", "bsc_handle", "key_type", "hash_alg", "key_length") elements = ("signing_cert", "signing_cert_crl", "pkcs10_request") booleans = ("generate_keypair",) - sql_template = rpki.sql.template("bsc", "bsc_id", "self_id", "hash_alg", + sql_template = rpki.sql.template("bsc", "bsc_id", "bsc_handle", + "self_id", "hash_alg", ("private_key_id", rpki.x509.RSA), ("pkcs10_request", rpki.x509.PKCS10), ("signing_cert", rpki.x509.X509), ("signing_cert_crl", rpki.x509.CRL)) + handles = (("self", self_elt),) private_key_id = None pkcs10_request = None @@ -422,7 +456,78 @@ class bsc_elt(data_elt): self.private_key_id = rpki.x509.RSA.generate(keylength = q_pdu.key_length or 2048) self.pkcs10_request = rpki.x509.PKCS10.create(self.private_key_id) r_pdu.pkcs10_request = self.pkcs10_request - cb() + data_elt.serve_pre_save_hook(self, q_pdu, r_pdu, cb, eb) + +class repository_elt(data_elt): + """ + <repository/> element. + """ + + element_name = "repository" + attributes = ("action", "tag", "self_handle", "repository_handle", "bsc_handle", "peer_contact_uri") + elements = ("bpki_cms_cert", "bpki_cms_glue", "bpki_https_cert", "bpki_https_glue") + + sql_template = rpki.sql.template("repository", "repository_id", "repository_handle", + "self_id", "bsc_id", "peer_contact_uri", + ("bpki_cms_cert", rpki.x509.X509), ("bpki_cms_glue", rpki.x509.X509), + ("bpki_https_cert", rpki.x509.X509), ("bpki_https_glue", rpki.x509.X509)) + handles = (("self", self_elt), ("bsc", bsc_elt)) + + bpki_cms_cert = None + bpki_cms_glue = None + bpki_https_cert = None + bpki_https_glue = None + + def parents(self): + """Fetch all parent objects that link to this repository object.""" + return parent_elt.sql_fetch_where(self.gctx, "repository_id = %s", (self.repository_id,)) + + def call_pubd(self, callback, errback, *pdus): + """ + Send a message to publication daemon and return the response. + """ + rpki.log.trace() + bsc = self.bsc() + q_msg = rpki.publication.msg(pdus) + q_msg.type = "query" + q_cms = rpki.publication.cms_msg.wrap(q_msg, bsc.private_key_id, bsc.signing_cert, bsc.signing_cert_crl) + bpki_ta_path = (self.gctx.bpki_ta, self.self().bpki_cert, self.self().bpki_glue, self.bpki_https_cert, self.bpki_https_glue) + + def done(r_cms): + try: + r_msg = rpki.publication.cms_msg.unwrap(r_cms, bpki_ta_path) + if len(r_msg) != 1 or isinstance(r_msg[0], rpki.publication.report_error_elt): + raise rpki.exceptions.BadPublicationReply, "Unexpected response from pubd: %s" % msg + callback() + except (rpki.async.ExitNow, SystemExit): + raise + except Exception, edata: + errback(edata) + + rpki.https.client( + client_key = bsc.private_key_id, + client_cert = bsc.signing_cert, + server_ta = bpki_ta_path, + url = self.peer_contact_uri, + msg = q_cms, + callback = done, + errback = errback) + + def publish(self, obj, uri, callback, errback): + """ + Publish one object in the repository. + """ + rpki.log.trace() + rpki.log.info("Publishing %s as %s" % (repr(obj), repr(uri))) + self.call_pubd(callback, errback, rpki.publication.obj2elt[type(obj)].make_pdu(action = "publish", uri = uri, payload = obj)) + + def withdraw(self, obj, uri, callback, errback): + """ + Withdraw one object from the repository. + """ + rpki.log.trace() + rpki.log.info("Withdrawing %s from at %s" % (repr(obj), repr(uri))) + self.call_pubd(callback, errback, rpki.publication.obj2elt[type(obj)].make_pdu(action = "withdraw", uri = uri)) class parent_elt(data_elt): """ @@ -430,15 +535,17 @@ class parent_elt(data_elt): """ element_name = "parent" - attributes = ("action", "tag", "self_id", "parent_id", "bsc_id", "repository_id", + attributes = ("action", "tag", "self_handle", "parent_handle", "bsc_handle", "repository_handle", "peer_contact_uri", "sia_base", "sender_name", "recipient_name") elements = ("bpki_cms_cert", "bpki_cms_glue", "bpki_https_cert", "bpki_https_glue") booleans = ("rekey", "reissue", "revoke") - sql_template = rpki.sql.template("parent", "parent_id", "self_id", "bsc_id", "repository_id", + sql_template = rpki.sql.template("parent", "parent_id", "parent_handle", + "self_id", "bsc_id", "repository_id", ("bpki_cms_cert", rpki.x509.X509), ("bpki_cms_glue", rpki.x509.X509), ("bpki_https_cert", rpki.x509.X509), ("bpki_https_glue", rpki.x509.X509), "peer_contact_uri", "sia_base", "sender_name", "recipient_name") + handles = (("self", self_elt), ("bsc", bsc_elt), ("repository", repository_elt)) bpki_cms_cert = None bpki_cms_glue = None @@ -528,14 +635,17 @@ class child_elt(data_elt): """ element_name = "child" - attributes = ("action", "tag", "self_id", "child_id", "bsc_id") + attributes = ("action", "tag", "self_handle", "child_handle", "bsc_handle") elements = ("bpki_cert", "bpki_glue") booleans = ("reissue", ) - sql_template = rpki.sql.template("child", "child_id", "self_id", "bsc_id", + sql_template = rpki.sql.template("child", "child_id", "child_handle", + "self_id", "bsc_id", ("bpki_cert", rpki.x509.X509), ("bpki_glue", rpki.x509.X509)) + handles = (("self", self_elt), ("bsc", bsc_elt)) + bpki_cert = None bpki_glue = None clear_https_ta_cache = False @@ -619,88 +729,20 @@ class child_elt(data_elt): rpki.log.error(traceback.format_exc()) done(q_msg.serve_error(data)) -class repository_elt(data_elt): - """ - <repository/> element. - """ - - element_name = "repository" - attributes = ("action", "tag", "self_id", "repository_id", "bsc_id", "peer_contact_uri") - elements = ("bpki_cms_cert", "bpki_cms_glue", "bpki_https_cert", "bpki_https_glue") - - sql_template = rpki.sql.template("repository", "repository_id", "self_id", "bsc_id", "peer_contact_uri", - ("bpki_cms_cert", rpki.x509.X509), ("bpki_cms_glue", rpki.x509.X509), - ("bpki_https_cert", rpki.x509.X509), ("bpki_https_glue", rpki.x509.X509)) - - bpki_cms_cert = None - bpki_cms_glue = None - bpki_https_cert = None - bpki_https_glue = None - - def parents(self): - """Fetch all parent objects that link to this repository object.""" - return parent_elt.sql_fetch_where(self.gctx, "repository_id = %s", (self.repository_id,)) - - def call_pubd(self, callback, errback, *pdus): - """ - Send a message to publication daemon and return the response. - """ - rpki.log.trace() - bsc = self.bsc() - q_msg = rpki.publication.msg(pdus) - q_msg.type = "query" - q_cms = rpki.publication.cms_msg.wrap(q_msg, bsc.private_key_id, bsc.signing_cert, bsc.signing_cert_crl) - bpki_ta_path = (self.gctx.bpki_ta, self.self().bpki_cert, self.self().bpki_glue, self.bpki_https_cert, self.bpki_https_glue) - - def done(r_cms): - try: - r_msg = rpki.publication.cms_msg.unwrap(r_cms, bpki_ta_path) - if len(r_msg) != 1 or isinstance(r_msg[0], rpki.publication.report_error_elt): - raise rpki.exceptions.BadPublicationReply, "Unexpected response from pubd: %s" % msg - callback() - except (rpki.async.ExitNow, SystemExit): - raise - except Exception, edata: - errback(edata) - - rpki.https.client( - client_key = bsc.private_key_id, - client_cert = bsc.signing_cert, - server_ta = bpki_ta_path, - url = self.peer_contact_uri, - msg = q_cms, - callback = done, - errback = errback) - - def publish(self, obj, uri, callback, errback): - """ - Publish one object in the repository. - """ - rpki.log.trace() - rpki.log.info("Publishing %s as %s" % (repr(obj), repr(uri))) - self.call_pubd(callback, errback, rpki.publication.obj2elt[type(obj)].make_pdu(action = "publish", uri = uri, payload = obj)) - - def withdraw(self, obj, uri, callback, errback): - """ - Withdraw one object from the repository. - """ - rpki.log.trace() - rpki.log.info("Withdrawing %s from at %s" % (repr(obj), repr(uri))) - self.call_pubd(callback, errback, rpki.publication.obj2elt[type(obj)].make_pdu(action = "withdraw", uri = uri)) - class route_origin_elt(data_elt): """ <route_origin/> element. """ element_name = "route_origin" - attributes = ("action", "tag", "self_id", "route_origin_id", "as_number", "ipv4", "ipv6") + attributes = ("action", "tag", "self_handle", "route_origin_handle", "as_number", "ipv4", "ipv6") booleans = ("suppress_publication",) - sql_template = rpki.sql.template("route_origin", "route_origin_id", "ca_detail_id", - "self_id", "as_number", + sql_template = rpki.sql.template("route_origin", "route_origin_id", "route_origin_handle", + "ca_detail_id", "self_id", "as_number", ("roa", rpki.x509.ROA), ("cert", rpki.x509.X509)) + handles = (("self", self_elt),) ca_detail_id = None cert = None @@ -964,7 +1006,7 @@ class list_resources_elt(rpki.xml_utils.base_elt, left_right_namespace): """ element_name = "list_resources" - attributes = ("self_id", "tag", "child_id", "valid_until", "asn", "ipv4", "ipv6") + attributes = ("self_handle", "tag", "child_handle", "valid_until", "asn", "ipv4", "ipv6") valid_until = None def startElement(self, stack, name, attrs): @@ -999,15 +1041,15 @@ class report_error_elt(rpki.xml_utils.base_elt, left_right_namespace): """ element_name = "report_error" - attributes = ("tag", "self_id", "error_code") + attributes = ("tag", "self_handle", "error_code") @classmethod - def from_exception(cls, e, self_id = None): + def from_exception(cls, e, self_handle = None): """ Generate a <report_error/> element from an exception. """ self = cls() - self.self_id = self_id + self.self_handle = self_handle self.error_code = e.__class__.__name__ self.text = str(e) return self @@ -1038,7 +1080,7 @@ class msg(rpki.xml_utils.msg, left_right_namespace): def fail(e): rpki.log.error(traceback.format_exc()) - r_msg.append(report_error_elt.from_exception(e, self_id = q_pdu.self_id)) + r_msg.append(report_error_elt.from_exception(e, self_handle = q_pdu.self_handle)) cb(r_msg) try: diff --git a/rpkid/rpki/publication.py b/rpkid/rpki/publication.py index a5b0437e..8130f78c 100644 --- a/rpkid/rpki/publication.py +++ b/rpkid/rpki/publication.py @@ -103,15 +103,12 @@ class config_elt(control_elt): else: control_elt.serve_set(self, r_msg, cb, eb) - def serve_fetch_one(self): + def serve_fetch_one_maybe(self): """ Find the config object on which a get or set method should operate. """ - r = self.sql_fetch(self.gctx, self.config_id) - if r is None: - raise rpki.exceptions.NotFound - return r + return self.sql_fetch(self.gctx, self.config_id) class client_elt(control_elt): """ @@ -119,10 +116,10 @@ class client_elt(control_elt): """ element_name = "client" - attributes = ("action", "tag", "client_id", "base_uri") + attributes = ("action", "tag", "client_handle", "base_uri") elements = ("bpki_cert", "bpki_glue") - sql_template = rpki.sql.template("client", "client_id", "base_uri", ("bpki_cert", rpki.x509.X509), ("bpki_glue", rpki.x509.X509)) + sql_template = rpki.sql.template("client", "client_id", "client_handle", "base_uri", ("bpki_cert", rpki.x509.X509), ("bpki_glue", rpki.x509.X509)) base_uri = None bpki_cert = None @@ -149,15 +146,12 @@ class client_elt(control_elt): self.clear_https_ta_cache = False cb() - def serve_fetch_one(self): + def serve_fetch_one_maybe(self): """ Find the client object on which a get, set, or destroy method - should operate. + should operate, or which would conflict with a create method. """ - r = self.sql_fetch(self.gctx, self.client_id) - if r is None: - raise rpki.exceptions.NotFound - return r + return self.sql_fetch_where1(self.gctx, "client_handle = %s", self.client_handle) def serve_fetch_all(self): """Find client objects on which a list method should operate.""" @@ -177,7 +171,7 @@ class publication_object_elt(rpki.xml_utils.base_elt, publication_namespace): different in any case. """ - attributes = ("action", "tag", "client_id", "uri") + attributes = ("action", "tag", "client_handle", "uri") payload = None def endElement(self, stack, name, text): diff --git a/rpkid/rpki/relaxng.py b/rpkid/rpki/relaxng.py index 9b4545c6..ddd2a191 100644 --- a/rpkid/rpki/relaxng.py +++ b/rpkid/rpki/relaxng.py @@ -139,9 +139,21 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <param name="maxLength">512000</param> </data> </define> - <!-- Base definition for all fields that are really just SQL primary indices --> - <define name="sql_id"> - <data type="nonNegativeInteger"/> + <!-- + Base definition for all fields that are really just SQL primary indices + sql_id = xsd:nonNegativeInteger + --> + <!-- + ...except that fields containing SQL primary indicies don't belong + in this protocol, so they're turninging into handles. + Length restriction is a MySQL implementation issue. + Handles are case-insensitive (because SQL is, among other reasons). + --> + <define name="object_handle"> + <data type="string"> + <param name="maxLength">255</param> + <param name="pattern">[\-_A-Za-z0-9]*</param> + </data> </define> <!-- URIs --> <define name="uri"> @@ -232,14 +244,15 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc </element> </optional> </define> - <define name="self_id"> - <attribute name="self_id"> - <ref name="sql_id"/> + <define name="self_handle"> + <attribute name="self_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="self_query" combine="choice"> <element name="self"> <ref name="ctl_create"/> + <ref name="self_handle"/> <ref name="self_bool"/> <ref name="self_payload"/> </element> @@ -247,13 +260,13 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="self_reply" combine="choice"> <element name="self"> <ref name="ctl_create"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="self_query" combine="choice"> <element name="self"> <ref name="ctl_set"/> - <ref name="self_id"/> + <ref name="self_handle"/> <ref name="self_bool"/> <ref name="self_payload"/> </element> @@ -261,19 +274,19 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="self_reply" combine="choice"> <element name="self"> <ref name="ctl_set"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="self_query" combine="choice"> <element name="self"> <ref name="ctl_get"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="self_reply" combine="choice"> <element name="self"> <ref name="ctl_get"/> - <ref name="self_id"/> + <ref name="self_handle"/> <ref name="self_payload"/> </element> </define> @@ -285,20 +298,20 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="self_reply" combine="choice"> <element name="self"> <ref name="ctl_list"/> - <ref name="self_id"/> + <ref name="self_handle"/> <ref name="self_payload"/> </element> </define> <define name="self_query" combine="choice"> <element name="self"> <ref name="ctl_destroy"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="self_reply" combine="choice"> <element name="self"> <ref name="ctl_destroy"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <!-- <bsc/> element. Key parameters hardwired for now. --> @@ -324,9 +337,9 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc </optional> </optional> </define> - <define name="bsc_id"> - <attribute name="bsc_id"> - <ref name="sql_id"/> + <define name="bsc_handle"> + <attribute name="bsc_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="bsc_payload"> @@ -351,7 +364,8 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="bsc_query" combine="choice"> <element name="bsc"> <ref name="ctl_create"/> - <ref name="self_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> <ref name="bsc_bool"/> <ref name="bsc_payload"/> </element> @@ -359,16 +373,16 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="bsc_reply" combine="choice"> <element name="bsc"> <ref name="ctl_create"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> <ref name="bsc_pkcs10"/> </element> </define> <define name="bsc_query" combine="choice"> <element name="bsc"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> <ref name="bsc_bool"/> <ref name="bsc_payload"/> </element> @@ -376,23 +390,23 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="bsc_reply" combine="choice"> <element name="bsc"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> <ref name="bsc_pkcs10"/> </element> </define> <define name="bsc_query" combine="choice"> <element name="bsc"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> </element> </define> <define name="bsc_reply" combine="choice"> <element name="bsc"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> <ref name="bsc_payload"/> <ref name="bsc_pkcs10"/> </element> @@ -400,14 +414,14 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="bsc_query" combine="choice"> <element name="bsc"> <ref name="ctl_list"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="bsc_reply" combine="choice"> <element name="bsc"> <ref name="ctl_list"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> <ref name="bsc_payload"/> <ref name="bsc_pkcs10"/> </element> @@ -415,21 +429,21 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="bsc_query" combine="choice"> <element name="bsc"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> </element> </define> <define name="bsc_reply" combine="choice"> <element name="bsc"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="bsc_id"/> + <ref name="self_handle"/> + <ref name="bsc_handle"/> </element> </define> <!-- <parent/> element --> - <define name="parent_id"> - <attribute name="parent_id"> - <ref name="sql_id"/> + <define name="parent_handle"> + <attribute name="parent_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="parent_bool"> @@ -461,10 +475,10 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc </attribute> </optional> <optional> - <ref name="bsc_id"/> + <ref name="bsc_handle"/> </optional> <optional> - <ref name="repository_id"/> + <ref name="repository_handle"/> </optional> <optional> <attribute name="sender_name"> @@ -500,7 +514,8 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="parent_query" combine="choice"> <element name="parent"> <ref name="ctl_create"/> - <ref name="self_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> <ref name="parent_bool"/> <ref name="parent_payload"/> </element> @@ -508,15 +523,15 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="parent_reply" combine="choice"> <element name="parent"> <ref name="ctl_create"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> </element> </define> <define name="parent_query" combine="choice"> <element name="parent"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> <ref name="parent_bool"/> <ref name="parent_payload"/> </element> @@ -524,57 +539,57 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="parent_reply" combine="choice"> <element name="parent"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> </element> </define> <define name="parent_query" combine="choice"> <element name="parent"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> </element> </define> <define name="parent_reply" combine="choice"> <element name="parent"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> <ref name="parent_payload"/> </element> </define> <define name="parent_query" combine="choice"> <element name="parent"> <ref name="ctl_list"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="parent_reply" combine="choice"> <element name="parent"> <ref name="ctl_list"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> <ref name="parent_payload"/> </element> </define> <define name="parent_query" combine="choice"> <element name="parent"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> </element> </define> <define name="parent_reply" combine="choice"> <element name="parent"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="parent_id"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> </element> </define> <!-- <child/> element --> - <define name="child_id"> - <attribute name="child_id"> - <ref name="sql_id"/> + <define name="child_handle"> + <attribute name="child_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="child_bool"> @@ -586,7 +601,7 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc </define> <define name="child_payload"> <optional> - <ref name="bsc_id"/> + <ref name="bsc_handle"/> </optional> <optional> <element name="bpki_cert"> @@ -602,7 +617,8 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="child_query" combine="choice"> <element name="child"> <ref name="ctl_create"/> - <ref name="self_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> <ref name="child_bool"/> <ref name="child_payload"/> </element> @@ -610,15 +626,15 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="child_reply" combine="choice"> <element name="child"> <ref name="ctl_create"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> </element> </define> <define name="child_query" combine="choice"> <element name="child"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> <ref name="child_bool"/> <ref name="child_payload"/> </element> @@ -626,57 +642,57 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="child_reply" combine="choice"> <element name="child"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> </element> </define> <define name="child_query" combine="choice"> <element name="child"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> </element> </define> <define name="child_reply" combine="choice"> <element name="child"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> <ref name="child_payload"/> </element> </define> <define name="child_query" combine="choice"> <element name="child"> <ref name="ctl_list"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="child_reply" combine="choice"> <element name="child"> <ref name="ctl_list"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> <ref name="child_payload"/> </element> </define> <define name="child_query" combine="choice"> <element name="child"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> </element> </define> <define name="child_reply" combine="choice"> <element name="child"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> </element> </define> <!-- <repository/> element --> - <define name="repository_id"> - <attribute name="repository_id"> - <ref name="sql_id"/> + <define name="repository_handle"> + <attribute name="repository_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="repository_payload"> @@ -686,7 +702,7 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc </attribute> </optional> <optional> - <ref name="bsc_id"/> + <ref name="bsc_handle"/> </optional> <optional> <element name="bpki_cms_cert"> @@ -712,79 +728,80 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="repository_query" combine="choice"> <element name="repository"> <ref name="ctl_create"/> - <ref name="self_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> <ref name="repository_payload"/> </element> </define> <define name="repository_reply" combine="choice"> <element name="repository"> <ref name="ctl_create"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> </element> </define> <define name="repository_query" combine="choice"> <element name="repository"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> <ref name="repository_payload"/> </element> </define> <define name="repository_reply" combine="choice"> <element name="repository"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> </element> </define> <define name="repository_query" combine="choice"> <element name="repository"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> </element> </define> <define name="repository_reply" combine="choice"> <element name="repository"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> <ref name="repository_payload"/> </element> </define> <define name="repository_query" combine="choice"> <element name="repository"> <ref name="ctl_list"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="repository_reply" combine="choice"> <element name="repository"> <ref name="ctl_list"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> <ref name="repository_payload"/> </element> </define> <define name="repository_query" combine="choice"> <element name="repository"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> </element> </define> <define name="repository_reply" combine="choice"> <element name="repository"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="repository_id"/> + <ref name="self_handle"/> + <ref name="repository_handle"/> </element> </define> <!-- <route_origin/> element --> - <define name="route_origin_id"> - <attribute name="route_origin_id"> - <ref name="sql_id"/> + <define name="route_origin_handle"> + <attribute name="route_origin_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="route_origin_bool"> @@ -814,7 +831,8 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="route_origin_query" combine="choice"> <element name="route_origin"> <ref name="ctl_create"/> - <ref name="self_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> <ref name="route_origin_bool"/> <ref name="route_origin_payload"/> </element> @@ -822,15 +840,15 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="route_origin_reply" combine="choice"> <element name="route_origin"> <ref name="ctl_create"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> </element> </define> <define name="route_origin_query" combine="choice"> <element name="route_origin"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> <ref name="route_origin_bool"/> <ref name="route_origin_payload"/> </element> @@ -838,66 +856,66 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <define name="route_origin_reply" combine="choice"> <element name="route_origin"> <ref name="ctl_set"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> </element> </define> <define name="route_origin_query" combine="choice"> <element name="route_origin"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> </element> </define> <define name="route_origin_reply" combine="choice"> <element name="route_origin"> <ref name="ctl_get"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> <ref name="route_origin_payload"/> </element> </define> <define name="route_origin_query" combine="choice"> <element name="route_origin"> <ref name="ctl_list"/> - <ref name="self_id"/> + <ref name="self_handle"/> </element> </define> <define name="route_origin_reply" combine="choice"> <element name="route_origin"> <ref name="ctl_list"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> <ref name="route_origin_payload"/> </element> </define> <define name="route_origin_query" combine="choice"> <element name="route_origin"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> </element> </define> <define name="route_origin_reply" combine="choice"> <element name="route_origin"> <ref name="ctl_destroy"/> - <ref name="self_id"/> - <ref name="route_origin_id"/> + <ref name="self_handle"/> + <ref name="route_origin_handle"/> </element> </define> <!-- <list_resources/> element --> <define name="list_resources_query"> <element name="list_resources"> <ref name="tag"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> </element> </define> <define name="list_resources_reply"> <element name="list_resources"> <ref name="tag"/> - <ref name="self_id"/> - <ref name="child_id"/> + <ref name="self_handle"/> + <ref name="child_handle"/> <attribute name="valid_until"> <data type="dateTime"> <param name="pattern">.*Z</param> @@ -930,7 +948,7 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <element name="report_error"> <ref name="tag"/> <optional> - <ref name="self_id"/> + <ref name="self_handle"/> </optional> <attribute name="error_code"> <ref name="error"/> @@ -1292,9 +1310,16 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <ref name="uri_t"/> </attribute> </define> + <!-- Handles on remote objects (replaces passing raw SQL IDs) --> + <define name="object_handle"> + <data type="string"> + <param name="maxLength">255</param> + <param name="pattern">[\-_A-Za-z0-9]*</param> + </data> + </define> <!-- <config/> element (use restricted to repository operator) - config_id attribute, create, list, and destroy commands omitted deliberately, see code for details + config_handle attribute, create, list, and destroy commands omitted deliberately, see code for details --> <define name="config_payload"> <optional> @@ -1346,9 +1371,9 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en </element> </define> <!-- <client/> element (use restricted to repository operator) --> - <define name="client_id"> - <attribute name="client_id"> - <data type="nonNegativeInteger"/> + <define name="client_handle"> + <attribute name="client_handle"> + <ref name="object_handle"/> </attribute> </define> <define name="client_payload"> @@ -1376,6 +1401,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> + <ref name="client_handle"/> <ref name="client_payload"/> </element> </define> @@ -1387,7 +1413,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> </element> </define> <define name="client_query" combine="choice"> @@ -1398,7 +1424,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> <ref name="client_payload"/> </element> </define> @@ -1410,7 +1436,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> </element> </define> <define name="client_query" combine="choice"> @@ -1421,7 +1447,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> </element> </define> <define name="client_reply" combine="choice"> @@ -1432,7 +1458,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> <ref name="client_payload"/> </element> </define> @@ -1454,7 +1480,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> <ref name="client_payload"/> </element> </define> @@ -1466,7 +1492,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> </element> </define> <define name="client_reply" combine="choice"> @@ -1477,7 +1503,7 @@ publication = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" en <optional> <ref name="tag"/> </optional> - <ref name="client_id"/> + <ref name="client_handle"/> </element> </define> <!-- <certificate/> element --> diff --git a/rpkid/rpki/rpki_engine.py b/rpkid/rpki/rpki_engine.py index 6426c3d0..5bbde36d 100644 --- a/rpkid/rpki/rpki_engine.py +++ b/rpkid/rpki/rpki_engine.py @@ -32,7 +32,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ -import traceback, lxml.etree +import traceback, lxml.etree, re import rpki.resource_set, rpki.up_down, rpki.left_right, rpki.x509, rpki.sql import rpki.https, rpki.config, rpki.exceptions, rpki.relaxng, rpki.log, rpki.async @@ -58,7 +58,7 @@ class rpkid_context(object): self.publication_kludge_base = cfg.get("publication-kludge-base", "publication/") - def irdb_query(self, self_id, child_id, callback, errback): + def irdb_query(self, self_handle, child_handle, callback, errback): """ Perform an IRDB callback query. """ @@ -68,8 +68,8 @@ class rpkid_context(object): q_msg = rpki.left_right.msg() q_msg.type = "query" q_msg.append(rpki.left_right.list_resources_elt()) - q_msg[0].self_id = self_id - q_msg[0].child_id = child_id + q_msg[0].self_handle = self_handle + q_msg[0].child_handle = child_handle q_cms = rpki.left_right.cms_msg.wrap(q_msg, self.rpkid_key, self.rpkid_cert) def unwrap(der): @@ -117,6 +117,8 @@ class rpkid_context(object): rpki.log.error(traceback.format_exc()) cb(500, "Unhandled exception %s" % data) + up_down_url_regexp = re.compile("/up-down/([-A-Z0-9_]+)/([-A-Z0-9_]+)$", re.I) + def up_down_handler(self, query, path, cb): """ Process one up-down PDU. @@ -130,12 +132,14 @@ class rpkid_context(object): try: self.sql.ping() - child_id = path.partition("/up-down/")[2] - if not child_id.isdigit(): + match = self.up_down_url_regexp.search(path) + if match is None: raise rpki.exceptions.BadContactURL, "Bad path: %s" % path - child = rpki.left_right.child_elt.sql_fetch(self, long(child_id)) + self_handle, child_handle = match.groups() + child = rpki.left_right.child_elt.sql_fetch_where1(self, "self.self_handle = %s AND child.child_handle = %s AND child.self_id = self.self_id", + (self_handle, child_handle), "self") if child is None: - raise rpki.exceptions.ChildNotFound, "Could not find child %s" % child_id + raise rpki.exceptions.ChildNotFound, "Could not find child %s" % child_handle child.serve_up_down(query, done) except (rpki.async.ExitNow, SystemExit): raise diff --git a/rpkid/rpki/sql.py b/rpkid/rpki/sql.py index 5ce8df2e..69ebd08a 100644 --- a/rpkid/rpki/sql.py +++ b/rpkid/rpki/sql.py @@ -126,12 +126,14 @@ class template(object): self.index = index_column self.columns = columns self.map = type_map - self.select = "SELECT %s FROM %s" % (", ".join(columns), table_name) - self.insert = "INSERT %s (%s) VALUES (%s)" % (table_name, ", ".join(data_columns), + self.select = "SELECT %s FROM %s" % (", ".join("%s.%s" % (table_name, c) for c in columns), table_name) + self.insert = "INSERT %s (%s) VALUES (%s)" % (table_name, + ", ".join(data_columns), ", ".join("%(" + s + ")s" for s in data_columns)) - self.update = "UPDATE %s SET %s WHERE %s = %%(%s)s" % \ - (table_name, ", ".join(s + " = %(" + s + ")s" for s in data_columns), - index_column, index_column) + self.update = "UPDATE %s SET %s WHERE %s = %%(%s)s" % (table_name, + ", ".join(s + " = %(" + s + ")s" for s in data_columns), + index_column, + index_column) self.delete = "DELETE FROM %s WHERE %s = %%s" % (table_name, index_column) class sql_persistent(object): @@ -178,11 +180,11 @@ class sql_persistent(object): return cls.sql_fetch_where1(gctx, "%s = %%s" % cls.sql_template.index, (id,)) @classmethod - def sql_fetch_where1(cls, gctx, where, args = None): + def sql_fetch_where1(cls, gctx, where, args = None, also_from = None): """ Fetch one object from SQL, based on an arbitrary SQL WHERE expression. """ - results = cls.sql_fetch_where(gctx, where, args) + results = cls.sql_fetch_where(gctx, where, args, also_from) if len(results) == 0: return None elif len(results) == 1: @@ -198,17 +200,20 @@ class sql_persistent(object): return cls.sql_fetch_where(gctx, None) @classmethod - def sql_fetch_where(cls, gctx, where, args = None): + def sql_fetch_where(cls, gctx, where, args = None, also_from = None): """ Fetch objects of this type matching an arbitrary SQL WHERE expression. """ if where is None: - assert args is None + assert args is None and also_from is None if cls.sql_debug: rpki.log.debug("sql_fetch_where(%s)" % repr(cls.sql_template.select)) gctx.sql.execute(cls.sql_template.select) else: - query = cls.sql_template.select + " WHERE " + where + query = cls.sql_template.select + if also_from is not None: + query += "," + also_from + query += " WHERE " + where if cls.sql_debug: rpki.log.debug("sql_fetch_where(%s, %s)" % (repr(query), repr(args))) gctx.sql.execute(query, args) diff --git a/rpkid/rpki/up_down.py b/rpkid/rpki/up_down.py index d7d7ad80..fbe10151 100644 --- a/rpkid/rpki/up_down.py +++ b/rpkid/rpki/up_down.py @@ -269,7 +269,7 @@ class list_pdu(base_elt): r_msg.payload.classes.append(rc) callback() - self.gctx.irdb_query(child.self_id, child.child_id, handle, errback) + self.gctx.irdb_query(child.self().self_handle, child.child_handle, handle, errback) @classmethod def query(cls, parent, cb, eb): @@ -403,7 +403,7 @@ class issue_pdu(base_elt): callback = got_child_cert, errback = errback) - self.gctx.irdb_query(child.self_id, child.child_id, got_resources, errback) + self.gctx.irdb_query(child.self().self_handle, child.child_handle, got_resources, errback) @classmethod def query(cls, parent, ca, ca_detail, callback, errback): diff --git a/rpkid/rpki/xml_utils.py b/rpkid/rpki/xml_utils.py index 917405f0..be2b9510 100644 --- a/rpkid/rpki/xml_utils.py +++ b/rpkid/rpki/xml_utils.py @@ -255,7 +255,8 @@ class data_elt(base_elt): if r_pdu is None: r_pdu = self.__class__() self.make_reply_clone_hook(r_pdu) - setattr(r_pdu, self.sql_template.index, getattr(self, self.sql_template.index)) + handle_name = self.element_name + "_handle" + setattr(r_pdu, handle_name, getattr(self, handle_name, None)) else: for b in r_pdu.booleans: setattr(r_pdu, b, False) @@ -267,6 +268,16 @@ class data_elt(base_elt): """Overridable hook.""" pass + def serve_fetch_one(self): + """ + Find the object on which a get, set, or destroy method should + operate. + """ + r = self.serve_fetch_one_maybe() + if r is None: + raise rpki.exceptions.NotFound + return r + def serve_pre_save_hook(self, q_pdu, r_pdu, cb, eb): """Overridable hook.""" cb() @@ -291,6 +302,9 @@ class data_elt(base_elt): r_msg.append(r_pdu) cb() + if self.serve_fetch_one_maybe() is not None: + raise rpki.exceptions.DuplicateObject + self.serve_pre_save_hook(self, r_pdu, one, eb) def serve_set(self, r_msg, cb, eb): |