aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpkid/Makefile.in2
-rw-r--r--rpkid/irdbd.sql11
-rw-r--r--rpkid/left-right-schema.rnc15
-rw-r--r--rpkid/left-right-schema.rng24
-rw-r--r--rpkid/rpki-sql-setup.py4
-rw-r--r--rpkid/rpki/http.py7
-rw-r--r--rpkid/rpki/irdbd.py32
-rw-r--r--rpkid/rpki/left_right.py232
-rw-r--r--rpkid/rpki/oids.py18
-rw-r--r--rpkid/rpki/publication.py4
-rw-r--r--rpkid/rpki/relaxng.py24
-rw-r--r--rpkid/rpki/rpki_engine.py213
-rw-r--r--rpkid/rpki/up_down.py26
-rw-r--r--rpkid/rpki/x509.py35
-rw-r--r--rpkid/rpki/xml_utils.py4
-rw-r--r--rpkid/rpkid.sql18
-rw-r--r--rpkid/tests/smoketest.py55
17 files changed, 529 insertions, 195 deletions
diff --git a/rpkid/Makefile.in b/rpkid/Makefile.in
index 05c42252..11012218 100644
--- a/rpkid/Makefile.in
+++ b/rpkid/Makefile.in
@@ -116,7 +116,7 @@ tags: Makefile
find . -type f \( -name '*.py' -o -name '*.sql' -o -name '*.rnc' -o -name '*.py.in' \) ! -name relaxng.py ! -name __doc__.py | etags -
lint:
- pylint --rcfile ../scripts/pylint.rc rpki/[a-z]*.py irbe_cli.py irdbd.py pubd.py rootd.py rpkid.py tests/smoketest.py tests/testpoke.py ../myrpki/myrpki.py ../myrpki/yamltest.py
+ pylint --rcfile ../scripts/pylint.rc rpki/[a-z]*.py *d.py rpki-*.py myrpki.py irbe_cli.py tests/*.py
# Documentation
diff --git a/rpkid/irdbd.sql b/rpkid/irdbd.sql
index 577bb4f9..fd461b42 100644
--- a/rpkid/irdbd.sql
+++ b/rpkid/irdbd.sql
@@ -1,6 +1,6 @@
-- $Id$
--- Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+-- Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
--
-- Permission to use, copy, modify, and distribute this software for any
-- purpose with or without fee is hereby granted, provided that the above
@@ -41,6 +41,7 @@ DROP TABLE IF EXISTS roa_request;
DROP TABLE IF EXISTS registrant_net;
DROP TABLE IF EXISTS registrant_asn;
DROP TABLE IF EXISTS registrant;
+DROP TABLE IF EXISTS gbr_request;
CREATE TABLE registrant (
registrant_id SERIAL NOT NULL,
@@ -91,6 +92,14 @@ CREATE TABLE roa_request_prefix (
FOREIGN KEY (roa_request_id) REFERENCES roa_request (roa_request_id) ON DELETE CASCADE
) ENGINE=InnoDB;
+CREATE TABLE gbr_request (
+ gbr_request_id SERIAL NOT NULL,
+ self_handle VARCHAR(40) NOT NULL,
+ parent_handle VARCHAR(40),
+ vcard LONGBLOB NOT NULL,
+ PRIMARY KEY (gbr_request_id)
+) ENGINE=InnoDB;
+
-- Local Variables:
-- indent-tabs-mode: nil
-- End:
diff --git a/rpkid/left-right-schema.rnc b/rpkid/left-right-schema.rnc
index 28f26cae..85f2348a 100644
--- a/rpkid/left-right-schema.rnc
+++ b/rpkid/left-right-schema.rnc
@@ -5,7 +5,7 @@
# libxml2 (including xmllint) only groks the XML syntax of RelaxNG, so
# run the compact syntax through trang to get XML syntax.
#
-# Copyright (C) 2009-2010 Internet Systems Consortium ("ISC")
+# Copyright (C) 2009-2011 Internet Systems Consortium ("ISC")
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -50,6 +50,7 @@ query_elt |= parent_query
query_elt |= child_query
query_elt |= repository_query
query_elt |= list_roa_requests_query
+query_elt |= list_gbr_requests_query
query_elt |= list_resources_query
query_elt |= list_published_objects_query
query_elt |= list_received_resources_query
@@ -62,6 +63,7 @@ reply_elt |= child_reply
reply_elt |= repository_reply
reply_elt |= list_resources_reply
reply_elt |= list_roa_requests_reply
+reply_elt |= list_gbr_requests_reply
reply_elt |= list_published_objects_reply
reply_elt |= list_received_resources_reply
reply_elt |= report_error_reply
@@ -250,6 +252,17 @@ list_roa_requests_reply = element list_roa_requests {
attribute ipv6 { ipv6_list }?
}
+# <list_gbr_requests/> element
+
+list_gbr_requests_query = element list_gbr_requests {
+ tag, self_handle, parent_handle
+}
+
+list_gbr_requests_reply = element list_gbr_requests {
+ tag, self_handle, parent_handle,
+ xsd:string
+}
+
# <list_published_objects/> element
list_published_objects_query = element list_published_objects {
diff --git a/rpkid/left-right-schema.rng b/rpkid/left-right-schema.rng
index 3f223b45..a3e74de6 100644
--- a/rpkid/left-right-schema.rng
+++ b/rpkid/left-right-schema.rng
@@ -7,7 +7,7 @@
libxml2 (including xmllint) only groks the XML syntax of RelaxNG, so
run the compact syntax through trang to get XML syntax.
- Copyright (C) 2009-2010 Internet Systems Consortium ("ISC")
+ Copyright (C) 2009-2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -84,6 +84,9 @@
<ref name="list_roa_requests_query"/>
</define>
<define name="query_elt" combine="choice">
+ <ref name="list_gbr_requests_query"/>
+ </define>
+ <define name="query_elt" combine="choice">
<ref name="list_resources_query"/>
</define>
<define name="query_elt" combine="choice">
@@ -115,6 +118,9 @@
<ref name="list_roa_requests_reply"/>
</define>
<define name="reply_elt" combine="choice">
+ <ref name="list_gbr_requests_reply"/>
+ </define>
+ <define name="reply_elt" combine="choice">
<ref name="list_published_objects_reply"/>
</define>
<define name="reply_elt" combine="choice">
@@ -883,6 +889,22 @@
</optional>
</element>
</define>
+ <!-- <list_gbr_requests/> element -->
+ <define name="list_gbr_requests_query">
+ <element name="list_gbr_requests">
+ <ref name="tag"/>
+ <ref name="self_handle"/>
+ <ref name="parent_handle"/>
+ </element>
+ </define>
+ <define name="list_gbr_requests_reply">
+ <element name="list_gbr_requests">
+ <ref name="tag"/>
+ <ref name="self_handle"/>
+ <ref name="parent_handle"/>
+ <data type="string"/>
+ </element>
+ </define>
<!-- <list_published_objects/> element -->
<define name="list_published_objects_query">
<element name="list_published_objects">
diff --git a/rpkid/rpki-sql-setup.py b/rpkid/rpki-sql-setup.py
index 360b76a9..dc463620 100644
--- a/rpkid/rpki-sql-setup.py
+++ b/rpkid/rpki-sql-setup.py
@@ -4,7 +4,7 @@ root password, pulls other information from rpki.conf.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -21,7 +21,7 @@ PERFORMANCE OF THIS SOFTWARE.
from __future__ import with_statement
-import os, getopt, sys, time, rpki.config, getpass, warnings
+import os, getopt, sys, rpki.config, getpass, warnings
# Silence warning while loading MySQLdb in Python 2.6, sigh
if hasattr(warnings, "catch_warnings"):
diff --git a/rpkid/rpki/http.py b/rpkid/rpki/http.py
index 042542b2..90b8c758 100644
--- a/rpkid/rpki/http.py
+++ b/rpkid/rpki/http.py
@@ -3,7 +3,7 @@ HTTP utilities, both client and server.
$Id$
-Copyright (C) 2009-2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009-2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -198,6 +198,7 @@ class http_message(object):
raise rpki.exceptions.HTTPBadVersion, "Couldn't parse version %s" % version
self.version = tuple(int(i) for i in version[5:].split("."))
+ @property
def persistent(self):
"""
Figure out whether this HTTP message encourages a persistent connection.
@@ -492,7 +493,7 @@ class http_server(http_stream):
pass the message body, path, and a reply callback to the handler.
"""
self.log("Received request %s %s" % (self.msg.cmd, self.msg.path))
- if not self.msg.persistent():
+ if not self.msg.persistent:
self.expect_close = True
handler = self.find_handler(self.msg.path)
error = None
@@ -717,7 +718,7 @@ class http_client(http_stream):
self.log("Message received, state %s" % self.state)
- if not self.msg.persistent():
+ if not self.msg.persistent:
self.expect_close = True
if self.state != "request-sent":
diff --git a/rpkid/rpki/irdbd.py b/rpkid/rpki/irdbd.py
index b5edf70e..bb05fee3 100644
--- a/rpkid/rpki/irdbd.py
+++ b/rpkid/rpki/irdbd.py
@@ -5,7 +5,7 @@ Usage: python irdbd.py [ { -c | --config } configfile ] [ { -h | --help } ]
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -50,6 +50,7 @@ else:
class main(object):
+
def handle_list_resources(self, q_pdu, r_msg):
r_pdu = rpki.left_right.list_resources_elt()
@@ -87,6 +88,7 @@ class main(object):
r_msg.append(r_pdu)
+
def handle_list_roa_requests(self, q_pdu, r_msg):
self.cur.execute(
@@ -112,10 +114,37 @@ class main(object):
r_msg.append(r_pdu)
+
+ def handle_list_gbr_requests(self, q_pdu, r_msg):
+
+ self.cur.execute(
+ "SELECT vcard FROM gbr_request self_handle = %s and parent_handle = %s",
+ (q_pdu.self_handle, q_pdu.parent_handle))
+
+ vcards = [result[0] for result in self.cur.fetchall()]
+
+ if not vcards:
+
+ self.cur.execute(
+ "SELECT vcard FROM gbr_request self_handle = %s and parent_handle IS NULL",
+ (q_pdu.self_handle,))
+
+ vcards = [result[0] for result in self.cur.fetchall()]
+
+ for vcard in vcards:
+ r_pdu = rpki.left_right.list_gbr_requests_elt()
+ r_pdu.tag = q_pdu.tag
+ r_pdu.self_handle = q_pdu.self_handle
+ r_pdu.parent_handle = q_pdu.parent_handle
+ r_pdu.vcard = vcard
+ r_msg.append(r_pdu)
+
+
handle_dispatch = {
rpki.left_right.list_resources_elt : handle_list_resources,
rpki.left_right.list_roa_requests_elt : handle_list_roa_requests }
+
def handler(self, query, path, cb):
try:
@@ -168,6 +197,7 @@ class main(object):
cb(500, "Unhandled exception %s: %s" % (data.__class__.__name__, data))
+
def __init__(self):
os.environ["TZ"] = "UTC"
diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py
index d74c1ef7..80583d47 100644
--- a/rpkid/rpki/left_right.py
+++ b/rpkid/rpki/left_right.py
@@ -3,7 +3,7 @@ RPKI "left-right" protocol.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -57,12 +57,14 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
self_id = None
self_handle = None
+ @property
def self(self):
"""
Fetch self object to which this object links.
"""
return self_elt.sql_fetch(self.gctx, self.self_id)
+ @property
def bsc(self):
"""
Return BSC object to which this object links.
@@ -146,30 +148,35 @@ class self_elt(data_elt):
bpki_cert = None
bpki_glue = None
+ @property
def bscs(self):
"""
Fetch all BSC objects that link to this self object.
"""
return bsc_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
+ @property
def repositories(self):
"""
Fetch all repository objects that link to this self object.
"""
return repository_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
+ @property
def parents(self):
"""
Fetch all parent objects that link to this self object.
"""
return parent_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
+ @property
def children(self):
"""
Fetch all child objects that link to this self object.
"""
return child_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
+ @property
def roas(self):
"""
Fetch all ROA objects that link to this self object.
@@ -205,7 +212,7 @@ class self_elt(data_elt):
rpki.log.trace()
def loop(iterator, parent):
parent.serve_rekey(iterator, eb)
- rpki.async.iterator(self.parents(), loop, cb)
+ rpki.async.iterator(self.parents, loop, cb)
def serve_revoke(self, cb, eb):
"""
@@ -214,7 +221,7 @@ class self_elt(data_elt):
rpki.log.trace()
def loop(iterator, parent):
parent.serve_revoke(iterator, eb)
- rpki.async.iterator(self.parents(), loop, cb)
+ rpki.async.iterator(self.parents, loop, cb)
def serve_reissue(self, cb, eb):
"""
@@ -223,7 +230,7 @@ class self_elt(data_elt):
rpki.log.trace()
def loop(iterator, parent):
parent.serve_reissue(iterator, eb)
- rpki.async.iterator(self.parents(), loop, cb)
+ rpki.async.iterator(self.parents, loop, cb)
def serve_revoke_forgotten(self, cb, eb):
"""
@@ -232,7 +239,7 @@ class self_elt(data_elt):
rpki.log.trace()
def loop(iterator, parent):
parent.serve_revoke_forgotten(iterator, eb)
- rpki.async.iterator(self.parents(), loop, cb)
+ rpki.async.iterator(self.parents, loop, cb)
def serve_publish_world_now(self, cb, eb):
"""
@@ -255,16 +262,16 @@ class self_elt(data_elt):
def loop(iterator, parent):
q_msg = rpki.publication.msg.query()
- for ca in parent.cas():
+ for ca in parent.cas:
ca_detail = ca.fetch_active()
if ca_detail is not None:
- q_msg.append(rpki.publication.crl_elt.make_publish(ca_detail.crl_uri(ca), ca_detail.latest_crl))
- q_msg.append(rpki.publication.manifest_elt.make_publish(ca_detail.manifest_uri(ca), ca_detail.latest_manifest))
- q_msg.extend(rpki.publication.certificate_elt.make_publish(c.uri(ca), c.cert) for c in ca_detail.child_certs())
- q_msg.extend(rpki.publication.roa_elt.make_publish(r.uri(), r.roa) for r in ca_detail.roas() if r.roa is not None)
- parent.repository().call_pubd(iterator, eb, q_msg)
+ q_msg.append(rpki.publication.crl_elt.make_publish(ca_detail.crl_uri, ca_detail.latest_crl))
+ q_msg.append(rpki.publication.manifest_elt.make_publish(ca_detail.manifest_uri, ca_detail.latest_manifest))
+ q_msg.extend(rpki.publication.certificate_elt.make_publish(c.uri, c.cert) for c in ca_detail.child_certs)
+ q_msg.extend(rpki.publication.roa_elt.make_publish(r.uri, r.roa) for r in ca_detail.roas if r.roa is not None)
+ parent.repository.call_pubd(iterator, eb, q_msg)
- rpki.async.iterator(self.parents(), loop, cb)
+ rpki.async.iterator(self.parents, loop, cb)
def serve_run_now(self, cb, eb):
"""
@@ -334,7 +341,7 @@ class self_elt(data_elt):
def parent_loop(parent_iterator, parent):
def got_list(r_msg):
- ca_map = dict((ca.parent_resource_class, ca) for ca in parent.cas())
+ ca_map = dict((ca.parent_resource_class, ca) for ca in parent.cas)
self.gctx.checkpoint()
def class_loop(class_iterator, rc):
@@ -379,7 +386,7 @@ class self_elt(data_elt):
rpki.up_down.list_pdu.query(parent, got_list, list_failed)
- rpki.async.iterator(self.parents(), parent_loop, callback)
+ rpki.async.iterator(self.parents, parent_loop, callback)
def update_children(self, cb):
@@ -404,8 +411,8 @@ class self_elt(data_elt):
def got_resources(irdb_resources):
try:
for child_cert in child_certs:
- ca_detail = child_cert.ca_detail()
- ca = ca_detail.ca()
+ ca_detail = child_cert.ca_detail
+ ca = ca_detail.ca
if ca_detail.state == "active":
old_resources = child_cert.cert.get_3779resources()
new_resources = irdb_resources.intersection(old_resources).intersection(ca_detail.latest_ca_cert.get_3779resources())
@@ -427,7 +434,7 @@ class self_elt(data_elt):
rpki.log.debug("Child certificate SKI %s has expired: cert.valid_until %s, irdb.valid_until %s"
% (child_cert.cert.gSKI(), old_resources.valid_until, irdb_resources.valid_until))
child_cert.sql_delete()
- publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri(ca), obj = child_cert.cert, repository = ca.parent().repository())
+ publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri, obj = child_cert.cert, repository = ca.parent.repository)
ca_detail.generate_manifest(publisher = publisher)
except (SystemExit, rpki.async.ExitNow):
@@ -440,9 +447,9 @@ class self_elt(data_elt):
iterator()
self.gctx.checkpoint()
- child_certs = child.child_certs()
+ child_certs = child.child_certs
if child_certs:
- self.gctx.irdb_query_child_resources(child.self().self_handle, child.child_handle, got_resources, lose)
+ self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, got_resources, lose)
else:
iterator()
@@ -455,7 +462,7 @@ class self_elt(data_elt):
self.gctx.checkpoint()
publisher.call_pubd(cb, lose)
- rpki.async.iterator(self.children(), loop, done)
+ rpki.async.iterator(self.children, loop, done)
def regenerate_crls_and_manifests(self, cb):
@@ -475,14 +482,14 @@ class self_elt(data_elt):
regen_margin = rpki.sundial.timedelta(seconds = self.regen_margin)
publisher = rpki.rpki_engine.publication_queue()
- for parent in self.parents():
- for ca in parent.cas():
+ for parent in self.parents:
+ for ca in parent.cas:
try:
for ca_detail in ca.fetch_revoked():
if now > ca_detail.latest_crl.getNextUpdate():
ca_detail.delete(ca = ca, publisher = publisher)
ca_detail = ca.fetch_active()
- if ca_detail is not None and now + regen_margin> ca_detail.latest_crl.getNextUpdate():
+ if ca_detail is not None and now + regen_margin > ca_detail.latest_crl.getNextUpdate():
ca_detail.generate_crl(publisher = publisher)
ca_detail.generate_manifest(publisher = publisher)
except (SystemExit, rpki.async.ExitNow):
@@ -501,6 +508,90 @@ class self_elt(data_elt):
publisher.call_pubd(cb, lose)
+ def update_ghostbusters(self, cb):
+ """
+ Generate or update Ghostbusters records for this self.
+
+ This is heavily based on .update_roas(), and probably both of them
+ need refactoring.
+ """
+
+ raise rpki.exceptions.NotImplementedYet
+
+ parents = dict((p.parent_handle, p) for p in self.parents)
+
+ def got_gbr_requests(gbr_requests):
+
+ self.gctx.checkpoint()
+
+ if self.gctx.sql.dirty:
+ rpki.log.warn("Unexpected dirty SQL cache, flushing")
+ self.gctx.sql.sweep()
+
+ ghostbusters = {}
+ orphans = []
+ for ghostbuster in self.ghostbusters:
+ k = (ghostbuster.ca_detail.ca.parent.parent_handle, ghostbuster.vcard)
+ if k not in ghostbusters:
+ ghostbusters[k] = ghostbuster
+ elif ghostbuster.ca_detail.state == "active" and ghostbusters[k].ca_detail.state != "active":
+ orphans.append(ghostbusters[k])
+ ghostbusters[k] = ghostbuster
+ else:
+ orphans.append(ghostbusters[k])
+
+ publisher = rpki.rpki_engine.publication_queue()
+ ca_details = set()
+
+ seen = set()
+ for gbr_request in gbr_requests:
+ if gbr_request.parent_handle not in parents:
+ rpki.log.warn("Unknown parent_handle %r in Ghostbuster request, skipping" % gbr_request.parent_handle)
+ continue
+ k = (gbr_request.parent_handle, gbr_request.vcard)
+ if k in seen:
+ rpki.log.warn("Skipping duplicate Ghostbuster request %r" % gbr_request)
+ continue
+ see.add(k)
+ ghostbuster = ghostbusters.pop(k, None)
+ if ghostbuster is None:
+ ghostbuster = rpki.rpki_engine.ghostbuster_obj(self.gctx, self.self_id, parents[gbr_request.parent_handle], vcard)
+ rpki.log.debug("Created new Ghostbuster request for %r" % gbr_request.parent_handle)
+ else:
+ rpki.log.debug("Found existing Ghostbuster request for %r" % gbr_request.parent_handle)
+ ghostbuster.update(publisher = publisher, fast = True)
+ ca_details.add(ghostbuster.ca_detail)
+
+ orphans.extend(ghostbusters.itervalues())
+ for ghostbuster in orphans:
+ ca_details.add(ghostbuster.ca_detail)
+ ghostbuster.revoke(publisher = publisher, fast = True)
+
+ for ca_detail in ca_details:
+ ca_detail.generate_crl(publisher = publisher)
+ ca_detail.generate_manifest(publisher = publisher)
+
+ self.gctx.sql.sweep()
+
+ def publication_failed(e):
+ rpki.log.traceback()
+ rpki.log.warn("Couldn't publish Ghostbuster updates for %s, skipping: %s" % (self.self_handle, e))
+ self.gctx.checkpoint()
+ cb()
+
+ self.gctx.checkpoint()
+ publisher.call_pubd(cb, publication_failed)
+
+ def gbr_requests_failed(e):
+ rpki.log.traceback()
+ rpki.log.warn("Could not fetch Ghostbusters record requests for %s, skipping: %s" % (self.self_handle, e))
+ cb()
+
+ self.gctx.checkpoint()
+ self.gctx.irdb_query_gbr_requests(self.self_handle, parents.iterkeys(),
+ got_gbr_requests, gbr_requests_failed)
+
+
def update_roas(self, cb):
"""
Generate or update ROAs for this self.
@@ -516,12 +607,12 @@ class self_elt(data_elt):
roas = {}
orphans = []
- for roa in self.roas():
+ for roa in self.roas:
k = (roa.asn, str(roa.ipv4), str(roa.ipv6))
if k not in roas:
roas[k] = roa
- elif (roa.roa is not None and roa.cert is not None and roa.ca_detail() is not None and roa.ca_detail().state == "active" and
- (roas[k].roa is None or roas[k].cert is None or roas[k].ca_detail() is None or roas[k].ca_detail().state != "active")):
+ elif (roa.roa is not None and roa.cert is not None and roa.ca_detail is not None and roa.ca_detail.state == "active" and
+ (roas[k].roa is None or roas[k].cert is None or roas[k].ca_detail is None or roas[k].ca_detail.state != "active")):
orphans.append(roas[k])
roas[k] = roa
else:
@@ -545,7 +636,7 @@ class self_elt(data_elt):
else:
rpki.log.debug("Found existing ROA %r matching %r" % (roa, k))
roa.update(publisher = publisher, fast = True)
- ca_details.add(roa.ca_detail())
+ ca_details.add(roa.ca_detail)
except (SystemExit, rpki.async.ExitNow):
raise
except Exception, e:
@@ -556,7 +647,7 @@ class self_elt(data_elt):
orphans.extend(roas.itervalues())
for roa in orphans:
try:
- ca_details.add(roa.ca_detail())
+ ca_details.add(roa.ca_detail)
roa.revoke(publisher = publisher, fast = True)
except (SystemExit, rpki.async.ExitNow):
raise
@@ -610,18 +701,21 @@ class bsc_elt(data_elt):
signing_cert = None
signing_cert_crl = None
+ @property
def repositories(self):
"""
Fetch all repository objects that link to this BSC object.
"""
return repository_elt.sql_fetch_where(self.gctx, "bsc_id = %s", (self.bsc_id,))
+ @property
def parents(self):
"""
Fetch all parent objects that link to this BSC object.
"""
return parent_elt.sql_fetch_where(self.gctx, "bsc_id = %s", (self.bsc_id,))
+ @property
def children(self):
"""
Fetch all child objects that link to this BSC object.
@@ -660,6 +754,7 @@ class repository_elt(data_elt):
bpki_cert = None
bpki_glue = None
+ @property
def parents(self):
"""
Fetch all parent objects that link to this repository object.
@@ -701,9 +796,9 @@ class repository_elt(data_elt):
for q_pdu in q_msg:
rpki.log.info("Sending <%s %r %r> to pubd" % (q_pdu.action, q_pdu.uri, q_pdu.payload))
- bsc = self.bsc()
+ bsc = self.bsc
q_der = rpki.publication.cms_msg().wrap(q_msg, bsc.private_key_id, bsc.signing_cert, bsc.signing_cert_crl)
- bpki_ta_path = (self.gctx.bpki_ta, self.self().bpki_cert, self.self().bpki_glue, self.bpki_cert, self.bpki_glue)
+ bpki_ta_path = (self.gctx.bpki_ta, self.self.bpki_cert, self.self.bpki_glue, self.bpki_cert, self.bpki_glue)
def done(r_der):
try:
@@ -755,12 +850,14 @@ class parent_elt(data_elt):
bpki_cms_cert = None
bpki_cms_glue = None
+ @property
def repository(self):
"""
Fetch repository object to which this parent object links.
"""
return repository_elt.sql_fetch(self.gctx, self.repository_id)
+ @property
def cas(self):
"""
Fetch all CA objects that link to this parent object.
@@ -790,7 +887,7 @@ class parent_elt(data_elt):
"""
def loop(iterator, ca):
ca.rekey(iterator, eb)
- rpki.async.iterator(self.cas(), loop, cb)
+ rpki.async.iterator(self.cas, loop, cb)
def serve_revoke(self, cb, eb):
"""
@@ -798,7 +895,7 @@ class parent_elt(data_elt):
"""
def loop(iterator, ca):
ca.revoke(cb = iterator, eb = eb)
- rpki.async.iterator(self.cas(), loop, cb)
+ rpki.async.iterator(self.cas, loop, cb)
def serve_reissue(self, cb, eb):
"""
@@ -806,7 +903,7 @@ class parent_elt(data_elt):
"""
def loop(iterator, ca):
ca.reissue(cb = iterator, eb = eb)
- rpki.async.iterator(self.cas(), loop, cb)
+ rpki.async.iterator(self.cas, loop, cb)
def serve_revoke_forgotten(self, cb, eb):
"""
@@ -824,7 +921,7 @@ class parent_elt(data_elt):
def got_list(r_msg):
- ca_map = dict((ca.parent_resource_class, ca) for ca in self.cas())
+ ca_map = dict((ca.parent_resource_class, ca) for ca in self.cas)
def rc_loop(rc_iterator, rc):
@@ -855,7 +952,7 @@ class parent_elt(data_elt):
rpki.log.trace()
- bsc = self.bsc()
+ bsc = self.bsc
if bsc is None:
raise rpki.exceptions.BSCNotFound, "Could not find BSC %s" % self.bsc_id
@@ -874,8 +971,8 @@ class parent_elt(data_elt):
def unwrap(r_der):
try:
r_msg = rpki.up_down.cms_msg(DER = r_der).unwrap((self.gctx.bpki_ta,
- self.self().bpki_cert,
- self.self().bpki_glue,
+ self.self.bpki_cert,
+ self.self.bpki_glue,
self.bpki_cms_cert,
self.bpki_cms_glue))
r_msg.payload.check_response()
@@ -913,12 +1010,20 @@ class child_elt(data_elt):
bpki_cert = None
bpki_glue = None
- def child_certs(self, ca_detail = None, ski = None, unique = False):
+ def fetch_child_certs(self, ca_detail = None, ski = None, unique = False):
"""
Fetch all child_cert objects that link to this child object.
"""
return rpki.rpki_engine.child_cert_obj.fetch(self.gctx, self, ca_detail, ski, unique)
+ @property
+ def child_certs(self):
+ """
+ Fetch all child_cert objects that link to this child object.
+ """
+ return self.fetch_child_certs()
+
+ @property
def parents(self):
"""
Fetch all parent objects that link to self object to which this child object links.
@@ -939,8 +1044,8 @@ class child_elt(data_elt):
Handle a left-right reissue action for this child.
"""
publisher = rpki.rpki_engine.publication_queue()
- for child_cert in self.child_certs():
- child_cert.reissue(child_cert.ca_detail(), publisher, force = True)
+ for child_cert in self.child_certs:
+ child_cert.reissue(child_cert.ca_detail, publisher, force = True)
publisher.call_pubd(cb, eb)
def ca_from_class_name(self, class_name):
@@ -952,7 +1057,7 @@ class child_elt(data_elt):
ca = rpki.rpki_engine.ca_obj.sql_fetch(self.gctx, long(class_name))
if ca is None:
raise rpki.exceptions.ClassNameUnknown, "Unknown class name %s" % class_name
- parent = ca.parent()
+ parent = ca.parent
if self.self_id != parent.self_id:
raise rpki.exceptions.ClassNameMismatch, "Class name mismatch: child.self_id = %d, parent.self_id = %d" % (self.self_id, parent.self_id)
return ca
@@ -962,7 +1067,7 @@ class child_elt(data_elt):
Extra server actions when destroying a child_elt.
"""
publisher = rpki.rpki_engine.publication_queue()
- for child_cert in self.child_certs():
+ for child_cert in self.child_certs:
child_cert.revoke(publisher = publisher,
generate_crl_and_manifest = True)
publisher.call_pubd(cb, eb)
@@ -974,12 +1079,12 @@ class child_elt(data_elt):
rpki.log.trace()
- bsc = self.bsc()
+ bsc = self.bsc
if bsc is None:
raise rpki.exceptions.BSCNotFound, "Could not find BSC %s" % self.bsc_id
q_msg = rpki.up_down.cms_msg(DER = query).unwrap((self.gctx.bpki_ta,
- self.self().bpki_cert,
- self.self().bpki_glue,
+ self.self.bpki_cert,
+ self.self.bpki_glue,
self.bpki_cert,
self.bpki_glue))
q_msg.payload.gctx = self.gctx
@@ -1061,6 +1166,18 @@ class list_roa_requests_elt(rpki.xml_utils.base_elt, left_right_namespace):
if self.ipv6 is not None:
self.ipv6 = rpki.resource_set.roa_prefix_set_ipv6(self.ipv6)
+class list_gbr_requests_elt(rpki.xml_utils.text_elt, left_right_namespace):
+ """
+ <list_gbr_requests/> element.
+ """
+
+ element_name = "list_gbr_requests"
+ attributes = ("self_handle", "tag", "parent_handle")
+ text_attribute = "vcard"
+
+ vcard = None
+
+
class list_published_objects_elt(rpki.xml_utils.text_elt, left_right_namespace):
"""
<list_published_objects/> element.
@@ -1078,14 +1195,14 @@ class list_published_objects_elt(rpki.xml_utils.text_elt, left_right_namespace):
misnomer here, there's no action attribute and no dispatch, we
just dump every published object for the specified <self/> and return.
"""
- for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents():
- for ca in parent.cas():
+ for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents:
+ for ca in parent.cas:
ca_detail = ca.fetch_active()
if ca_detail is not None:
- r_msg.append(self.make_reply(ca_detail.crl_uri(ca), ca_detail.latest_crl))
- r_msg.append(self.make_reply(ca_detail.manifest_uri(ca), ca_detail.latest_manifest))
- r_msg.extend(self.make_reply(c.uri(ca), c.cert) for c in ca_detail.child_certs())
- r_msg.extend(self.make_reply(r.uri(), r.roa) for r in ca_detail.roas() if r.roa is not None)
+ r_msg.append(self.make_reply(ca_detail.crl_uri, ca_detail.latest_crl))
+ r_msg.append(self.make_reply(ca_detail.manifest_uri, ca_detail.latest_manifest))
+ r_msg.extend(self.make_reply(c.uri, c.cert) for c in ca_detail.child_certs)
+ r_msg.extend(self.make_reply(r.uri, r.roa) for r in ca_detail.roas if r.roa is not None)
cb()
def make_reply(self, uri, obj):
@@ -1112,8 +1229,8 @@ class list_received_resources_elt(rpki.xml_utils.base_elt, left_right_namespace)
just dump a bunch of data about every certificate issued to us by
one of our parents, then return.
"""
- for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents():
- for ca in parent.cas():
+ for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents:
+ for ca in parent.cas:
ca_detail = ca.fetch_active()
if ca_detail is not None and ca_detail.latest_ca_cert is not None:
r_msg.append(self.make_reply(parent.parent_handle, ca_detail.ca_cert_uri, ca_detail.latest_ca_cert))
@@ -1172,10 +1289,11 @@ class msg(rpki.xml_utils.msg, left_right_namespace):
## @var pdus
# Dispatch table of PDUs for this protocol.
pdus = dict((x.element_name, x)
- for x in (self_elt, child_elt, parent_elt, bsc_elt, repository_elt,
- list_resources_elt, list_roa_requests_elt,
- list_published_objects_elt, list_received_resources_elt,
- report_error_elt))
+ for x in (self_elt, child_elt, parent_elt, bsc_elt,
+ repository_elt, list_resources_elt,
+ list_roa_requests_elt, list_gbr_requests_elt,
+ list_published_objects_elt,
+ list_received_resources_elt, report_error_elt))
def serve_top_level(self, gctx, cb):
"""
diff --git a/rpkid/rpki/oids.py b/rpkid/rpki/oids.py
index 90e486b7..2b1ffdd9 100644
--- a/rpkid/rpki/oids.py
+++ b/rpkid/rpki/oids.py
@@ -3,7 +3,22 @@ OID database.
$Id$
-Copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -31,6 +46,7 @@ oid2name = {
(1, 2, 840, 113549, 1, 9, 16, 1, 24) : "id-ct-routeOriginAttestation",
(1, 2, 840, 113549, 1, 9, 16, 1, 26) : "id-ct-rpkiManifest",
(1, 2, 840, 113549, 1, 9, 16, 1, 28) : "id-ct-xml",
+ (1, 2, 840, 113549, 1, 9, 16, 1, 35) : "id-ct-rpkiGhostbusters",
(1, 3, 6, 1, 5, 5, 7, 1, 1) : "authorityInfoAccess",
(1, 3, 6, 1, 5, 5, 7, 1, 11) : "subjectInfoAccess",
(1, 3, 6, 1, 5, 5, 7, 1, 7) : "sbgp-ipAddrBlock",
diff --git a/rpkid/rpki/publication.py b/rpkid/rpki/publication.py
index 1f5ed812..4c6df14b 100644
--- a/rpkid/rpki/publication.py
+++ b/rpkid/rpki/publication.py
@@ -3,7 +3,7 @@ RPKI "publication" protocol.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -32,7 +32,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-import base64, os, errno
+import os, errno
import rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.xml_utils
import rpki.http, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log, rpki.roa
diff --git a/rpkid/rpki/relaxng.py b/rpkid/rpki/relaxng.py
index d42b213a..3e6de5f6 100644
--- a/rpkid/rpki/relaxng.py
+++ b/rpkid/rpki/relaxng.py
@@ -13,7 +13,7 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc
libxml2 (including xmllint) only groks the XML syntax of RelaxNG, so
run the compact syntax through trang to get XML syntax.
- Copyright (C) 2009-2010 Internet Systems Consortium ("ISC")
+ Copyright (C) 2009-2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -90,6 +90,9 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc
<ref name="list_roa_requests_query"/>
</define>
<define name="query_elt" combine="choice">
+ <ref name="list_gbr_requests_query"/>
+ </define>
+ <define name="query_elt" combine="choice">
<ref name="list_resources_query"/>
</define>
<define name="query_elt" combine="choice">
@@ -121,6 +124,9 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc
<ref name="list_roa_requests_reply"/>
</define>
<define name="reply_elt" combine="choice">
+ <ref name="list_gbr_requests_reply"/>
+ </define>
+ <define name="reply_elt" combine="choice">
<ref name="list_published_objects_reply"/>
</define>
<define name="reply_elt" combine="choice">
@@ -889,6 +895,22 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc
</optional>
</element>
</define>
+ <!-- <list_gbr_requests/> element -->
+ <define name="list_gbr_requests_query">
+ <element name="list_gbr_requests">
+ <ref name="tag"/>
+ <ref name="self_handle"/>
+ <ref name="parent_handle"/>
+ </element>
+ </define>
+ <define name="list_gbr_requests_reply">
+ <element name="list_gbr_requests">
+ <ref name="tag"/>
+ <ref name="self_handle"/>
+ <ref name="parent_handle"/>
+ <data type="string"/>
+ </element>
+ </define>
<!-- <list_published_objects/> element -->
<define name="list_published_objects_query">
<element name="list_published_objects">
diff --git a/rpkid/rpki/rpki_engine.py b/rpkid/rpki/rpki_engine.py
index d7ff9c5e..4a70ca0e 100644
--- a/rpkid/rpki/rpki_engine.py
+++ b/rpkid/rpki/rpki_engine.py
@@ -3,7 +3,7 @@ Global context for rpkid.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -83,25 +83,30 @@ class rpkid_context(object):
else:
rpki.log.debug("Not using internal clock, start_cron() call ignored")
- def irdb_query(self, q_pdu, callback, errback, expected_pdu_count = None):
+ def irdb_query(self, callback, errback, *q_pdus, **kwargs):
"""
Perform an IRDB callback query.
"""
rpki.log.trace()
+ q_types = tuple(type(q_pdu) for q_pdu in q_pdus)
+
+ expected_pdu_count = kwargs.pop("expected_pdu_count", None)
+ assert len(kwargs) == 0
+
q_msg = rpki.left_right.msg.query()
- q_msg.append(q_pdu)
+ q_msg.extend(q_pdus)
q_der = rpki.left_right.cms_msg().wrap(q_msg, self.rpkid_key, self.rpkid_cert)
def unwrap(r_der):
r_cms = rpki.left_right.cms_msg(DER = r_der)
r_msg = r_cms.unwrap((self.bpki_ta, self.irdb_cert))
- if not r_msg.is_reply() or not all(type(r_pdu) is type(q_pdu) for r_pdu in r_msg):
+ if not r_msg.is_reply() or not all(type(r_pdu) in q_types for r_pdu in r_msg):
raise rpki.exceptions.BadIRDBReply, "Unexpected response to IRDB query: %s" % r_cms.pretty_print_content()
if expected_pdu_count is not None and len(r_msg) != expected_pdu_count:
assert isinstance(expected_pdu_count, (int, long))
- raise rpki.exceptions.BadIRDBReply, "Expected exactly %d PDU%s from IRDB: %s" (
+ raise rpki.exceptions.BadIRDBReply, "Expected exactly %d PDU%s from IRDB: %s" % (
expected_pdu_count, "" if expected_pdu_count == 1 else "s", r_cms.pretty_print_content())
callback(r_msg)
@@ -129,7 +134,7 @@ class rpkid_context(object):
v6 = r_msg[0].ipv6,
valid_until = r_msg[0].valid_until))
- self.irdb_query(q_pdu, done, errback, expected_pdu_count = 1)
+ self.irdb_query(done, errback, q_pdu, expected_pdu_count = 1)
def irdb_query_roa_requests(self, self_handle, callback, errback):
"""
@@ -141,7 +146,24 @@ class rpkid_context(object):
q_pdu = rpki.left_right.list_roa_requests_elt()
q_pdu.self_handle = self_handle
- self.irdb_query(q_pdu, callback, errback)
+ self.irdb_query(callback, errback, q_pdu)
+
+ def irdb_query_gbr_requests(self, self_handle, parent_handles, callback, errback):
+ """
+ Ask IRDB about self's ghostbuster record requests.
+ """
+
+ rpki.log.trace()
+
+ q_pdus = []
+
+ for parent_handle in parent_handles:
+ q_pdu = rpki.left_right.list_gbr_requests_elt()
+ q_pdu.self_handle = self_handle
+ q_pdu.parent_handle = parent_handle
+ q_pdus.append(q_pdu)
+
+ self.irdb_query(callback, errback, *q_pdus)
def left_right_handler(self, query, path, cb):
"""
@@ -290,12 +312,14 @@ class ca_obj(rpki.sql.sql_persistent):
last_issued_sn = 0
last_manifest_sn = 0
+ @property
def parent(self):
"""
Fetch parent object to which this CA object links.
"""
return rpki.left_right.parent_elt.sql_fetch(self.gctx, self.parent_id)
+ @property
def ca_details(self):
"""
Fetch all ca_detail objects that link to this CA object.
@@ -375,7 +399,7 @@ class ca_obj(rpki.sql.sql_persistent):
rpki.log.warn("Certificate in database missing from list_response, class %r, SKI %s, maybe parent certificate went away?"
% (rc.class_name, ca_detail.public_key.gSKI()))
publisher = publication_queue()
- ca_detail.delete(ca = ca_detail.ca(), publisher = publisher)
+ ca_detail.delete(ca = ca_detail.ca, publisher = publisher)
return publisher.call_pubd(iterator, eb)
else:
@@ -473,7 +497,7 @@ class ca_obj(rpki.sql.sql_persistent):
callback()
publisher = publication_queue()
- for ca_detail in self.ca_details():
+ for ca_detail in self.ca_details:
ca_detail.delete(ca = self, publisher = publisher)
publisher.call_pubd(done, lose)
@@ -511,7 +535,7 @@ class ca_obj(rpki.sql.sql_persistent):
rpki.log.trace()
- parent = self.parent()
+ parent = self.parent
old_detail = self.fetch_active()
new_detail = ca_detail_obj.create(self)
@@ -583,47 +607,60 @@ class ca_detail_obj(rpki.sql.sql_persistent):
assert self.public_key is None or self.private_key_id is None or self.public_key.get_DER() == self.private_key_id.get_public_DER()
assert self.manifest_public_key is None or self.manifest_private_key_id is None or self.manifest_public_key.get_DER() == self.manifest_private_key_id.get_public_DER()
+ @property
def ca(self):
"""
Fetch CA object to which this ca_detail links.
"""
return ca_obj.sql_fetch(self.gctx, self.ca_id)
- def child_certs(self, child = None, ski = None, unique = False):
+ def fetch_child_certs(self, child = None, ski = None, unique = False):
"""
Fetch all child_cert objects that link to this ca_detail.
"""
return rpki.rpki_engine.child_cert_obj.fetch(self.gctx, child, self, ski, unique)
+ @property
+ def child_certs(self):
+ """
+ Fetch all child_cert objects that link to this ca_detail.
+ """
+ return self.fetch_child_certs()
+
+ @property
def revoked_certs(self):
"""
Fetch all revoked_cert objects that link to this ca_detail.
"""
return revoked_cert_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,))
+ @property
def roas(self):
"""
Fetch all ROA objects that link to this ca_detail.
"""
return rpki.rpki_engine.roa_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,))
- def crl_uri(self, ca):
+ @property
+ def crl_uri(self):
"""
Return publication URI for this ca_detail's CRL.
"""
- return ca.sia_uri + self.crl_uri_tail()
+ return self.ca.sia_uri + self.crl_uri_tail
+ @property
def crl_uri_tail(self):
"""
Return tail (filename portion) of publication URI for this ca_detail's CRL.
"""
return self.public_key.gSKI() + ".crl"
- def manifest_uri(self, ca):
+ @property
+ def manifest_uri(self):
"""
Return publication URI for this ca_detail's manifest.
"""
- return ca.sia_uri + self.public_key.gSKI() + ".mnf"
+ return self.ca.sia_uri + self.public_key.gSKI() + ".mnf"
def activate(self, ca, cert, uri, callback, errback, predecessor = None):
"""
@@ -634,7 +671,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
self.latest_ca_cert = cert
self.ca_cert_uri = uri.rsync()
- self.generate_manifest_cert(ca)
+ self.generate_manifest_cert()
self.state = "active"
self.generate_crl(publisher = publisher)
self.generate_manifest(publisher = publisher)
@@ -643,9 +680,9 @@ class ca_detail_obj(rpki.sql.sql_persistent):
if predecessor is not None:
predecessor.state = "deprecated"
predecessor.sql_mark_dirty()
- for child_cert in predecessor.child_certs():
+ for child_cert in predecessor.child_certs:
child_cert.reissue(ca_detail = self, publisher = publisher)
- for roa in predecessor.roas():
+ for roa in predecessor.roas:
roa.regenerate(publisher = publisher)
publisher.call_pubd(callback, errback)
@@ -658,27 +695,27 @@ class ca_detail_obj(rpki.sql.sql_persistent):
raise an exception.
"""
- repository = ca.parent().repository()
- for child_cert in self.child_certs():
- publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri(ca), obj = child_cert.cert, repository = repository,
+ repository = ca.parent.repository
+ for child_cert in self.child_certs:
+ publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri, obj = child_cert.cert, repository = repository,
handler = False if allow_failure else None)
- for roa in self.roas():
+ for roa in self.roas:
roa.revoke(publisher = publisher, allow_failure = allow_failure)
try:
latest_manifest = self.latest_manifest
except AttributeError:
latest_manifest = None
if latest_manifest is not None:
- publisher.withdraw(cls = rpki.publication.manifest_elt, uri = self.manifest_uri(ca), obj = self.latest_manifest, repository = repository,
+ publisher.withdraw(cls = rpki.publication.manifest_elt, uri = self.manifest_uri, obj = self.latest_manifest, repository = repository,
handler = False if allow_failure else None)
try:
latest_crl = self.latest_crl
except AttributeError:
latest_crl = None
if latest_crl is not None:
- publisher.withdraw(cls = rpki.publication.crl_elt, uri = self.crl_uri(ca), obj = self.latest_crl, repository = repository,
+ publisher.withdraw(cls = rpki.publication.crl_elt, uri = self.crl_uri, obj = self.latest_crl, repository = repository,
handler = False if allow_failure else None)
- for cert in self.child_certs() + self.revoked_certs():
+ for cert in self.child_certs + self.revoked_certs:
cert.sql_delete()
self.sql_delete()
@@ -705,15 +742,15 @@ class ca_detail_obj(rpki.sql.sql_persistent):
time has passed.
"""
- ca = self.ca()
- parent = ca.parent()
+ ca = self.ca
+ parent = ca.parent
def parent_revoked(r_msg):
if r_msg.payload.ski != self.latest_ca_cert.gSKI():
raise rpki.exceptions.SKIMismatch
- crl_interval = rpki.sundial.timedelta(seconds = parent.self().crl_interval)
+ crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval)
nextUpdate = rpki.sundial.now()
@@ -729,7 +766,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
publisher = publication_queue()
- for child_cert in self.child_certs():
+ for child_cert in self.child_certs:
nextUpdate = nextUpdate.later(child_cert.cert.getNotAfter())
child_cert.revoke(publisher = publisher)
@@ -758,7 +795,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
publisher = publication_queue()
if sia_uri_changed or old_resources.oversized(new_resources):
- for child_cert in self.child_certs():
+ for child_cert in self.child_certs:
child_resources = child_cert.cert.get_3779resources()
if sia_uri_changed or child_resources.oversized(new_resources):
child_cert.reissue(
@@ -800,19 +837,19 @@ class ca_detail_obj(rpki.sql.sql_persistent):
serial = ca.next_serial_number(),
sia = sia,
aia = self.ca_cert_uri,
- crldp = self.crl_uri(ca),
+ crldp = self.crl_uri,
resources = resources,
notAfter = self.latest_ca_cert.getNotAfter(),
is_ca = False)
- def generate_manifest_cert(self, ca):
+ def generate_manifest_cert(self):
"""
Generate a new manifest certificate for this ca_detail.
"""
resources = rpki.resource_set.resource_bag.from_inheritance()
- self.latest_manifest_cert = self.issue_ee(ca, resources, self.manifest_public_key)
+ self.latest_manifest_cert = self.issue_ee(self.ca, resources, self.manifest_public_key)
def issue(self, ca, child, subject_key, sia, resources, publisher, child_cert = None):
"""
@@ -830,7 +867,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
subject_key = subject_key,
serial = ca.next_serial_number(),
aia = self.ca_cert_uri,
- crldp = self.crl_uri(ca),
+ crldp = self.crl_uri,
sia = sia,
resources = resources,
notAfter = resources.valid_until)
@@ -851,9 +888,9 @@ class ca_detail_obj(rpki.sql.sql_persistent):
child_cert.sql_store()
publisher.publish(
cls = rpki.publication.certificate_elt,
- uri = child_cert.uri(ca),
+ uri = child_cert.uri,
obj = child_cert.cert,
- repository = ca.parent().repository(),
+ repository = ca.parent.repository,
handler = child_cert.published_callback)
self.generate_manifest(publisher = publisher)
return child_cert
@@ -865,16 +902,16 @@ class ca_detail_obj(rpki.sql.sql_persistent):
new CRL is needed.
"""
- ca = self.ca()
- parent = ca.parent()
- crl_interval = rpki.sundial.timedelta(seconds = parent.self().crl_interval)
+ ca = self.ca
+ parent = ca.parent
+ crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval)
now = rpki.sundial.now()
if nextUpdate is None:
nextUpdate = now + crl_interval
certlist = []
- for revoked_cert in self.revoked_certs():
+ for revoked_cert in self.revoked_certs:
if now > revoked_cert.expires + crl_interval:
revoked_cert.sql_delete()
else:
@@ -891,7 +928,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
self.crl_published = rpki.sundial.now()
self.sql_mark_dirty()
- publisher.publish(cls = rpki.publication.crl_elt, uri = self.crl_uri(ca), obj = self.latest_crl, repository = parent.repository(),
+ publisher.publish(cls = rpki.publication.crl_elt, uri = self.crl_uri, obj = self.latest_crl, repository = parent.repository,
handler = self.crl_published_callback)
def crl_published_callback(self, pdu):
@@ -907,20 +944,20 @@ class ca_detail_obj(rpki.sql.sql_persistent):
Generate a new manifest for this ca_detail.
"""
- ca = self.ca()
- parent = ca.parent()
- crl_interval = rpki.sundial.timedelta(seconds = parent.self().crl_interval)
+ ca = self.ca
+ parent = ca.parent
+ crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval)
now = rpki.sundial.now()
if nextUpdate is None:
nextUpdate = now + crl_interval
if self.latest_manifest_cert is None or self.latest_manifest_cert.getNotAfter() < nextUpdate:
- self.generate_manifest_cert(ca)
+ self.generate_manifest_cert()
- objs = [(self.crl_uri_tail(), self.latest_crl)]
- objs.extend((c.uri_tail(), c.cert) for c in self.child_certs())
- objs.extend((r.uri_tail(), r.roa) for r in self.roas() if r.roa is not None)
+ objs = [(self.crl_uri_tail, self.latest_crl)]
+ objs.extend((c.uri_tail, c.cert) for c in self.child_certs)
+ objs.extend((r.uri_tail, r.roa) for r in self.roas if r.roa is not None)
self.latest_manifest = rpki.x509.SignedManifest.build(
serial = ca.next_manifest_number(),
@@ -933,7 +970,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
self.manifest_published = rpki.sundial.now()
self.sql_mark_dirty()
- publisher.publish(cls = rpki.publication.manifest_elt, uri = self.manifest_uri(ca), obj = self.latest_manifest, repository = parent.repository(),
+ publisher.publish(cls = rpki.publication.manifest_elt, uri = self.manifest_uri, obj = self.latest_manifest, repository = parent.repository,
handler = self.manifest_published_callback)
def manifest_published_callback(self, pdu):
@@ -950,9 +987,9 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
publisher = publication_queue()
- for roa in self.roas():
+ for roa in self.roas:
roa.regenerate(publisher, fast = True)
- for child_cert in self.child_certs():
+ for child_cert in self.child_certs:
child_cert.reissue(self, publisher, force = True)
publisher.call_pubd(cb, eb)
@@ -983,40 +1020,44 @@ class child_cert_obj(rpki.sql.sql_persistent):
if child_id or ca_detail_id or cert:
self.sql_mark_dirty()
+ @property
def child(self):
"""
Fetch child object to which this child_cert object links.
"""
return rpki.left_right.child_elt.sql_fetch(self.gctx, self.child_id)
+ @property
def ca_detail(self):
"""
Fetch ca_detail object to which this child_cert object links.
"""
return ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
+ @property
def uri_tail(self):
"""
Return the tail (filename) portion of the URI for this child_cert.
"""
return self.cert.gSKI() + ".cer"
- def uri(self, ca):
+ @property
+ def uri(self):
"""
Return the publication URI for this child_cert.
"""
- return ca.sia_uri + self.uri_tail()
+ return self.ca_detail.ca.sia_uri + self.uri_tail
def revoke(self, publisher, generate_crl_and_manifest = False):
"""
Revoke a child cert.
"""
- ca_detail = self.ca_detail()
- ca = ca_detail.ca()
- rpki.log.debug("Revoking %r %r" % (self, self.uri(ca)))
+ ca_detail = self.ca_detail
+ ca = ca_detail.ca
+ rpki.log.debug("Revoking %r %r" % (self, self.uri))
revoked_cert_obj.revoke(cert = self.cert, ca_detail = ca_detail)
- publisher.withdraw(cls = rpki.publication.certificate_elt, uri = self.uri(ca), obj = self.cert, repository = ca.parent().repository())
+ publisher.withdraw(cls = rpki.publication.certificate_elt, uri = self.uri, obj = self.cert, repository = ca.parent.repository)
self.gctx.sql.sweep()
self.sql_delete()
if generate_crl_and_manifest:
@@ -1033,12 +1074,12 @@ class child_cert_obj(rpki.sql.sql_persistent):
updated child_cert_obj must use the return value from this method.
"""
- ca = ca_detail.ca()
- child = self.child()
+ ca = ca_detail.ca
+ child = self.child
old_resources = self.cert.get_3779resources()
old_sia = self.cert.get_SIA()
- old_ca_detail = self.ca_detail()
+ old_ca_detail = self.ca_detail
needed = False
@@ -1085,7 +1126,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
return self
if must_revoke:
- for x in child.child_certs(ca_detail = ca_detail, ski = self.ski):
+ for x in child.fetch_child_certs(ca_detail = ca_detail, ski = self.ski):
rpki.log.debug("Revoking child_cert %r" % x)
x.revoke(publisher = publisher)
ca_detail.generate_crl(publisher = publisher)
@@ -1100,7 +1141,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
child_cert = None if must_revoke or new_issuer else self,
publisher = publisher)
- rpki.log.debug("New child_cert %r uri %s" % (child_cert, child_cert.uri(ca)))
+ rpki.log.debug("New child_cert %r uri %s" % (child_cert, child_cert.uri))
return child_cert
@@ -1171,6 +1212,7 @@ class revoked_cert_obj(rpki.sql.sql_persistent):
if serial or revoked or expires or ca_detail_id:
self.sql_mark_dirty()
+ @property
def ca_detail(self):
"""
Fetch ca_detail object to which this revoked_cert_obj links.
@@ -1209,12 +1251,14 @@ class roa_obj(rpki.sql.sql_persistent):
roa = None
published = None
+ @property
def self(self):
"""
Fetch self object to which this roa_obj links.
"""
return rpki.left_right.self_elt.sql_fetch(self.gctx, self.self_id)
+ @property
def ca_detail(self):
"""
Fetch ca_detail object to which this roa_obj links.
@@ -1282,7 +1326,7 @@ class roa_obj(rpki.sql.sql_persistent):
rpki.log.debug("ROA doesn't exist, generating %s" % me)
return self.generate(publisher = publisher, fast = fast)
- ca_detail = self.ca_detail()
+ ca_detail = self.ca_detail
if ca_detail is None:
rpki.log.debug("ROA has no associated ca_detail, generating %s" % me)
@@ -1292,7 +1336,7 @@ class roa_obj(rpki.sql.sql_persistent):
rpki.log.debug("ROA's associated ca_detail not active (state %r), regenerating %s" % (ca_detail.state, me))
return self.regenerate(publisher = publisher, fast = fast)
- regen_time = self.cert.getNotAfter() - rpki.sundial.timedelta(seconds = self.self().regen_margin)
+ regen_time = self.cert.getNotAfter() - rpki.sundial.timedelta(seconds = self.self.regen_margin)
if rpki.sundial.now() > regen_time:
rpki.log.debug("ROA past threshold %s, regenerating %s" % (regen_time, me))
@@ -1313,9 +1357,6 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Generate a ROA.
- At present this does not support ROAs with multiple signatures
- (neither does the current CMS code).
-
At present we have no way of performing a direct lookup from a
desired set of resources to a covering certificate, so we have to
search. This could be quite slow if we have a lot of active
@@ -1343,11 +1384,11 @@ class roa_obj(rpki.sql.sql_persistent):
v4 = self.ipv4.to_resource_set() if self.ipv4 is not None else rpki.resource_set.resource_set_ipv4()
v6 = self.ipv6.to_resource_set() if self.ipv6 is not None else rpki.resource_set.resource_set_ipv6()
- ca_detail = self.ca_detail()
+ ca_detail = self.ca_detail
if ca_detail is None or ca_detail.state != "active":
ca_detail = None
- for parent in self.self().parents():
- for ca in parent.cas():
+ for parent in self.self.parents:
+ for ca in parent.cas:
ca_detail = ca.fetch_active()
if ca_detail is not None:
resources = ca_detail.latest_ca_cert.get_3779resources()
@@ -1360,7 +1401,7 @@ class roa_obj(rpki.sql.sql_persistent):
if ca_detail is None:
raise rpki.exceptions.NoCoveringCertForROA, "generate() could not find a certificate covering %s %s" % (v4, v6)
- ca = ca_detail.ca()
+ ca = ca_detail.ca
resources = rpki.resource_set.resource_bag(v4 = v4, v6 = v6)
keypair = rpki.x509.RSA.generate()
@@ -1369,13 +1410,13 @@ class roa_obj(rpki.sql.sql_persistent):
ca = ca,
resources = resources,
subject_key = keypair.get_RSApublic(),
- sia = ((rpki.oids.name2oid["id-ad-signedObject"], ("uri", self.uri(keypair))),))
+ sia = ((rpki.oids.name2oid["id-ad-signedObject"], ("uri", self.uri_from_key(keypair))),))
self.roa = rpki.x509.ROA.build(self.asn, self.ipv4, self.ipv6, keypair, (self.cert,))
self.published = rpki.sundial.now()
self.sql_store()
- rpki.log.debug("Generating ROA %r" % self.uri())
- publisher.publish(cls = rpki.publication.roa_elt, uri = self.uri(), obj = self.roa, repository = ca.parent().repository(), handler = self.published_callback)
+ rpki.log.debug("Generating ROA %r" % self.uri)
+ publisher.publish(cls = rpki.publication.roa_elt, uri = self.uri, obj = self.roa, repository = ca.parent.repository, handler = self.published_callback)
if not fast:
ca_detail.generate_manifest(publisher = publisher)
@@ -1403,10 +1444,10 @@ class roa_obj(rpki.sql.sql_persistent):
flushing the SQL cache.
"""
- ca_detail = self.ca_detail()
+ ca_detail = self.ca_detail
cert = self.cert
roa = self.roa
- uri = self.uri()
+ uri = self.uri
if ca_detail.state != 'active':
self.ca_detail_id = None
@@ -1416,7 +1457,7 @@ class roa_obj(rpki.sql.sql_persistent):
rpki.log.debug("Withdrawing ROA %r and revoking its EE cert" % uri)
rpki.rpki_engine.revoked_cert_obj.revoke(cert = cert, ca_detail = ca_detail)
- publisher.withdraw(cls = rpki.publication.roa_elt, uri = uri, obj = roa, repository = ca_detail.ca().parent().repository(),
+ publisher.withdraw(cls = rpki.publication.roa_elt, uri = uri, obj = roa, repository = ca_detail.ca.parent.repository,
handler = False if allow_failure else None)
self.sql_mark_deleted()
if not fast:
@@ -1428,23 +1469,31 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Reissue ROA associated with this roa_obj.
"""
- if self.ca_detail() is None:
+ if self.ca_detail is None:
self.generate(publisher = publisher, fast = fast)
else:
self.revoke(publisher = publisher, regenerate = True, fast = fast)
- def uri(self, key = None):
+ def uri_from_key(self, key):
+ """
+ Return publication URI for a public key.
+ """
+ return self.ca_detail.ca.sia_uri + key.gSKI() + ".roa"
+
+ @property
+ def uri(self):
"""
Return the publication URI for this roa_obj's ROA.
"""
- return self.ca_detail().ca().sia_uri + self.uri_tail(key)
+ return self.ca_detail.ca.sia_uri + self.uri_tail
- def uri_tail(self, key = None):
+ @property
+ def uri_tail(self):
"""
Return the tail (filename portion) of the publication URI for this
roa_obj's ROA.
"""
- return (key or self.cert).gSKI() + ".roa"
+ return self.cert.gSKI() + ".roa"
class publication_queue(object):
diff --git a/rpkid/rpki/up_down.py b/rpkid/rpki/up_down.py
index dcfa54bb..b8fc212b 100644
--- a/rpkid/rpki/up_down.py
+++ b/rpkid/rpki/up_down.py
@@ -3,7 +3,7 @@ RPKI "up-down" protocol.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -251,8 +251,8 @@ class list_pdu(base_elt):
r_msg.payload = list_response_pdu()
- for parent in child.parents():
- for ca in parent.cas():
+ for parent in child.parents:
+ for ca in parent.cas:
ca_detail = ca.fetch_active()
if not ca_detail:
continue
@@ -263,16 +263,16 @@ class list_pdu(base_elt):
rc.class_name = str(ca.ca_id)
rc.cert_url = multi_uri(ca_detail.ca_cert_uri)
rc.from_resource_bag(resources)
- for child_cert in child.child_certs(ca_detail = ca_detail):
+ for child_cert in child.fetch_child_certs(ca_detail = ca_detail):
c = certificate_elt()
- c.cert_url = multi_uri(child_cert.uri(ca))
+ c.cert_url = multi_uri(child_cert.uri)
c.cert = child_cert.cert
rc.certs.append(c)
rc.issuer = ca_detail.latest_ca_cert
r_msg.payload.classes.append(rc)
callback()
- self.gctx.irdb_query_child_resources(child.self().self_handle, child.child_handle, handle, errback)
+ self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, handle, errback)
@classmethod
def query(cls, parent, cb, eb):
@@ -378,7 +378,7 @@ class issue_pdu(base_elt):
resources = irdb_resources.intersection(ca_detail.latest_ca_cert.get_3779resources())
req_key = self.pkcs10.getPublicKey()
req_sia = self.pkcs10.get_SIA()
- child_cert = child.child_certs(ca_detail = ca_detail, ski = req_key.get_SKI(), unique = True)
+ child_cert = child.fetch_child_certs(ca_detail = ca_detail, ski = req_key.get_SKI(), unique = True)
# Generate new cert or regenerate old one if necessary
@@ -401,7 +401,7 @@ class issue_pdu(base_elt):
def done():
c = certificate_elt()
- c.cert_url = multi_uri(child_cert.uri(ca))
+ c.cert_url = multi_uri(child_cert.uri)
c.cert = child_cert.cert
rc = class_elt()
rc.class_name = self.class_name
@@ -417,7 +417,7 @@ class issue_pdu(base_elt):
assert child_cert and child_cert.sql_in_db
publisher.call_pubd(done, errback)
- self.gctx.irdb_query_child_resources(child.self().self_handle, child.child_handle, got_resources, errback)
+ self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, got_resources, errback)
@classmethod
def query(cls, parent, ca, ca_detail, callback, errback):
@@ -426,7 +426,7 @@ class issue_pdu(base_elt):
"""
assert ca_detail is not None and ca_detail.state in ("pending", "active")
sia = ((rpki.oids.name2oid["id-ad-caRepository"], ("uri", ca.sia_uri)),
- (rpki.oids.name2oid["id-ad-rpkiManifest"], ("uri", ca_detail.manifest_uri(ca))))
+ (rpki.oids.name2oid["id-ad-rpkiManifest"], ("uri", ca_detail.manifest_uri)))
self = cls()
self.class_name = ca.parent_resource_class
self.pkcs10 = rpki.x509.PKCS10.create_ca(ca_detail.private_key_id, sia)
@@ -484,8 +484,8 @@ class revoke_pdu(revoke_syntax):
ca = child.ca_from_class_name(self.class_name)
publisher = rpki.rpki_engine.publication_queue()
- for ca_detail in ca.ca_details():
- for child_cert in child.child_certs(ca_detail = ca_detail, ski = self.get_SKI()):
+ for ca_detail in ca.ca_details:
+ for child_cert in child.fetch_child_certs(ca_detail = ca_detail, ski = self.get_SKI()):
child_cert.revoke(publisher = publisher)
self.gctx.sql.sweep()
publisher.call_pubd(done, eb)
@@ -495,7 +495,7 @@ class revoke_pdu(revoke_syntax):
"""
Send a "revoke" request for certificate(s) named by gski to parent associated with ca.
"""
- parent = ca.parent()
+ parent = ca.parent
self = cls()
self.class_name = ca.parent_resource_class
self.ski = gski
diff --git a/rpkid/rpki/x509.py b/rpkid/rpki/x509.py
index ebf8e089..7fda419d 100644
--- a/rpkid/rpki/x509.py
+++ b/rpkid/rpki/x509.py
@@ -13,7 +13,7 @@ some of the nasty details. This involves a lot of format conversion.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -1218,6 +1218,39 @@ class XML_CMS_object(CMS_object):
self.schema_check()
return self.saxify(self.get_content())
+class GBR_object(CMS_object):
+ """
+ Class to hold CMS-wrapped VCard (Ghostbuster record).
+ """
+
+ pem_converter = PEM_converter("GHOSTBUSTERS RECORD")
+ econtent_oid = POWify_OID("id-ct-rpkiGhostbusters")
+
+ def encode(self):
+ """
+ Encode inner content for signing. At the moment we're treating
+ the VCard as an opaque byte string, so no encoding needed here.
+ """
+ return self.get_content()
+
+ def decode(self, vcard):
+ """
+ Decode XML and set inner content. At the moment we're treating
+ the VCard as an opaque byte string, so no encoding needed here.
+ """
+ self.content = vcard
+
+ @classmethod
+ def build(cls, vcard, keypair, certs):
+ """
+ Build a Ghostbusters record.
+ """
+ self = cls()
+ self.set_content(vcard)
+ self.sign(keypair, certs)
+ return self
+
+
class CRL(DER_object):
"""
Class to hold a Certificate Revocation List.
diff --git a/rpkid/rpki/xml_utils.py b/rpkid/rpki/xml_utils.py
index 7b8297a4..27c1f1e6 100644
--- a/rpkid/rpki/xml_utils.py
+++ b/rpkid/rpki/xml_utils.py
@@ -3,7 +3,7 @@ XML utilities.
$Id$
-Copyright (C) 2009 Internet Systems Consortium ("ISC")
+Copyright (C) 2009-2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -32,7 +32,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-import xml.sax, lxml.sax, lxml.etree, base64
+import xml.sax, lxml.sax, lxml.etree
import rpki.exceptions
class sax_handler(xml.sax.handler.ContentHandler):
diff --git a/rpkid/rpkid.sql b/rpkid/rpkid.sql
index 2bf868b5..2813c1dc 100644
--- a/rpkid/rpkid.sql
+++ b/rpkid/rpkid.sql
@@ -1,6 +1,6 @@
-- $Id$
--- Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+-- Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
--
-- Permission to use, copy, modify, and distribute this software for any
-- purpose with or without fee is hereby granted, provided that the above
@@ -33,6 +33,7 @@
-- DROP TABLE commands must be in correct (reverse dependency) order
-- to satisfy FOREIGN KEY constraints.
+DROP TABLE IF EXISTS ghostbuster;
DROP TABLE IF EXISTS roa_prefix;
DROP TABLE IF EXISTS roa;
DROP TABLE IF EXISTS revoked_cert;
@@ -214,6 +215,21 @@ CREATE TABLE roa_prefix (
FOREIGN KEY (roa_id) REFERENCES roa (roa_id) ON DELETE CASCADE
) ENGINE=InnoDB;
+CREATE TABLE ghostbuster (
+ ghostbuster_id SERIAL NOT NULL,
+ vcard LONGBLOB NOT NULL,
+ cert LONGBLOB NOT NULL,
+ gbr LONGBLOB NOT NULL,
+ published DATETIME,
+ self_id BIGINT UNSIGNED NOT NULL,
+ ca_detail_id BIGINT UNSIGNED NOT NULL,
+ PRIMARY KEY (ghostbuster_id),
+ CONSTRAINT ghostbuster_self_id
+ FOREIGN KEY (self_id) REFERENCES self (self_id) ON DELETE CASCADE,
+ CONSTRAINT ghostbuster_ca_detail_id
+ FOREIGN KEY (ca_detail_id) REFERENCES ca_detail (ca_detail_id) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
-- Local Variables:
-- indent-tabs-mode: nil
-- End:
diff --git a/rpkid/tests/smoketest.py b/rpkid/tests/smoketest.py
index 448d93b4..63528a77 100644
--- a/rpkid/tests/smoketest.py
+++ b/rpkid/tests/smoketest.py
@@ -17,7 +17,7 @@ things that don't belong in yaml_script.
$Id$
-Copyright (C) 2009--2010 Internet Systems Consortium ("ISC")
+Copyright (C) 2009--2011 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -390,14 +390,14 @@ class allocation_db(list):
list.__init__(self)
self.root = allocation(yaml, self)
- assert self.root.is_root()
+ assert self.root.is_root
if self.root.crl_interval is None:
self.root.crl_interval = rpki.sundial.timedelta.parse(cfg.get("crl_interval", "1d")).convert_to_seconds()
if self.root.regen_margin is None:
self.root.regen_margin = rpki.sundial.timedelta.parse(cfg.get("regen_margin", "1d")).convert_to_seconds()
for a in self:
if a.sia_base is None:
- a.sia_base = (rootd_sia if a.is_root() else a.parent.sia_base) + a.name + "/"
+ a.sia_base = (rootd_sia if a.is_root else a.parent.sia_base) + a.name + "/"
if a.base.valid_until is None:
a.base.valid_until = a.parent.base.valid_until
if a.crl_interval is None:
@@ -410,16 +410,16 @@ class allocation_db(list):
a.client_handle = a.sia_base[i:].rstrip("/")
self.root.closure()
self.map = dict((a.name, a) for a in self)
- self.engines = [a for a in self if a.is_engine()]
- self.leaves = [a for a in self if a.is_leaf()]
+ self.engines = [a for a in self if a.is_engine]
+ self.leaves = [a for a in self if a.is_leaf]
for i, a in enumerate(self.engines):
a.set_engine_number(i)
for a in self:
- if a.is_hosted():
+ if a.is_hosted:
a.hosted_by = self.map[a.hosted_by]
a.hosted_by.hosts.append(a)
- assert a.is_twig(), "%s is not twig" % a.name
- assert not a.hosted_by.is_hosted(), "%s is hosted by a hosted entity" % a.name
+ assert a.is_twig, "%s is not twig" % a.name
+ assert not a.hosted_by.is_hosted, "%s is hosted by a hosted entity" % a.name
def apply_delta(self, delta, cb):
"""
@@ -579,7 +579,7 @@ class allocation(object):
raise e
cb()
- if self.is_leaf():
+ if self.is_leaf:
raise RuntimeError, "Can't rekey YAML leaf %s, sorry" % self.name
elif target is None:
rpki.log.info("Rekeying <self/> %s" % self.name)
@@ -596,7 +596,7 @@ class allocation(object):
raise e
cb()
- if self.is_leaf():
+ if self.is_leaf:
rpki.log.info("Attempting to revoke YAML leaf %s" % self.name)
subprocess.check_call((prog_python, prog_poke, "-y", self.name + ".yaml", "-r", "revoke"))
cb()
@@ -617,21 +617,26 @@ class allocation(object):
if self.sia_base: s += " SIA: %s\n" % self.sia_base
return s + "Until: %s\n" % self.resources.valid_until
+ @property
def is_leaf(self):
#return not self.kids and not self.roa_requests
return False
+ @property
def is_root(self):
return self.parent is None
+ @property
def is_twig(self):
- return not self.is_leaf() and not self.is_root()
+ return not self.is_leaf and not self.is_root
+ @property
def is_hosted(self):
return self.hosted_by is not None
+ @property
def is_engine(self):
- return not self.is_leaf() and not self.is_hosted()
+ return not self.is_leaf and not self.is_hosted
def set_engine_number(self, n):
"""
@@ -646,7 +651,7 @@ class allocation(object):
"""
Get rpki port to use for this entity.
"""
- if self.is_hosted():
+ if self.is_hosted:
assert self.hosted_by.rpki_port is not None
return self.hosted_by.rpki_port
else:
@@ -658,7 +663,7 @@ class allocation(object):
Create BPKI certificates for this entity.
"""
rpki.log.info("Constructing BPKI keys and certs for %s" % self.name)
- if self.is_leaf():
+ if self.is_leaf:
setup_bpki_cert_chain(self.name, ee = ("RPKI",))
else:
setup_bpki_cert_chain(name = self.name,
@@ -779,10 +784,10 @@ class allocation(object):
rpki.log.info("Calling rpkid for %s" % self.name)
- if self.is_hosted():
+ if self.is_hosted:
rpki.log.info("rpkid %s is hosted by rpkid %s, switching" % (self.name, self.hosted_by.name))
self = self.hosted_by
- assert not self.is_hosted()
+ assert not self.is_hosted
assert isinstance(pdus, (list, tuple))
assert self.rpki_port is not None
@@ -799,7 +804,7 @@ class allocation(object):
r_cms = rpki.left_right.cms_msg(DER = r_der)
r_msg = r_cms.unwrap((self.rpkid_ta, self.rpkid_cert))
rpki.log.debug(r_cms.pretty_print_content())
- assert r_msg.is_reply()
+ assert r_msg.is_reply
for r_pdu in r_msg:
assert not isinstance(r_pdu, rpki.left_right.report_error_elt)
cb(r_msg)
@@ -821,7 +826,7 @@ class allocation(object):
if reverse:
certifier = certificant
certificant = self.name + "-SELF"
- elif self.is_leaf():
+ elif self.is_leaf:
certifier = self.name + "-TA"
else:
certifier = self.name + "-SELF"
@@ -871,7 +876,7 @@ class allocation(object):
#10 requests we get back when we tell rpkid to generate BSC keys.
"""
- assert not self.is_hosted() and not self.is_leaf()
+ assert not self.is_hosted and not self.is_leaf
selves = [self] + self.hosts
@@ -889,7 +894,7 @@ class allocation(object):
crl_interval = s.crl_interval,
regen_margin = s.regen_margin,
bpki_cert = (s.cross_certify(s.hosted_by.name + "-TA", reverse = True)
- if s.is_hosted() else
+ if s.is_hosted else
rpki.x509.X509(Auto_file = s.name + "-SELF.cer"))))
rpkid_pdus.append(rpki.left_right.bsc_elt.make_pdu(
@@ -918,9 +923,9 @@ class allocation(object):
self_handle = s.name,
child_handle = k.name,
bsc_handle = "b",
- bpki_cert = s.cross_certify(k.name + ("-TA" if k.is_leaf() else "-SELF"))))
+ bpki_cert = s.cross_certify(k.name + ("-TA" if k.is_leaf else "-SELF"))))
- if s.is_root():
+ if s.is_root:
rootd_cert = s.cross_certify(rootd_name + "-TA")
rpkid_pdus.append(rpki.left_right.parent_elt.make_pdu(
action = "create",
@@ -1009,7 +1014,7 @@ class allocation(object):
stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
ski = rpki.x509.RSA(PEM_file = self.name + ".key").gSKI()
- if self.parent.is_hosted():
+ if self.parent.is_hosted:
parent_host = self.parent.hosted_by.name
else:
parent_host = self.parent.name
@@ -1024,7 +1029,7 @@ class allocation(object):
"parent_host" : parent_host,
"my_name" : self.name,
"http_port" : self.parent.get_rpki_port(),
- "class_name" : 2 if self.parent.is_hosted() else 1,
+ "class_name" : 2 if self.parent.is_hosted else 1,
"sia" : self.sia_base,
"ski" : ski })
f.close()
@@ -1190,7 +1195,7 @@ def call_pubd(pdus, cb):
r_cms = rpki.publication.cms_msg(DER = r_der)
r_msg = r_cms.unwrap((pubd_ta, pubd_pubd_cert))
rpki.log.debug(r_cms.pretty_print_content())
- assert r_msg.is_reply()
+ assert r_msg.is_reply
for r_pdu in r_msg:
assert not isinstance(r_pdu, rpki.publication.report_error_elt)
cb(r_msg)