aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/left-right-xml4
-rw-r--r--docs/rpki-db-schema.pdfbin7249 -> 7305 bytes
-rw-r--r--docs/rpki-db-schema.sql1
-rw-r--r--rpkid/left-right-protocol-samples/pdu.053.xml2
-rw-r--r--rpkid/left-right-protocol-samples/pdu.056.xml2
-rw-r--r--rpkid/left-right-schema.rnc1
-rw-r--r--rpkid/left-right-schema.rng5
-rw-r--r--rpkid/rpki/gctx.py11
-rw-r--r--rpkid/rpki/https.py18
-rw-r--r--rpkid/rpki/left_right.py29
-rw-r--r--rpkid/rpki/relaxng.py7
-rw-r--r--rpkid/rpki/sql.py6
-rw-r--r--rpkid/testbed.1.yaml5
-rw-r--r--rpkid/testbed.py22
14 files changed, 78 insertions, 35 deletions
diff --git a/docs/left-right-xml b/docs/left-right-xml
index 6d60dbb8..1f9b983f 100644
--- a/docs/left-right-xml
+++ b/docs/left-right-xml
@@ -817,7 +817,7 @@
<msg version="1" xmlns="http://www.hactrn.net/uris/rpki/left-right-spec/">
<route_origin action="set" type="query" self_id="42" route_origin_id="88"
suppress_publication="yes"
- as_number="12345" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
+ as_number="12345" exact_match="true" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
</msg>
<msg version="1" xmlns="http://www.hactrn.net/uris/rpki/left-right-spec/">
@@ -830,7 +830,7 @@
<msg version="1" xmlns="http://www.hactrn.net/uris/rpki/left-right-spec/">
<route_origin action="get" type="reply" self_id="42" route_origin_id="88"
- as_number="12345" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
+ as_number="12345" exact_match="true" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
</msg>
<msg version="1" xmlns="http://www.hactrn.net/uris/rpki/left-right-spec/">
diff --git a/docs/rpki-db-schema.pdf b/docs/rpki-db-schema.pdf
index 5a82b7d3..bff9e381 100644
--- a/docs/rpki-db-schema.pdf
+++ b/docs/rpki-db-schema.pdf
Binary files differ
diff --git a/docs/rpki-db-schema.sql b/docs/rpki-db-schema.sql
index 8e345b19..6a436e80 100644
--- a/docs/rpki-db-schema.sql
+++ b/docs/rpki-db-schema.sql
@@ -166,6 +166,7 @@ DROP TABLE IF EXISTS route_origin;
CREATE TABLE route_origin (
route_origin_id SERIAL NOT NULL,
as_number DECIMAL(24,0),
+ exact_match BOOLEAN NOT NULL,
cert LONGBLOB,
roa LONGBLOB,
self_id BIGINT unsigned NOT NULL,
diff --git a/rpkid/left-right-protocol-samples/pdu.053.xml b/rpkid/left-right-protocol-samples/pdu.053.xml
index a36dc495..64546be7 100644
--- a/rpkid/left-right-protocol-samples/pdu.053.xml
+++ b/rpkid/left-right-protocol-samples/pdu.053.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--Automatically generated, do not edit.-->
<msg xmlns="http://www.hactrn.net/uris/rpki/left-right-spec/" version="1">
- <route_origin action="set" type="query" self_id="42" route_origin_id="88" suppress_publication="yes" as_number="12345" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
+ <route_origin action="set" type="query" self_id="42" route_origin_id="88" suppress_publication="yes" as_number="12345" exact_match="true" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
</msg>
diff --git a/rpkid/left-right-protocol-samples/pdu.056.xml b/rpkid/left-right-protocol-samples/pdu.056.xml
index 554cf859..1ad64cce 100644
--- a/rpkid/left-right-protocol-samples/pdu.056.xml
+++ b/rpkid/left-right-protocol-samples/pdu.056.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="US-ASCII"?>
<!--Automatically generated, do not edit.-->
<msg xmlns="http://www.hactrn.net/uris/rpki/left-right-spec/" version="1">
- <route_origin action="get" type="reply" self_id="42" route_origin_id="88" as_number="12345" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
+ <route_origin action="get" type="reply" self_id="42" route_origin_id="88" as_number="12345" exact_match="true" ipv4="10.0.0.44/32,10.2.0.6-10.2.0.77" ipv6="2002:a00::/48,2002:a02:6::-2002:a02:4d::"/>
</msg>
diff --git a/rpkid/left-right-schema.rnc b/rpkid/left-right-schema.rnc
index a815e587..32bdb678 100644
--- a/rpkid/left-right-schema.rnc
+++ b/rpkid/left-right-schema.rnc
@@ -172,6 +172,7 @@ ro_id = attribute route_origin_id { sql_id }
ro_bool = attribute suppress_publication { "yes" }?
ro_payload = (attribute as_number { xsd:token { maxLength="1024" } }?,
+ attribute exact_match { xsd:boolean }?,
attribute ipv4 { xsd:token { maxLength="1024" } }?,
attribute ipv6 { xsd:token { maxLength="1024" } }?)
diff --git a/rpkid/left-right-schema.rng b/rpkid/left-right-schema.rng
index cfc36b70..0ce5da88 100644
--- a/rpkid/left-right-schema.rng
+++ b/rpkid/left-right-schema.rng
@@ -784,6 +784,11 @@
</attribute>
</optional>
<optional>
+ <attribute name="exact_match">
+ <data type="boolean"/>
+ </attribute>
+ </optional>
+ <optional>
<attribute name="ipv4">
<data type="token">
<param name="maxLength">1024</param>
diff --git a/rpkid/rpki/gctx.py b/rpkid/rpki/gctx.py
index 9f2770c4..44d47f28 100644
--- a/rpkid/rpki/gctx.py
+++ b/rpkid/rpki/gctx.py
@@ -176,7 +176,13 @@ class global_context(object):
self.https_ta_cache = None
def build_x509store(self):
- """Build a dynamic x509store object."""
+ """Build a dynamic x509store object.
+
+ This probably should be refactored to do the real work in the
+ rpki.https module so that this module can treat the x509store as a
+ black box. This method's jobs would then be just to identify
+ certs that need to be added and to cache an opaque object.
+ """
if self.https_ta_cache is None:
@@ -186,7 +192,8 @@ class global_context(object):
[c.peer_biz_glue for c in children if c.peer_biz_glue is not None] + \
self.https_ta_irbe
for x in certs:
- rpki.log.debug("HTTPS dynamic trust anchor %s" % x.getSubject())
+ if rpki.https.debug_tls_certs:
+ rpki.log.debug("HTTPS dynamic trust anchor %s" % x.getSubject())
store.addTrust(x.get_POW())
self.https_ta_cache = store
diff --git a/rpkid/rpki/https.py b/rpkid/rpki/https.py
index 7fd0c5f2..f73667b2 100644
--- a/rpkid/rpki/https.py
+++ b/rpkid/rpki/https.py
@@ -30,6 +30,9 @@ import POW
# Do not set this to True for production use!
disable_tls_certificate_validation_exceptions = False
+# Chatter suppression
+debug_tls_certs = False
+
rpki_content_type = "application/x-rpki"
class Checker(tlslite.api.Checker):
@@ -43,9 +46,10 @@ class Checker(tlslite.api.Checker):
if dynamic_x509store is None:
self.x509store = POW.X509Store()
for x in trust_anchors:
- rpki.log.debug("HTTPS trust anchor %s" % x.getSubject())
+ if debug_tls_certs:
+ rpki.log.debug("HTTPS trust anchor %s" % x.getSubject())
self.x509store.addTrust(x.get_POW())
- else:
+ elif debug_tls_certs:
rpki.log.debug("HTTPS dynamic trust anchors")
def x509store_thunk(self):
@@ -66,8 +70,9 @@ class Checker(tlslite.api.Checker):
chain = [rpki.x509.X509(tlslite = chain.x509List[i]) for i in range(chain.getNumCerts())]
- for i in range(len(chain)):
- rpki.log.debug("Received %s TLS cert[%d] %s" % (peer, i, chain[i].getSubject()))
+ if debug_tls_certs:
+ for i in range(len(chain)):
+ rpki.log.debug("Received %s TLS cert[%d] %s" % (peer, i, chain[i].getSubject()))
if not self.x509store_thunk().verifyChain(chain[0].get_POW(), [x.get_POW() for x in chain[1:]]):
if disable_tls_certificate_validation_exceptions:
@@ -107,8 +112,9 @@ def client(msg, client_key, client_certs, server_ta, url, timeout = 300):
u.query == "" and \
u.fragment == ""
- for client_cert in client_certs:
- rpki.log.debug("Sending client TLS cert %s" % client_cert.getSubject())
+ if debug_tls_certs:
+ for client_cert in client_certs:
+ rpki.log.debug("Sending client TLS cert %s" % client_cert.getSubject())
# We could add a "settings = foo" argument to the following call to
# pass in a tlslite.HandshakeSettings object that would let us
diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py
index a8cd3092..3803d5f4 100644
--- a/rpkid/rpki/left_right.py
+++ b/rpkid/rpki/left_right.py
@@ -18,7 +18,7 @@
import base64, lxml.etree, time, traceback, os
import rpki.sax_utils, rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions
-import rpki.https, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log
+import rpki.https, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log, rpki.roa
xmlns = "http://www.hactrn.net/uris/rpki/left-right-spec/"
@@ -817,10 +817,10 @@ class route_origin_elt(data_elt):
"""<route_origin/> element."""
element_name = "route_origin"
- attributes = ("action", "type", "tag", "self_id", "route_origin_id", "as_number", "ipv4", "ipv6")
+ attributes = ("action", "type", "tag", "self_id", "route_origin_id", "as_number", "exact_match", "ipv4", "ipv6")
booleans = ("suppress_publication",)
- sql_template = rpki.sql.template("route_origin", "route_origin_id", "self_id", "as_number",
+ sql_template = rpki.sql.template("route_origin", "route_origin_id", "self_id", "as_number", "exact_match",
"ca_detail_id", "roa",
("cert", rpki.x509.X509))
@@ -841,11 +841,12 @@ class route_origin_elt(data_elt):
def sql_insert_hook(self):
"""Extra SQL insert actions for route_origin_elt -- handle address ranges."""
- if self.ipv4 + self.ipv6:
+ if self.ipv4 or self.ipv6:
self.gctx.cur.executemany("""
INSERT route_origin_range (route_origin_id, start_ip, end_ip)
VALUES (%s, %s, %s)""",
- ((self.route_origin_id, x.min, x.max) for x in self.ipv4 + self.ipv6))
+ ((self.route_origin_id, x.min, x.max)
+ for x in (self.ipv4 or []) + (self.ipv6 or [])))
def sql_delete_hook(self):
"""Extra SQL delete actions for route_origin_elt -- handle address ranges."""
@@ -855,6 +856,11 @@ class route_origin_elt(data_elt):
"""Fetch all ca_detail objects that link to this route_origin object."""
return rpki.sql.ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
+ def serve_pre_save_hook(self, q_pdu, r_pdu):
+ """Extra server actions for route_origin_elt -- normalize exact_match."""
+ if self.exact_match is None:
+ self.exact_match = False
+
def serve_post_save_hook(self, q_pdu, r_pdu):
"""Extra server actions for route_origin_elt."""
self.unimplemented_control("suppress_publication")
@@ -899,6 +905,10 @@ class route_origin_elt(data_elt):
/dev/random, but there is not much we can do about that.
"""
+ if self.ipv4 is None and self.ipv6 is None:
+ rpki.log.warn("Can't generate ROA for empty address list")
+ return
+
# Ugly and expensive search for covering ca_detail, there has to
# be a better way.
#
@@ -911,7 +921,8 @@ class route_origin_elt(data_elt):
ca_detail = ca.fetch_active()
if ca_detail is not None:
resources = ca_detail.latest_ca_cert.get_3779resources()
- if self.v4.issubset(resources.v4) and self.v6.issubset(resources.v6):
+ if ((self.ipv4 is None or self.ipv4.issubset(resources.v4)) and
+ (self.ipv6 is None or self.ipv6.issubset(resources.v6))):
break
ca_detail = None
if ca_detail is not None:
@@ -921,20 +932,20 @@ class route_origin_elt(data_elt):
rpki.log.warn("generate_roa() could not find a covering certificate")
return
- resources = rpki.resource_set.resource_bag(v4 = self.v4, v6 = self.v6)
+ resources = rpki.resource_set.resource_bag(v4 = self.ipv4, v6 = self.ipv6)
payload = rpki.roa.RouteOriginAttestation()
payload.version.set(0)
payload.asID.set(self.as_number)
payload.exactMatch.set(self.exact_match)
- payload.ipAddrBlocks.set((a.to_roa_tuple() for a in (self.v4, self.v6) if a))
+ payload.ipAddrBlocks.set((a.to_roa_tuple() for a in (self.ipv4, self.ipv6) if a))
keypair = rpki.x509.RSA()
keypair.generate()
sia = ((rpki.oids.name2oid["id-ad-signedObject"], ("uri", self.roa_uri(ca, keypair))),)
- self.cert = ca_detail.issue_ee(ca, resources, sia)
+ self.cert = ca_detail.issue_ee(ca, resources, keypair.get_RSApublic(), sia = sia)
self.roa = rpki.cms.sign(payload.toString(), keypair, (self.cert,))
self.ca_detail_id = ca_detail.ca_detail_id
self.sql_store()
diff --git a/rpkid/rpki/relaxng.py b/rpkid/rpki/relaxng.py
index 03bfc2b5..755e42d0 100644
--- a/rpkid/rpki/relaxng.py
+++ b/rpkid/rpki/relaxng.py
@@ -6,7 +6,7 @@ import lxml.etree
## Parsed RelaxNG left_right schema
left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" encoding="UTF-8"?>
<!--
- $Id: left-right-schema.rng 1640 2008-04-09 02:26:30Z sra $
+ $Id: left-right-schema.rnc 1640 2008-04-09 02:26:30Z sra $
RelaxNG (Compact Syntax) Schema for RPKI left-right protocol.
@@ -790,6 +790,11 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc
</attribute>
</optional>
<optional>
+ <attribute name="exact_match">
+ <data type="boolean"/>
+ </attribute>
+ </optional>
+ <optional>
<attribute name="ipv4">
<data type="token">
<param name="maxLength">1024</param>
diff --git a/rpkid/rpki/sql.py b/rpkid/rpki/sql.py
index fe6c0f0a..dad37606 100644
--- a/rpkid/rpki/sql.py
+++ b/rpkid/rpki/sql.py
@@ -555,12 +555,12 @@ class ca_detail_obj(sql_persistant):
self.sql_store()
return self
- def issue_ee(self, ca, resources, sia = None):
+ def issue_ee(self, ca, resources, subject_key, sia = None):
"""Issue a new EE certificate."""
return self.latest_ca_cert.issue(
keypair = self.private_key_id,
- subject_key = self.manifest_public_key,
+ subject_key = subject_key,
serial = ca.next_serial_number(),
sia = sia,
aia = self.ca_cert_uri,
@@ -578,7 +578,7 @@ class ca_detail_obj(sql_persistant):
v4 = rpki.resource_set.resource_set_ipv4("<inherit>"),
v6 = rpki.resource_set.resource_set_ipv6("<inherit>"))
- self.latest_manifest_cert = self.issue_ee(ca, resources)
+ self.latest_manifest_cert = self.issue_ee(ca, resources, self.manifest_public_key)
def issue(self, ca, child, subject_key, sia, resources, child_cert = None):
"""Issue a new certificate to a child. Optional child_cert
diff --git a/rpkid/testbed.1.yaml b/rpkid/testbed.1.yaml
index 1ddfe902..628e8f3d 100644
--- a/rpkid/testbed.1.yaml
+++ b/rpkid/testbed.1.yaml
@@ -23,8 +23,11 @@ kids:
- name: Alice
ipv4: 192.0.2.1-192.0.2.33
asn: 64533
+ route_origin:
+ - asn: 42
+ ipv4: 192.0.2.32/32
ipv4: 10.3.0.0/16
- route_origins:
+ route_origin:
- asn: 666
ipv4: 10.3.0.44/32
---
diff --git a/rpkid/testbed.py b/rpkid/testbed.py
index 1a9dee29..5d1a8e7e 100644
--- a/rpkid/testbed.py
+++ b/rpkid/testbed.py
@@ -337,10 +337,8 @@ class allocation_db(list):
if self.root.crl_interval is None:
self.root.crl_interval = timedelta.parse(cfg.get("crl_interval", "1d")).convert_to_seconds()
for a in self:
- if a.sia_base is None and a.parent is not None:
- a.sia_base = a.parent.sia_base + a.name + "/"
- elif a.sia_base is None and a.parent is None:
- a.sia_base = rootd_sia + a.name + "/"
+ if a.sia_base is None:
+ a.sia_base = (rootd_sia if a.is_root() else a.parent.sia_base) + a.name + "/"
if a.base.valid_until is None:
a.base.valid_until = a.parent.base.valid_until
if a.crl_interval is None:
@@ -394,8 +392,8 @@ class allocation(object):
if "crl_interval" in yaml:
self.crl_interval = timedelta.parse(yaml["crl_interval"]).convert_to_seconds()
self.route_origins = set()
- if "route_origins" in yaml:
- for y in yaml.get("route_origins"):
+ if "route_origin" in yaml:
+ for y in yaml.get("route_origin"):
self.route_origins.add(route_origin.parse(y))
self.extra_conf = yaml.get("extra_conf", [])
@@ -465,7 +463,7 @@ class allocation(object):
if self.sia_base: s += " SIA: %s\n" % self.sia_base
return s + "Until: %s\n" % self.resources.valid_until.strftime("%Y-%m-%dT%H:%M:%SZ")
- def is_leaf(self): return not self.kids
+ def is_leaf(self): return not self.kids and not self.route_origins
def is_root(self): return self.parent is None
def is_twig(self): return not self.is_leaf() and not self.is_root()
@@ -620,7 +618,7 @@ class allocation(object):
self.repository_id = self.call_rpkid(rpki.left_right.repository_elt.make_pdu(action = "create", self_id = self.self_id, bsc_id = self.bsc_id)).repository_id
rpki.log.info("Creating rpkid parent object for %s" % self.name)
- if self.parent is None:
+ if self.is_root():
self.parent_id = self.call_rpkid(rpki.left_right.parent_elt.make_pdu(
action = "create", self_id = self.self_id, bsc_id = self.bsc_id, repository_id = self.repository_id, sia_base = self.sia_base,
peer_biz_cert = rootd_ta, peer_biz_glue = rootd_ta, sender_name = self.name, recipient_name = "Walrus",
@@ -635,10 +633,16 @@ class allocation(object):
db = MySQLdb.connect(user = "irdb", db = self.irdb_db_name, passwd = irdb_db_pass)
cur = db.cursor()
for kid in self.kids:
- kid.child_id = self.call_rpkid(rpki.left_right.child_elt.make_pdu(action = "create", self_id = self.self_id, bsc_id = self.bsc_id, peer_biz_cert = kid.rpkid_ta)).child_id
+ kid.child_id = self.call_rpkid(rpki.left_right.child_elt.make_pdu(
+ action = "create", self_id = self.self_id, bsc_id = self.bsc_id, peer_biz_cert = kid.rpkid_ta)).child_id
cur.execute("UPDATE registrant SET rpki_self_id = %s, rpki_child_id = %s WHERE IRBE_mapped_id = %s", (self.self_id, kid.child_id, kid.name))
db.close()
+ rpki.log.info("Creating rpkid route_origin objects for %s" % self.name)
+ for ro in self.route_origins:
+ ro.route_origin_id = self.call_rpkid(rpki.left_right.route_origin_elt.make_pdu(
+ action = "create", self_id = self.self_id, as_number = ro.asn, ipv4 = ro.v4, ipv6 = ro.v6)).route_origin_id
+
def write_leaf_yaml(self):
"""Write YAML scripts for leaf nodes. Only supports list requests
at the moment: issue requests would require class and SIA values,