aboutsummaryrefslogtreecommitdiff
path: root/scripts/rpki
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2007-11-14 17:22:06 +0000
committerRob Austein <sra@hactrn.net>2007-11-14 17:22:06 +0000
commit8d48fee8d4f99bcd07c8def5fdc4a5cbb302ae35 (patch)
tree50c6596a54b0cba28bdccf5d3ff6f5b0343653a2 /scripts/rpki
parentd8cc553708a7cc662d3f33d5efa270ecb2bfa513 (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.py8
-rw-r--r--scripts/rpki/sql.py97
-rw-r--r--scripts/rpki/up_down.py22
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)