aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2007-11-15 03:24:02 +0000
committerRob Austein <sra@hactrn.net>2007-11-15 03:24:02 +0000
commita096bcdca38b419f40c8d37584a4f7900f039589 (patch)
treeb8b392eb4614b1a2cccec74e1c849cac6cd1ec5a
parent0c09c0596e642b5bb3cc107b0933cf9ad847086c (diff)
CRL support, not yet tested
svn path=/scripts/biz-certs/Bob-CA.srl; revision=1296
-rw-r--r--scripts/biz-certs/Bob-CA.srl2
-rw-r--r--scripts/rpki/left_right.py20
-rw-r--r--scripts/rpki/oids.py1
-rw-r--r--scripts/rpki/sql.py157
-rw-r--r--scripts/rpki/up_down.py25
-rw-r--r--scripts/rpki/x509.py16
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)