diff options
-rw-r--r-- | docs/left-right-xml | 4 | ||||
-rw-r--r-- | docs/rpki-db-schema.pdf | bin | 7249 -> 7305 bytes | |||
-rw-r--r-- | docs/rpki-db-schema.sql | 1 | ||||
-rw-r--r-- | rpkid/left-right-protocol-samples/pdu.053.xml | 2 | ||||
-rw-r--r-- | rpkid/left-right-protocol-samples/pdu.056.xml | 2 | ||||
-rw-r--r-- | rpkid/left-right-schema.rnc | 1 | ||||
-rw-r--r-- | rpkid/left-right-schema.rng | 5 | ||||
-rw-r--r-- | rpkid/rpki/gctx.py | 11 | ||||
-rw-r--r-- | rpkid/rpki/https.py | 18 | ||||
-rw-r--r-- | rpkid/rpki/left_right.py | 29 | ||||
-rw-r--r-- | rpkid/rpki/relaxng.py | 7 | ||||
-rw-r--r-- | rpkid/rpki/sql.py | 6 | ||||
-rw-r--r-- | rpkid/testbed.1.yaml | 5 | ||||
-rw-r--r-- | rpkid/testbed.py | 22 |
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 Binary files differindex 5a82b7d3..bff9e381 100644 --- a/docs/rpki-db-schema.pdf +++ b/docs/rpki-db-schema.pdf 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, |