diff options
author | Rob Austein <sra@hactrn.net> | 2014-02-21 02:05:36 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2014-02-21 02:05:36 +0000 |
commit | a25c336c1d7752b60a251fcce51f2fbd81d930bf (patch) | |
tree | 51d7cadf92d447a8f22d7ea00ce618ad9305ea83 | |
parent | 401bbea99c1ba43ae0987b6346c65293a8efafa0 (diff) |
Add router certificate support to yamltest, rpkic, etc.
svn path=/branches/tk671/; revision=5680
-rw-r--r-- | rpkid/ext/POW.c | 2 | ||||
-rw-r--r-- | rpkid/router-certificate-schema.rnc | 19 | ||||
-rw-r--r-- | rpkid/router-certificate-schema.rng | 48 | ||||
-rw-r--r-- | rpkid/rpki/irdb/models.py | 6 | ||||
-rw-r--r-- | rpkid/rpki/irdb/zookeeper.py | 12 | ||||
-rw-r--r-- | rpkid/rpki/irdbd.py | 2 | ||||
-rw-r--r-- | rpkid/rpki/relaxng.py | 48 | ||||
-rw-r--r-- | rpkid/rpki/x509.py | 4 | ||||
-rw-r--r-- | rpkid/tests/smoketest.py | 2 | ||||
-rw-r--r-- | rpkid/tests/yamltest.py | 67 |
10 files changed, 152 insertions, 58 deletions
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c index 54c8274a..b5d9ccaf 100644 --- a/rpkid/ext/POW.c +++ b/rpkid/ext/POW.c @@ -1455,7 +1455,7 @@ extension_get_eku(X509_EXTENSIONS **exts) if ((result = PyFrozenSet_New(NULL)) == NULL) goto error; - for (i = 0; sk_ASN1_OBJECT_num(ext); i++) { + for (i = 0; i < sk_ASN1_OBJECT_num(ext); i++) { if ((oid = ASN1_OBJECT_to_PyString(sk_ASN1_OBJECT_value(ext, i))) == NULL || PySet_Add(result, oid) < 0) goto error; diff --git a/rpkid/router-certificate-schema.rnc b/rpkid/router-certificate-schema.rnc index eade85f0..8ec5f84a 100644 --- a/rpkid/router-certificate-schema.rnc +++ b/rpkid/router-certificate-schema.rnc @@ -29,27 +29,32 @@ default namespace = "http://www.hactrn.net/uris/rpki/router-certificate/" version = "1" - base64 = xsd:base64Binary { maxLength="512000" } router_id = xsd:unsignedInt asn_list = xsd:string { maxLength="512000" pattern="[\-,0-9]*" } timestamp = xsd:dateTime { pattern=".*Z" } -# Core PDU used in this schema. +# Core payload used in this schema. -router_certificate_request = element router_certificate_request { +payload = ( attribute router_id { router_id }, attribute asn { asn_list }, attribute valid_until { timestamp }?, base64 -} +) -start |= router_certificate_request +# We allow two forms, one with a wrapper to allow multiple requests in +# a single file, one without for brevity; the version attribute goes +# in the outermost element in either case. -# Wrapper element to support multiple requests in a single document. +start |= element router_certificate_request { + attribute version { version }, + payload +} start |= element router_certificate_requests { - router_certificate_request* + attribute version { version }, + element router_certificate_request { payload }* } # Local Variables: diff --git a/rpkid/router-certificate-schema.rng b/rpkid/router-certificate-schema.rng index bd0a70d2..afd14d5e 100644 --- a/rpkid/router-certificate-schema.rng +++ b/rpkid/router-certificate-schema.rng @@ -51,31 +51,43 @@ <param name="pattern">.*Z</param> </data> </define> - <!-- Core PDU used in this schema. --> - <define name="router_certificate_request"> - <element name="router_certificate_request"> - <attribute name="router_id"> - <ref name="router_id"/> - </attribute> - <attribute name="asn"> - <ref name="asn_list"/> + <!-- Core payload used in this schema. --> + <define name="payload"> + <attribute name="router_id"> + <ref name="router_id"/> + </attribute> + <attribute name="asn"> + <ref name="asn_list"/> + </attribute> + <optional> + <attribute name="valid_until"> + <ref name="timestamp"/> </attribute> - <optional> - <attribute name="valid_until"> - <ref name="timestamp"/> - </attribute> - </optional> - <ref name="base64"/> - </element> + </optional> + <ref name="base64"/> </define> + <!-- + We allow two forms, one with a wrapper to allow multiple requests in + a single file, one without for brevity; the version attribute goes + in the outermost element in either case. + --> <start combine="choice"> - <ref name="router_certificate_request"/> + <element name="router_certificate_request"> + <attribute name="version"> + <ref name="version"/> + </attribute> + <ref name="payload"/> + </element> </start> - <!-- Wrapper element to support multiple requests in a single document. --> <start combine="choice"> <element name="router_certificate_requests"> + <attribute name="version"> + <ref name="version"/> + </attribute> <zeroOrMore> - <ref name="router_certificate_request"/> + <element name="router_certificate_request"> + <ref name="payload"/> + </element> </zeroOrMore> </element> </start> diff --git a/rpkid/rpki/irdb/models.py b/rpkid/rpki/irdb/models.py index 6772b542..e29e332e 100644 --- a/rpkid/rpki/irdb/models.py +++ b/rpkid/rpki/irdb/models.py @@ -596,12 +596,12 @@ class EECertificateRequest(ResourceSet): ee_asn = rpki.irdb.EECertificateRequestASN.objects.raw(""" SELECT * FROM irdb_eecertificaterequestasn - WHERE eecertificaterequest_id = %s + WHERE ee_certificate_request_id = %s """, [self.id]) - ee_net = rpki.irdb.EECertificateRequestNET.objects.raw(""" + ee_net = rpki.irdb.EECertificateRequestNet.objects.raw(""" SELECT * FROM irdb_eecertificaterequestnet - WHERE eecertificaterequest_id = %s + WHERE ee_certificate_request_id = %s """, [self.id]) return ee_asn, ee_net diff --git a/rpkid/rpki/irdb/zookeeper.py b/rpkid/rpki/irdb/zookeeper.py index 9f7cd15e..339503fb 100644 --- a/rpkid/rpki/irdb/zookeeper.py +++ b/rpkid/rpki/irdb/zookeeper.py @@ -1642,7 +1642,7 @@ class Zookeeper(object): pkcs10 = rpki.x509.PKCS10(Base64 = req.text) router_id = long(req.get("router_id")) - asns = req.get("asn") + asns = rpki.resource_set.resource_set_as(req.get("asn")) if not valid_until: valid_until = req.get("valid_until") @@ -1656,13 +1656,11 @@ class Zookeeper(object): pkcs10.check_valid_request_router() - gski = pkcs10.gSKI() - ee_request = self.resource_ca.ee_certificate_requests.create( - pkcs10 = pkcs10, gski = gski, valid_until = valid_until, router_id = router_id) + pkcs10 = pkcs10, + gski = pkcs10.gSKI(), + valid_until = valid_until, + router_id = router_id) for range in asns: ee_request.asns.create(start_as = str(range.min), end_as = str(range.max)) - - self.log("Added Router certificate request g(SKI) %s router-id %d ASNs %s" % ( - gski, router_id, asns)) diff --git a/rpkid/rpki/irdbd.py b/rpkid/rpki/irdbd.py index c67111ce..1fec3cbc 100644 --- a/rpkid/rpki/irdbd.py +++ b/rpkid/rpki/irdbd.py @@ -87,7 +87,7 @@ class main(object): def handle_list_ee_certificate_requests(self, q_pdu, r_msg): for ee_req in rpki.irdb.EECertificateRequest.objects.filter(issuer__handle__exact = q_pdu.self_handle): - resource = ee_req.resource_bag + resources = ee_req.resource_bag r_pdu = rpki.left_right.list_ee_certificate_requests_elt() r_pdu.tag = q_pdu.tag r_pdu.self_handle = q_pdu.self_handle diff --git a/rpkid/rpki/relaxng.py b/rpkid/rpki/relaxng.py index f69968be..a7553d51 100644 --- a/rpkid/rpki/relaxng.py +++ b/rpkid/rpki/relaxng.py @@ -2366,31 +2366,43 @@ router_certificate = lxml.etree.RelaxNG(lxml.etree.fromstring(r'''<?xml version= <param name="pattern">.*Z</param> </data> </define> - <!-- Core PDU used in this schema. --> - <define name="router_certificate_request"> - <element name="router_certificate_request"> - <attribute name="router_id"> - <ref name="router_id"/> - </attribute> - <attribute name="asn"> - <ref name="asn_list"/> + <!-- Core payload used in this schema. --> + <define name="payload"> + <attribute name="router_id"> + <ref name="router_id"/> + </attribute> + <attribute name="asn"> + <ref name="asn_list"/> + </attribute> + <optional> + <attribute name="valid_until"> + <ref name="timestamp"/> </attribute> - <optional> - <attribute name="valid_until"> - <ref name="timestamp"/> - </attribute> - </optional> - <ref name="base64"/> - </element> + </optional> + <ref name="base64"/> </define> + <!-- + We allow two forms, one with a wrapper to allow multiple requests in + a single file, one without for brevity; the version attribute goes + in the outermost element in either case. + --> <start combine="choice"> - <ref name="router_certificate_request"/> + <element name="router_certificate_request"> + <attribute name="version"> + <ref name="version"/> + </attribute> + <ref name="payload"/> + </element> </start> - <!-- Wrapper element to support multiple requests in a single document. --> <start combine="choice"> <element name="router_certificate_requests"> + <attribute name="version"> + <ref name="version"/> + </attribute> <zeroOrMore> - <ref name="router_certificate_request"/> + <element name="router_certificate_request"> + <ref name="payload"/> + </element> </zeroOrMore> </element> </start> diff --git a/rpkid/rpki/x509.py b/rpkid/rpki/x509.py index c69090e2..847c90f6 100644 --- a/rpkid/rpki/x509.py +++ b/rpkid/rpki/x509.py @@ -1001,14 +1001,14 @@ class PKCS10(DER_object): bc = self.get_POW().getBasicConstraints() sia = self.get_POW().getSIA() + caRepository, rpkiManifest, signedObject = sia or (None, None, None) + if alg not in (rpki.oids.sha256WithRSAEncryption, rpki.oids.ecdsa_with_SHA256): raise rpki.exceptions.BadPKCS10("PKCS #10 has bad signature algorithm for EE: %s" % alg) if bc is not None and (bc[0] or bc[1] is not None): raise rpki.exceptions.BadPKCS10("PKCS #10 EE has bad basicConstraints") - caRepository, rpkiManifest, signedObject = sias or (None, None, None) - if caRepository: raise rpki.exceptions.BadPKCS10("PKCS #10 EE must not have id-ad-caRepository") diff --git a/rpkid/tests/smoketest.py b/rpkid/tests/smoketest.py index 5512b5bc..b81117ae 100644 --- a/rpkid/tests/smoketest.py +++ b/rpkid/tests/smoketest.py @@ -387,7 +387,7 @@ class router_cert(object): @classmethod def ecparams(cls): if cls._ecparams is None: - cls._ecparams = rpki.x509.KeyParams.generateEC() + cls._ecparams = rpki.x509.KeyParams.generateEC() return cls._ecparams def __init__(self, asn, router_id): diff --git a/rpkid/tests/yamltest.py b/rpkid/tests/yamltest.py index 9131a595..1b52ced6 100644 --- a/rpkid/tests/yamltest.py +++ b/rpkid/tests/yamltest.py @@ -46,12 +46,14 @@ import sys import yaml import signal import time +import lxml.etree import rpki.resource_set import rpki.sundial import rpki.config import rpki.log import rpki.csv_utils import rpki.x509 +import rpki.relaxng # Nasty regular expressions for parsing config files. Sadly, while # the Python ConfigParser supports writing config files, it does so in @@ -109,6 +111,45 @@ class roa_request(object): """ return cls(y.get("asn"), y.get("ipv4"), y.get("ipv6")) + +class router_cert(object): + """ + Representation for a router_cert object. + """ + + _ecparams = None + + @classmethod + def ecparams(cls): + if cls._ecparams is None: + cls._ecparams = rpki.x509.KeyParams.generateEC() + return cls._ecparams + + def __init__(self, asn, router_id): + self.asn = rpki.resource_set.resource_set_as("".join(str(asn).split())) + self.router_id = router_id + self.keypair = rpki.x509.ECDSA.generate(self.ecparams()) + self.pkcs10 = rpki.x509.PKCS10.create( + keypair = self.keypair, + cn = "ROUTER-%d" % self.asn[0].min, + sn = self.router_id, + eku = (rpki.oids.id_kp_bgpsec_router,)) + self.gski = self.pkcs10.gSKI() + + def __eq__(self, other): + return self.asn == other.asn and self.router_id == other.router_id and self.gski == other.gski + + def __hash__(self): + v6 = tuple(self.v6) if self.v6 is not None else None + return tuple(self.asn).__hash__() + router_id.__hash__() + self.gski.__hash__() + + def __str__(self): + return "%s: %s: %s" % (self.asn, self.router_id, self.gski) + + @classmethod + def parse(cls, yaml): + return cls(yaml.get("asn"), yaml.get("router_id")) + class allocation_db(list): """ Our allocation database. @@ -207,6 +248,7 @@ class allocation(object): if "regen_margin" in yaml: self.regen_margin = rpki.sundial.timedelta.parse(yaml["regen_margin"]).convert_to_seconds() self.roa_requests = [roa_request.parse(y) for y in yaml.get("roa_request", yaml.get("route_origin", ()))] + self.router_certs = [router_cert.parse(y) for y in yaml.get("router_cert", ())] if "ghostbusters" in yaml: self.ghostbusters = yaml.get("ghostbusters") elif "ghostbuster" in yaml: @@ -218,6 +260,8 @@ class allocation(object): self.base.v4 |= r.v4.to_resource_set() if r.v6: self.base.v6 |= r.v6.to_resource_set() + for r in self.router_certs: + self.base.asn |= r.asn self.hosted_by = yaml.get("hosted_by") self.hosts = [] if not self.is_hosted: @@ -365,6 +409,28 @@ class allocation(object): if not args.stop_after_config: self.run_rpkic("load_ghostbuster_requests", fn) + def dump_router_certificates(self): + """ + Write EE certificates (router certificates, etc). + """ + if self.router_certs: + fn = "%s.routercerts.xml" % d.name + if not args.skip_config: + path = self.path(fn) + print "Writing", path + xmlns = "{http://www.hactrn.net/uris/rpki/router-certificate/}" + xml = lxml.etree.Element(xmlns + "router_certificate_requests", version = "1") + for r in self.router_certs: + x = lxml.etree.SubElement(xml, xmlns + "router_certificate_request", + router_id = str(r.router_id), + asn = str(r.asn), + valid_until = str(self.resources.valid_until)) + x.text = r.pkcs10.get_Base64() + rpki.relaxng.router_certificate.assertValid(xml) + lxml.etree.ElementTree(xml).write(path, pretty_print = True) + if not args.stop_after_config: + self.run_rpkic("add_router_certificate_request", fn) + @property def pubd(self): """ @@ -761,6 +827,7 @@ try: d.dump_prefixes() d.dump_roas() d.dump_ghostbusters() + d.dump_router_certificates() # Wait until something terminates. |