diff options
Diffstat (limited to 'scripts/rpki')
-rw-r--r-- | scripts/rpki/up_down.py | 42 | ||||
-rw-r--r-- | scripts/rpki/x509.py | 42 |
2 files changed, 52 insertions, 32 deletions
diff --git a/scripts/rpki/up_down.py b/scripts/rpki/up_down.py index 7bd4c51a..09a2f478 100644 --- a/scripts/rpki/up_down.py +++ b/scripts/rpki/up_down.py @@ -19,7 +19,7 @@ oid2name = { (1, 3, 6, 1, 5, 5, 7, 48, 5) : "caRepository", } -name2oid = dict((v,k) for (k,v) in oid2name) +name2oid = dict((v,k) for k,v in oid2name.items()) class base_elt(object): """Generic PDU object. @@ -223,7 +223,7 @@ class issue_pdu(base_elt): def serve_pdu(self, gctx, q_msg, r_msg, child): # - # Step 1: Check the request PDU + # Step 1: Check the request if not self.class_name.isdigit(): raise rpki.exceptions.BadClassNameSyntax, "Bad class name %s" % self.class_name ca_id = long(self.class_name) @@ -231,31 +231,9 @@ class issue_pdu(base_elt): ca_detail = rpki.sql.ca_detail_elt.sql_fetch_active(gctx.db, gctx.cur, ca_id) if ca is None or ca_detail is None: raise rpki.exceptions.NotInDatabase + self.pkcs10.check_valid_rpki() # - # Step 2: Check the PKCS #10 request - if not self.pkcs10.get_POWpkix().verify(): - raise rpki.exceptions.BadPKCS10, "Signature check failed" - if self.pkcs10.get_POWpkix().certificationRequestInfo.version != 0: - raise rpki.exceptions.BadPKCS10, "Bad version number %s" % self.pkcs10.get_POWpkix().certificationRequestInfo.version - if oid2name.get(self.pkcs10.get_POWpkix().signatureAlgorithm) not in ("sha256WithRSAEncryption", "sha384WithRSAEncryption", "sha512WithRSAEncryption"): - raise rpki.exceptions.BadPKCS10, "Bad signature algorithm %s" % self.pkcs10.get_POWpkix().signatureAlgorithm - exts = self.pkcs10.getExtensions() - for oid, critical, value in exts: - if oid2name.get(oid) not in ("basicConstraints", "keyUsage", "subjectInfoAccess"): - raise rpki.exceptions.BadExtension, "Forbidden extension %s" % oid - req_exts = dict((oid2name[oid], value) for (oid, critical, value) in exts) - if "basicConstraints" not in req_exts or not req_exts["basicConstraints"][0]: - raise rpki.exceptions.BadPKCS10, "request for EE cert not allowed here" - if req_exts["basicConstraints"][1] is not None: - raise rpki.exceptions.BadPKCS10, "basicConstraints must not specify Path Length" - if "keyUsage" in req_exts and (not req_exts["keyUsage"][5] or not req_exts["keyUsage"][6]): - raise rpki.exceptions.BadPKCS10, "keyUsage doesn't match basicConstraints" - for method, location in req_exts.get("subjectInfoAccess", ()): - if oid2name.get(method) == "caRepository" and (location[0] != "uri" or (location[1].startswith("rsync://") and not location[1].endswith("/"))): - raise rpki.exceptions.BadPKCS10, "Certificate request includes bad SIA component: %s" % location - assert "subjectInfoAccess" in req_exts, "Can't (yet) handle PKCS #10 without an SIA extension" - # - # Step 3: See whether we can just return the current child cert + # Step 2: See whether we can just return the current child cert rc_as, rc_v4, rc_v6 = ca_detail.latest_ca_cert.get_3779resources(rpki.left_right.irdb_query(gctx, child.self_id, child.child_id)) pubkey = self.certificationRequestInfo.subjectPublicKeyInfo.get() for child_cert in rpki.sql.child_cert_obj.sql_fetch_where(gctx.db, gctx.cur, "child_id = %s AND ca_detail_id = %s" % (child.child_id, ca_detail.ca_detail_id)): @@ -266,18 +244,18 @@ class issue_pdu(base_elt): if child_cert is not None and ((rc_as, rc_v4, rc_v6) != child_cert.latest_ca_cert.get_3779resources()): child_cert = None if child_cert is not None and \ - dict((oid2name[oid], value) for (oid, critical, value) in child_cert.get_POWpkix().getExtensions()).get("subjectInfoAccess") != req_exts.get("subjectInfoAccess"): + child_cert.get_POWpkix().getExtension(name2oid["subjectInfoAccess"]) != self.get_POWpkix().getExtension(name2oid["subjectInfoAccess"]): child_cert = None # Do we need to check certificate expiration here too? Maybe we # can just trust the cron job that handles renewals for that? # - # Step 4: If we found a reusable cert, return it, otherwise - # generate a new one. - if child_cert: - raise NotImplementedError - else: + # Step 3: If we didn't find a reusable cert, generate a new one. + if child_cert is None: raise NotImplementedError + # And finally, return what we got + raise NotImplementedError + class issue_response_pdu(class_response_syntax): """Up-Down protocol "issue_response" PDU.""" diff --git a/scripts/rpki/x509.py b/scripts/rpki/x509.py index 2061864c..cc11c4f3 100644 --- a/scripts/rpki/x509.py +++ b/scripts/rpki/x509.py @@ -304,6 +304,48 @@ class PKCS10_Request(DER_object): self.POWpkix = req return self.POWpkix + def check_valid_rpki(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. + + Throws an exception if the request isn't valid, so if this method + returns at all, the request is ok. + """ + + if not self.get_POWpkix().verify(): + raise rpki.exceptions.BadPKCS10, "Signature check failed" + + if self.get_POWpkix().certificationRequestInfo.version != 0: + raise rpki.exceptions.BadPKCS10, "Bad version number %s" % self.get_POWpkix().certificationRequestInfo.version + + if oid2name.get(self.get_POWpkix().signatureAlgorithm) not in ("sha256WithRSAEncryption", "sha384WithRSAEncryption", "sha512WithRSAEncryption"): + raise rpki.exceptions.BadPKCS10, "Bad signature algorithm %s" % self.get_POWpkix().signatureAlgorithm + + exts = self.getExtensions() + for oid, critical, value in exts: + if oid2name.get(oid) not in ("basicConstraints", "keyUsage", "subjectInfoAccess"): + raise rpki.exceptions.BadExtension, "Forbidden extension %s" % oid + req_exts = dict((oid2name[oid], value) for (oid, critical, value) in exts) + + if "basicConstraints" not in req_exts or not req_exts["basicConstraints"][0]: + raise rpki.exceptions.BadPKCS10, "request for EE cert not allowed here" + + if req_exts["basicConstraints"][1] is not None: + raise rpki.exceptions.BadPKCS10, "basicConstraints must not specify Path Length" + + if "keyUsage" in req_exts and (not req_exts["keyUsage"][5] or not req_exts["keyUsage"][6]): + raise rpki.exceptions.BadPKCS10, "keyUsage doesn't match basicConstraints" + + for method, location in req_exts.get("subjectInfoAccess", ()): + if oid2name.get(method) == "caRepository" and (location[0] != "uri" or (location[1].startswith("rsync://") and not location[1].endswith("/"))): + raise rpki.exceptions.BadPKCS10, "Certificate request includes bad SIA component: %s" % location + + # This one is an implementation restriction. I don't yet + # understand what the spec is telling me to do in this case. + assert "subjectInfoAccess" in req_exts, "Can't (yet) handle PKCS #10 without an SIA extension" + class RSA_Keypair(DER_object): """Class to hold an RSA key pair.""" |