aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpkid/rpki/irdb/models.py8
-rw-r--r--rpkid/rpki/irdb/zookeeper.py2
-rw-r--r--rpkid/rpki/rootd.py2
-rw-r--r--rpkid/rpki/up_down.py2
-rw-r--r--rpkid/rpki/x509.py144
5 files changed, 99 insertions, 59 deletions
diff --git a/rpkid/rpki/irdb/models.py b/rpkid/rpki/irdb/models.py
index 3553581e..b6fc28be 100644
--- a/rpkid/rpki/irdb/models.py
+++ b/rpkid/rpki/irdb/models.py
@@ -586,7 +586,7 @@ class EECertificateRequest(ResourceSet):
# At one point I had a router_id field here, but I don't think it
# serves any real purpose. Put it back if I remember why I thought
- # we needed it, but the current I-D has router-id encoded in teh
+ # we needed it, but the current I-D has router-id encoded in the
# subject name.
# Need subject name field here? It's in the PKCS #10, but then so
@@ -597,6 +597,12 @@ class EECertificateRequest(ResourceSet):
# X.509 commonName and serialNumber if necessary, question is whether
# this is necessary.
+ # Well, we need //some// way of storing the router-id, and the PKCS
+ # #10 doesn't contain a subject name, so we need an additional field.
+ # Question becomes whether user wants to control which AS is used
+ # in the router certificate's name in the rare case where there's
+ # more than one (AS aliasing, I gather).
+
def _select_resource_bag(self):
ee_asn = rpki.irdb.EECertificateRequestASN.objects.raw("""
SELECT *
diff --git a/rpkid/rpki/irdb/zookeeper.py b/rpkid/rpki/irdb/zookeeper.py
index 6c7d2206..97e56d5a 100644
--- a/rpkid/rpki/irdb/zookeeper.py
+++ b/rpkid/rpki/irdb/zookeeper.py
@@ -1600,7 +1600,7 @@ class Zookeeper(object):
.load_asns() and .load_prefixes() for other strategies.
"""
- pkcs10.check_valid_rpki(kind = kind)
+ pkcs10.check_valid_request_ee(kind = kind)
ee_request = self.resource_ca.ee_certificate_requests.create(
pkcs10 = pkcs10,
gski = pkcs10.gSKI(),
diff --git a/rpkid/rpki/rootd.py b/rpkid/rpki/rootd.py
index 49488602..e0c59726 100644
--- a/rpkid/rpki/rootd.py
+++ b/rpkid/rpki/rootd.py
@@ -49,7 +49,7 @@ class list_pdu(rpki.up_down.list_pdu):
class issue_pdu(rpki.up_down.issue_pdu):
def serve_pdu(self, q_msg, r_msg, ignored, callback, errback):
- self.pkcs10.check_valid_rpki()
+ self.pkcs10.check_valid_request_ca()
r_msg.payload = rpki.up_down.issue_response_pdu()
rootd.compose_response(r_msg, self.pkcs10)
callback()
diff --git a/rpkid/rpki/up_down.py b/rpkid/rpki/up_down.py
index 6d1fa45a..d2ad85d3 100644
--- a/rpkid/rpki/up_down.py
+++ b/rpkid/rpki/up_down.py
@@ -365,7 +365,7 @@ class issue_pdu(base_elt):
raise rpki.exceptions.NotImplementedYet("req_* attributes not implemented yet, sorry")
# Check the request
- self.pkcs10.check_valid_rpki()
+ self.pkcs10.check_valid_request_ca()
ca = child.ca_from_class_name(self.class_name)
ca_detail = ca.active_ca_detail
if ca_detail is None:
diff --git a/rpkid/rpki/x509.py b/rpkid/rpki/x509.py
index 99350ce7..30e32aa8 100644
--- a/rpkid/rpki/x509.py
+++ b/rpkid/rpki/x509.py
@@ -890,22 +890,19 @@ class PKCS10(DER_object):
"""
return self.getPublicKey().get_SKI()
- def check_valid_rpki(self, kind = "ca"):
+
+ def check_valid_request_common(self):
"""
- Check this certification request to see whether it's a valid
- request for an RPKI certificate. This is broken out of the
- up-down protocol code because it's somewhat involved and the
- up-down code doesn't need to know the details.
+ Common code for checking this certification requests to see
+ whether they conform to the RPKI certificate profile.
Throws an exception if the request isn't valid, so if this method
returns at all, the request is ok.
- This needs refactoring, as the nested conditionals to handle the
- different kinds of certificates have gotten rather nasty.
+ You probably don't want to call this directly, as it only performs
+ the checks that are common to all RPKI certificates.
"""
- assert kind in ("ca", "ee", "router")
-
if not self.get_POW().verify():
raise rpki.exceptions.BadPKCS10("PKCS #10 signature check failed")
@@ -914,73 +911,110 @@ class PKCS10(DER_object):
if ver != 0:
raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad version number %s" % ver)
- alg = self.get_POW().getSignatureAlgorithm()
+ ku = self.get_POW().getKeyUsage()
- if alg != (rpki.oids.ecdsa_with_SHA256 if kind == "router" else rpki.oids.sha256WithRSAEncryption):
- raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad signature algorithm %s" % alg)
+ if ku is not None and self.expected_ca_keyUsage != ku:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 keyUsage doesn't match profile: %r" % ku)
- bc = self.get_POW().getBasicConstraints()
-
- if kind == "ca":
- if bc is None or not bc[0]:
- raise rpki.exceptions.BadPKCS10("Request for EE certificate not allowed here")
- else:
- if bc is not None and bc[0]:
- raise rpki.exceptions.BadPKCS10("Request for CA certificate not allowed here")
-
- if bc is not None and bc[1] is not None:
- raise rpki.exceptions.BadPKCS10("PKCS #10 basicConstraints must not specify Path Length")
+ forbidden_extensions = self.get_POW().getExtensionOIDs() - self.allowed_extensions
- ku = self.get_POW().getKeyUsage()
+ if forbidden_extensions:
+ raise rpki.exceptions.BadExtension("Forbidden extension%s in PKCS #10 certificate request: %s" % (
+ "" if len(forbidden_extensions) == 1 else "s",
+ ", ".join(forbidden_extensions)))
- if ku is not None and self.expected_ca_keyUsage != ku:
- raise rpki.exceptions.BadPKCS10("PKCS #10 keyUsage doesn't match basicConstraints: %r" % ku)
- eku = self.get_POW().getEKU()
+ def check_valid_request_ca(self):
+ """
+ Check this certification request to see whether it's a valid
+ request for an RPKI certificate. This is broken out of the
+ up-down protocol code because it's somewhat involved and the
+ up-down code doesn't need to know the details.
- if kind == "ca" and eku is not None:
- raise rpki.exceptions.BadPKCS10("EKU not allowed in CA certificate PKCS #10")
- elif kind == "router" and (eku is None or rpki.oids.id_kp_bgpsec_router not in eku):
- raise rpki.exceptions.BadPKCS10("EKU required for router certificate PKCS #10")
+ Throws an exception if the request isn't valid, so if this method
+ returns at all, the request is ok.
- if any(oid not in self.allowed_extensions
- for oid in self.get_POW().getExtensionOIDs()):
- raise rpki.exceptions.BadExtension("Forbidden extension(s) in PKCS #10 certificate request")
+ This needs refactoring, as the nested conditionals to handle the
+ different kinds of certificates have gotten rather nasty.
+ """
+ self.check_valid_request_common()
+
+ alg = self.get_POW().getSignatureAlgorithm()
+ bc = self.get_POW().getBasicConstraints()
+ eku = self.get_POW().getEKU()
sias = self.get_POW().getSIA()
- if kind == "router":
+ if alg != rpki.oids.sha256WithRSAEncryption:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad signature algorithm %s" % alg)
+
+ if bc is None or not bc[0] or bc[1] is not None:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 bad basicConstraints")
- if sias is not None:
- raise rpki.exceptions.BadPKCS10("router certificate PKCS #10 must not contain SIA extension")
+ if eku is not None:
+ raise rpki.exceptions.BadPKCS10("EKU not allowed in CA certificate PKCS #10")
+
+ if sias is None:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 is missing SIA extension")
+
+ caRepository, rpkiManifest, signedObject = sias
- elif kind == "ca":
+ if signedObject:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request has SIA id-ad-signedObject")
- if sias is None:
- raise rpki.exceptions.BadPKCS10("PKCS #10 is missing SIA extension")
+ if not caRepository:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-caRepository")
- caRepository, rpkiManifest, signedObject = sias
+ if not any(uri.startswith("rsync://") for uri in caRepository):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository contains no rsync URIs")
- if signedObject:
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request has SIA id-ad-signedObject")
+ if not rpkiManifest:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-rpkiManifest")
- if not caRepository:
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-caRepository")
+ if not any(uri.startswith("rsync://") for uri in rpkiManifest):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest contains no rsync URIs")
- if not any(uri.startswith("rsync://") for uri in caRepository):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository contains no rsync URIs")
+ if any(uri.startswith("rsync://") and not uri.endswith("/") for uri in caRepository):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository does not end with slash")
- if not rpkiManifest:
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-rpkiManifest")
+ if any(uri.startswith("rsync://") and uri.endswith("/") for uri in rpkiManifest):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest ends with slash")
+
+
+ def check_valid_request_router(self):
+ """
+ Check this certification request to see whether it's a valid
+ request for a BGPSEC router certificate.
+
+ Throws an exception if the request isn't valid, so if this method
+ returns at all, the request is ok.
+
+ draft-ietf-sidr-bgpsec-pki-profiles 3.2 says follow RFC 6487 3
+ except where explicitly overriden, and does not override for SIA.
+ But draft-ietf-sidr-bgpsec-pki-profiles also says that router
+ certificates don't get SIA, while RFC 6487 requires SIA. So what
+ do we do with SIA in PKCS #10 for router certificates?
+
+ For the moment, ignore it, but make sure we don't include it in
+ the certificate when we get to the code that generates that.
+ """
+
+ self.check_valid_request_common()
+
+ alg = self.get_POW().getSignatureAlgorithm()
+ bc = self.get_POW().getBasicConstraints()
+ eku = self.get_POW().getEKU()
+ #sia = self.get_POW().getSIA()
+
+ if alg != rpki.oids.ecdsa_with_SHA256:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad signature algorithm %s" % alg)
- if not any(uri.startswith("rsync://") for uri in rpkiManifest):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest contains no rsync URIs")
+ if bc is not None and (bc[0] or bc[1] is not None):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 has bad basicConstraints for router")
- if any(uri.startswith("rsync://") and not uri.endswith("/") for uri in caRepository):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository does not end with slash")
+ if eku is None or rpki.oids.id_kp_bgpsec_router not in eku:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 for router requires EKU")
- if any(uri.startswith("rsync://") and uri.endswith("/") for uri in rpkiManifest):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest ends with slash")
@classmethod
def create(cls, keypair, exts = None, is_ca = False,