diff options
author | Rob Austein <sra@hactrn.net> | 2007-11-15 03:24:02 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2007-11-15 03:24:02 +0000 |
commit | a096bcdca38b419f40c8d37584a4f7900f039589 (patch) | |
tree | b8b392eb4614b1a2cccec74e1c849cac6cd1ec5a | |
parent | 0c09c0596e642b5bb3cc107b0933cf9ad847086c (diff) |
CRL support, not yet tested
svn path=/scripts/biz-certs/Bob-CA.srl; revision=1296
-rw-r--r-- | scripts/biz-certs/Bob-CA.srl | 2 | ||||
-rw-r--r-- | scripts/rpki/left_right.py | 20 | ||||
-rw-r--r-- | scripts/rpki/oids.py | 1 | ||||
-rw-r--r-- | scripts/rpki/sql.py | 157 | ||||
-rw-r--r-- | scripts/rpki/up_down.py | 25 | ||||
-rw-r--r-- | scripts/rpki/x509.py | 16 |
6 files changed, 119 insertions, 102 deletions
diff --git a/scripts/biz-certs/Bob-CA.srl b/scripts/biz-certs/Bob-CA.srl index 5e3fd115..2c61affc 100644 --- a/scripts/biz-certs/Bob-CA.srl +++ b/scripts/biz-certs/Bob-CA.srl @@ -1 +1 @@ -90801F1ED19454B1 +90801F1ED19454B2 diff --git a/scripts/rpki/left_right.py b/scripts/rpki/left_right.py index f57accc1..6c24bebb 100644 --- a/scripts/rpki/left_right.py +++ b/scripts/rpki/left_right.py @@ -733,17 +733,19 @@ def irdb_query(gctx, self_id, child_id = None): q_elt = q_msg.toXML() rpki.relaxng.left_right.assertValid(q_elt) q_cms = rpki.cms.xml_sign(q_elt, gctx.cms_key, gctx.cms_certs) - r_cms = rpki.https.client(privateKey = gctx.https_key, - certChain = gctx.https_certs, - x509TrustList = gctx.https_tas, - url = gctx.irdb_url, - msg = q_cms) + r_cms = rpki.https.client( + privateKey = gctx.https_key, + certChain = gctx.https_certs, + x509TrustList = gctx.https_tas, + url = gctx.irdb_url, + msg = q_cms) r_elt = rpki.cms.xml_verify(r_cms, gctx.cms_ta_irdb) rpki.relaxng.left_right.assertValid(r_elt) r_msg = rpki.left_right.sax_handler.saxify(r_elt) if len(r_msg) == 0 or not isinstance(r_msg[0], list_resources_elt) or r_msg[0].type != "reply": raise rpki.exceptions.BadIRDBReply, "Unexpected response to IRDB query: %s" % r_msg.toXML() - return rpki.resource_set.resource_bag(r_msg[0].as, - r_msg[0].ipv4, - r_msg[0].ipv6, - r_msg[0].valid_until) + return rpki.resource_set.resource_bag( + as = r_msg[0].as, + v4 = r_msg[0].ipv4, + v6 = r_msg[0].ipv6, + valid_until = r_msg[0].valid_until) diff --git a/scripts/rpki/oids.py b/scripts/rpki/oids.py index 6537ba9f..32bd6e4c 100644 --- a/scripts/rpki/oids.py +++ b/scripts/rpki/oids.py @@ -22,6 +22,7 @@ oid2name = { (2, 5, 29, 14) : "subjectKeyIdentifier", (2, 5, 29, 15) : "keyUsage", (2, 5, 29, 19) : "basicConstraints", + (2, 5, 29, 20) : "cRLNumber", (2, 5, 29, 31) : "cRLDistributionPoints", (2, 5, 29, 32) : "certificatePolicies", (2, 5, 29, 35) : "authorityKeyIdentifier", diff --git a/scripts/rpki/sql.py b/scripts/rpki/sql.py index 228960f6..3f01686b 100644 --- a/scripts/rpki/sql.py +++ b/scripts/rpki/sql.py @@ -200,11 +200,12 @@ class sql_persistant(object): class ca_obj(sql_persistant): """Internal CA object.""" - sql_template = template("ca", "ca_id", "last_crl_sn", - ("next_crl_update", rpki.sundial.datetime), - "last_issued_sn", "last_manifest_sn", - ("next_manifest_update", rpki.sundial.datetime), - "sia_uri", "parent_id", "parent_resource_class") + sql_template = template( + "ca", "ca_id", "last_crl_sn", + ("next_crl_update", rpki.sundial.datetime), + "last_issued_sn", "last_manifest_sn", + ("next_manifest_update", rpki.sundial.datetime), + "sia_uri", "parent_id", "parent_resource_class") last_crl_sn = 0 last_issued_sn = 0 @@ -313,20 +314,21 @@ class ca_obj(sql_persistant): class ca_detail_obj(sql_persistant): """Internal CA detail object.""" - sql_template = template("ca_detail", - "ca_detail_id", - ("private_key_id", rpki.x509.RSA), - ("public_key", rpki.x509.RSApublic), - ("latest_ca_cert", rpki.x509.X509), - ("manifest_private_key_id", rpki.x509.RSA), - ("manifest_public_key", rpki.x509.RSApublic), - ("latest_manifest_cert", rpki.x509.X509), - ("latest_manifest", rpki.x509.SignedManifest), - ("latest_crl", rpki.x509.CRL), - "state", - ("state_timer", rpki.sundial.datetime), - "ca_cert_uri", - "ca_id") + sql_template = template( + "ca_detail", + "ca_detail_id", + ("private_key_id", rpki.x509.RSA), + ("public_key", rpki.x509.RSApublic), + ("latest_ca_cert", rpki.x509.X509), + ("manifest_private_key_id", rpki.x509.RSA), + ("manifest_public_key", rpki.x509.RSApublic), + ("latest_manifest_cert", rpki.x509.X509), + ("latest_manifest", rpki.x509.SignedManifest), + ("latest_crl", rpki.x509.CRL), + "state", + ("state_timer", rpki.sundial.datetime), + "ca_cert_uri", + "ca_id") def sql_decode(self, vals): """Extra assertions for SQL decode of a ca_detail_obj.""" @@ -390,19 +392,21 @@ class ca_detail_obj(sql_persistant): def generate_manifest_cert(self, ca): """Generate a new manifest certificate for this ca_detail.""" - resources = rpki.resource_set.resource_bag(as = rpki.resource_set.resource_set_as("<inherit>"), - v4 = rpki.resource_set.resource_set_ipv4("<inherit>"), - v6 = rpki.resource_set.resource_set_ipv6("<inherit>")) - - self.latest_manifest_cert = self.latest_ca_cert.issue(keypair = self.private_key_id, - subject_key = self.manifest_public_key, - serial = ca.next_serial_number(), - sia = None, - aia = self.ca_cert_uri, - crldp = ca.sia_uri + self.latest_ca_cert.gSKI() + ".crl", - resources = resources, - notAfter = self.latest_ca_cert.getNotAfter(), - is_ca = False) + resources = rpki.resource_set.resource_bag( + as = rpki.resource_set.resource_set_as("<inherit>"), + v4 = rpki.resource_set.resource_set_ipv4("<inherit>"), + v6 = rpki.resource_set.resource_set_ipv6("<inherit>")) + + self.latest_manifest_cert = self.latest_ca_cert.issue( + keypair = self.private_key_id, + subject_key = self.manifest_public_key, + serial = ca.next_serial_number(), + sia = None, + aia = self.ca_cert_uri, + crldp = ca.sia_uri + self.latest_ca_cert.gSKI() + ".crl", + resources = resources, + notAfter = self.latest_ca_cert.getNotAfter(), + is_ca = False) def issue(self, gctx, ca, child, subject_key, sia, resources, child_cert = None): """Issue a new certificate to a child. Optional child_cert @@ -413,19 +417,21 @@ class ca_detail_obj(sql_persistant): assert child_cert is None or (child_cert.child_id == child.child_id and child_cert.ca_detail_id == self.ca_detail_id) - cert = self.latest_ca_cert.issue(keypair = self.private_key_id, - subject_key = subject_key, - serial = ca.next_serial_number(), - aia = self.ca_cert_uri, - crldp = ca.sia_uri + self.latest_ca_cert.gSKI() + ".crl", - sia = sia, - resources = resources, - notAfter = resources.valid_until) + cert = self.latest_ca_cert.issue( + keypair = self.private_key_id, + subject_key = subject_key, + serial = ca.next_serial_number(), + aia = self.ca_cert_uri, + crldp = ca.sia_uri + self.latest_ca_cert.gSKI() + ".crl", + sia = sia, + resources = resources, + notAfter = resources.valid_until) if child_cert is None: - child_cert = rpki.sql.child_cert_obj(child_id = child.child_id, - ca_detail_id = self.ca_detail_id, - cert = cert) + child_cert = rpki.sql.child_cert_obj( + child_id = child.child_id, + ca_detail_id = self.ca_detail_id, + cert = cert) else: child_cert.cert = cert @@ -449,30 +455,26 @@ class ca_detail_obj(sql_persistant): """ ca = ca_obj.sql_fetch(gctx, self.ca_id) - self_obj = rpki.left_right.self_elt.sql_fetch_where1(gctx, """ - self.self_id = parent.self_id AND - parent.parent_id = %s - """ % ca.parent_id) + parent = rpki.left_right.parent_elt.sql_fetch(gctx, ca.parent_id) + self_obj = rpki.left_right.self_elt.sql_fetch(gctx, parent.self_id) + crl_interval = rpki.sundial.timedelta(seconds = self_obj.crl_interval) now = rpki.sundial.datetime.utcnow() - then = now + rpki.sundial.timedelta(seconds = self_obj.crl_interval) - certs = [] - for cert in child_cert_obj.sql_fetch_where(gctx, "child_cert.ca_detail_id = %s AND child_cert.revoked" % self.ca_detail_id): - raise rpki.exceptions.NotImplementedYet - # Extract expiration time, figure out whether we still need to list this cert. - # If not, delete it from child_cert table. Otherwise, we need to include this - # cert, so: extract serial and revocation time, convert date to format - # POW.pkix wants, and add to serial and revocation time to certs[] list. - # Tuple of the form (serial, ("generalTime", timestamp), ()) - - # Sort certs[] into serial order? Not sure it's necessary, but should be simple and harmless. - # Stuff result into crl structure - - crl = rpki.x509.CRL() - - # Sign crl + certlist = [] + for child_cert in child_cert_obj.sql_fetch_where(gctx, "child_cert.ca_detail_id = %s AND child_cert.revoked IS NOT NULL" % self.ca_detail_id): + if now > child_cert.cert.getNotAfter() + crl_interval: + child_cert.sql_delete() + else: + certlist.append((child_cert.cert.getSerial(), child_cert.revoked, ())) + certlist.sort() - raise rpki.exceptions.NotImplementedYet + return rpki.x509.CRL.generate( + keypair = self.private_key_id, + issuer = self.latest_ca_cert, + serial = ca.next_crl_number(), + thisUpdate = now, + nextUpdate = now + crl_interval, + revokedCertificates = certlist) def generate_manifest(self, gctx): """Generate a new manifest for this ca_detail.""" @@ -480,7 +482,7 @@ class ca_detail_obj(sql_persistant): ca = ca_obj.sql_fetch(gctx, self.ca_id) parent = rpki.left_right.parent_elt.sql_fetch(gctx, ca.parent_id) self_obj = rpki.left_right.self_elt.sql_fetch(gctx, parent.self_id) - certs = child_cert_obj.sql_fetch_where(gctx, "child_cert.ca_detail_id = %s AND NOT child_cert.revoked" % self.ca_detail_id) + certs = child_cert_obj.sql_fetch_where(gctx, "child_cert.ca_detail_id = %s AND child_cert.revoked IS NULL" % self.ca_detail_id) m = rpki.x509.SignedManifest() m.build(serial = ca.next_manifest_number(), @@ -495,21 +497,21 @@ class ca_detail_obj(sql_persistant): class child_cert_obj(sql_persistant): """Certificate that has been issued to a child.""" - sql_template = template("child_cert", "child_cert_id", ("cert", rpki.x509.X509), "child_id", "ca_detail_id", "ski", "revoked") + sql_template = template("child_cert", "child_cert_id", ("cert", rpki.x509.X509), "child_id", "ca_detail_id", "ski", ("revoked", rpki.sundial.datetime)) def __init__(self, child_id = None, ca_detail_id = None, cert = None): """Initialize a child_cert_obj.""" self.child_id = child_id self.ca_detail_id = ca_detail_id self.cert = cert - self.revoked = False + self.revoked = None if child_id or ca_detail_id or cert: self.sql_mark_dirty() def revoke(self): """Mark a child cert as revoked.""" - if not self.revoked: - self.revoked = True + if self.revoked is None: + self.revoked = rpki.sundial.datetime.utcnow() self.sql_mark_dirty() def reissue(self, gctx, ca_detail, resources, sia): @@ -539,14 +541,15 @@ class child_cert_obj(sql_persistant): else: child_cert = self - child_cert = ca_detail.issue(gctx = gctx, - ca = ca, - child = child, - subject_key = self.cert.getPublicKey(), - sia = sia, - resources = resources, - notAfter = resources.valid_until, - child_cert = child_cert) + child_cert = ca_detail.issue( + gctx = gctx, + ca = ca, + child = child, + subject_key = self.cert.getPublicKey(), + sia = sia, + resources = resources, + notAfter = resources.valid_until, + child_cert = child_cert) if must_revoke: assert child_cert is not self diff --git a/scripts/rpki/up_down.py b/scripts/rpki/up_down.py index 777743cf..0804bd61 100644 --- a/scripts/rpki/up_down.py +++ b/scripts/rpki/up_down.py @@ -269,17 +269,19 @@ class issue_pdu(base_elt): # Generate new cert or regenerate old one if necessary if child_cert is None: - child_cert = ca_detail.issue(gctx = gctx, - ca = ca, - child = child, - subject_key = req_key, - sia = req_sia, - resources = resources) + child_cert = ca_detail.issue( + gctx = gctx, + ca = ca, + child = child, + subject_key = req_key, + sia = req_sia, + resources = resources) else: - child_cert = child_cert.reissue(gctx = gctx, - ca_detail = ca_detail, - sia = req_sia, - resources = resources) + child_cert = child_cert.reissue( + gctx = gctx, + ca_detail = ca_detail, + sia = req_sia, + resources = resources) # Save anything we modified and generate response rpki.sql.sql_sweep(gctx) @@ -342,8 +344,7 @@ class revoke_pdu(revoke_syntax): raise rpki.exceptions.BadClassNameSyntax, "Bad class name %s" % self.class_name ca_id = long(self.class_name) ski = self.get_SKI() - for ca_detail in rpki.sql.ca_detail_obj.sql_fetch_where(gctx, """ - ca_id = %s AND state != 'revoked'""" % ca_id): + for ca_detail in rpki.sql.ca_detail_obj.sql_fetch_where(gctx, "ca_id = %s AND state != 'revoked'" % ca_id): for child_cert in rpki.sql.child_cert_obj.sql_fetch_where(gctx, """ child_id = %s AND ca_detail_id = %s AND ski = '%s' """ % (child.child_id, ca_detail.ca_detail_id, ski)): diff --git a/scripts/rpki/x509.py b/scripts/rpki/x509.py index 488c1d73..b6c56d1e 100644 --- a/scripts/rpki/x509.py +++ b/scripts/rpki/x509.py @@ -650,7 +650,17 @@ class CRL(DER_object): self.POWpkix = crl return self.POWpkix - def build(self, serial, nextUpdate, names_and_objs, version = 0): + @classmethod + def generate(cls, keypair, issuer, serial, thisUpdate, nextUpdate, revokedCertificates, version = 1, digestType = "sha256WithRSAEncryption"): crl = POW.pkix.CertificateList() - raise rpki.exceptions.NotImplementedYet - self.set(POWpkix = crl) + crl.setVersion(version) + crl.setIssuer(issuer.get_POWpkix().getIssuer()) + crl.setThisUpdate(thisUpdate.toASN1tuple()) + crl.setNextUpdate(nextUpdate.toASN1tuple()) + if revokedCertificates: + crl.setRevokedCertificates(revokedCertificates) + crl.setExtensions( + (rpki.oids.name2oid["authorityKeyIdentifier"], False, (issuer.get_SKI(), (), None)), + (rpki.oids.name2oid["cRLNumber"], False, serial)) + crl.sign(keypair.get_POW(), digestType) + return cls(POWpkix = crl) |