aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/rpki')
-rw-r--r--rpkid/rpki/exceptions.py5
-rw-r--r--rpkid/rpki/https.py4
-rw-r--r--rpkid/rpki/left_right.py254
-rw-r--r--rpkid/rpki/publication.py22
-rw-r--r--rpkid/rpki/relaxng.py306
-rw-r--r--rpkid/rpki/rpki_engine.py20
-rw-r--r--rpkid/rpki/sql.py25
-rw-r--r--rpkid/rpki/up_down.py4
-rw-r--r--rpkid/rpki/xml_utils.py16
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):