aboutsummaryrefslogtreecommitdiff
path: root/rpki/rootd.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpki/rootd.py')
-rw-r--r--rpki/rootd.py810
1 files changed, 405 insertions, 405 deletions
diff --git a/rpki/rootd.py b/rpki/rootd.py
index 1d4f5659..e3a460f4 100644
--- a/rpki/rootd.py
+++ b/rpki/rootd.py
@@ -44,416 +44,416 @@ logger = logging.getLogger(__name__)
class ReplayTracker(object):
- """
- Stash for replay protection timestamps.
- """
+ """
+ Stash for replay protection timestamps.
+ """
- def __init__(self):
- self.cms_timestamp = None
+ def __init__(self):
+ self.cms_timestamp = None
class main(object):
- def root_newer_than_subject(self):
- return self.rpki_root_cert.mtime > os.stat(self.rpki_subject_cert_file).st_mtime
-
-
- def get_subject_cert(self):
- try:
- x = rpki.x509.X509(Auto_file = self.rpki_subject_cert_file)
- logger.debug("Read subject cert %s", self.rpki_subject_cert_file)
- return x
- except IOError:
- return None
-
-
- def set_subject_cert(self, cert):
- logger.debug("Writing subject cert %s, SKI %s", self.rpki_subject_cert_file, cert.hSKI())
- with open(self.rpki_subject_cert_file, "wb") as f:
- f.write(cert.get_DER())
-
-
- def del_subject_cert(self):
- logger.debug("Deleting subject cert %s", self.rpki_subject_cert_file)
- os.remove(self.rpki_subject_cert_file)
-
-
- def get_subject_pkcs10(self):
- try:
- x = rpki.x509.PKCS10(Auto_file = self.rpki_subject_pkcs10)
- logger.debug("Read subject PKCS #10 %s", self.rpki_subject_pkcs10)
- return x
- except IOError:
- return None
-
-
- def set_subject_pkcs10(self, pkcs10):
- logger.debug("Writing subject PKCS #10 %s", self.rpki_subject_pkcs10)
- with open(self.rpki_subject_pkcs10, "wb") as f:
- f.write(pkcs10.get_DER())
-
-
- def del_subject_pkcs10(self):
- logger.debug("Deleting subject PKCS #10 %s", self.rpki_subject_pkcs10)
- try:
- os.remove(self.rpki_subject_pkcs10)
- except OSError:
- pass
-
-
- def issue_subject_cert_maybe(self, new_pkcs10):
- now = rpki.sundial.now()
- subject_cert = self.get_subject_cert()
- if subject_cert is None:
- subject_cert_hash = None
- else:
- subject_cert_hash = rpki.x509.sha256(subject_cert.get_DER()).encode("hex")
- old_pkcs10 = self.get_subject_pkcs10()
- if new_pkcs10 is not None and new_pkcs10 != old_pkcs10:
- self.set_subject_pkcs10(new_pkcs10)
- if subject_cert is not None:
- logger.debug("PKCS #10 changed, regenerating subject certificate")
+ def root_newer_than_subject(self):
+ return self.rpki_root_cert.mtime > os.stat(self.rpki_subject_cert_file).st_mtime
+
+
+ def get_subject_cert(self):
+ try:
+ x = rpki.x509.X509(Auto_file = self.rpki_subject_cert_file)
+ logger.debug("Read subject cert %s", self.rpki_subject_cert_file)
+ return x
+ except IOError:
+ return None
+
+
+ def set_subject_cert(self, cert):
+ logger.debug("Writing subject cert %s, SKI %s", self.rpki_subject_cert_file, cert.hSKI())
+ with open(self.rpki_subject_cert_file, "wb") as f:
+ f.write(cert.get_DER())
+
+
+ def del_subject_cert(self):
+ logger.debug("Deleting subject cert %s", self.rpki_subject_cert_file)
+ os.remove(self.rpki_subject_cert_file)
+
+
+ def get_subject_pkcs10(self):
+ try:
+ x = rpki.x509.PKCS10(Auto_file = self.rpki_subject_pkcs10)
+ logger.debug("Read subject PKCS #10 %s", self.rpki_subject_pkcs10)
+ return x
+ except IOError:
+ return None
+
+
+ def set_subject_pkcs10(self, pkcs10):
+ logger.debug("Writing subject PKCS #10 %s", self.rpki_subject_pkcs10)
+ with open(self.rpki_subject_pkcs10, "wb") as f:
+ f.write(pkcs10.get_DER())
+
+
+ def del_subject_pkcs10(self):
+ logger.debug("Deleting subject PKCS #10 %s", self.rpki_subject_pkcs10)
+ try:
+ os.remove(self.rpki_subject_pkcs10)
+ except OSError:
+ pass
+
+
+ def issue_subject_cert_maybe(self, new_pkcs10):
+ now = rpki.sundial.now()
+ subject_cert = self.get_subject_cert()
+ if subject_cert is None:
+ subject_cert_hash = None
+ else:
+ subject_cert_hash = rpki.x509.sha256(subject_cert.get_DER()).encode("hex")
+ old_pkcs10 = self.get_subject_pkcs10()
+ if new_pkcs10 is not None and new_pkcs10 != old_pkcs10:
+ self.set_subject_pkcs10(new_pkcs10)
+ if subject_cert is not None:
+ logger.debug("PKCS #10 changed, regenerating subject certificate")
+ self.revoke_subject_cert(now)
+ subject_cert = None
+ if subject_cert is not None and subject_cert.getNotAfter() <= now + self.rpki_subject_regen:
+ logger.debug("Subject certificate has reached expiration threshold, regenerating")
+ self.revoke_subject_cert(now)
+ subject_cert = None
+ if subject_cert is not None and self.root_newer_than_subject():
+ logger.debug("Root certificate has changed, regenerating subject")
+ self.revoke_subject_cert(now)
+ subject_cert = None
+ if subject_cert is not None:
+ return subject_cert, None
+ pkcs10 = old_pkcs10 if new_pkcs10 is None else new_pkcs10
+ if pkcs10 is None:
+ logger.debug("No PKCS #10 request, can't generate subject certificate yet")
+ return None, None
+ resources = self.rpki_root_cert.get_3779resources()
+ notAfter = now + self.rpki_subject_lifetime
+ logger.info("Generating subject cert %s with resources %s, expires %s",
+ self.rpki_subject_cert_uri, resources, notAfter)
+ req_key = pkcs10.getPublicKey()
+ req_sia = pkcs10.get_SIA()
+ self.next_serial_number()
+ subject_cert = self.rpki_root_cert.issue(
+ keypair = self.rpki_root_key,
+ subject_key = req_key,
+ serial = self.serial_number,
+ sia = req_sia,
+ aia = self.rpki_root_cert_uri,
+ crldp = self.rpki_root_crl_uri,
+ resources = resources,
+ notBefore = now,
+ notAfter = notAfter)
+ self.set_subject_cert(subject_cert)
+ pubd_msg = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
+ type = "query", version = rpki.publication.version)
+ pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_subject_cert_uri)
+ pdu.text = subject_cert.get_Base64()
+ if subject_cert_hash is not None:
+ pdu.set("hash", subject_cert_hash)
+ self.generate_crl_and_manifest(now, pubd_msg)
+ return subject_cert, pubd_msg
+
+
+ def generate_crl_and_manifest(self, now, pubd_msg):
+ subject_cert = self.get_subject_cert()
+ self.next_serial_number()
+ self.next_crl_number()
+ while self.revoked and self.revoked[0][1] + 2 * self.rpki_subject_regen < now:
+ del self.revoked[0]
+ crl = rpki.x509.CRL.generate(
+ keypair = self.rpki_root_key,
+ issuer = self.rpki_root_cert,
+ serial = self.crl_number,
+ thisUpdate = now,
+ nextUpdate = now + self.rpki_subject_regen,
+ revokedCertificates = self.revoked)
+ crl_hash = self.read_hash_maybe(self.rpki_root_crl_file)
+ logger.debug("Writing CRL %s", self.rpki_root_crl_file)
+ with open(self.rpki_root_crl_file, "wb") as f:
+ f.write(crl.get_DER())
+ pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_root_crl_uri)
+ pdu.text = crl.get_Base64()
+ if crl_hash is not None:
+ pdu.set("hash", crl_hash)
+ manifest_content = [(os.path.basename(self.rpki_root_crl_uri), crl)]
+ if subject_cert is not None:
+ manifest_content.append((os.path.basename(self.rpki_subject_cert_uri), subject_cert))
+ manifest_resources = rpki.resource_set.resource_bag.from_inheritance()
+ manifest_keypair = rpki.x509.RSA.generate()
+ manifest_cert = self.rpki_root_cert.issue(
+ keypair = self.rpki_root_key,
+ subject_key = manifest_keypair.get_public(),
+ serial = self.serial_number,
+ sia = (None, None, self.rpki_root_manifest_uri, self.rrdp_notification_uri),
+ aia = self.rpki_root_cert_uri,
+ crldp = self.rpki_root_crl_uri,
+ resources = manifest_resources,
+ notBefore = now,
+ notAfter = now + self.rpki_subject_lifetime,
+ is_ca = False)
+ manifest = rpki.x509.SignedManifest.build(
+ serial = self.crl_number,
+ thisUpdate = now,
+ nextUpdate = now + self.rpki_subject_regen,
+ names_and_objs = manifest_content,
+ keypair = manifest_keypair,
+ certs = manifest_cert)
+ mft_hash = self.read_hash_maybe(self.rpki_root_manifest_file)
+ logger.debug("Writing manifest %s", self.rpki_root_manifest_file)
+ with open(self.rpki_root_manifest_file, "wb") as f:
+ f.write(manifest.get_DER())
+ pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_root_manifest_uri)
+ pdu.text = manifest.get_Base64()
+ if mft_hash is not None:
+ pdu.set("hash", mft_hash)
+ cer_hash = rpki.x509.sha256(self.rpki_root_cert.get_DER()).encode("hex")
+ if cer_hash != self.rpki_root_cert_hash:
+ pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_root_cert_uri)
+ pdu.text = self.rpki_root_cert.get_Base64()
+ if self.rpki_root_cert_hash is not None:
+ pdu.set("hash", self.rpki_root_cert_hash)
+ self.rpki_root_cert_hash = cer_hash
+
+
+ @staticmethod
+ def read_hash_maybe(fn):
+ try:
+ with open(fn, "rb") as f:
+ return rpki.x509.sha256(f.read()).encode("hex")
+ except IOError:
+ return None
+
+
+ def revoke_subject_cert(self, now):
+ self.revoked.append((self.get_subject_cert().getSerial(), now))
+
+
+ def publish(self, q_msg):
+ if q_msg is None:
+ return
+ assert len(q_msg) > 0
+
+ if not all(q_pdu.get("hash") is not None for q_pdu in q_msg):
+ logger.debug("Some publication PDUs are missing hashes, checking published data...")
+ q = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
+ type = "query", version = rpki.publication.version)
+ SubElement(q, rpki.publication.tag_list)
+ published_hash = dict((r.get("uri"), r.get("hash")) for r in self.call_pubd(q))
+ for q_pdu in q_msg:
+ q_uri = q_pdu.get("uri")
+ if q_pdu.get("hash") is None and published_hash.get(q_uri) is not None:
+ logger.debug("Updating hash of %s to %s from previously published data", q_uri, published_hash[q_uri])
+ q_pdu.set("hash", published_hash[q_uri])
+
+ r_msg = self.call_pubd(q_msg)
+ if len(q_msg) != len(r_msg):
+ raise rpki.exceptions.BadPublicationReply("Wrong number of response PDUs from pubd: sent %s, got %s" % (len(q_msg), len(r_msg)))
+
+
+ def call_pubd(self, q_msg):
+ for q_pdu in q_msg:
+ logger.info("Sending %s to pubd", q_pdu.get("uri"))
+ r_msg = rpki.http_simple.client(
+ proto_cms_msg = rpki.publication.cms_msg,
+ client_key = self.rootd_bpki_key,
+ client_cert = self.rootd_bpki_cert,
+ client_crl = self.rootd_bpki_crl,
+ server_ta = self.bpki_ta,
+ server_cert = self.pubd_bpki_cert,
+ url = self.pubd_url,
+ q_msg = q_msg,
+ replay_track = self.pubd_replay_tracker)
+ rpki.publication.raise_if_error(r_msg)
+ return r_msg
+
+
+ def compose_response(self, r_msg, pkcs10 = None):
+ subject_cert, pubd_msg = self.issue_subject_cert_maybe(pkcs10)
+ bag = self.rpki_root_cert.get_3779resources()
+ rc = SubElement(r_msg, rpki.up_down.tag_class,
+ class_name = self.rpki_class_name,
+ cert_url = str(rpki.up_down.multi_uri(self.rpki_root_cert_uri)),
+ resource_set_as = str(bag.asn),
+ resource_set_ipv4 = str(bag.v4),
+ resource_set_ipv6 = str(bag.v6),
+ resource_set_notafter = str(bag.valid_until))
+ if subject_cert is not None:
+ c = SubElement(rc, rpki.up_down.tag_certificate,
+ cert_url = str(rpki.up_down.multi_uri(self.rpki_subject_cert_uri)))
+ c.text = subject_cert.get_Base64()
+ SubElement(rc, rpki.up_down.tag_issuer).text = self.rpki_root_cert.get_Base64()
+ self.publish(pubd_msg)
+
+
+ def handle_list(self, q_msg, r_msg):
+ self.compose_response(r_msg)
+
+
+ def handle_issue(self, q_msg, r_msg):
+ # This is where we'd check q_msg[0].get("class_name") if this weren't rootd.
+ self.compose_response(r_msg, rpki.x509.PKCS10(Base64 = q_msg[0].text))
+
+
+ def handle_revoke(self, q_msg, r_msg):
+ class_name = q_msg[0].get("class_name")
+ ski = q_msg[0].get("ski")
+ logger.debug("Revocation requested for class %s SKI %s", class_name, ski)
+ subject_cert = self.get_subject_cert()
+ if subject_cert is None:
+ logger.debug("No subject certificate, nothing to revoke")
+ raise rpki.exceptions.NotInDatabase
+ if subject_cert.gSKI() != ski:
+ logger.debug("Subject certificate has different SKI %s, not revoking", subject_cert.gSKI())
+ raise rpki.exceptions.NotInDatabase
+ logger.debug("Revoking certificate %s", ski)
+ now = rpki.sundial.now()
+ pubd_msg = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
+ type = "query", version = rpki.publication.version)
self.revoke_subject_cert(now)
- subject_cert = None
- if subject_cert is not None and subject_cert.getNotAfter() <= now + self.rpki_subject_regen:
- logger.debug("Subject certificate has reached expiration threshold, regenerating")
- self.revoke_subject_cert(now)
- subject_cert = None
- if subject_cert is not None and self.root_newer_than_subject():
- logger.debug("Root certificate has changed, regenerating subject")
- self.revoke_subject_cert(now)
- subject_cert = None
- if subject_cert is not None:
- return subject_cert, None
- pkcs10 = old_pkcs10 if new_pkcs10 is None else new_pkcs10
- if pkcs10 is None:
- logger.debug("No PKCS #10 request, can't generate subject certificate yet")
- return None, None
- resources = self.rpki_root_cert.get_3779resources()
- notAfter = now + self.rpki_subject_lifetime
- logger.info("Generating subject cert %s with resources %s, expires %s",
- self.rpki_subject_cert_uri, resources, notAfter)
- req_key = pkcs10.getPublicKey()
- req_sia = pkcs10.get_SIA()
- self.next_serial_number()
- subject_cert = self.rpki_root_cert.issue(
- keypair = self.rpki_root_key,
- subject_key = req_key,
- serial = self.serial_number,
- sia = req_sia,
- aia = self.rpki_root_cert_uri,
- crldp = self.rpki_root_crl_uri,
- resources = resources,
- notBefore = now,
- notAfter = notAfter)
- self.set_subject_cert(subject_cert)
- pubd_msg = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
- type = "query", version = rpki.publication.version)
- pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_subject_cert_uri)
- pdu.text = subject_cert.get_Base64()
- if subject_cert_hash is not None:
- pdu.set("hash", subject_cert_hash)
- self.generate_crl_and_manifest(now, pubd_msg)
- return subject_cert, pubd_msg
-
-
- def generate_crl_and_manifest(self, now, pubd_msg):
- subject_cert = self.get_subject_cert()
- self.next_serial_number()
- self.next_crl_number()
- while self.revoked and self.revoked[0][1] + 2 * self.rpki_subject_regen < now:
- del self.revoked[0]
- crl = rpki.x509.CRL.generate(
- keypair = self.rpki_root_key,
- issuer = self.rpki_root_cert,
- serial = self.crl_number,
- thisUpdate = now,
- nextUpdate = now + self.rpki_subject_regen,
- revokedCertificates = self.revoked)
- crl_hash = self.read_hash_maybe(self.rpki_root_crl_file)
- logger.debug("Writing CRL %s", self.rpki_root_crl_file)
- with open(self.rpki_root_crl_file, "wb") as f:
- f.write(crl.get_DER())
- pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_root_crl_uri)
- pdu.text = crl.get_Base64()
- if crl_hash is not None:
- pdu.set("hash", crl_hash)
- manifest_content = [(os.path.basename(self.rpki_root_crl_uri), crl)]
- if subject_cert is not None:
- manifest_content.append((os.path.basename(self.rpki_subject_cert_uri), subject_cert))
- manifest_resources = rpki.resource_set.resource_bag.from_inheritance()
- manifest_keypair = rpki.x509.RSA.generate()
- manifest_cert = self.rpki_root_cert.issue(
- keypair = self.rpki_root_key,
- subject_key = manifest_keypair.get_public(),
- serial = self.serial_number,
- sia = (None, None, self.rpki_root_manifest_uri, self.rrdp_notification_uri),
- aia = self.rpki_root_cert_uri,
- crldp = self.rpki_root_crl_uri,
- resources = manifest_resources,
- notBefore = now,
- notAfter = now + self.rpki_subject_lifetime,
- is_ca = False)
- manifest = rpki.x509.SignedManifest.build(
- serial = self.crl_number,
- thisUpdate = now,
- nextUpdate = now + self.rpki_subject_regen,
- names_and_objs = manifest_content,
- keypair = manifest_keypair,
- certs = manifest_cert)
- mft_hash = self.read_hash_maybe(self.rpki_root_manifest_file)
- logger.debug("Writing manifest %s", self.rpki_root_manifest_file)
- with open(self.rpki_root_manifest_file, "wb") as f:
- f.write(manifest.get_DER())
- pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_root_manifest_uri)
- pdu.text = manifest.get_Base64()
- if mft_hash is not None:
- pdu.set("hash", mft_hash)
- cer_hash = rpki.x509.sha256(self.rpki_root_cert.get_DER()).encode("hex")
- if cer_hash != self.rpki_root_cert_hash:
- pdu = SubElement(pubd_msg, rpki.publication.tag_publish, uri = self.rpki_root_cert_uri)
- pdu.text = self.rpki_root_cert.get_Base64()
- if self.rpki_root_cert_hash is not None:
- pdu.set("hash", self.rpki_root_cert_hash)
- self.rpki_root_cert_hash = cer_hash
-
-
- @staticmethod
- def read_hash_maybe(fn):
- try:
- with open(fn, "rb") as f:
- return rpki.x509.sha256(f.read()).encode("hex")
- except IOError:
- return None
-
-
- def revoke_subject_cert(self, now):
- self.revoked.append((self.get_subject_cert().getSerial(), now))
-
-
- def publish(self, q_msg):
- if q_msg is None:
- return
- assert len(q_msg) > 0
-
- if not all(q_pdu.get("hash") is not None for q_pdu in q_msg):
- logger.debug("Some publication PDUs are missing hashes, checking published data...")
- q = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
- type = "query", version = rpki.publication.version)
- SubElement(q, rpki.publication.tag_list)
- published_hash = dict((r.get("uri"), r.get("hash")) for r in self.call_pubd(q))
- for q_pdu in q_msg:
- q_uri = q_pdu.get("uri")
- if q_pdu.get("hash") is None and published_hash.get(q_uri) is not None:
- logger.debug("Updating hash of %s to %s from previously published data", q_uri, published_hash[q_uri])
- q_pdu.set("hash", published_hash[q_uri])
-
- r_msg = self.call_pubd(q_msg)
- if len(q_msg) != len(r_msg):
- raise rpki.exceptions.BadPublicationReply("Wrong number of response PDUs from pubd: sent %s, got %s" % (len(q_msg), len(r_msg)))
-
-
- def call_pubd(self, q_msg):
- for q_pdu in q_msg:
- logger.info("Sending %s to pubd", q_pdu.get("uri"))
- r_msg = rpki.http_simple.client(
- proto_cms_msg = rpki.publication.cms_msg,
- client_key = self.rootd_bpki_key,
- client_cert = self.rootd_bpki_cert,
- client_crl = self.rootd_bpki_crl,
- server_ta = self.bpki_ta,
- server_cert = self.pubd_bpki_cert,
- url = self.pubd_url,
- q_msg = q_msg,
- replay_track = self.pubd_replay_tracker)
- rpki.publication.raise_if_error(r_msg)
- return r_msg
-
-
- def compose_response(self, r_msg, pkcs10 = None):
- subject_cert, pubd_msg = self.issue_subject_cert_maybe(pkcs10)
- bag = self.rpki_root_cert.get_3779resources()
- rc = SubElement(r_msg, rpki.up_down.tag_class,
- class_name = self.rpki_class_name,
- cert_url = str(rpki.up_down.multi_uri(self.rpki_root_cert_uri)),
- resource_set_as = str(bag.asn),
- resource_set_ipv4 = str(bag.v4),
- resource_set_ipv6 = str(bag.v6),
- resource_set_notafter = str(bag.valid_until))
- if subject_cert is not None:
- c = SubElement(rc, rpki.up_down.tag_certificate,
- cert_url = str(rpki.up_down.multi_uri(self.rpki_subject_cert_uri)))
- c.text = subject_cert.get_Base64()
- SubElement(rc, rpki.up_down.tag_issuer).text = self.rpki_root_cert.get_Base64()
- self.publish(pubd_msg)
-
-
- def handle_list(self, q_msg, r_msg):
- self.compose_response(r_msg)
-
-
- def handle_issue(self, q_msg, r_msg):
- # This is where we'd check q_msg[0].get("class_name") if this weren't rootd.
- self.compose_response(r_msg, rpki.x509.PKCS10(Base64 = q_msg[0].text))
-
-
- def handle_revoke(self, q_msg, r_msg):
- class_name = q_msg[0].get("class_name")
- ski = q_msg[0].get("ski")
- logger.debug("Revocation requested for class %s SKI %s", class_name, ski)
- subject_cert = self.get_subject_cert()
- if subject_cert is None:
- logger.debug("No subject certificate, nothing to revoke")
- raise rpki.exceptions.NotInDatabase
- if subject_cert.gSKI() != ski:
- logger.debug("Subject certificate has different SKI %s, not revoking", subject_cert.gSKI())
- raise rpki.exceptions.NotInDatabase
- logger.debug("Revoking certificate %s", ski)
- now = rpki.sundial.now()
- pubd_msg = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
- type = "query", version = rpki.publication.version)
- self.revoke_subject_cert(now)
- self.del_subject_cert()
- self.del_subject_pkcs10()
- SubElement(r_msg, q_msg[0].tag, class_name = class_name, ski = ski)
- self.generate_crl_and_manifest(now, pubd_msg)
- self.publish(pubd_msg)
-
-
- # Need to do something about mapping exceptions to up-down error
- # codes, right now everything shows up as "internal error".
- #
- #exceptions = {
- # rpki.exceptions.ClassNameUnknown : 1201,
- # rpki.exceptions.NoActiveCA : 1202,
- # (rpki.exceptions.ClassNameUnknown, revoke_pdu) : 1301,
- # (rpki.exceptions.NotInDatabase, revoke_pdu) : 1302 }
- #
- # Might be that what we want here is a subclass of
- # rpki.exceptions.RPKI_Exception which carries an extra data field
- # for the up-down error code, so that we can add the correct code
- # when we instantiate it.
- #
- # There are also a few that are also schema violations, which means
- # we'd have to catch them before validating or pick them out of a
- # message that failed validation or otherwise break current
- # modularity. Maybe an optional pre-validation check method hook in
- # rpki.x509.XML_CMS_object which we can use to intercept such things?
-
-
- def handler(self, request, q_der):
- try:
- q_cms = rpki.up_down.cms_msg(DER = q_der)
- q_msg = q_cms.unwrap((self.bpki_ta, self.child_bpki_cert))
- q_type = q_msg.get("type")
- logger.info("Serving %s query", q_type)
- r_msg = Element(rpki.up_down.tag_message, nsmap = rpki.up_down.nsmap, version = rpki.up_down.version,
- sender = q_msg.get("recipient"), recipient = q_msg.get("sender"), type = q_type + "_response")
- try:
- self.rpkid_cms_timestamp = q_cms.check_replay(self.rpkid_cms_timestamp, request.path)
- getattr(self, "handle_" + q_type)(q_msg, r_msg)
- except Exception, e:
- logger.exception("Exception processing up-down %s message", q_type)
- rpki.up_down.generate_error_response_from_exception(r_msg, e, q_type)
- request.send_cms_response(rpki.up_down.cms_msg().wrap(r_msg, self.rootd_bpki_key, self.rootd_bpki_cert,
- self.rootd_bpki_crl if self.include_bpki_crl else None))
- except Exception, e:
- logger.exception("Unhandled exception processing up-down message")
- request.send_error(500, "Unhandled exception %s: %s" % (e.__class__.__name__, e))
-
-
- def next_crl_number(self):
- if self.crl_number is None:
- try:
- crl = rpki.x509.CRL(DER_file = self.rpki_root_crl_file)
- self.crl_number = crl.getCRLNumber()
- except: # pylint: disable=W0702
- self.crl_number = 0
- self.crl_number += 1
- return self.crl_number
-
-
- def next_serial_number(self):
- if self.serial_number is None:
- subject_cert = self.get_subject_cert()
- if subject_cert is not None:
- self.serial_number = subject_cert.getSerial() + 1
- else:
- self.serial_number = 0
- self.serial_number += 1
- return self.serial_number
-
-
- def __init__(self):
- self.serial_number = None
- self.crl_number = None
- self.revoked = []
- self.rpkid_cms_timestamp = None
- self.pubd_replay_tracker = ReplayTracker()
-
- os.environ["TZ"] = "UTC"
- time.tzset()
-
- parser = argparse.ArgumentParser(description = __doc__)
- parser.add_argument("-c", "--config",
- help = "override default location of configuration file")
- parser.add_argument("-f", "--foreground", action = "store_true",
- help = "do not daemonize")
- parser.add_argument("--pidfile",
- help = "override default location of pid file")
- rpki.log.argparse_setup(parser)
- args = parser.parse_args()
-
- rpki.log.init("rootd", args)
-
- self.cfg = rpki.config.parser(set_filename = args.config, section = "rootd")
- self.cfg.set_global_flags()
-
- if not args.foreground:
- rpki.daemonize.daemon(pidfile = args.pidfile)
-
- self.bpki_ta = rpki.x509.X509(Auto_update = self.cfg.get("bpki-ta"))
- self.rootd_bpki_key = rpki.x509.RSA( Auto_update = self.cfg.get("rootd-bpki-key"))
- self.rootd_bpki_cert = rpki.x509.X509(Auto_update = self.cfg.get("rootd-bpki-cert"))
- self.rootd_bpki_crl = rpki.x509.CRL( Auto_update = self.cfg.get("rootd-bpki-crl"))
- self.child_bpki_cert = rpki.x509.X509(Auto_update = self.cfg.get("child-bpki-cert"))
-
- if self.cfg.has_option("pubd-bpki-cert"):
- self.pubd_bpki_cert = rpki.x509.X509(Auto_update = self.cfg.get("pubd-bpki-cert"))
- else:
- self.pubd_bpki_cert = None
-
- self.http_server_host = self.cfg.get("server-host", "")
- self.http_server_port = self.cfg.getint("server-port")
-
- self.rpki_class_name = self.cfg.get("rpki-class-name")
-
- self.rpki_root_key = rpki.x509.RSA( Auto_update = self.cfg.get("rpki-root-key-file"))
- self.rpki_root_cert = rpki.x509.X509(Auto_update = self.cfg.get("rpki-root-cert-file"))
- self.rpki_root_cert_uri = self.cfg.get("rpki-root-cert-uri")
- self.rpki_root_cert_hash = None
-
- self.rpki_root_manifest_file = self.cfg.get("rpki-root-manifest-file")
- self.rpki_root_manifest_uri = self.cfg.get("rpki-root-manifest-uri")
-
- self.rpki_root_crl_file = self.cfg.get("rpki-root-crl-file")
- self.rpki_root_crl_uri = self.cfg.get("rpki-root-crl-uri")
-
- self.rpki_subject_cert_file = self.cfg.get("rpki-subject-cert-file")
- self.rpki_subject_cert_uri = self.cfg.get("rpki-subject-cert-uri")
- self.rpki_subject_pkcs10 = self.cfg.get("rpki-subject-pkcs10-file")
- self.rpki_subject_lifetime = rpki.sundial.timedelta.parse(self.cfg.get("rpki-subject-lifetime", "8w"))
- self.rpki_subject_regen = rpki.sundial.timedelta.parse(self.cfg.get("rpki-subject-regen",
- self.rpki_subject_lifetime.convert_to_seconds() / 2))
-
- self.include_bpki_crl = self.cfg.getboolean("include-bpki-crl", False)
-
- self.pubd_url = self.cfg.get("pubd-contact-uri")
-
- self.rrdp_notification_uri = self.cfg.get("rrdp-notification-uri")
-
- rpki.http_simple.server(host = self.http_server_host,
- port = self.http_server_port,
- handlers = (("/", self.handler, rpki.up_down.allowed_content_types),))
+ self.del_subject_cert()
+ self.del_subject_pkcs10()
+ SubElement(r_msg, q_msg[0].tag, class_name = class_name, ski = ski)
+ self.generate_crl_and_manifest(now, pubd_msg)
+ self.publish(pubd_msg)
+
+
+ # Need to do something about mapping exceptions to up-down error
+ # codes, right now everything shows up as "internal error".
+ #
+ #exceptions = {
+ # rpki.exceptions.ClassNameUnknown : 1201,
+ # rpki.exceptions.NoActiveCA : 1202,
+ # (rpki.exceptions.ClassNameUnknown, revoke_pdu) : 1301,
+ # (rpki.exceptions.NotInDatabase, revoke_pdu) : 1302 }
+ #
+ # Might be that what we want here is a subclass of
+ # rpki.exceptions.RPKI_Exception which carries an extra data field
+ # for the up-down error code, so that we can add the correct code
+ # when we instantiate it.
+ #
+ # There are also a few that are also schema violations, which means
+ # we'd have to catch them before validating or pick them out of a
+ # message that failed validation or otherwise break current
+ # modularity. Maybe an optional pre-validation check method hook in
+ # rpki.x509.XML_CMS_object which we can use to intercept such things?
+
+
+ def handler(self, request, q_der):
+ try:
+ q_cms = rpki.up_down.cms_msg(DER = q_der)
+ q_msg = q_cms.unwrap((self.bpki_ta, self.child_bpki_cert))
+ q_type = q_msg.get("type")
+ logger.info("Serving %s query", q_type)
+ r_msg = Element(rpki.up_down.tag_message, nsmap = rpki.up_down.nsmap, version = rpki.up_down.version,
+ sender = q_msg.get("recipient"), recipient = q_msg.get("sender"), type = q_type + "_response")
+ try:
+ self.rpkid_cms_timestamp = q_cms.check_replay(self.rpkid_cms_timestamp, request.path)
+ getattr(self, "handle_" + q_type)(q_msg, r_msg)
+ except Exception, e:
+ logger.exception("Exception processing up-down %s message", q_type)
+ rpki.up_down.generate_error_response_from_exception(r_msg, e, q_type)
+ request.send_cms_response(rpki.up_down.cms_msg().wrap(r_msg, self.rootd_bpki_key, self.rootd_bpki_cert,
+ self.rootd_bpki_crl if self.include_bpki_crl else None))
+ except Exception, e:
+ logger.exception("Unhandled exception processing up-down message")
+ request.send_error(500, "Unhandled exception %s: %s" % (e.__class__.__name__, e))
+
+
+ def next_crl_number(self):
+ if self.crl_number is None:
+ try:
+ crl = rpki.x509.CRL(DER_file = self.rpki_root_crl_file)
+ self.crl_number = crl.getCRLNumber()
+ except: # pylint: disable=W0702
+ self.crl_number = 0
+ self.crl_number += 1
+ return self.crl_number
+
+
+ def next_serial_number(self):
+ if self.serial_number is None:
+ subject_cert = self.get_subject_cert()
+ if subject_cert is not None:
+ self.serial_number = subject_cert.getSerial() + 1
+ else:
+ self.serial_number = 0
+ self.serial_number += 1
+ return self.serial_number
+
+
+ def __init__(self):
+ self.serial_number = None
+ self.crl_number = None
+ self.revoked = []
+ self.rpkid_cms_timestamp = None
+ self.pubd_replay_tracker = ReplayTracker()
+
+ os.environ["TZ"] = "UTC"
+ time.tzset()
+
+ parser = argparse.ArgumentParser(description = __doc__)
+ parser.add_argument("-c", "--config",
+ help = "override default location of configuration file")
+ parser.add_argument("-f", "--foreground", action = "store_true",
+ help = "do not daemonize")
+ parser.add_argument("--pidfile",
+ help = "override default location of pid file")
+ rpki.log.argparse_setup(parser)
+ args = parser.parse_args()
+
+ rpki.log.init("rootd", args)
+
+ self.cfg = rpki.config.parser(set_filename = args.config, section = "rootd")
+ self.cfg.set_global_flags()
+
+ if not args.foreground:
+ rpki.daemonize.daemon(pidfile = args.pidfile)
+
+ self.bpki_ta = rpki.x509.X509(Auto_update = self.cfg.get("bpki-ta"))
+ self.rootd_bpki_key = rpki.x509.RSA( Auto_update = self.cfg.get("rootd-bpki-key"))
+ self.rootd_bpki_cert = rpki.x509.X509(Auto_update = self.cfg.get("rootd-bpki-cert"))
+ self.rootd_bpki_crl = rpki.x509.CRL( Auto_update = self.cfg.get("rootd-bpki-crl"))
+ self.child_bpki_cert = rpki.x509.X509(Auto_update = self.cfg.get("child-bpki-cert"))
+
+ if self.cfg.has_option("pubd-bpki-cert"):
+ self.pubd_bpki_cert = rpki.x509.X509(Auto_update = self.cfg.get("pubd-bpki-cert"))
+ else:
+ self.pubd_bpki_cert = None
+
+ self.http_server_host = self.cfg.get("server-host", "")
+ self.http_server_port = self.cfg.getint("server-port")
+
+ self.rpki_class_name = self.cfg.get("rpki-class-name")
+
+ self.rpki_root_key = rpki.x509.RSA( Auto_update = self.cfg.get("rpki-root-key-file"))
+ self.rpki_root_cert = rpki.x509.X509(Auto_update = self.cfg.get("rpki-root-cert-file"))
+ self.rpki_root_cert_uri = self.cfg.get("rpki-root-cert-uri")
+ self.rpki_root_cert_hash = None
+
+ self.rpki_root_manifest_file = self.cfg.get("rpki-root-manifest-file")
+ self.rpki_root_manifest_uri = self.cfg.get("rpki-root-manifest-uri")
+
+ self.rpki_root_crl_file = self.cfg.get("rpki-root-crl-file")
+ self.rpki_root_crl_uri = self.cfg.get("rpki-root-crl-uri")
+
+ self.rpki_subject_cert_file = self.cfg.get("rpki-subject-cert-file")
+ self.rpki_subject_cert_uri = self.cfg.get("rpki-subject-cert-uri")
+ self.rpki_subject_pkcs10 = self.cfg.get("rpki-subject-pkcs10-file")
+ self.rpki_subject_lifetime = rpki.sundial.timedelta.parse(self.cfg.get("rpki-subject-lifetime", "8w"))
+ self.rpki_subject_regen = rpki.sundial.timedelta.parse(self.cfg.get("rpki-subject-regen",
+ self.rpki_subject_lifetime.convert_to_seconds() / 2))
+
+ self.include_bpki_crl = self.cfg.getboolean("include-bpki-crl", False)
+
+ self.pubd_url = self.cfg.get("pubd-contact-uri")
+
+ self.rrdp_notification_uri = self.cfg.get("rrdp-notification-uri")
+
+ rpki.http_simple.server(host = self.http_server_host,
+ port = self.http_server_port,
+ handlers = (("/", self.handler, rpki.up_down.allowed_content_types),))