aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2014-02-21 02:05:36 +0000
committerRob Austein <sra@hactrn.net>2014-02-21 02:05:36 +0000
commita25c336c1d7752b60a251fcce51f2fbd81d930bf (patch)
tree51d7cadf92d447a8f22d7ea00ce618ad9305ea83
parent401bbea99c1ba43ae0987b6346c65293a8efafa0 (diff)
Add router certificate support to yamltest, rpkic, etc.
svn path=/branches/tk671/; revision=5680
-rw-r--r--rpkid/ext/POW.c2
-rw-r--r--rpkid/router-certificate-schema.rnc19
-rw-r--r--rpkid/router-certificate-schema.rng48
-rw-r--r--rpkid/rpki/irdb/models.py6
-rw-r--r--rpkid/rpki/irdb/zookeeper.py12
-rw-r--r--rpkid/rpki/irdbd.py2
-rw-r--r--rpkid/rpki/relaxng.py48
-rw-r--r--rpkid/rpki/x509.py4
-rw-r--r--rpkid/tests/smoketest.py2
-rw-r--r--rpkid/tests/yamltest.py67
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.