diff options
Diffstat (limited to 'rpki')
-rw-r--r-- | rpki/http_simple.py | 29 | ||||
-rw-r--r-- | rpki/irdb/zookeeper.py | 55 | ||||
-rw-r--r-- | rpki/rootd.py | 31 |
3 files changed, 63 insertions, 52 deletions
diff --git a/rpki/http_simple.py b/rpki/http_simple.py index 4a05d607..2a00ff9c 100644 --- a/rpki/http_simple.py +++ b/rpki/http_simple.py @@ -1,5 +1,5 @@ # $Id$ - +# # Copyright (C) 2014 Dragon Research Labs ("DRL") # # Permission to use, copy, modify, and distribute this software for any @@ -97,11 +97,10 @@ class BadContentType(Exception): "Wrong HTTP Content-Type" -def client(url, query): +def client(proto_cms_msg, client_key, client_cert, server_ta, server_cert, url, q_msg, + debug = False, replay_track = None, client_crl = None): """ - Issue single a query and return the response. - - Might want to add CMS processing here, not sure yet. + Issue single a query and return the response, handling all the CMS and XML goo. """ u = urlparse.urlparse(url) @@ -109,10 +108,14 @@ def client(url, query): if u.scheme not in ("", "http") or u.username or u.password or u.params or u.query or u.fragment: raise BadURL("Unusable URL %s", url) - http = httplib.HTTPConnection(u.hostname, u.port or httplib.HTTP_PORT) + q_cms = proto_cms_msg() + q_der = q_cms.wrap(q_msg, client_key, client_cert, client_crl) - http.request("POST", u.path, query, {"Content-Type" : rpki_content_type}) + if debug: + debug.write("<!-- Query -->\n" + q_cms.pretty_print_content() + "\n") + http = httplib.HTTPConnection(u.hostname, u.port or httplib.HTTP_PORT) + http.request("POST", u.path, q_der, {"Content-Type" : rpki_content_type}) r = http.getresponse() if r.status != 200: @@ -121,4 +124,14 @@ def client(url, query): if r.getheader("Content-Type") != rpki_content_type: raise BadContentType("HTTP Content-Type %r, expected %r" % (r.getheader("Content-Type"), rpki_content_type)) - return r.read() + r_der = r.read() + r_cms = proto_cms_msg(DER = r_der) + r_msg = r_cms.unwrap((server_ta, server_cert)) + + if replay_track is not None: + replay_track.cms_timestamp = r_cms.check_replay(replay_track.cms_timestamp, url) + + if debug: + debug.write("<!-- Reply -->\n" + r_cms.pretty_print_content() + "\n") + + return r_msg diff --git a/rpki/irdb/zookeeper.py b/rpki/irdb/zookeeper.py index c9f7d78e..41060f9e 100644 --- a/rpki/irdb/zookeeper.py +++ b/rpki/irdb/zookeeper.py @@ -28,12 +28,11 @@ import types import rpki.config import rpki.sundial import rpki.oids -import rpki.http +import rpki.http_simple import rpki.resource_set import rpki.relaxng import rpki.left_right import rpki.x509 -import rpki.async import rpki.irdb import rpki.publication_control import django.db.transaction @@ -189,9 +188,9 @@ class etree_wrapper(object): class Zookeeper(object): ## @var show_xml - # Whether to show XML for debugging + # If not None, a file-like object to which to prettyprint XML, for debugging. - show_xml = False + show_xml = None def __init__(self, cfg = None, handle = None, logstream = None): @@ -1035,11 +1034,6 @@ class Zookeeper(object): def call_rpkid(self, *pdus): """ Issue a call to rpkid, return result. - - Implementation is a little silly, constructs a wrapper object, - invokes it once, then throws it away. Hard to do better without - rewriting a bit of the HTTP code, as we want to be sure we're - using the current BPKI certificate and key objects. """ url = "http://%s:%s/left-right" % ( @@ -1054,16 +1048,15 @@ class Zookeeper(object): elif len(pdus) == 1 and isinstance(pdus[0], (tuple, list)): pdus = pdus[0] - call_rpkid = rpki.async.sync_wrapper(rpki.http.caller( - proto = rpki.left_right, - client_key = irbe.private_key, - client_cert = irbe.certificate, - server_ta = self.server_ca.certificate, - server_cert = rpkid.certificate, - url = url, - debug = self.show_xml)) - - return call_rpkid(*pdus) + return rpki.http_simple.client( + proto_cms_msg = rpki.left_right.cms_msg, + client_key = irbe.private_key, + client_cert = irbe.certificate, + server_ta = self.server_ca.certificate, + server_cert = rpkid.certificate, + url = url, + q_msg = rpki.left_right.msg.query(*pdus), + debug = self.show_xml) def run_rpkid_now(self): @@ -1145,11 +1138,6 @@ class Zookeeper(object): def call_pubd(self, *pdus): """ Issue a call to pubd, return result. - - Implementation is a little silly, constructs a wrapper object, - invokes it once, then throws it away. Hard to do better without - rewriting a bit of the HTTP code, as we want to be sure we're - using the current BPKI certificate and key objects. """ url = "http://%s:%s/control" % ( @@ -1164,16 +1152,15 @@ class Zookeeper(object): elif len(pdus) == 1 and isinstance(pdus[0], (tuple, list)): pdus = pdus[0] - call_pubd = rpki.async.sync_wrapper(rpki.http.caller( - proto = rpki.publication_control, - client_key = irbe.private_key, - client_cert = irbe.certificate, - server_ta = self.server_ca.certificate, - server_cert = pubd.certificate, - url = url, - debug = self.show_xml)) - - return call_pubd(*pdus) + return rpki.http_simple.client( + proto_cms_msg = rpki.publication_control.cms_msg, + client_key = irbe.private_key, + client_cert = irbe.certificate, + server_ta = self.server_ca.certificate, + server_cert = pubd.certificate, + url = url, + q_msg = rpki.publication_control.msg.query(*pdus), + debug = self.show_xml) def check_error_report(self, pdus): diff --git a/rpki/rootd.py b/rpki/rootd.py index a9562881..2bd7ce44 100644 --- a/rpki/rootd.py +++ b/rpki/rootd.py @@ -46,6 +46,16 @@ from lxml.etree import Element, SubElement logger = logging.getLogger(__name__) +class ReplayTracker(object): + """ + Stash for replay protection timestamps. + """ + + def __init__(self): + self.cms_timestamp = None + + + class main(object): @@ -248,11 +258,16 @@ class main(object): def call_pubd(self, q_msg): for q_pdu in q_msg: logger.info("Sending %s to pubd", q_pdu.get("uri")) - q_der = rpki.publication.cms_msg_no_sax().wrap(q_msg, self.rootd_bpki_key, self.rootd_bpki_cert, self.rootd_bpki_crl) - r_der = rpki.http_simple.client(self.pubd_url, q_der) - r_cms = rpki.publication.cms_msg_no_sax(DER = r_der) - r_msg = r_cms.unwrap((self.bpki_ta, self.pubd_bpki_cert)) - self.pubd_cms_timestamp = r_cms.check_replay(self.pubd_cms_timestamp, self.pubd_url) + r_msg = rpki.http_simple.client( + proto_cms_msg = rpki.publication.cms_msg_no_sax, + 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 @@ -373,15 +388,11 @@ class main(object): def __init__(self): - - global rootd - rootd = self # Gross, but simpler than what we'd have to do otherwise - self.serial_number = None self.crl_number = None self.revoked = [] self.rpkid_cms_timestamp = None - self.pubd_cms_timestamp = None + self.pubd_replay_tracker = ReplayTracker() os.environ["TZ"] = "UTC" time.tzset() |