diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/apnic-to-csv.py | 49 | ||||
-rw-r--r-- | scripts/arin-to-csv.py | 121 | ||||
-rw-r--r-- | scripts/convert-from-csv-to-entitydb.py | 233 | ||||
-rw-r--r-- | scripts/ripe-asns-to-csv.py | 106 | ||||
-rw-r--r-- | scripts/ripe-prefixes-to-csv.awk | 43 | ||||
-rw-r--r-- | scripts/test-myrpki-cms.py | 66 | ||||
-rw-r--r-- | scripts/testbed-rootcert.py | 65 | ||||
-rw-r--r-- | scripts/translate-handles.py | 49 | ||||
-rwxr-xr-x | scripts/verify-bpki.sh | 43 |
9 files changed, 775 insertions, 0 deletions
diff --git a/scripts/apnic-to-csv.py b/scripts/apnic-to-csv.py new file mode 100644 index 00000000..54e9137c --- /dev/null +++ b/scripts/apnic-to-csv.py @@ -0,0 +1,49 @@ +""" +Parse APNIC "Extended Allocation and Assignment" reports and write +out (just) the RPKI-relevant fields in myrpki-format CSV syntax. + +$Id$ + +Copyright (C) 2010 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. +""" + +import csv, myrpki, rpki.ipaddrs + +translations = dict((src, dst) for src, dst in myrpki.csv_reader("translations.csv", columns = 2)) + +asns = myrpki.csv_writer("asns.csv") +prefixes = myrpki.csv_writer("prefixes.csv") + +for line in open("delegated-apnic-extended-latest"): + + line = line.rstrip() + + if not line.startswith("apnic|") or line.endswith("|summary"): + continue + + registry, cc, rectype, start, value, date, status, opaque_id = line.split("|") + + assert registry == "apnic" + + opaque_id = translations.get(opaque_id, opaque_id) + + if rectype == "asn": + asns.writerow((opaque_id, "%s-%s" % (start, int(start) + int(value) - 1))) + + elif rectype == "ipv4": + prefixes.writerow((opaque_id, "%s-%s" % (start, rpki.ipaddrs.v4addr(rpki.ipaddrs.v4addr(start) + long(value) - 1)))) + + elif rectype == "ipv6": + prefixes.writerow((opaque_id, "%s/%s" % (start, value))) diff --git a/scripts/arin-to-csv.py b/scripts/arin-to-csv.py new file mode 100644 index 00000000..55e5762a --- /dev/null +++ b/scripts/arin-to-csv.py @@ -0,0 +1,121 @@ +""" +Parse a WHOIS research dump and write out (just) the RPKI-relevant +fields in myrpki-format CSV syntax. + +NB: The input data for this script comes from ARIN under an agreement +that allows research use but forbids redistribution, so if you think +you need a copy of the data, please talk to ARIN about it, not us. + +$Id$ + +Copyright (C) 2009 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. +""" + +import gzip, csv, myrpki + +class Handle(object): + + want_tags = () + + debug = False + + def set(self, tag, val): + if tag in self.want_tags: + setattr(self, tag, "".join(val.split(" "))) + + def check(self): + for tag in self.want_tags: + if not hasattr(self, tag): + return False + if self.debug: + print repr(self) + return True + +class ASHandle(Handle): + + want_tags = ("ASHandle", "ASNumber", "OrgID") + + def __repr__(self): + return "<%s %s.%s %s>" % (self.__class__.__name__, + self.OrgID, self.ASHandle, self.ASNumber) + + def finish(self, ctx): + if self.check(): + ctx.asns.writerow((ctx.translations.get(self.OrgID, self.OrgID), self.ASNumber)) + +class NetHandle(Handle): + + NetType = None + + want_tags = ("NetHandle", "NetRange", "NetType", "OrgID") + + def finish(self, ctx): + if self.NetType in ("allocation", "assignment") and self.check(): + ctx.prefixes.writerow((ctx.translations.get(self.OrgID, self.OrgID), self.NetRange)) + + def __repr__(self): + return "<%s %s.%s %s %s>" % (self.__class__.__name__, + self.OrgID, self.NetHandle, + self.NetType, self.NetRange) + +class V6NetHandle(NetHandle): + + want_tags = ("V6NetHandle", "NetRange", "NetType", "OrgID") + + def __repr__(self): + return "<%s %s.%s %s %s>" % (self.__class__.__name__, + ctx.translations.get(self.OrgID, self.OrgID), + self.V6NetHandle, self.NetType, self.NetRange) + +class main(object): + + types = { + "ASHandle" : ASHandle, + "NetHandle" : NetHandle, + "V6NetHandle" : V6NetHandle } + + translations = {} + + @staticmethod + def parseline(line): + tag, sep, val = line.partition(":") + assert sep, "Couldn't find separator in %r" % line + return tag.strip(), val.strip() + + def __init__(self): + self.asns = myrpki.csv_writer("asns.csv") + self.prefixes = myrpki.csv_writer("prefixes.csv") + try: + self.translations = dict((src, dst) for src, dst in myrpki.csv_reader("translations.csv", columns = 2)) + except IOError: + pass + f = gzip.open("arin_db.txt.gz") + cur = None + for line in f: + line = line.expandtabs().strip() + if not line: + if cur: + cur.finish(self) + cur = None + elif not line.startswith("#"): + tag, val = self.parseline(line) + if cur is None: + cur = self.types[tag]() if tag in self.types else False + if cur: + cur.set(tag, val) + if cur: + cur.finish(self) + +main() diff --git a/scripts/convert-from-csv-to-entitydb.py b/scripts/convert-from-csv-to-entitydb.py new file mode 100644 index 00000000..282d2e75 --- /dev/null +++ b/scripts/convert-from-csv-to-entitydb.py @@ -0,0 +1,233 @@ +""" +Convert {parents,children,pubclients}.csv into new XML formats. + +$Id$ + +Copyright (C) 2010 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. +""" + +import subprocess, csv, re, os, getopt, sys, base64, urlparse +import rpki.sundial, myrpki, rpki.config + +from lxml.etree import Element, SubElement, ElementTree + +section_regexp = re.compile("\s*\[\s*(.+?)\s*\]\s*$") +variable_regexp = re.compile("\s*([-a-zA-Z0-9_]+)(\s*=\s*)(.+?)\s*$") + +cfg_file = "myrpki.conf" +template_file = os.path.join(os.path.dirname(sys.argv[0]), "examples", "myrpki.conf") +new_cfg_file = None +preserve_valid_until = False + +opts, argv = getopt.getopt(sys.argv[1:], "c:hn:pt:?", ["config=", "new_config=", "preserve_valid_until", "template_config=", "help"]) +for o, a in opts: + if o in ("-h", "--help", "-?"): + print __doc__ + sys.exit(0) + elif o in ("-c", "--config"): + cfg_file = a + elif o in ("-n", "--new_config"): + new_cfg_file = a + elif o in ("-p", "--preserve_valid_until"): + preserve_valid_until = True + elif o in ("-t", "--template_config"): + template_file = a +if argv: + raise RuntimeError, "Unexpected arguments %r" % (argv,) +if os.path.samefile(cfg_file, template_file): + raise RuntimeError, "Old config and template for new config can't be the same file" +if new_cfg_file is None: + new_cfg_file = cfg_file + ".new" +if os.path.exists(new_cfg_file): + raise RuntimeError, "%s already exists, NOT overwriting" % new_cfg_file + +cfg = rpki.config.parser(cfg_file) + +# These have no counterparts in new config file, just read them from old + +repository_bpki_certificate = cfg.get(option = "repository_bpki_certificate", section = "myrpki") +repository_handle = cfg.get(option = "repository_handle", section = "myrpki") +parents_csv = cfg.get(option = "parents_csv", section = "myrpki", default = "parents.csv") +children_csv = cfg.get(option = "children_csv", section = "myrpki", default = "children.csv") +pubclients_csv = cfg.get(option = "pubclients_csv", section = "myrpki", default = "pubclients.csv") +pubd_base = cfg.get(option = "pubd_base", section = "myirbe") + +# Here we need to construct values for the new config file from the +# old one. Basic model here is to look at whatever variables need to +# be set in the template (mostly just the [myrpki], I hope), pull +# necessary data from old config file any way we can. Stuff that +# didn't make the jump from old config file to new we can just ignore, +# stuff that is automated via macro expansions in the new config file +# should be ok without modification. + +r = {} + +if cfg.has_section("myrpki"): + for i in ("handle", "roa_csv", "prefix_csv", "asn_csv", "xml_filename"): + r["myrpki", i] = cfg.get(section = "myrpki", option = i) + r["myrpki", "bpki_resources_directory"] = cfg.get(option = "bpki_directory", section = "myrpki") + +if cfg.has_section("myirbe"): + r["myrpki", "bpki_servers_directory"] = cfg.get(option = "bpki_directory", section = "myirbe") + r["myrpki", "run_rpkid"] = True + r["myrpki", "run_pubd"] = cfg.getboolean(option = "want_pubd", section = "myirbe", default = False) + r["myrpki", "run_rootd"] = cfg.getboolean(option = "want_rootd", section = "myirbe", default = False) +else: + for i in ("run_rpkid", "run_pubd", "run_rootd"): + r["myrpki", i] = False + +if cfg.has_section("rpkid"): + r["myrpki", "rpkid_server_host"] = cfg.get(option = "server-host", section = "rpkid") + r["myrpki", "rpkid_server_port"] = cfg.get(option = "server-port", section = "rpkid") + +if cfg.has_section("irdbd"): + u = urlparse.urlparse(cfg.get(option = "https-url", section = "irdbd")) + r["myrpki", "irdbd_server_host"] = u.hostname or "localhost" + r["myrpki", "irdbd_server_port"] = u.port or 443 + +if cfg.has_section("pubd"): + r["myrpki", "pubd_server_host"] = cfg.get(option = "server-host", section = "pubd") + r["myrpki", "pubd_server_port"] = cfg.get(option = "server-port", section = "pubd") + r["myrpki", "publication_base_directory"] = cfg.get(option = "publication-base", section = "pubd") + +if cfg.has_section("rootd"): + r["myrpki", "rootd_server_port"] = cfg.get(option = "server-port", section = "rootd") + u = urlparse.urlparse(cfg.get(option = "rpki-base-uri", section = "rootd")) + r["myrpki", "publication_rsync_server"] = u.netloc + +for i in ("rpkid", "irdbd", "pubd"): + if cfg.has_section(i): + for j in ("sql-database", "sql-username", "sql-password"): + r[i, j] = cfg.get(section = i, option = j) + +f = open(new_cfg_file, "w") +f.write("# Automatically converted from %s using %s as a template.\n\n" % (cfg_file, template_file)) +section = None +for line in open(template_file): + m = section_regexp.match(line) + if m: + section = m.group(1) + m = variable_regexp.match(line) + if m: + option, whitespace = m.group(1, 2) + else: + option = None + if (section, option) in r: + line = "%s%s%s\n" % (option, whitespace, r[section, option]) + f.write(line) +f.close() +print "Wrote", new_cfg_file + +# Get all of these from the new config file; in theory we just set all +# of them, but we want to use values matching new config in any case. + +newcfg = rpki.config.parser(new_cfg_file, "myrpki") + +handle = newcfg.get("handle") +bpki_resources_directory = newcfg.get("bpki_resources_directory") +bpki_servers_directory = newcfg.get("bpki_servers_directory") +pubd_server_host = newcfg.get("pubd_server_host") +pubd_server_port = newcfg.get("pubd_server_port") +rpkid_server_host = newcfg.get("rpkid_server_host") +rpkid_server_port = newcfg.get("rpkid_server_port") +entitydb_dir = newcfg.get("entitydb_dir", "entitydb") + +bpki_resources_pemfile = bpki_resources_directory + "/ca.cer" +bpki_servers_pemfile = bpki_servers_directory + "/ca.cer" + +def entitydb(*args): + return os.path.join(entitydb_dir, *args) + +# Now convert the .csv files. It'd be nice to have XML validation +# enabled for this, so try to turn it on ourselves if the magic +# environment variable hasn't already been set. + +rng_file = os.path.join(os.path.dirname(sys.argv[0]), "myrpki.rng") +if not os.getenv("MYRPKI_RNG") and os.path.exists(rng_file): + os.putenv("MYRPKI_RNG", rng_file) + +for d in map(entitydb, ("children", "parents", "repositories", "pubclients")): + if not os.path.exists(d): + os.makedirs(d) + +one_year_from_now = str(rpki.sundial.now() + rpki.sundial.timedelta(days = 365)) + +if os.path.exists(children_csv): + for child_handle, valid_until, child_resource_pemfile in myrpki.csv_reader(children_csv, columns = 3): + try: + + e = Element("parent", + valid_until = valid_until if preserve_valid_until else one_year_from_now, + service_uri = "https://%s:%s/up-down/%s/%s" % (rpkid_server_host, rpkid_server_port, handle, child_handle), + child_handle = child_handle, + parent_handle = handle) + myrpki.PEMElement(e, "bpki_resource_ta", bpki_resources_pemfile) + myrpki.PEMElement(e, "bpki_server_ta", bpki_servers_pemfile) + myrpki.PEMElement(e, "bpki_child_ta", child_resource_pemfile) + myrpki.etree_write(e, entitydb("children", "%s.xml" % child_handle)) + + except IOError: + pass + +if os.path.exists(parents_csv): + for parent_handle, parent_service_uri, parent_cms_pemfile, parent_https_pemfile, parent_myhandle, parent_sia_base in myrpki.csv_reader(parents_csv, columns = 6): + try: + + e = Element("parent", + valid_until = one_year_from_now, + service_uri = parent_service_uri, + child_handle = parent_myhandle, + parent_handle = parent_handle) + myrpki.PEMElement(e, "bpki_resource_ta", parent_cms_pemfile) + myrpki.PEMElement(e, "bpki_server_ta", parent_https_pemfile) + myrpki.PEMElement(e, "bpki_child_ta", bpki_resources_pemfile) + myrpki.etree_write(e, entitydb("parents", "%s.xml" % parent_handle)) + + client_handle = "/".join(parent_sia_base.rstrip("/").split("/")[3:]) + assert client_handle.startswith(repository_handle) + + e = Element("repository", + parent_handle = parent_handle, + client_handle = client_handle, + service_uri = "%s/client/%s" % (pubd_base.rstrip("/"), client_handle), + sia_base = parent_sia_base, + type = "confirmed") + myrpki.PEMElement(e, "bpki_server_ta", repository_bpki_certificate) + myrpki.PEMElement(e, "bpki_client_ta", bpki_resources_pemfile) + SubElement(e, "contact_info").text = "Automatically generated by convert-csv.py" + myrpki.etree_write(e, entitydb("repositories", "%s.xml" % parent_handle)) + + except IOError: + pass + +if os.path.exists(pubclients_csv): + for client_handle, client_resource_pemfile, client_sia_base in myrpki.csv_reader(pubclients_csv, columns = 3): + try: + + parent_handle = client_handle.split("/")[-2] if "/" in client_handle else handle + + e = Element("repository", + parent_handle = parent_handle, + client_handle = client_handle, + service_uri = "https://%s:%s/client/%s" % (pubd_server_host, pubd_server_port, client_handle), + sia_base = client_sia_base, + type = "confirmed") + myrpki.PEMElement(e, "bpki_server_ta", bpki_servers_pemfile) + myrpki.PEMElement(e, "bpki_client_ta", client_resource_pemfile) + SubElement(e, "contact_info").text = "Automatically generated by convert-csv.py" + myrpki.etree_write(e, entitydb("pubclients", "%s.xml" % client_handle.replace("/", "."))) + + except IOError: + pass diff --git a/scripts/ripe-asns-to-csv.py b/scripts/ripe-asns-to-csv.py new file mode 100644 index 00000000..04a92627 --- /dev/null +++ b/scripts/ripe-asns-to-csv.py @@ -0,0 +1,106 @@ +""" +Parse a WHOIS research dump and write out (just) the RPKI-relevant +fields in myrpki-format CSV syntax. + +NB: The input data for this script is publicly available via FTP, but +you'll have to fetch the data from RIPE yourself, and be sure to see +the terms and conditions referenced by the data file header comments. + +$Id$ + +Copyright (C) 2009 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. +""" + +import gzip, csv, myrpki + +class Handle(dict): + + want_tags = () + + debug = False + + def set(self, tag, val): + if tag in self.want_tags: + self[tag] = "".join(val.split(" ")) + + def check(self): + for tag in self.want_tags: + if not tag in self: + return False + if self.debug: + self.log() + return True + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, + " ".join("%s:%s" % (tag, self.get(tag, "?")) + for tag in self.want_tags)) + + def log(self): + print repr(self) + + def finish(self, ctx): + self.check() + +class aut_num(Handle): + want_tags = ("aut-num", "mnt-by", "as-name") + + def set(self, tag, val): + if tag == "aut-num" and val.startswith("AS"): + val = val[2:] + Handle.set(self, tag, val) + + def finish(self, ctx): + if self.check(): + ctx.asns.writerow((self["mnt-by"], self["aut-num"])) + +class main(object): + + types = dict((x.want_tags[0], x) for x in (aut_num,)) + + + def finish_statement(self, done): + if self.statement: + tag, sep, val = self.statement.partition(":") + assert sep, "Couldn't find separator in %r" % self.statement + tag = tag.strip().lower() + val = val.strip().upper() + if self.cur is None: + self.cur = self.types[tag]() if tag in self.types else False + if self.cur is not False: + self.cur.set(tag, val) + if done and self.cur: + self.cur.finish(self) + self.cur = None + + filenames = ("ripe.db.aut-num.gz",) + + def __init__(self): + self.asns = myrpki.csv_writer("asns.csv") + for fn in self.filenames: + f = gzip.open(fn) + self.statement = "" + self.cur = None + for line in f: + line = line.expandtabs().partition("#")[0].rstrip("\n") + if line and not line[0].isalpha(): + self.statement += line[1:] if line[0] == "+" else line + else: + self.finish_statement(not line) + self.statement = line + self.finish_statement(True) + f.close() + +main() diff --git a/scripts/ripe-prefixes-to-csv.awk b/scripts/ripe-prefixes-to-csv.awk new file mode 100644 index 00000000..582d5ce7 --- /dev/null +++ b/scripts/ripe-prefixes-to-csv.awk @@ -0,0 +1,43 @@ +#!/usr/bin/awk -f +# $Id$ + +# ftp -pa ftp://ftp.ripe.net/pub/stats/ripencc/membership/alloclist.txt + +BEGIN { + translation["ie.google"] = "GoogleIreland"; +} + +function done() { + if (handle in translation) + handle = translation[handle]; + for (i = 1; i <= n_allocs; i++) + print handle "\t" alloc[i]; + n_allocs = 0; +} + +/^[a-z]/ { + done(); + handle = $0; + nr = NR; +} + +NR == nr + 1 { + name = $0; +} + +NR > nr + 2 && NF > 1 && $2 !~ /:/ { + split($2, a, "/"); + len = a[2]; + split(a[1], a, /[.]/); + for (i = length(a); i < 4; i++) + a[i+1] = 0; + alloc[++n_allocs] = sprintf("%d.%d.%d.%d/%d", a[1], a[2], a[3], a[4], len); +} + +NR > nr + 2 && NF > 1 && $2 ~ /:/ { + alloc[++n_allocs] = $2; +} + +END { + done(); +} diff --git a/scripts/test-myrpki-cms.py b/scripts/test-myrpki-cms.py new file mode 100644 index 00000000..29bea39c --- /dev/null +++ b/scripts/test-myrpki-cms.py @@ -0,0 +1,66 @@ +""" +Scratch pad for working out what CMS referral code looks like. + +This is only in subversion for archival and backup, I don't expect +users to run this, and will delete it in the near future. + + +$Id$ + +Copyright (C) 2010 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. +""" + +import subprocess, os, sys, myrpki + +original_xml = '''\ +<publication_referral xmlns="http://www.hactrn.net/uris/rpki/publication-spec/" + sia_base=rsync://repository.example/path/to/me/space-i-give-to-my-child"> + Base64 encoded BPKI TA of resource holding aspect of my child xxx blah blah blah blah xxx +</publication_referral> +''' + +f = open("original.xml", "w") +f.write(original_xml) +f.close() + +myrpki.openssl = "/u/sra/rpki/subvert-rpki.hactrn.net/openssl/openssl/apps/openssl" +os.putenv("OPENSSL_CONF", "/dev/null") + +bpki = myrpki.CA("test/Alice/myrpki.conf", "test/Alice/bpki/resources") +bpki.ee("/CN=Alice Signed Referral CMS Test EE Certificate", "CMSEE") + +# "id-ct-xml" from rpki.oids +oid = ".".join(map(str, (1, 2, 840, 113549, 1, 9, 16, 1, 28))) + +format = "DER" # PEM or DER + +subprocess.check_call((myrpki.openssl, "cms", "-sign", + "-binary", "-nodetach", "-nosmimecap", "-keyid", "-outform", format, + "-econtent_type", oid, "-md", "sha256", + "-inkey", "test/Alice/bpki/resources/CMSEE.key", + "-signer", "test/Alice/bpki/resources/CMSEE.cer", + "-in", "original.xml", + "-out", "original.%s" % format.lower())) + +if format == "DER": + subprocess.call(("dumpasn1", "-a", "original.cms")) + +# verifying may not be necessary here, that might be pubd's job. or +# at least we can make it the job of the code formerly known as irdbd, +# where we have full libraries available to us. but blunder ahead... + +subprocess.check_call((myrpki.openssl, "cms", "-verify", "-inform", format, + "-CAfile", "test/Alice/bpki/resources/ca.cer", + "-in", "original.%s" % format.lower())) diff --git a/scripts/testbed-rootcert.py b/scripts/testbed-rootcert.py new file mode 100644 index 00000000..54d1480c --- /dev/null +++ b/scripts/testbed-rootcert.py @@ -0,0 +1,65 @@ +""" +Generate config for a test RPKI root certificate for resources +specified in asns.csv and prefixes.csv. + +This script is separate from arin-to-csv.py so that we can convert on +the fly rather than having to pull the entire database into memory. + +$Id$ + +Copyright (C) 2009-2010 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. +""" + +import csv, myrpki, sys + +if len(sys.argv) != 2: + raise RuntimeError, "Usage: %s [holder]" % sys.argv[0] + +print '''\ +[req] +default_bits = 2048 +default_md = sha256 +distinguished_name = req_dn +prompt = no +encrypt_key = no + +[req_dn] +CN = Pseudo-%(HOLDER)s testbed root RPKI certificate + +[x509v3_extensions] +basicConstraints = critical,CA:true +subjectKeyIdentifier = hash +keyUsage = critical,keyCertSign,cRLSign +subjectInfoAccess = 1.3.6.1.5.5.7.48.5;URI:rsync://%(holder)s.rpki.net/rpki/%(holder)s/,1.3.6.1.5.5.7.48.10;URI:rsync://%(holder)s.rpki.net/rpki/%(holder)s/root.mnf +certificatePolicies = critical,1.3.6.1.5.5.7.14.2 +sbgp-autonomousSysNum = critical,@rfc3779_asns +sbgp-ipAddrBlock = critical,@rfc3997_addrs + +[rfc3779_asns] +''' % { "holder" : sys.argv[1].lower(), + "HOLDER" : sys.argv[1].upper() } + +for i, asn in enumerate(asn for handle, asn in myrpki.csv_reader("asns.csv", columns = 2)): + print "AS.%d = %s" % (i, asn) + +print '''\ + +[rfc3997_addrs] + +''' + +for i, prefix in enumerate(prefix for handle, prefix in myrpki.csv_reader("prefixes.csv", columns = 2)): + v = 6 if ":" in prefix else 4 + print "IPv%d.%d = %s" % (v, i, prefix) diff --git a/scripts/translate-handles.py b/scripts/translate-handles.py new file mode 100644 index 00000000..308b878e --- /dev/null +++ b/scripts/translate-handles.py @@ -0,0 +1,49 @@ +""" +Translate handles from the ones provided in a database dump into the +ones we use in our testbed. This has been broken out into a separate +program for two reasons: + +- Conversion of some of the RIR data is a very slow process, and it's + both annoying and unnecessary to run it every time we add a new + participant to the testbed. + +- This handle translation business now has fingers into half a dozen + scripts, so it needs refactoring in any case, either as a common + library function or as a separate script. + +This program takes a list of .CSV files on its command line, and +rewrites them as needed after performing the translation. + +$Id$ + +Copyright (C) 2010 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. +""" + +import os, sys, myrpki + +translations = dict((src, dst) for src, dst in myrpki.csv_reader("translations.csv", columns = 2)) + +for filename in sys.argv[1:]: + + tmpfile = "%s.%d" % os.getpid() + csvout = myrpki.csv_writer(tmpfile) + + for cols in myrpki.csv_reader(filename): + if cols[0] in translations: + cols[0] = translations[cols[0]] + csvout(cols) + + del csvout + os.rename(tmpfile, filename) diff --git a/scripts/verify-bpki.sh b/scripts/verify-bpki.sh new file mode 100755 index 00000000..0e36d796 --- /dev/null +++ b/scripts/verify-bpki.sh @@ -0,0 +1,43 @@ +#!/bin/sh - +# $Id$ +# +# Copyright (C) 2009-2010 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. + +# Tests of generated BPKI certificates. Kind of cheesy, but does test +# the basic stuff. + +exec 2>&1 + +for bpki in bpki/* +do + crls=$(find $bpki -name '*.crl') + + # Check that CRLs verify properly + for crl in $crls + do + echo -n "$crl: " + openssl crl -CAfile $bpki/ca.cer -noout -in $crl + done + + # Check that issued certificates verify properly + cat $bpki/ca.cer $crls | openssl verify -crl_check -CAfile /dev/stdin $(find $bpki -name '*.cer' ! -name 'ca.cer' ! -name '*.cacert.cer') + +done + +# Check that cross-certified BSC certificates verify properly +if test -d bpki/servers +then + cat bpki/servers/xcert.*.cer | openssl verify -verbose -CAfile bpki/servers/ca.cer -untrusted /dev/stdin bpki/resources/bsc.*.cer +fi |