diff options
author | Rob Austein <sra@hactrn.net> | 2007-11-14 17:22:06 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2007-11-14 17:22:06 +0000 |
commit | 8d48fee8d4f99bcd07c8def5fdc4a5cbb302ae35 (patch) | |
tree | 50c6596a54b0cba28bdccf5d3ff6f5b0343653a2 /scripts/rpki | |
parent | d8cc553708a7cc662d3f33d5efa270ecb2bfa513 (diff) |
Rewrite child_cert.reissue() to support the full range of actions it
might need to take, from returning the existing cert unchanged to
generating a new cert while revoking the old one.
svn path=/scripts/biz-certs/Bob-CA.srl; revision=1294
Diffstat (limited to 'scripts/rpki')
-rw-r--r-- | scripts/rpki/resource_set.py | 8 | ||||
-rw-r--r-- | scripts/rpki/sql.py | 97 | ||||
-rw-r--r-- | scripts/rpki/up_down.py | 22 |
3 files changed, 77 insertions, 50 deletions
diff --git a/scripts/rpki/resource_set.py b/scripts/rpki/resource_set.py index a98824b8..795c695d 100644 --- a/scripts/rpki/resource_set.py +++ b/scripts/rpki/resource_set.py @@ -434,17 +434,19 @@ class resource_bag(object): return not (self == other) def intersection(self, other): - """Compute intersection with another resource_bag.""" + """Compute intersection with another resource_bag. + valid_until attribute (if any) inherits from self. + """ return self.__class__(self.as.intersection(other.as), self.v4.intersection(other.v4), - self.v6.intersection(other.v6)) + self.v6.intersection(other.v6), + self.valid_until) # Test suite for set operations. This will probably go away eventually if __name__ == "__main__": def test(t, s1, s2): - """Lame unit test.""" print r1 = t(s1) r2 = t(s2) diff --git a/scripts/rpki/sql.py b/scripts/rpki/sql.py index 1074e829..6fabc88d 100644 --- a/scripts/rpki/sql.py +++ b/scripts/rpki/sql.py @@ -367,8 +367,7 @@ class ca_detail_obj(sql_persistant): child_cert.reissue(gctx = gctx, ca_detail = self, resources = child_resources.intersection(current_resources), - sia = ca.sia_uri, - valid_until = child_resources.valid_until) + sia = ca.sia_uri) @classmethod def create(cls, gctx, ca): @@ -395,17 +394,17 @@ class ca_detail_obj(sql_persistant): 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, + 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, valid_until, child_cert = None): + 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 argument specifies an existing child_cert object to update in place; if not specified, we create a new one. Returns the @@ -414,19 +413,19 @@ 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, + 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 = valid_until) + 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, + child_cert = rpki.sql.child_cert_obj(child_id = child.child_id, ca_detail_id = self.ca_detail_id, - cert = cert) + cert = cert) else: child_cert.cert = cert @@ -507,20 +506,48 @@ class child_cert_obj(sql_persistant): if child_id or ca_detail_id or cert: self.sql_mark_dirty() - def reissue(self, gctx, ca_detail, resources, sia, valid_until): - """Reissue an existing child_cert_obj, reusing the public key.""" - - # if sia is None: sia = self.cert.get_SIA() - - return ca_detail.issue(gctx = gctx, - ca = ca_obj.sql_fetch(gctx, ca_detail.ca_id), - child = rpki.left_right.child_elt.sql_fetch(gctx, self.child_id), - subject_key = self.cert.getPublicKey(), - sia = sia, - resources = resources, - notAfter = valid_until, - child_cert = self) - def revoke(self): """Mark a child cert as revoked.""" self.revoked = True + + def reissue(self, gctx, ca_detail, resources, sia): + """Reissue an existing cert, reusing the public key. If the cert + we would generate is identical to the one we already have, we just + return the one we already have. If we have to revoke the old + certificate when generating the new one, we have to generate a new + child_cert_obj, so calling code that needs the updated + child_cert_obj must use the return value from this method. + """ + + ca = ca_obj.sql_fetch(gctx, ca_detail.ca_id) + child = rpki.left_right.child_elt.sql_fetch(gctx, self.child_id) + + old_resources = self.cert.get_3779resources() + old_sia = self.cert.get_SIA() + + assert resources.valid_until is not None and old_resources.valid_until is not None + + if resources == old_resources and sia == old_sia: + return self + + must_revoke = old_resources.oversized(resources) or old_resources.valid_until > resources.valid_until + + if must_revoke: + child_cert = None + 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) + + if must_revoke: + assert child_cert is not self + self.revoke() + + return child_cert diff --git a/scripts/rpki/up_down.py b/scripts/rpki/up_down.py index 7f127971..82852bac 100644 --- a/scripts/rpki/up_down.py +++ b/scripts/rpki/up_down.py @@ -259,7 +259,7 @@ class issue_pdu(base_elt): # Check current cert, if any irdb_resources = rpki.left_right.irdb_query(gctx, child.self_id, child.child_id) - resources = ca_detail.latest_ca_cert.get_3779resources().intersection(irdb_resources) + resources = irdb_resources.intersection(ca_detail.latest_ca_cert.get_3779resources()) req_key = self.pkcs10.getPublicKey() req_sia = self.pkcs10.get_SIA() child_cert = rpki.sql.child_cert_obj.sql_fetch_where1(gctx, """ @@ -269,19 +269,17 @@ 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, + child_cert = ca_detail.issue(gctx = gctx, + ca = ca, + child = child, subject_key = req_key, - sia = req_sia, - resources = resources, - valid_until = irdb_resources.valid_until) - elif resources != child_cert.cert.get_3779resources() or child_cert.cert.get_SIA() != req_sia: - child_cert = child_cert.reissue(gctx = gctx, + sia = req_sia, + resources = resources) + else: + child_cert = child_cert.reissue(gctx = gctx, ca_detail = ca_detail, - sia = req_sia, - resources = resources, - valid_until = irdb_resources.valid_until) + sia = req_sia, + resources = resources) # Save anything we modified and generate response rpki.sql.sql_sweep(gctx) |