aboutsummaryrefslogtreecommitdiff
path: root/rpki/rootd.py
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-10-26 06:29:00 +0000
committerRob Austein <sra@hactrn.net>2015-10-26 06:29:00 +0000
commitb46deb1417dc3596e9ac9fe2fe8cc0b7f42457e7 (patch)
treeca0dc0276d1adc168bc3337ce0564c4ec4957c1b /rpki/rootd.py
parent397beaf6d9900dc3b3cb612c89ebf1d57b1d16f6 (diff)
"Any programmer who fails to comply with the standard naming, formatting,
or commenting conventions should be shot. If it so happens that it is inconvenient to shoot him, then he is to be politely requested to recode his program in adherence to the above standard." -- Michael Spier, Digital Equipment Corporation svn path=/branches/tk705/; revision=6152
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),))