diff options
author | Rob Austein <sra@hactrn.net> | 2007-09-18 21:44:21 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2007-09-18 21:44:21 +0000 |
commit | 2c5df0fe0ecf1683bf2935d027411905035042b0 (patch) | |
tree | 259f542f3669c0855fe2b9a12e606f7df7bc0888 /scripts/rpki | |
parent | f0d2933a30b05039919a3aecbb53e640d4c9c126 (diff) |
Start adding our own exceptions.
svn path=/scripts/rpki/cms.py; revision=988
Diffstat (limited to 'scripts/rpki')
-rw-r--r-- | scripts/rpki/cms.py | 4 | ||||
-rw-r--r-- | scripts/rpki/exceptions.py | 30 | ||||
-rw-r--r-- | scripts/rpki/https.py | 35 | ||||
-rw-r--r-- | scripts/rpki/left_right.py | 18 | ||||
-rw-r--r-- | scripts/rpki/up_down.py | 30 | ||||
-rw-r--r-- | scripts/rpki/x509.py | 14 |
6 files changed, 84 insertions, 47 deletions
diff --git a/scripts/rpki/cms.py b/scripts/rpki/cms.py index a00d3ba2..633ab1dc 100644 --- a/scripts/rpki/cms.py +++ b/scripts/rpki/cms.py @@ -6,7 +6,7 @@ For the moment these just call the OpenSSL CLI tool, which is slow, requires disk I/O, and likes PEM format. Fix this later. """ -import os, rpki.x509 +import os, rpki.x509, rpki.exceptions # openssl smime -sign -nodetach -outform DER -signer biz-certs/Alice-EE.cer -certfile biz-certs/Alice-CA.cer -inkey biz-certs/Alice-EE.key -in PLAN -out PLAN.der @@ -64,4 +64,4 @@ def decode(cms, ta): if status == "Verification successful\n": return xml else: - raise RuntimeError, "CMS verification failed: %s" % status + raise rpki.exceptions.CMSVerificationFailed, "CMS verification failed with status %s" % status diff --git a/scripts/rpki/exceptions.py b/scripts/rpki/exceptions.py new file mode 100644 index 00000000..76fa4c27 --- /dev/null +++ b/scripts/rpki/exceptions.py @@ -0,0 +1,30 @@ +# $Id$ + +"""Exception definitions for RPKI modules.""" + +class NotInDatabase(Exception): + """Lookup failed for an object expected to be in the database.""" + +class BadURISyntax(Exception): + """Illegal syntax for a URI.""" + +class BadStatusCode(Exception): + """Unrecognized protocol status code.""" + +class BadQuery(Exception): + """Unexpected protocol query.""" + +class MultipleROAsFound(Exception): + """Found multiple ROAs in a relationship that should be one-to-one.""" + +class CMSVerificationFailed(Exception): + """Verification of a CMS message failed.""" + +class HTTPRequestFailed(Exception): + """HTTP request failed.""" + +class DERObjectConversionError(Exception): + """Error trying to convert a DER-based object from one representation to another.""" + +class NotACertificateChain(Exception): + """Certificates don't form a proper chain.""" diff --git a/scripts/rpki/https.py b/scripts/rpki/https.py index eec5b81d..18a3c738 100644 --- a/scripts/rpki/https.py +++ b/scripts/rpki/https.py @@ -7,7 +7,7 @@ subversion repository; generalizing it would not be hard, but the more general version should use SQL anyway. """ -import httplib, BaseHTTPServer, tlslite.api, glob, rpki.x509 +import httplib, BaseHTTPServer, tlslite.api, glob, rpki.x509, traceback, rpki.exceptions rpki_content_type = "application/x-rpki" @@ -32,29 +32,32 @@ def client(msg, privateKey, certChain, x509TrustList, host="localhost", port=443 return response.read() else: r = response.read() - raise RuntimeError, (response.status, r) + raise rpki.exceptions.HTTPRequestFailed, "HTTP request failed with status %s, response %s" % (response.status, r) class requestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """Derived type to supply POST handler.""" rpki_handlers = None # Subclass must bind - def do_POST(self): - """POST handler.""" - assert self.headers["Content-Type"] == rpki_content_type - query_string = self.rfile.read(int(self.headers["Content-Length"])) - handler = None + def rpki_find_handler(self): for s,h in self.rpki_handlers: if self.path.startswith(s): - handler = h - break - if handler is None: - rcode, rtext = 404, "No handler found for URL " + self.path - else: - try: - rcode, rtext = handler(query=query_string, path=self.path) - except Exception, edata: - rcode, rtext = 500, "Unhandled exception %s" % edata + return h + return None + + def do_POST(self): + """POST handler.""" + try: + handler = self.rpki_find_handler() + if self.headers["Content-Type"] != rpki_content_type: + rcode, rtext = 415, "Received Content-Type %s, expected %s" % (self.headers["Content-Type"], rpki_content_type) + elif handler is None: + rcode, rtext = 404, "No handler found for URL " + self.path + else: + rcode, rtext = handler(query=self.rfile.read(int(self.headers["Content-Length"])), path=self.path) + except Exception, edata: + traceback.print_exc() + rcode, rtext = 500, "Unhandled exception %s" % edata self.send_response(rcode) self.send_header("Content-Type", rpki_content_type) self.end_headers() diff --git a/scripts/rpki/left_right.py b/scripts/rpki/left_right.py index 9b1f0d89..ffaa17ad 100644 --- a/scripts/rpki/left_right.py +++ b/scripts/rpki/left_right.py @@ -2,7 +2,7 @@ """RPKI "left-right" protocol.""" -import base64, rpki.sax_utils, rpki.resource_set, lxml.etree, rpki.x509, rpki.sql +import base64, rpki.sax_utils, rpki.resource_set, lxml.etree, rpki.x509, rpki.sql, rpki.exceptions xmlns = "http://www.hactrn.net/uris/rpki/left-right-spec/" @@ -123,12 +123,14 @@ class data_elt(base_elt, rpki.sql.sql_persistant): r_msg.append(make_error_report(self)) def serve_dispatch(self, db, cur, r_msg): - assert self.type == "query" - { "create" : self.serve_create, - "set" : self.serve_set, - "get" : self.serve_get, - "list" : self.serve_list, - "destroy" : self.serve_destroy }[self.action](db, cur, r_msg) + dispatch = { "create" : self.serve_create, + "set" : self.serve_set, + "get" : self.serve_get, + "list" : self.serve_list, + "destroy" : self.serve_destroy } + if self.type != "query" or self.action not in dispatch: + raise rpki.exceptions.BadQuery, "Unexpected query: type %s, action %s" % (self.type, self.action) + dispatch[self.action](db, cur, r_msg) class extension_preference_elt(base_elt): """Container for extension preferences.""" @@ -349,7 +351,7 @@ class route_origin_elt(data_elt): roa = roas[0][0] ca_detail_id = roas[0][1] elif len(roas) > 0: - raise RunTimeError, "Multiple ROAs found, mapping should be one-to-one" + raise rpki.exceptions.MultipleROAsFound, "Multiple ROAs found for route_origin %s, mapping should be one-to-one" % self.route_origin_id def sql_insert_hook(self, db, cur): if self.ipv4 + self.ipv6: diff --git a/scripts/rpki/up_down.py b/scripts/rpki/up_down.py index d1437775..ebff70d0 100644 --- a/scripts/rpki/up_down.py +++ b/scripts/rpki/up_down.py @@ -2,7 +2,7 @@ """RPKI "up-down" protocol.""" -import base64, sax_utils, resource_set, lxml.etree, x509 +import base64, rpki.sax_utils, rpki.resource_set, lxml.etree, x509, rpki.exceptions xmlns="http://www.apnic.net/specs/rescerts/up-down/" @@ -55,7 +55,8 @@ class multi_uri(list): elif isinstance(ini, str): self[:] = ini.split(",") for s in self: - assert s.strip() == s and s.find("://") >= 0, "Bad URI \"%s\"" % s + if s.strip() != s or s.find("://") < 0: + raise rpki.exceptions.BadURISyntax, "Bad URI \"%s\"" % s else: raise TypeError @@ -76,13 +77,13 @@ class certificate_elt(base_elt): """Handle attributes of <certificate/> element.""" assert name == "certificate", "Unexpected name %s, stack %s" % (name, stack) self.cert_url = multi_uri(attrs["cert_url"]) - self.req_resource_set_as = resource_set.resource_set_as(attrs.get("req_resource_set_as")) - self.req_resource_set_ipv4 = resource_set.resource_set_ipv4(attrs.get("req_resource_set_ipv4")) - self.req_resource_set_ipv6 = resource_set.resource_set_ipv6(attrs.get("req_resource_set_ipv6")) + self.req_resource_set_as = rpki.resource_set.resource_set_as(attrs.get("req_resource_set_as")) + self.req_resource_set_ipv4 = rpki.resource_set.resource_set_ipv4(attrs.get("req_resource_set_ipv4")) + self.req_resource_set_ipv6 = rpki.resource_set.resource_set_ipv6(attrs.get("req_resource_set_ipv6")) def endElement(self, stack, name, text): """Handle text content of a <certificate/> element.""" - assert name == "certificate" + assert name == "certificate", "Unexpected name %s, stack %s" % (name, stack) self.cert = x509.X509(Base64=text) stack.pop() @@ -110,9 +111,9 @@ class class_elt(base_elt): self.class_name = attrs["class_name"] self.cert_url = multi_uri(attrs["cert_url"]) self.suggested_sia_head = attrs.get("suggested_sia_head") - self.resource_set_as = resource_set.resource_set_as(attrs["resource_set_as"]) - self.resource_set_ipv4 = resource_set.resource_set_ipv4(attrs["resource_set_ipv4"]) - self.resource_set_ipv6 = resource_set.resource_set_ipv6(attrs["resource_set_ipv6"]) + self.resource_set_as = rpki.resource_set.resource_set_as(attrs["resource_set_as"]) + self.resource_set_ipv4 = rpki.resource_set.resource_set_ipv4(attrs["resource_set_ipv4"]) + self.resource_set_ipv6 = rpki.resource_set.resource_set_ipv6(attrs["resource_set_ipv6"]) def endElement(self, stack, name, text): """Handle <class/> elements and their children.""" @@ -161,9 +162,9 @@ class issue_pdu(base_elt): """Handle "issue" PDU.""" assert name == "request", "Unexpected name %s, stack %s" % (name, stack) self.class_name = attrs["class_name"] - self.req_resource_set_as = resource_set.resource_set_as(attrs.get("req_resource_set_as")) - self.req_resource_set_ipv4 = resource_set.resource_set_ipv4(attrs.get("req_resource_set_ipv4")) - self.req_resource_set_ipv6 = resource_set.resource_set_ipv6(attrs.get("req_resource_set_ipv6")) + self.req_resource_set_as = rpki.resource_set.resource_set_as(attrs.get("req_resource_set_as")) + self.req_resource_set_ipv4 = rpki.resource_set.resource_set_ipv4(attrs.get("req_resource_set_ipv4")) + self.req_resource_set_ipv6 = rpki.resource_set.resource_set_ipv6(attrs.get("req_resource_set_ipv6")) def endElement(self, stack, name, text): """Handle "issue" PDU.""" @@ -219,7 +220,8 @@ class error_response_pdu(base_elt): """Handle "error_response" PDU.""" if name == "status": code = int(text) - assert code in self.codes + if code not in self.codes: + raise rpki.exceptions.BadStatusCode, "%s is not a known status code" self.status = code elif name == "last_message_processed": self.last_message_processed = text @@ -274,7 +276,7 @@ class message_pdu(base_elt): def __str__(self): lxml.etree.tostring(self.toXML(), pretty_print=True, encoding="UTF-8") -class sax_handler(sax_utils.handler): +class sax_handler(rpki.sax_utils.handler): """SAX handler for Up-Down protocol.""" def create_top_level(self, name, attrs): diff --git a/scripts/rpki/x509.py b/scripts/rpki/x509.py index ad3f0e85..3e352baf 100644 --- a/scripts/rpki/x509.py +++ b/scripts/rpki/x509.py @@ -12,7 +12,7 @@ bring together the functionality I need in a way that hides at least some of the nasty details. This involves a lot of format conversion. """ -import POW, tlslite.api, POW.pkix, base64 +import POW, tlslite.api, POW.pkix, base64, rpki.exceptions class PEM_converter(object): """Convert between DER and PEM encodings for various kinds of ASN.1 data.""" @@ -108,7 +108,7 @@ class DER_object(object): self.clear() self.DER = text return - raise TypeError + raise rpki.exceptions.DERObjectConversionError, "Can't honor conversion request %s" % repr(kw) def get_DER(self): """Get the DER value of this object. @@ -118,7 +118,7 @@ class DER_object(object): assert not self.empty() if self.DER: return self.DER - raise RuntimeError, "No conversion path to DER available" + raise rpki.exceptions.DERObjectConversionError, "No conversion path to DER available" def get_Base64(self): """Get the Base64 encoding of the DER value of this object.""" @@ -153,7 +153,7 @@ class X509(DER_object): if self.POWpkix: self.DER = self.POWpkix.toString() return self.get_DER() - raise RuntimeError + raise rpki.exceptions.DERObjectConversionError, "No conversion path to DER available" def get_POW(self): """Get the POW value of this certificate.""" @@ -232,7 +232,7 @@ class X509_chain(list): chain.append(cert) bag.remove(cert) if len(chain) != 1: - raise RuntimeError, "Certificates in bag don't form a proper chain" + raise rpki.exceptions.NotACertificateChain, "Certificates in bag don't form a proper chain" while bag: cert = subject_map[chain[-1].getIssuer()] chain.append(cert) @@ -274,7 +274,7 @@ class PKCS10_Request(DER_object): if self.POWpkix: self.DER = self.POWpkix.toString() return self.get_DER() - raise RuntimeError + raise rpki.exceptions.DERObjectConversionError, "No conversion path to DER available" def get_POWpkix(self): """Get the POW.pkix value of this certification request.""" @@ -301,7 +301,7 @@ class RSA_Keypair(DER_object): if self.POW: self.DER = self.POW.derWrite() return self.get_DER() - raise RuntimeError + raise rpki.exceptions.DERObjectConversionError, "No conversion path to DER available" def get_POW(self): assert not self.empty() |