diff options
author | Rob Austein <sra@hactrn.net> | 2015-10-16 23:07:52 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-10-16 23:07:52 +0000 |
commit | 6d5fe21be4393ef644965669b4de2c976bc0096f (patch) | |
tree | 076b45bf49c706c62e8167dd4da0041725033b1c | |
parent | 8734d57231a81d28ed60e417b9a6361c412c0f8b (diff) |
PyLint. As usual, a lot of noise and a handful of real, albeit minor, bugs.
svn path=/branches/tk705/; revision=6123
32 files changed, 177 insertions, 164 deletions
diff --git a/Makefile.in b/Makefile.in index 1e06fb8e..faba9054 100644 --- a/Makefile.in +++ b/Makefile.in @@ -216,9 +216,9 @@ schemas/relaxng/oob-setup.rng: schemas/relaxng/oob-setup.rnc # Eg: PYLINT_FLAGS='--disable=W0311' -lint: - { find rpki rp ca -name '*.py' -print; find rp ca -type f -perm -1 -print | xargs grep -El '^#!.+python'; } | \ - sort -u | xargs pylint --rcfile ${abs_top_srcdir}/buildtools/pylint.rc ${PYLINT_FLAGS} +lint: .FORCE + pylint --rcfile ${abs_top_srcdir}/buildtools/pylint.rc ${PYLINT_FLAGS} \ + rpki `find rp ca -type f -perm -1 -print | xargs grep -El '^#!.+python'` tags: Makefile .FORCE find rpki rp ca schemas -type f \ diff --git a/buildtools/pylint.rc b/buildtools/pylint.rc index ed296108..34302f74 100644 --- a/buildtools/pylint.rc +++ b/buildtools/pylint.rc @@ -19,11 +19,21 @@ [MASTER] profile=no -ignore=.svn + +# Including "gui" here is a temporary measure: it's risky, but so is +# making ten zillion cosmetic changes in a co-worker's code on a +# long-running development branch. + +ignore=.svn,.git,migrations,south_migrations,irbe_cli,gui + persistent=yes cache-size=500 load-plugins= +# Extension (C, etc) modules that pylint should trust enough to import. + +extension-pkg-whitelist=lxml,rpki.POW + [MESSAGES CONTROL] # Enable only checker(s) with the given id(s). This option conflicts with the @@ -44,14 +54,13 @@ disable-msg-cat= #enable-msg= # Disable the message(s) with the given id(s). -disable=R0801,R0903,R0913,C0321,R0904,W0201,E1101,W0614,C0301,R0901,C0302,R0902,R0201,W0613,R0912,R0915,W0703,W0212,R0914,W0603,W0142,I0011,C0111,C0103,R0401,C0326,R0911,C0325 +disable=R0801,R0903,R0913,C0321,R0904,W0201,E1101,W0614,C0301,R0901,C0302,R0902,R0201,W0613,R0912,R0915,W0703,W0212,R0914,W0603,W0142,I0011,C0111,C0103,R0401,C0326,R0911,C0325,C0330,W0311,E1124 [REPORTS] #output-format=parseable msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} -include-ids=yes files-output=no reports=no evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) diff --git a/ca/rpkigui-apache-conf-gen b/ca/rpkigui-apache-conf-gen index 0658254f..8ac9c94a 100755 --- a/ca/rpkigui-apache-conf-gen +++ b/ca/rpkigui-apache-conf-gen @@ -475,7 +475,7 @@ class Debian(Platform): self.run("service", "apache2", "restart") class Ubuntu(Debian): - + # On Ubuntu, the filename must end in .conf on Trusty and must not # end in .conf on Precise. @property diff --git a/ca/rpkigui-query-routes b/ca/rpkigui-query-routes index 1f698f23..179f8c2c 100755 --- a/ca/rpkigui-query-routes +++ b/ca/rpkigui-query-routes @@ -49,7 +49,6 @@ qs = rv.RouteOrigin.objects.filter( prefix_max__gte=r.max ) - def validity_marker(route, roa, roa_prefix): "Return + if the roa would cause the route to be accepted, or - if not" # we already know the ROA covers this route because they are returned diff --git a/ca/tests/bgpsec-yaml.py b/ca/tests/bgpsec-yaml.py index 1562f86e..d33184bf 100755 --- a/ca/tests/bgpsec-yaml.py +++ b/ca/tests/bgpsec-yaml.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # # $Id$ -# +# # Copyright (C) 2014 Dragon Research Labs ("DRL") # # Permission to use, copy, modify, and distribute this software for any @@ -30,11 +30,11 @@ root = "Root" class Kid(object): - def __init__(self, n): - self.name = "ISP-%03d" % n - self.ipv4 = "10.%d.0.0/16" % n - self.asn = n - self.router_id = n * 10000 + def __init__(self, i): + self.name = "ISP-%03d" % i + self.ipv4 = "10.%d.0.0/16" % i + self.asn = i + self.router_id = i * 10000 @property def declare(self): @@ -72,12 +72,12 @@ docs.append([shell_first, gym = kids[50:70] for kid in gym: - docs.append([shell_next, + docs.append([shell_next, kid.del_routercert, sleeper]) for kid in gym: - docs.append([shell_next, + docs.append([shell_next, kid.add_routercert, sleeper]) diff --git a/ca/tests/test-rrdp.py b/ca/tests/test-rrdp.py index 9b7f207c..1a9db929 100755 --- a/ca/tests/test-rrdp.py +++ b/ca/tests/test-rrdp.py @@ -26,7 +26,7 @@ import time import signal import textwrap import argparse -import subprocess +import subprocess parser = argparse.ArgumentParser(description = __doc__) parser.add_argument("--use-smoketest", action = "store_true") @@ -88,9 +88,9 @@ else: def handle_sigusr1(signum, frame): raise GotSIGUSR1 old_sigusr1 = signal.signal(signal.SIGUSR1, handle_sigusr1) - argv = ("python", "yamltest.py", args.yaml_file, "--notify-when-startup-complete", str(os.getpid())) - log("Running: " + " ".join(argv)) - yamltest = subprocess.Popen(argv) + cmd = ("python", "yamltest.py", args.yaml_file, "--notify-when-startup-complete", str(os.getpid())) + log("Running: " + " ".join(cmd)) + yamltest = subprocess.Popen(cmd) log("Waiting for SIGUSR1 from yamltest") try: while True: diff --git a/ca/tests/yamltest.py b/ca/tests/yamltest.py index a279b530..71a83c14 100644 --- a/ca/tests/yamltest.py +++ b/ca/tests/yamltest.py @@ -446,9 +446,9 @@ class allocation(object): if not args.skip_config and args.store_router_private_keys: path = self.path("%s.routercerts.keys" % d.name) print "Writing", path - with open(path, "w") as f: - for r in self.router_certs: - f.write(r.keypair.get_PEM()) + with open(path, "w") as f: + for r in self.router_certs: + f.write(r.keypair.get_PEM()) @property def pubd(self): @@ -996,3 +996,7 @@ try: finally: if args.pidfile is not None: os.unlink(args.pidfile) + +# Local Variables: +# indent-tabs-mode: nil +# End: diff --git a/rp/utils/find_roa b/rp/utils/find_roa index 4cfcccac..2b537bf4 100755 --- a/rp/utils/find_roa +++ b/rp/utils/find_roa @@ -61,7 +61,7 @@ class Prefix(object): if self.prefix & ((1 << (self.prefix.bits - self.length)) - 1) != 0: raise ValueError - def matches(self, roa): + def matches(self, roa): # pylint: disable=W0621 return any(self.prefix == prefix and self.length == length and (not args.match_maxlength or @@ -71,13 +71,13 @@ class Prefix(object): for prefix, length, maxlength in roa.prefixes) -class ROA(rpki.POW.ROA): +class ROA(rpki.POW.ROA): # pylint: disable=W0232 """ Aspects of a ROA that we care about. """ @classmethod - def parse(cls, fn): + def parse(cls, fn): # pylint: disable=W0621 assert fn.startswith(args.rcynic_dir) self = cls.derReadFile(fn) self.fn = fn @@ -112,7 +112,7 @@ class ROA(rpki.POW.ROA): def show_expiration(self): print self x = self.certs()[0] - fn = self.fn + fn = self.fn # pylint: disable=W0621 uri = self.uri while uri is not None: name = fn if args.show_filenames else uri diff --git a/rp/utils/print_roa b/rp/utils/print_roa index d5db0c3c..c96a7c66 100755 --- a/rp/utils/print_roa +++ b/rp/utils/print_roa @@ -24,14 +24,14 @@ signature. import argparse import rpki.POW -class ROA(rpki.POW.ROA): +class ROA(rpki.POW.ROA): # pylint: disable=W0232 @staticmethod - def _format_prefix(prefix): - if prefix[2] is None or prefix[1] == prefix[2]: - return "%s/%d" % (prefix[0], prefix[1]) + def _format_prefix(p): + if p[2] in (None, p[1]): + return "%s/%d" % (p[0], p[1]) else: - return "%s/%d-%d" % (prefix[0], prefix[1], prefix[2]) + return "%s/%d-%d" % (p[0], p[1], p[2]) def parse(self): self.extractWithoutVerifying() @@ -58,12 +58,12 @@ for roa in args.roas: print "asID: ", roa.getASID() if roa.v4_prefixes: print " addressFamily:", 1 - for p in roa.v4_prefixes: - print " IPAddress:", p + for prefix in roa.v4_prefixes: + print " IPAddress:", prefix if roa.v6_prefixes: print " addressFamily:", 2 - for p in roa.v6_prefixes: - print " IPAddress:", p + for prefix in roa.v6_prefixes: + print " IPAddress:", prefix if args.cms: print roa.pprint() for cer in roa.certs(): diff --git a/rp/utils/print_rpki_manifest b/rp/utils/print_rpki_manifest index 5ebc6356..ce9b25ea 100755 --- a/rp/utils/print_rpki_manifest +++ b/rp/utils/print_rpki_manifest @@ -39,8 +39,8 @@ for mft in args.manifests: print "nextUpdate: ", mft.getNextUpdate() print "fileHashAlg: ", rpki.oids.oid2name(mft.getAlgorithm()) for i, fah in enumerate(mft.getFiles()): - name, hash = fah - print "fileList[%3d]: %s %s" % (i, ":".join(("%02X" % ord(h) for h in hash)), name) + name, obj_hash = fah + print "fileList[%3d]: %s %s" % (i, ":".join(("%02X" % ord(h) for h in obj_hash)), name) if args.cms: print mft.pprint() for cer in mft.certs(): diff --git a/rp/utils/scan_roas b/rp/utils/scan_roas index a1b64f01..4f3dc7f0 100755 --- a/rp/utils/scan_roas +++ b/rp/utils/scan_roas @@ -31,10 +31,10 @@ def check_dir(d): raise argparse.ArgumentTypeError("%r is not a directory" % d) return d -class ROA(rpki.POW.ROA): +class ROA(rpki.POW.ROA): # pylint: disable=W0232 @classmethod - def parse(cls, fn): + def parse(cls, fn): # pylint: disable=W0621 self = cls.derReadFile(fn) self.extractWithoutVerifying() return self diff --git a/rpki/config.py b/rpki/config.py index 077f9350..0be0d1a0 100644 --- a/rpki/config.py +++ b/rpki/config.py @@ -312,7 +312,7 @@ class parser(object): rpki.x509.generate_insecure_debug_only_rsa_key = rpki.x509.insecure_debug_only_rsa_key_generator(*self.get("insecure-debug-only-rsa-key-db").split()) except ConfigParser.NoOptionError: pass - except: + except: # pylint: disable=W0702 logger.warning("insecure-debug-only-rsa-key-db configured but initialization failed, check for corrupted database file") try: diff --git a/rpki/django_settings/gui.py b/rpki/django_settings/gui.py index 5007df8b..4e9ac0f3 100644 --- a/rpki/django_settings/gui.py +++ b/rpki/django_settings/gui.py @@ -20,7 +20,7 @@ This module contains GUI-specific configuration settings for Django libraries. # Pull in the irdb configuration, which in turn pulls in the common configuration. -from .irdb import * +from .irdb import * # pylint: disable=W0401 __version__ = "$Id$" @@ -151,6 +151,6 @@ TEMPLATE_CONTEXT_PROCESSORS = ( # putting that configuration into rpki.conf and just adding code here # to read that configuration. try: - from local_settings import * -except: + from local_settings import * # pylint: disable=W0401,F0401 +except ImportError: pass diff --git a/rpki/django_settings/irdb.py b/rpki/django_settings/irdb.py index 7749b9d6..11e7417a 100644 --- a/rpki/django_settings/irdb.py +++ b/rpki/django_settings/irdb.py @@ -21,7 +21,7 @@ the GUI code also uses this but adds a bunch of other stuff, thus has its own settings file. """ -from .common import * +from .common import * # pylint: disable=W0401 __version__ = "$Id$" @@ -44,6 +44,6 @@ INSTALLED_APPS = ["rpki.irdb"] # putting that configuration into rpki.conf and just adding code here # to read that configuration. try: - from local_settings import * -except: + from local_settings import * # pylint: disable=W0401,F0401 +except ImportError: pass diff --git a/rpki/django_settings/pubd.py b/rpki/django_settings/pubd.py index 6f1fe06b..7ae533e7 100644 --- a/rpki/django_settings/pubd.py +++ b/rpki/django_settings/pubd.py @@ -19,7 +19,7 @@ This module contains configuration settings for Django libraries for the pubd program. """ -from .common import * +from .common import * # pylint: disable=W0401 __version__ = "$Id$" @@ -43,6 +43,6 @@ INSTALLED_APPS = ["rpki.pubdb"] # putting that configuration into rpki.conf and just adding code here # to read that configuration. try: - from local_settings import * -except: + from local_settings import * # pylint: disable=W0401,F0401 +except ImportError: pass diff --git a/rpki/django_settings/rpkid.py b/rpki/django_settings/rpkid.py index e3abb0eb..a2aa9401 100644 --- a/rpki/django_settings/rpkid.py +++ b/rpki/django_settings/rpkid.py @@ -19,7 +19,7 @@ This module contains configuration settings for Django libraries for the rpkid program. """ -from .common import * +from .common import * # pylint: disable=W0401 __version__ = "$Id$" @@ -31,7 +31,7 @@ DATABASES = dict( NAME = cfg.get("sql-database", section = "rpkid"), USER = cfg.get("sql-username", section = "rpkid"), PASSWORD = cfg.get("sql-password", section = "rpkid"))) - + # Apps. @@ -43,6 +43,6 @@ INSTALLED_APPS = ["rpki.rpkidb"] # putting that configuration into rpki.conf and just adding code here # to read that configuration. try: - from local_settings import * -except: + from local_settings import * # pylint: disable=W0401,F0401 +except ImportError: pass diff --git a/rpki/fields.py b/rpki/fields.py index d1025c35..4a826f4e 100644 --- a/rpki/fields.py +++ b/rpki/fields.py @@ -175,7 +175,7 @@ class CRLField(DERField): class PKCS10Field(DERField): description = "PKCS #10 certificate request" - rpki_type = rpki.x509.PKCS10 + rpki_type = rpki.x509.PKCS10 class ManifestField(DERField): description = "RPKI Manifest" diff --git a/rpki/http_simple.py b/rpki/http_simple.py index e5b78334..ee9cac35 100644 --- a/rpki/http_simple.py +++ b/rpki/http_simple.py @@ -39,19 +39,16 @@ class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): try: content_type = self.headers.get("Content-Type") content_length = self.headers.get("Content-Length") - for h in self.rpki_handlers: - if self.path.startswith(h[0]): - break - else: - self.send_error(404, "No handler for path %s" % self.path) - if content_type not in (h[2] if len(h) > 2 else (default_content_type,)): - self.send_error(415, "No handler for Content-Type %s" % content_type) - h[1](self, (self.rfile.read() - if content_length is None else - self.rfile.read(int(content_length)))) + for handler_path, handler, handler_content_type in self.rpki_handlers: + if self.path.startswith(handler_path) and content_type in handler_content_type: + return handler(self, + self.rfile.read() + if content_length is None else + self.rfile.read(int(content_length))) + self.send_error(404, "No handler for path %s" % self.path) except Exception, e: logger.exception("Unhandled exception") - self.send_error(501, "Unhandled exception") + self.send_error(501, "Unhandled exception %s" % e) def send_cms_response(self, der): self.send_response(200) @@ -77,8 +74,11 @@ def server(handlers, port, host = ""): Run an HTTP server and wait (forever) for connections. """ - if not isinstance(handlers, (tuple, list)): - handlers = (("/", handlers),) + if isinstance(handlers, (tuple, list)): + handlers = tuple(h[:3] if len(h) > 2 else (h[0], h[1], default_content_type) + for h in handlers) + else: + handlers = (("/", handlers, default_content_type),) class RequestHandler(HTTPRequestHandler): rpki_handlers = handlers diff --git a/rpki/irdb/zookeeper.py b/rpki/irdb/zookeeper.py index d0597e86..4b4a2f46 100644 --- a/rpki/irdb/zookeeper.py +++ b/rpki/irdb/zookeeper.py @@ -24,7 +24,7 @@ Management code for the IRDB. import os import copy -import types + import rpki.config import rpki.sundial import rpki.oids @@ -35,6 +35,7 @@ import rpki.left_right import rpki.x509 import rpki.irdb import rpki.publication_control + import django.db.transaction from lxml.etree import (Element, SubElement, ElementTree, @@ -898,7 +899,7 @@ class Zookeeper(object): raise CouldntFindRepoParent turtle = turtles[0] if isinstance(turtle, rpki.irdb.models.Rootd): - parent_handle = self.handle + parent_handle = self.handle else: parent_handle = turtle.handle self.log("No explicit parent_handle given, guessing parent {}".format(parent_handle)) @@ -1646,7 +1647,7 @@ class Zookeeper(object): SubElement(q_msg, rpki.left_right.tag_self, action = "list") self.call_rpkid(q_msg) - self_handles = set(s.get("self_handle") for s in r_msg) + self_handles = set(s.get("self_handle") for s in q_msg) ca_handles = set(ca.handle for ca in rpki.irdb.models.ResourceHolderCA.objects.all()) assert ca_handles <= self_handles diff --git a/rpki/irdbd.py b/rpki/irdbd.py index d2c7bd4e..d58128e5 100644 --- a/rpki/irdbd.py +++ b/rpki/irdbd.py @@ -25,7 +25,6 @@ import os import time import logging import argparse -import urlparse import rpki.http_simple import rpki.config import rpki.resource_set diff --git a/rpki/left_right.py b/rpki/left_right.py index 39057ca2..7189f888 100644 --- a/rpki/left_right.py +++ b/rpki/left_right.py @@ -67,12 +67,6 @@ tag_signing_cert = xmlns + "signing_cert" tag_signing_cert_crl = xmlns + "signing_cert_crl" -## @var enforce_strict_up_down_xml_sender -# Enforce strict checking of XML "sender" field in up-down protocol - -enforce_strict_up_down_xml_sender = False - - class base_elt(rpki.sql.sql_persistent): """ Virtual class for persistent left-right protocol elements. @@ -453,7 +447,7 @@ class self_elt(base_elt): obj = c.cert, repository = repository) for u in objects: - h, r = objects[h] + h, r = objects[u] publisher.queue(uri = u, old_hash = h, repository = r) publisher.call_pubd(cb, eb) @@ -630,7 +624,7 @@ class repository_elt(base_elt): cb() - def call_pubd(self, callback, errback, q_msg, handlers = {}, length_check = True): + def call_pubd(self, callback, errback, q_msg, handlers = {}, length_check = True): # pylint: disable=W0102 """ Send a message to publication daemon and return the response. @@ -1130,7 +1124,7 @@ class child_elt(base_elt): def done(): SubElement(r_msg, key.tag, class_name = class_name, ski = key.get("ski")) callback() - + key = q_msg[0] assert key.tag == rpki.up_down.tag_key class_name = key.get("class_name") @@ -1138,9 +1132,9 @@ class child_elt(base_elt): publisher = rpki.rpkid.publication_queue() - ca = child.ca_from_class_name(class_name) + ca = self.ca_from_class_name(class_name) for ca_detail in ca.ca_details: - for child_cert in child.fetch_child_certs(ca_detail = ca_detail, ski = ski): + for child_cert in self.fetch_child_certs(ca_detail = ca_detail, ski = ski): child_cert.revoke(publisher = publisher) self.gctx.sql.sweep() @@ -1174,7 +1168,7 @@ class child_elt(base_elt): q_type = q_msg.get("type") logger.info("Serving %s query from child %s [sender %s, recipient %s]", q_type, self.child_handle, q_msg.get("sender"), q_msg.get("recipient")) - if enforce_strict_up_down_xml_sender and q_msg.get("sender") != self.child_handle: + if rpki.up_down.enforce_strict_up_down_xml_sender and q_msg.get("sender") != self.child_handle: raise rpki.exceptions.BadSender("Unexpected XML sender %s" % q_msg.get("sender")) self.gctx.sql.sweep() diff --git a/rpki/log.py b/rpki/log.py index 43561463..7bad6dc2 100644 --- a/rpki/log.py +++ b/rpki/log.py @@ -32,7 +32,7 @@ import traceback as tb try: have_setproctitle = False if os.getenv("DISABLE_SETPROCTITLE") is None: - import setproctitle + import setproctitle # pylint: disable=F0401 have_setproctitle = True except ImportError: pass diff --git a/rpki/pubd.py b/rpki/pubd.py index 64b432dd..b5d36199 100644 --- a/rpki/pubd.py +++ b/rpki/pubd.py @@ -98,8 +98,8 @@ class main(object): import django django.setup() - global rpki - import rpki.pubdb + global rpki # pylint: disable=W0602 + import rpki.pubdb # pylint: disable=W0621 self.bpki_ta = rpki.x509.X509(Auto_update = self.cfg.get("bpki-ta")) self.irbe_cert = rpki.x509.X509(Auto_update = self.cfg.get("irbe-cert")) diff --git a/rpki/pubdb/models.py b/rpki/pubdb/models.py index c6196eab..446867b8 100644 --- a/rpki/pubdb/models.py +++ b/rpki/pubdb/models.py @@ -110,7 +110,7 @@ class Session(models.Model): """ self.delta_set.filter(expires__lt = rpki.sundial.now()).delete() - + def generate_snapshot(self): """ @@ -240,37 +240,38 @@ class Delta(models.Model): self.session.save() - def publish(self, client, der, uri, hash): + def publish(self, client, der, uri, obj_hash): try: obj = client.publishedobject_set.get(session = self.session, uri = uri) - if obj.hash == hash: + if obj.hash == obj_hash: obj.delete() - elif hash is None: + elif obj_hash is None: raise rpki.exceptions.ExistingObjectAtURI("Object already published at %s" % uri) else: - raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, hash)) + raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, obj_hash)) except rpki.pubdb.models.PublishedObject.DoesNotExist: pass logger.debug("Publishing %s", uri) PublishedObject.objects.create(session = self.session, client = client, der = der, uri = uri, hash = rpki.x509.sha256(der).encode("hex")) se = DERSubElement(self.elt, rrdp_tag_publish, der = der, uri = uri) - if hash is not None: - se.set("hash", hash) + if obj_hash is not None: + se.set("hash", obj_hash) rpki.relaxng.rrdp.assertValid(self.elt) - def withdraw(self, client, uri, hash): + def withdraw(self, client, uri, obj_hash): obj = client.publishedobject_set.get(session = self.session, uri = uri) - if obj.hash != hash: - raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, hash)) + if obj.hash != obj_hash: + raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, obj_hash)) logger.debug("Withdrawing %s", uri) obj.delete() - SubElement(self.elt, rrdp_tag_withdraw, uri = uri, hash = hash).tail = "\n" + SubElement(self.elt, rrdp_tag_withdraw, uri = uri, hash = obj_hash).tail = "\n" rpki.relaxng.rrdp.assertValid(self.elt) def update_rsync_files(self, publication_base): + from errno import ENOENT min_path_len = len(publication_base.rstrip("/")) for pdu in self.elt: assert pdu.tag in (rrdp_tag_publish, rrdp_tag_withdraw) @@ -287,7 +288,7 @@ class Delta(models.Model): try: os.remove(fn) except OSError, e: - if e.errno != errno.ENOENT: + if e.errno != ENOENT: raise dn = os.path.dirname(fn) while len(dn) > min_path_len: @@ -307,6 +308,6 @@ class PublishedObject(models.Model): client = models.ForeignKey(Client) session = models.ForeignKey(Session) - class Meta: + class Meta: # pylint: disable=C1001,W0232 unique_together = (("session", "hash"), ("session", "uri")) diff --git a/rpki/publication.py b/rpki/publication.py index 117bd0ef..7939b9de 100644 --- a/rpki/publication.py +++ b/rpki/publication.py @@ -21,19 +21,14 @@ RPKI publication protocol. """ -import os -import errno import logging import rpki.x509 import rpki.exceptions import rpki.relaxng -from lxml.etree import Element, SubElement - logger = logging.getLogger(__name__) - nsmap = rpki.relaxng.publication.nsmap version = rpki.relaxng.publication.version diff --git a/rpki/publication_control.py b/rpki/publication_control.py index b5e08f3e..ddb9d417 100644 --- a/rpki/publication_control.py +++ b/rpki/publication_control.py @@ -25,7 +25,6 @@ protocol itself. """ import logging -import collections import rpki.x509 import rpki.exceptions diff --git a/rpki/rootd.py b/rpki/rootd.py index 1a669b97..1d4f5659 100644 --- a/rpki/rootd.py +++ b/rpki/rootd.py @@ -22,12 +22,9 @@ Trivial RPKI up-down protocol root server. """ import os -import sys import time import logging -import httplib import argparse -import urlparse import rpki.resource_set import rpki.up_down @@ -109,7 +106,10 @@ class main(object): def issue_subject_cert_maybe(self, new_pkcs10): now = rpki.sundial.now() subject_cert = self.get_subject_cert() - hash = None if subject_cert is None else rpki.x509.sha256(subject_cert.get_DER()).encode("hex") + 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) @@ -153,8 +153,8 @@ class main(object): 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 hash is not None: - pdu.set("hash", hash) + 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 @@ -172,14 +172,14 @@ class main(object): thisUpdate = now, nextUpdate = now + self.rpki_subject_regen, revokedCertificates = self.revoked) - hash = self.read_hash_maybe(self.rpki_root_crl_file) + 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 hash is not None: - pdu.set("hash", hash) + 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)) @@ -203,21 +203,21 @@ class main(object): names_and_objs = manifest_content, keypair = manifest_keypair, certs = manifest_cert) - hash = self.read_hash_maybe(self.rpki_root_manifest_file) + 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 hash is not None: - pdu.set("hash", hash) - hash = rpki.x509.sha256(self.rpki_root_cert.get_DER()).encode("hex") - if hash != self.rpki_root_cert_hash: + 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 = hash + self.rpki_root_cert_hash = cer_hash @staticmethod diff --git a/rpki/rpkic.py b/rpki/rpkic.py index eefa0116..ad695976 100644 --- a/rpki/rpkic.py +++ b/rpki/rpkic.py @@ -46,7 +46,7 @@ import rpki.x509 import rpki.async import rpki.version -from lxml.etree import Element, SubElement +from lxml.etree import SubElement from rpki.cli import Cmd, parsecmd, cmdarg diff --git a/rpki/rpkid.py b/rpki/rpkid.py index 8b9626cd..bc13cd9a 100644 --- a/rpki/rpkid.py +++ b/rpki/rpkid.py @@ -108,8 +108,8 @@ class main(object): import django django.setup() - global rpki - import rpki.rpkidb + global rpki # pylint: disable=W0602 + import rpki.rpkidb # pylint: disable=W0621 self.sql = rpki.sql.session(self.cfg) @@ -214,7 +214,7 @@ class main(object): def done(r_msg): if len(r_msg) != 1: raise rpki.exceptions.BadIRDBReply( - "Expected exactly one PDU from IRDB: %s" % r_cms.pretty_print_content()) + "Expected exactly one PDU from IRDB: %s" % r_msg.pretty_print_content()) callback(rpki.resource_set.resource_bag( asn = rpki.resource_set.resource_set_as(r_msg[0].get("asn")), v4 = rpki.resource_set.resource_set_ipv4(r_msg[0].get("ipv4")), @@ -261,7 +261,7 @@ class main(object): try: return self._left_right_models except AttributeError: - import rpki.rpkidb.models + import rpki.rpkidb.models # pylint: disable=W0621 self._left_right_models = { rpki.left_right.tag_self : rpki.rpkidb.models.Self, rpki.left_right.tag_bsc : rpki.rpkidb.models.BSC, @@ -326,7 +326,7 @@ class main(object): uri = g.uri, **kw).text = g.ghostbuster.get_Base64() for c in ca_detail.ee_certificates: - SubElement(r_msg, rpki.left_right.tag_list_published_objects, + SubElement(r_msg, rpki.left_right.tag_list_published_objects, uri = c.uri, **kw).text = c.cert.get_Base64() def handle_list_received_resources(self, q_pdu, r_msg): @@ -495,7 +495,7 @@ class main(object): obj.xml_template.acknowledge(obj, q_pdu, r_msg) else: - raise BadQuery + raise rpki.exceptions.BadQuery except (rpki.async.ExitNow, SystemExit): raise @@ -2804,21 +2804,21 @@ class publication_queue(object): logger.debug("Removing publication duplicate %r", self.uris[uri]) old_pdu = self.uris.pop(uri) self.msgs[rid].remove(old_pdu) - hash = old_pdu.get("hash") + pdu_hash = old_pdu.get("hash") elif old_hash is not None: - hash = old_hash + pdu_hash = old_hash elif old_obj is None: - hash = None + pdu_hash = None else: - hash = rpki.x509.sha256(old_obj.get_DER()).encode("hex") + pdu_hash = rpki.x509.sha256(old_obj.get_DER()).encode("hex") if new_obj is None: - pdu = SubElement(self.msgs[rid], rpki.publication.tag_withdraw, uri = uri, hash = hash) + pdu = SubElement(self.msgs[rid], rpki.publication.tag_withdraw, uri = uri, hash = pdu_hash) else: pdu = SubElement(self.msgs[rid], rpki.publication.tag_publish, uri = uri) pdu.text = new_obj.get_Base64() - if hash is not None: - pdu.set("hash", hash) + if pdu_hash is not None: + pdu.set("hash", pdu_hash) if handler is not None: tag = str(id(pdu)) diff --git a/rpki/rpkidb/models.py b/rpki/rpkidb/models.py index 163aee60..0a4346e0 100644 --- a/rpki/rpkidb/models.py +++ b/rpki/rpkidb/models.py @@ -5,6 +5,7 @@ Django ORM models for rpkid. from __future__ import unicode_literals import logging +import base64 from django.db import models @@ -14,7 +15,7 @@ from rpki.fields import (EnumField, SundialField, BlobField, CertificateField, KeyField, CRLField, PKCS10Field, ManifestField, ROAField, GhostbusterField) -from lxml.etree import Element, SubElement, tostring as ElementToString +from lxml.etree import Element, SubElement logger = logging.getLogger(__name__) @@ -134,7 +135,7 @@ class XMLTemplate(object): setattr(obj, k, self.element_type[k](Base64 = v)) -class XMLManager(models.Manager): +class XMLManager(models.Manager): # pylint: disable=W0232 """ Add a few methods which locate or create an object or objects corresponding to the handles in an XML element, as appropriate. @@ -273,7 +274,7 @@ class Self(models.Model): for c in ca_detail.ee_certificates.all(): reconcile(uri = c.uri, obj = c.cert, repository = repository) for u in objects: - h, r = objects[h] + h, r = objects[u] publisher.queue(uri = u, old_hash = h, repository = r) publisher.call_pubd(cb, eb) @@ -289,9 +290,11 @@ class Self(models.Model): def schedule_cron_tasks(self, completion): - if self.cron_tasks is None: - self.cron_tasks = tuple(task(self) for task in rpki.rpkid_tasks.task_classes) - for task in self.cron_tasks: + try: + tasks = self.cron_tasks + except AttributeError: + tasks = self.cron_tasks = tuple(task(self) for task in rpki.rpkid_tasks.task_classes) + for task in tasks: self.gctx.task_add(task) completion.register(task) @@ -323,7 +326,7 @@ class BSC(models.Model): self = models.ForeignKey(Self, related_name = "bscs") objects = XMLManager() - class Meta: + class Meta: # pylint: disable=C1001,W0232 unique_together = ("self", "bsc_handle") xml_template = XMLTemplate( @@ -351,7 +354,7 @@ class Repository(models.Model): self = models.ForeignKey(Self, related_name = "repositories") objects = XMLManager() - class Meta: + class Meta: # pylint: disable=C1001,W0232 unique_together = ("self", "repository_handle") xml_template = XMLTemplate( @@ -372,7 +375,7 @@ class Repository(models.Model): self.save() - def call_pubd(self, callback, errback, q_msg, handlers = {}, length_check = True): + def call_pubd(self, callback, errback, q_msg, handlers = {}, length_check = True): # pylint: disable=W0102 """ Send a message to publication daemon and return the response. @@ -443,7 +446,7 @@ class Parent(models.Model): repository = models.ForeignKey(Repository, related_name = "parents") objects = XMLManager() - class Meta: + class Meta: # pylint: disable=C1001,W0232 unique_together = ("self", "parent_handle") xml_template = XMLTemplate( @@ -609,7 +612,7 @@ class Parent(models.Model): raise rpki.exceptions.BSCNotFound("Could not find BSC") if self.bsc.signing_cert is None: - raise rpki.exceptions.BSCNotReady("BSC %r is not yet usable" % eslf.bsc.bsc_handle) + raise rpki.exceptions.BSCNotReady("BSC %r is not yet usable" % self.bsc.bsc_handle) q_der = rpki.up_down.cms_msg().wrap(q_msg, self.bsc.private_key_id, @@ -720,7 +723,7 @@ class CA(models.Model): logger.warning("SKI %s in resource class %s is in database but missing from list_response to %s from %s, " "maybe parent certificate went away?", ca_detail.public_key.gSKI(), class_name, parent.self.self_handle, parent.parent_handle) - publisher = publication_queue() + publisher = rpki.rpkid.publication_queue() ca_detail.destroy(ca = ca_detail.ca, publisher = publisher) return publisher.call_pubd(iterator, eb) if ca_detail.state == "active" and ca_detail.ca_cert_uri != rc_cert_uri: @@ -808,7 +811,7 @@ class CA(models.Model): logger.debug("Deleting %r", self) self.delete() callback() - publisher = publication_queue() + publisher = rpki.rpkid.publication_queue() for ca_detail in self.ca_details.all(): ca_detail.destroy(ca = self, publisher = publisher, allow_failure = True) publisher.call_pubd(done, lose) @@ -963,7 +966,7 @@ class CADetail(models.Model): Activate this ca_detail. """ - publisher = publication_queue() + publisher = rpki.rpkid.publication_queue() self.latest_ca_cert = cert self.ca_cert_uri = uri self.generate_manifest_cert() @@ -1053,7 +1056,7 @@ class CADetail(models.Model): nextUpdate = nextUpdate.later(self.latest_manifest.getNextUpdate()) if self.latest_crl is not None: nextUpdate = nextUpdate.later(self.latest_crl.getNextUpdate()) - publisher = publication_queue() + publisher = rpki.rpkid.publication_queue() for child_cert in self.child_certs.all(): nextUpdate = nextUpdate.later(child_cert.cert.getNotAfter()) child_cert.revoke(publisher = publisher) @@ -1091,7 +1094,7 @@ class CADetail(models.Model): if self.state == "pending": return self.activate(ca = ca, cert = cert, uri = cert_url, callback = callback, errback = errback) validity_changed = self.latest_ca_cert is None or self.latest_ca_cert.getNotAfter() != cert.getNotAfter() - publisher = publication_queue() + publisher = rpki.rpkid.publication_queue() if self.latest_ca_cert != cert: self.latest_ca_cert = cert self.save() @@ -1310,7 +1313,7 @@ class CADetail(models.Model): Reissue all current certificates issued by this ca_detail. """ - publisher = publication_queue() + publisher = rpki.rpkid.publication_queue() self.check_failed_publication(publisher) for roa in self.roas.all(): roa.regenerate(publisher, fast = True) @@ -1410,7 +1413,7 @@ class Child(models.Model): bsc = models.ForeignKey(BSC, related_name = "children") objects = XMLManager() - class Meta: + class Meta: # pylint: disable=C1001,W0232 unique_together = ("self", "child_handle") xml_template = XMLTemplate( @@ -1563,7 +1566,10 @@ class Child(models.Model): """ def done(): - callback(rpki.up_down.cms_msg().wrap(r_msg, bsc.private_key_id, bsc.signing_cert, bsc.signing_cert_crl)) + callback(rpki.up_down.cms_msg().wrap(r_msg, + self.bsc.private_key_id, + self.bsc.signing_cert, + self.bsc.signing_cert_crl)) def lose(e): logger.exception("Unhandled exception serving child %r", self) @@ -1582,7 +1588,7 @@ class Child(models.Model): q_type = q_msg.get("type") logger.info("Serving %s query from child %s [sender %s, recipient %s]", q_type, self.child_handle, q_msg.get("sender"), q_msg.get("recipient")) - if enforce_strict_up_down_xml_sender and q_msg.get("sender") != self.child_handle: + if rpki.up_down.enforce_strict_up_down_xml_sender and q_msg.get("sender") != self.child_handle: raise rpki.exceptions.BadSender("Unexpected XML sender %s" % q_msg.get("sender")) r_msg = Element(rpki.up_down.tag_message, nsmap = rpki.up_down.nsmap, version = rpki.up_down.version, @@ -1763,7 +1769,6 @@ class EECert(models.Model): """ cn, sn = subject_name.extract_cn_and_sn() - ca = ca_detail.ca sia = (None, None, ca_detail.ca.sia_uri + subject_key.gSKI() + ".cer", ca_detail.ca.parent.repository.rrdp_notification_uri) cert = ca_detail.issue_ee( ca = ca_detail.ca, @@ -2131,17 +2136,17 @@ class ROA(models.Model): v6 = rpki.resource_set.resource_set_ipv6(self.ipv6) if self.ca_detail is not None and self.ca_detail.state == "active" and not self.ca_detail.has_expired(): - logger.debug("Keeping old ca_detail %r for ROA %r", ca_detail, self) + logger.debug("Keeping old ca_detail %r for ROA %r", self.ca_detail, self) else: logger.debug("Searching for new ca_detail for ROA %r", self) for ca_detail in CADetail.objects.filter(ca__parent__self = self.self, state = "active"): resources = ca_detail.latest_ca_cert.get_3779resources() if not ca_detail.has_expired() and v4.issubset(resources.v4) and v6.issubset(resources.v6): + logger.debug("Using new ca_detail %r for ROA %r", ca_detail, self) + self.ca_detail = ca_detail break else: raise rpki.exceptions.NoCoveringCertForROA("Could not find a certificate covering %r" % self) - logger.debug("Using new ca_detail %r for ROA %r", ca_detail, self) - self.ca_detail = ca_detail resources = rpki.resource_set.resource_bag(v4 = v4, v6 = v6) keypair = rpki.x509.RSA.generate() @@ -2160,7 +2165,7 @@ class ROA(models.Model): repository = self.ca_detail.ca.parent.repository, handler = self.published_callback) if not fast: - ca_detail.generate_manifest(publisher = publisher) + self.ca_detail.generate_manifest(publisher = publisher) def published_callback(self, pdu): diff --git a/rpki/up_down.py b/rpki/up_down.py index fbd7b97f..1303647e 100644 --- a/rpki/up_down.py +++ b/rpki/up_down.py @@ -21,16 +21,14 @@ RPKI "up-down" protocol. """ -import base64 import logging -import lxml.etree import rpki.resource_set import rpki.x509 import rpki.exceptions import rpki.log import rpki.relaxng -from lxml.etree import Element, SubElement, tostring as ElementToString +from lxml.etree import SubElement, tostring as ElementToString logger = logging.getLogger(__name__) @@ -48,6 +46,11 @@ content_type = "application/x-rpki" # queries. allowed_content_types = ("application/rpki-updown", "application/x-rpki") +## @var enforce_strict_up_down_xml_sender +# Enforce strict checking of XML "sender" field in up-down protocol + +enforce_strict_up_down_xml_sender = False + tag_certificate = xmlns + "certificate" tag_class = xmlns + "class" tag_description = xmlns + "description" @@ -119,7 +122,7 @@ def check_response(r_msg, q_type): raise rpki.exceptions.UpstreamError(error_response_codes[int(r_msg.findtext(tag_status))]) if r_type != q_type + "_response": - raise UnexpectedUpDownResponse + raise rpki.exceptions.UnexpectedUpDownResponse if r_type == "issue_response" and (len(r_msg) != 1 or len(r_msg[0]) != 2): logger.debug("Weird issue_response %r: len(r_msg) %s len(r_msg[0]) %s", diff --git a/rpki/x509.py b/rpki/x509.py index b8a1bfa9..2d50b129 100644 --- a/rpki/x509.py +++ b/rpki/x509.py @@ -1107,6 +1107,8 @@ class PKCS10(DER_object): if any(uri.startswith("rsync://") and uri.endswith("/") for uri in rpkiManifest): raise rpki.exceptions.BadPKCS10("PKCS #10 CA SIA id-ad-rpkiManifest ends with slash") + if any(not uri.startswith("http://") and not uri.startswith("https://") for uri in rpkiNotify): + raise rpki.exceptions.BadPKCS10("PKCS #10 CA SIA id-ad-rpkiNotify neither HTTP nor HTTPS") def check_valid_request_ee(self): """ @@ -1151,6 +1153,8 @@ class PKCS10(DER_object): if signedObject and not any(uri.startswith("rsync://") for uri in signedObject): raise rpki.exceptions.BadPKCS10("PKCS #10 EE SIA id-ad-signedObject contains no rsync URIs") + if rpkiNotify and any(not uri.startswith("http://") and not uri.startswith("https://") for uri in rpkiNotify): + raise rpki.exceptions.BadPKCS10("PKCS #10 EE SIA id-ad-rpkiNotify neither HTTP nor HTTPS") def check_valid_request_router(self): """ |