aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/irdb.py6
-rw-r--r--scripts/rpki/exceptions.py4
-rw-r--r--scripts/rpki/left_right.py53
-rw-r--r--scripts/rpki/sql.py49
-rw-r--r--scripts/rpki/up_down.py7
-rwxr-xr-xscripts/rpkid.py6
6 files changed, 88 insertions, 37 deletions
diff --git a/scripts/irdb.py b/scripts/irdb.py
index 5894ccc6..5423c506 100755
--- a/scripts/irdb.py
+++ b/scripts/irdb.py
@@ -92,4 +92,8 @@ privateKey = rpki.x509.RSA_Keypair(PEM_file = cfg.get(section, "https-key"))
certChain = rpki.x509.X509_chain()
certChain.load_from_PEM(cfg.multiget(section, "https-cert"))
-rpki.https.server(privateKey=privateKey, certChain=certChain, handlers=handler)
+rpki.https.server(privateKey = privateKey,
+ certChain = certChain,
+ host = cfg.get(section, "https-host"),
+ port = int(cfg.get(section, "https-port")),
+ handlers = { cfg.get(section, "https-url") : handler })
diff --git a/scripts/rpki/exceptions.py b/scripts/rpki/exceptions.py
index f1be383e..6302d1b9 100644
--- a/scripts/rpki/exceptions.py
+++ b/scripts/rpki/exceptions.py
@@ -14,8 +14,8 @@ class BadStatusCode(Exception):
class BadQuery(Exception):
"""Unexpected protocol query."""
-class MultipleROAsFound(Exception):
- """Found multiple ROAs in a relationship that should be one-to-one."""
+class DBConsistancyError(Exception):
+ """Found multiple matches for a database query that shouldn't ever return that."""
class CMSVerificationFailed(Exception):
"""Verification of a CMS message failed."""
diff --git a/scripts/rpki/left_right.py b/scripts/rpki/left_right.py
index 4715700e..643ab5e0 100644
--- a/scripts/rpki/left_right.py
+++ b/scripts/rpki/left_right.py
@@ -3,7 +3,7 @@
"""RPKI "left-right" protocol."""
import base64, lxml.etree
-import rpki.sax_utils, rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.pkcs10
+import rpki.sax_utils, rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.pkcs10, rpki.https
xmlns = "http://www.hactrn.net/uris/rpki/left-right-spec/"
@@ -444,7 +444,7 @@ class route_origin_elt(data_elt):
roa = roas[0][0]
ca_detail_id = roas[0][1]
elif len(roas) > 0:
- raise rpki.exceptions.MultipleROAsFound, "Multiple ROAs found for route_origin %s, mapping should be one-to-one" % self.route_origin_id
+ raise rpki.exceptions.DBConsistancyError, "Multiple ROAs found for route_origin %s, mapping should be one-to-one" % self.route_origin_id
def sql_insert_hook(self, db, cur):
if self.ipv4 + self.ipv6:
@@ -486,7 +486,7 @@ class resource_class_elt(base_elt):
"""<resource_class/> element."""
element_name = "resource_class"
- attributes = ("as", "req_as", "ipv4", "req_ipv4", "ipv6", "req_ipv6", "subject_name")
+ attributes = ("as", "ipv4", "ipv6", "subject_name")
def startElement(self, stack, name, attrs):
"""Handle <resource_class/> element."""
@@ -494,16 +494,10 @@ class resource_class_elt(base_elt):
self.read_attrs(attrs)
if self.as is not None:
self.as = rpki.resource_set.resource_set_as(self.as)
- if self.req_as is not None:
- self.req_as = rpki.resource_set.resource_set_as(self.req_as)
if self.ipv4 is not None:
self.ipv4 = rpki.resource_set.resource_set_ipv4(self.ipv4)
- if self.req_ipv4 is not None:
- self.req_ipv4 = rpki.resource_set.resource_set_ipv4(self.req_ipv4)
if self.ipv6 is not None:
self.ipv6 = rpki.resource_set.resource_set_ipv6(self.ipv6)
- if self.req_ipv6 is not None:
- self.req_ipv6 = rpki.resource_set.resource_set_ipv6(self.req_ipv6)
def endElement(self, stack, name, text):
"""Handle <resource_class/> element."""
@@ -610,3 +604,44 @@ class sax_handler(rpki.sax_utils.handler):
"""Top-level PDU for this protocol is <msg/>."""
assert name == "msg" and attrs["version"] == "1"
return self.pdu()
+
+def irdb_query(gctx, self_id, child_id=None):
+ """Perform an IRDB callback query.
+
+ In the long run this should not be a blocking routine, it should
+ instead issue a query and set up a handler to receive the response.
+ For the moment, though, we're doing simple lock step and damn the
+ torpedos.
+ """
+
+ q_msg = msg_elt()
+ q_msg.append(list_resources_elt())
+ q_msg[0].type = "query"
+ q_msg[0].self_id = self_id
+ q_msg[0].child_id = child_id
+ q_elt = q_msg.toXML()
+ rpki.relaxng.left_right.assertValid(q_elt)
+ q_cms = rpki.cms.xml_encode(q_elt, gctx.cms_key, gctx.cms_certs)
+ r_cms = rpki.https.client(privateKey = gctx.https_key,
+ certChain = gctx.https_certs,
+ x509TrustList = gctx.https_tas,
+ host = gctx.irdb_host,
+ port = gctx.irdb_port,
+ url = gctx.irdb_url,
+ msg = q_cms)
+ r_elt = rpki.cms.xml_decode(r_cms, gctx.cms_ta_irbe)
+ rpki.relaxng.left_right.assertValid(r_elt)
+ r_msg = rpki.left_right.sax_handler.saxify(r_elt)
+ if len(r_msg) != 0 or not isinstance(r_msg[0], list_resources_elt) or r_msg[0].type != "reply":
+ raise rpki.exceptions.BadIRDBReply, "Unexpected response to IRDB query: %s" % r_msg.toXML()
+ as = rpki.resource_set.resource_set_as()
+ ipv4 = rpki.resource_set.resource_set_ipv4()
+ ipv6 = rpki.resource_set.resource_set_ipv6()
+ for r in r_msg[0].resources:
+ if r.as is not None:
+ as.union(r.as)
+ if r.ipv4 is not None:
+ ipv4.union(r.ipv4)
+ if r.ipv6 is not None:
+ ipv6.union(r.ipv6)
+ return as, ipv4, ipv6
diff --git a/scripts/rpki/sql.py b/scripts/rpki/sql.py
index bab07e5e..2831a447 100644
--- a/scripts/rpki/sql.py
+++ b/scripts/rpki/sql.py
@@ -14,16 +14,15 @@ def connect(cfg, section="sql"):
class template(object):
"""SQL template generator."""
def __init__(self, table_name, *columns):
- index_column = columns[0]
- data_columns = columns[1:]
- self.table = table_name
- self.index = index_column
- self.columns = columns
- 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.delete = "DELETE FROM %s WHERE %s = %%s" % (table_name, index_column)
- self.select_all = "SELECT %s FROM %s" % (", ".join(columns), table_name)
- self.select_one = self.select_all + " WHERE " + index_column + " = %s"
+ index_column = columns[0]
+ data_columns = columns[1:]
+ self.table = table_name
+ self.index = index_column
+ self.columns = columns
+ self.select = "SELECT %s FROM %s" % (", ".join(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.delete = "DELETE FROM %s WHERE %s = %%s" % (table_name, index_column)
## @var sql_cache
# Cache of objects pulled from SQL.
@@ -58,27 +57,33 @@ class sql_persistant(object):
@classmethod
def sql_fetch(cls, db, cur, id):
- key = (cls, id)
- if key in sql_cache:
- return sql_cache[key]
- cur.execute(cls.sql_template.select_one, id)
- row = cur.fetchone()
- if row is None:
+ results = cls.sql_fetch_where(db, cur, "WHERE %s = %s" % (cls.sql_template.index, id))
+ assert len(results) <= 1
+ if len(results) == 0:
return None
+ elif len(results) == 1:
+ return results[0]
else:
- return cls.sql_init(db, cur, row, key)
+ raise rpki.exceptions.DBConsistancyError, "Database contained multiple matches for %s.%s" % (cls.__name__, id)
@classmethod
def sql_fetch_all(cls, db, cur):
- cur.execute(cls.sql_template.select_all)
- all = []
+ return cls.sql_fetch_where(db, cur, None)
+
+ @classmethod
+ def sql_fetch_where(cls, db, cur, where):
+ if where is None:
+ cur.execute(cls.sql_template.select)
+ else:
+ cur.execute(cls.sql_template.select + where)
+ results = []
for row in cur.fetchall():
key = (cls, row[0])
if key in sql_cache:
- all.append(sql_cache[key])
+ results.append(sql_cache[key])
else:
- all.append(cls.sql_init(db, cur, row, key))
- return all
+ results.append(cls.sql_init(db, cur, row, key))
+ return results
@classmethod
def sql_init(cls, db, cur, row, key):
diff --git a/scripts/rpki/up_down.py b/scripts/rpki/up_down.py
index 507e42e6..dbaba3fd 100644
--- a/scripts/rpki/up_down.py
+++ b/scripts/rpki/up_down.py
@@ -144,18 +144,19 @@ class list_pdu(base_elt):
raise NotImplementedError
# Tasks:
- #
+
# 1) extract child's resource set from irdb
#
+ irdb_as, irdb_ipv4, irdb_ipv6 = rpki.left_right.irdb_query(gctx, child.self_id, child.child_id)
+
# 2) for every ca, compute intersection of child's resource set
# with ca's resource set; if result is non-null, this ca is one
# of the resource classes for this child
#
# 3) establish ca_child_link bindings based on (2)?
#
- # 4) generate result pdu
+ # 4) generate result pdu, unless we do that as part of (2)
- child_data = irdb_query(child)
r_msg.payload = list_response_pdu()
for ca in rpki.sql.fetch_column(gctx.cur, "SELECT ca_id FROM child_ca_link WHERE child_id = %s" % child.child_id):
klass = class_elt()
diff --git a/scripts/rpkid.py b/scripts/rpkid.py
index cdac0c60..5ef0809d 100755
--- a/scripts/rpkid.py
+++ b/scripts/rpkid.py
@@ -66,8 +66,14 @@ gctx.cms_certs = gctx.cfg.multiget(gctx.cfg_section, "cms-cert")
gctx.https_key = rpki.x509.RSA_Keypair(PEM_file = gctx.cfg.get(gctx.cfg_section, "https-key"))
gctx.https_certs = certChain = rpki.x509.X509_chain()
+gctx.https_tas = rpki.x509.X509_chain()
gctx.https_certs.load_from_PEM(gctx.cfg.multiget(gctx.cfg_section, "https-cert"))
+gctx.https_tas.load_from_PEM(gctx.cfg.multiget(gctx.cfg_section, "https-ta"))
+
+gctx.irdb_host = gctx.cfg.get(gctx.cfg_section, "irdb-host")
+gctx.irdb_port = gctx.cfg.get(gctx.cfg_section, "irdb-port")
+gctx.irdb_url = gctx.cfg.get(gctx.cfg_section, "irdb-url")
rpki.https.server(privateKey=gctx.https_key, certChain=gctx.https_certs,
handlers=(("/left-right", left_right_handler),