diff options
-rw-r--r-- | myrpki.rototill/PLAN | 75 | ||||
-rw-r--r-- | myrpki.rototill/examples/myrpki.conf | 6 | ||||
-rw-r--r-- | myrpki.rototill/myrpki.py | 238 | ||||
-rw-r--r-- | myrpki.rototill/myrpki.rnc | 41 | ||||
-rw-r--r-- | myrpki.rototill/myrpki.rng | 100 | ||||
-rw-r--r-- | myrpki.rototill/yamltest.py | 3 |
6 files changed, 281 insertions, 182 deletions
diff --git a/myrpki.rototill/PLAN b/myrpki.rototill/PLAN index e42ee79f..92fc8bd7 100644 --- a/myrpki.rototill/PLAN +++ b/myrpki.rototill/PLAN @@ -326,3 +326,78 @@ Step 3: setup_client.py (icky name) reads, um, self.xml and parent's Step 4: Have not yet completely worked out whether publication data from step 3 becomes part of self.xml object. Perhaps. + + +long comment from do_configure_publication_client(), so long that it +was obscuring the code: + + # Critical thing at this point is to figure out what client's + # sia_base value should be. Three cases: + # + # - client has no particular relationship to any other client: + # sia_base is top-level, or as close as we can make it taking + # rsyncd module into account (maybe homed under us, hmm, how do + # we detect case where we are talking to ourself?) + # + # - client is a direct child of ours to whom we (in our parent + # role) made an offer of publication service. client homes + # under us, presumably. + # + # - client is a child of a client of ours who referred the new + # client to us, along with a signed referral. signed referral + # includes sia_base of referring client, new client homes under + # that per referring client's wishes. + # + # ... which implies that there's a fourth case, where we are both + # the client and the server. + + # Checking of signed referrals goes somewhere around here. Must + # be after reading client's XML, but before deciding what the + # client's sia_base and handle will be. + + # Ok, so we end up with four cases in terms of our checking: + # + # - Signed referral provided. Must be signed by existing client + # (somebody already listed in entitydb/pubclients/, suggesting + # that it might be useful to include ski there as an XML field? + # or maybe just outer unsigned XML wrapper that expresses the + # referral include handle of referrer so we can look up + # directly? yeah, that). sia_base offered (within inner signed + # referral XML) must be underneath signing client's space (so + # we'd have to look up the signing client entitydb data for that + # anyway). + # + # Case trivially detectable by presence of signed referral. + # + # - Client is direct child of entity running pubd, so entity + # running pubd clearly has the right to offer service to its + # children. So just assign publication location to child after + # checking that this really is a child of ours (ie, must be in + # entitydb/children). + # + # Detectable by handle being listed in entitydb/children. + # + # - Client is self, ie, entity that runs pubd is its own client. + # Trivial to check (handle and BPKI match). This gets top-level + # (rsyncd module) name. + # + # Detectable by handle matching ours. + # + # - All other cases get top-level directories of their own, no + # nesting. I guess such can go under an APNIC-style customers + # rsyncd module, or something like that. + # + # Detectable by none of the other cases matching. + + # All of which would be OK except that I don't know how to map it + # into Randy's view of a single pubd running multiple rsyncd + # modules. Part of the problem there is that rsyncd.conf has to + # be updated whenever a new module is added, we can't do it + # automatically. + # + # Perhaps (just suggested on testbed list) our rsync URIs should look like: + # + # rsync://host[:port]/arbitrarymodule/client_handle + # + # where arbitrarymodule defaults to "rpki" and has no particular + # relationship to any client_handle. diff --git a/myrpki.rototill/examples/myrpki.conf b/myrpki.rototill/examples/myrpki.conf index 3321e2ed..a2ea7302 100644 --- a/myrpki.rototill/examples/myrpki.conf +++ b/myrpki.rototill/examples/myrpki.conf @@ -114,6 +114,12 @@ publication_rsync_module = rpki publication_rsync_server = ${myrpki::pubd_server_host} +# Name of OpenSSL binary. You might need to change this if you have +# no system copy installed, or if the system copy doesn't support CMS. +# The copy of openssl built by this package should suffice. + +openssl = openssl + ################################################################# [rpkid] diff --git a/myrpki.rototill/myrpki.py b/myrpki.rototill/myrpki.py index 13398be6..82a88386 100644 --- a/myrpki.rototill/myrpki.py +++ b/myrpki.rototill/myrpki.py @@ -516,8 +516,8 @@ class CA(object): path_restriction = { 0 : "ca_x509_ext_xcert0", 1 : "ca_x509_ext_xcert1" } - def __init__(self, cfg, dir): - self.cfg = cfg + def __init__(self, cfg_file, dir): + self.cfg = cfg_file self.dir = dir self.cer = dir + "/ca.cer" self.key = dir + "/ca.key" @@ -527,16 +527,36 @@ class CA(object): self.serial = dir + "/serial" self.crlnum = dir + "/crl_number" + cfg = rpki.config.parser(cfg_file, "myrpki") + self.openssl = cfg.get("openssl", "openssl") + self.env = { "PATH" : os.environ["PATH"], "BPKI_DIRECTORY" : dir, - "RANDFILE" : ".OpenSSL.whines.unless.I.set.this" } + "RANDFILE" : ".OpenSSL.whines.unless.I.set.this", + "OPENSSL_CONF" : cfg_file } + + def run_openssl(self, *cmd, **kwargs): + """ + Run an OpenSSL command, suppresses stderr unless OpenSSL returns + failure, and returns stdout. + """ + stdin = kwargs.pop("stdin", None) + env = self.env.copy() + env.update(kwargs) + cmd = (self.openssl,) + cmd + p = subprocess.Popen(cmd, env = env, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) + stdout, stderr = p.communicate(stdin) + if p.wait() != 0: + sys.stderr.write("OpenSSL reported: " + stderr + "\n") + raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) + return stdout def run_ca(self, *args): """ Run OpenSSL "ca" command with tailored environment variables and common initial arguments. "ca" is rather chatty, so we suppress its output except on errors. """ - cmd = (openssl, "ca", "-batch", "-config", self.cfg) + args + cmd = (self.openssl, "ca", "-batch", "-config", self.cfg) + args p = subprocess.Popen(cmd, env = self.env, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) log = p.communicate()[0] if p.wait() != 0: @@ -548,9 +568,12 @@ class CA(object): Run OpenSSL "req" command with tailored environment variables and common arguments. "req" is rather chatty, so we suppress its output except on errors. """ - if not os.path.exists(key_file) or not os.path.exists(req_file): - cmd = (openssl, "req", "-new", "-sha256", "-newkey", "rsa:2048", - "-config", self.cfg, "-keyout", key_file, "-out", req_file) + if not os.path.exists(key_file): + self.run_openssl("genrsa", "-out", key_file, "2048") + if not os.path.exists(req_file): + cmd = (self.openssl, "req", "-new", "-sha256", "-config", self.cfg, + "-key", key_file, + "-out", req_file) p = subprocess.Popen(cmd, env = self.env, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) log = p.communicate()[0] if p.wait() != 0: @@ -612,33 +635,51 @@ class CA(object): """ Sign an XML object with CMS, return Base64 text. """ - oid = ".".join(str(i) for i in rpki.oids.name2oid("id-ct-xml")) - cmd = (openssl, "cms", "-sign", "-binary", "-nodetach", "-nosmimecap", + self.ee(ee_name, base_name) + xml = ElementToString(etree_pre_write(elt)) + oid = ".".join(str(i) for i in rpki.oids.name2oid["id-ct-xml"]) + cmd = (self.openssl, "cms", "-sign", "-binary", "-nodetach", "-nosmimecap", "-keyid", "-outform", "DER", "-md", "sha256", "-econtent_type", oid, "-inkey", "%s/%s.key" % (self.dir, base_name), "-signer", "%s/%s.cer" % (self.dir, base_name)) - p = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE) - cms = p.communicate(etree_pre_write(ElementToString(elt)))[0] + p = subprocess.Popen(cmd, env = self.env, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) + cms, err = p.communicate(xml) if p.wait() != 0: + sys.stderr.write("OpenSSL reported: " + err + "\n") raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) return base64.b64encode(cms) - def cms_xml_verify(self, cms, ca): + def cms_xml_verify(self, b64, ca): """ Attempt to verify and extract XML from a Base64-encoded signed CMS object. CA is the filename of a certificate that we expect to be the issuer of the EE certificate bundled with the CMS, and must previously have been cross-certified under our trust anchor. """ - cmd = (openssl, "cms", "-verify", "-inform", "DER", - "-CAfile", self.cer, "-certfile", ca) - p = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE) - xml, err = p.communicate(base64.b64decode(cms)) - if p.wait() != 0: - if err: - sys.stderr("OpenSSL reported: " + err + "\n") - raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) - return etree_post_read(ElementFromString(xml)) + + # In theory, we should be able to use the -certfile parameter to + # pass in the CA certificate, but in practice, I have never gotten + # this to work, either with the command line tool or in the + # OpenSSL C API. Dunno why. Passing both TA and CA via -CAfile + # does work, so we do that, using a temporary file, sigh. + + CAfile = os.path.join(self.dir, "temp.%s.pem" % os.getpid()) + try: + f = open(CAfile, "w") + f.write(open(self.cer).read()) + f.write(open(ca).read()) + f.close() + cmd = (self.openssl, "cms", "-verify", "-inform", "DER", "-CAfile", CAfile) + p = subprocess.Popen(cmd, env = self.env, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) + xml, err = p.communicate(base64.b64decode(b64)) + if p.wait() != 0: + if err: + sys.stderr.write("OpenSSL reported: " + err + "\n") + raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) + return etree_post_read(ElementFromString(xml)) + finally: + if os.path.exists(CAfile): + os.unlink(CAfile) def bsc(self, pkcs10): """ @@ -652,8 +693,8 @@ class CA(object): assert pkcs10 - cmd = (openssl, "dgst", "-md5") - p = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE) + cmd = (self.openssl, "dgst", "-md5") + p = subprocess.Popen(cmd, env = self.env, stdin = subprocess.PIPE, stdout = subprocess.PIPE) hash = p.communicate(pkcs10)[0].strip() if p.wait() != 0: raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) @@ -663,8 +704,8 @@ class CA(object): if not os.path.exists(cer_file): - cmd = (openssl, "req", "-inform", "DER", "-out", req_file) - p = subprocess.Popen(cmd, stdin = subprocess.PIPE) + cmd = (self.openssl, "req", "-inform", "DER", "-out", req_file) + p = subprocess.Popen(cmd, env = self.env, stdin = subprocess.PIPE) p.communicate(pkcs10) if p.wait() != 0: raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) @@ -679,8 +720,8 @@ class CA(object): """ fn = os.path.join(self.dir, filename or "temp.%s.cer" % os.getpid()) try: - cmd = (openssl, "x509", "-inform", "DER", "-out", fn) - p = subprocess.Popen(cmd, stdin = subprocess.PIPE) + cmd = (self.openssl, "x509", "-inform", "DER", "-out", fn) + p = subprocess.Popen(cmd, env = self.env, stdin = subprocess.PIPE) p.communicate(base64.b64decode(b64)) if p.wait() != 0: raise subprocess.CalledProcessError(returncode = p.returncode, cmd = cmd) @@ -705,26 +746,31 @@ class CA(object): # Extract public key and subject name from PEM file and hash it so # we can use the result as a tag for cross-certifying this cert. - cmd1 = (openssl, "x509", "-noout", "-pubkey", "-subject", "-in", cert) - cmd2 = (openssl, "dgst", "-md5") + cmd1 = (self.openssl, "x509", "-noout", "-pubkey", "-subject", "-in", cert) + cmd2 = (self.openssl, "dgst", "-md5") - p1 = subprocess.Popen(cmd1, stdout = subprocess.PIPE) - p2 = subprocess.Popen(cmd2, stdin = p1.stdout, stdout = subprocess.PIPE) + p1 = subprocess.Popen(cmd1, env = self.env, stdout = subprocess.PIPE) + p2 = subprocess.Popen(cmd2, env = self.env, stdin = p1.stdout, stdout = subprocess.PIPE) - xcert = "%s/xcert.%s.cer" % (self.dir, p2.communicate()[0].strip()) + hash = p2.communicate()[0] if p1.wait() != 0: raise subprocess.CalledProcessError(returncode = p1.returncode, cmd = cmd1) if p2.wait() != 0: raise subprocess.CalledProcessError(returncode = p2.returncode, cmd = cmd2) + # Sigh. Idiots just couldn't leave well enough alone. + hash = "".join(hash.split()) + if hash.startswith("(stdin)="): + hash = hash[len("(stdin)="):] + # Cross-certify the cert we were given, if we haven't already. # This only works for self-signed certs, due to limitations of the # OpenSSL command line tool, but that suffices for our purposes. + xcert = "%s/xcert.%s.cer" % (self.dir, hash.strip()) if not os.path.exists(xcert): self.run_ca("-ss_cert", cert, "-out", xcert, "-extensions", self.path_restriction[path_restriction]) - return xcert def etree_validate(e): @@ -795,9 +841,11 @@ def etree_post_read(e, validate = True): raise RuntimeError, "XML tag %r is not in namespace %r" % (i.tag, namespace) return e -# When this file is run as a script, run main() with command line -# arguments. main() can't use sys.argv directly as that might be the -# command line for some other program that loads this module. +def b64_equal(thing1, thing2): + """ + Compare two Base64-encoded values for equality. + """ + return "".join(thing1.split()) == "".join(thing2.split()) @@ -843,9 +891,6 @@ class main(rpki.cli.Cmd): self.cfg = rpki.config.parser(self.cfg_file, "myrpki") - global openssl - openssl = self.cfg.get("openssl", "openssl") - self.histfile = self.cfg.get("history_file", ".setup_history") self.handle = self.cfg.get("handle") self.run_rpkid = self.cfg.getboolean("run_rpkid") @@ -941,8 +986,8 @@ class main(rpki.cli.Cmd): if self.run_pubd: e = Element("repository", type = "request", handle = self.handle, parent_handle = self.handle) - SubElement(e, "contact_info").text = self.pubd_contact_info PEMElement(e, "bpki_ta", self.bpki_resources.cer) + SubElement(e, "contact_info").text = self.pubd_contact_info etree_write(e, self.entitydb("repositories", "%s.xml" % self.handle)) @@ -1012,11 +1057,14 @@ class main(rpki.cli.Cmd): if repo_handle == self.handle: SubElement(e, "repository", type = "offer") else: - r = SubElement(e, "repository", type = "hint", - proposed_sia_base = repo.get("sia_base") + child_handle + "/") + proposed_sia_base = repo.get("sia_base") + child_handle + "/" + r = Element("referral", authorized_sia_base = proposed_sia_base) + r.text = c.findtext("bpki_ta") + auth = self.bpki_resources.cms_xml_sign( + "/CN=%s Publication Referral" % self.handle, "referral", r) + r = SubElement(e, "repository", type = "referral") + SubElement(r, "authorization", referrer = repo.get("client_handle")).text = auth SubElement(r, "contact_info").text = repo.findtext("contact_info") - # CMS-signed blob authorizing use of part of our space by our - # child goes here, once I've written that code. except RuntimeError, err: print err @@ -1030,10 +1078,10 @@ class main(rpki.cli.Cmd): the parent's configure_child command as input. This command reads the parent's response XML, extracts the parent's BPKI and service URI information, cross-certifies the parent's BPKI data into this - entity's BPKI, and checks for offers or hints of publication - service. If a publication offer or hint is present, this command - generates a request-for-service message to that repository, in - case the user wants to avail herself of the hint or off. + entity's BPKI, and checks for offers or referrals of publication + service. If a publication offer or referral is present, we + generate a request-for-service message to that repository, in case + the user wants to avail herself of the referral or offer. """ parent_handle = None @@ -1061,14 +1109,14 @@ class main(rpki.cli.Cmd): r = p.find("repository") - if r is not None and r.get("type") in ("offer", "hint"): + if r is not None and r.get("type") in ("offer", "referral"): r.set("handle", self.handle) r.set("parent_handle", parent_handle) PEMElement(r, "bpki_ta", self.bpki_resources.cer) etree_write(r, self.entitydb("repositories", "%s.xml" % parent_handle)) else: - print "Couldn't find repository offer or hint" + print "Couldn't find repository offer or referral" def do_configure_publication_client(self, arg): @@ -1092,83 +1140,23 @@ class main(rpki.cli.Cmd): c = etree_read(argv[0]) - # Critical thing at this point is to figure out what client's - # sia_base value should be. Three cases: - # - # - client has no particular relationship to any other client: - # sia_base is top-level, or as close as we can make it taking - # rsyncd module into account (maybe homed under us, hmm, how do - # we detect case where we are talking to ourself?) - # - # - client is a direct child of ours to whom we (in our parent - # role) made an offer of publication service. client homes - # under us, presumably. - # - # - client is a child of a client of ours who referred the new - # client to us, along with a signed referral. signed referral - # includes sia_base of referring client, new client homes under - # that per referring client's wishes. - # - # ... which implies that there's a fourth case, where we are both - # the client and the server. - - # Checking of signed referrals goes somewhere around here. Must - # be after reading client's XML, but before deciding what the - # client's sia_base and handle will be. - - # Ok, so we end up with four cases in terms of our checking: - # - # - Signed referral provided. Must be signed by existing client - # (somebody already listed in entitydb/pubclients/, suggesting - # that it might be useful to include ski there as an XML field? - # or maybe just outer unsigned XML wrapper that expresses the - # hint include handle of referrer so we can look up directly? - # yeah, that). sia_base offered (within inner signed referral - # XML) must be underneath signing client's space (so we'd have - # to look up the signing client entitydb data for that anyway). - # - # Case trivially detectable by presence of signed referral. - # - # - Client is direct child of entity running pubd, so entity - # running pubd clearly has the right to offer service to its - # children. So just assign publication location to child after - # checking that this really is a child of ours (ie, must be in - # entitydb/children). - # - # Detectable by handle being listed in entitydb/children. - # - # - Client is self, ie, entity that runs pubd is its own client. - # Trivial to check (handle and BPKI match). This gets top-level - # (rsyncd module) name. - # - # Detectable by handle matching ours. - # - # - All other cases get top-level directories of their own, no - # nesting. I guess such can go under an APNIC-style customers - # rsyncd module, or something like that. - # - # Detectable by none of the other cases matching. - - # All of which would be OK except that I don't know how to map it - # into Randy's view of a single pubd running multiple rsyncd - # modules. Part of the problem there is that rsyncd.conf has to - # be updated whenever a new module is added, we can't do it - # automatically. - # - # Perhaps (just suggested on testbed list) our rsync URIs should look like: - # - # rsync://host[:port]/arbitrarymodule/client_handle - # - # where arbitrarymodule defaults to "rpki" and has no particular - # relationship to any client_handle. - - # For the moment we cheat egregiously, no crypto, blind trust of - # what we're sent, while I focus on the basic semantics. - if sia_base is None: - if c.get("proposed_sia_base"): - sia_base = c.get("proposed_sia_base") + auth = c.find("authorization") + if auth is not None: + try: + referrer = etree_read(self.entitydb("pubclients", "%s.xml" % auth.get("referrer").replace("/","."))) + referrer = self.bpki_servers.fxcert(referrer.findtext("bpki_client_ta")) + referral = self.bpki_servers.cms_xml_verify(auth.text, referrer) + if not b64_equal(referral.text, c.findtext("bpki_ta")): + raise RuntimeError, "Referral trust anchor does not match" + sia_base = referral.get("authorized_sia_base") + + except: + # Yes we need better handling than this + print "Couldn't process referral:" + raise + else: sia_base = "rsync://%s/%s/%s/" % (self.rsync_server, self.rsync_module, self.handle) if c.get("handle") != self.handle: diff --git a/myrpki.rototill/myrpki.rnc b/myrpki.rototill/myrpki.rnc index e2e18b33..98dcbbc7 100644 --- a/myrpki.rototill/myrpki.rnc +++ b/myrpki.rototill/myrpki.rnc @@ -21,6 +21,7 @@ start |= myrpki_pdu start |= identity_pdu start |= parent_pdu start |= repository_pdu +start |= referral_pdu myrpki_pdu = element myrpki { attribute version { version }, @@ -71,13 +72,16 @@ parent_pdu = element parent { attribute service_uri { uri }?, attribute child_handle { object_handle }, attribute parent_handle { object_handle }, - element bpki_resource_ta { base64 }?, - element bpki_server_ta { base64 }?, - element bpki_child_ta { base64 }?, + element bpki_resource_ta { base64 }, + element bpki_server_ta { base64 }, + element bpki_child_ta { base64 }, element repository { ((attribute type { "offer" }) | - (attribute type { "hint" }, - attribute proposed_sia_base { uri }, + (attribute type { "referral" }, + element authorization { + attribute referrer { pubd_handle }, + base64 + }, element contact_info { xsd:string })) }? } @@ -90,8 +94,8 @@ repository_pdu |= element repository { attribute service_uri { uri }, attribute sia_base { uri }, attribute repository_handle { object_handle }, - element bpki_server_ta { base64 }?, - element bpki_client_ta { base64 }?, + element bpki_server_ta { base64 }, + element bpki_client_ta { base64 }, element contact_info { xsd:string }? } @@ -100,8 +104,12 @@ repository_pdu |= element repository { attribute type { "request" }, attribute handle { pubd_handle }, attribute parent_handle { object_handle }, + element bpki_ta { base64 }, element contact_info { xsd:string }?, - element bpki_ta { base64 }? + element authorization { + attribute referrer { pubd_handle }, + base64 + }? } repository_pdu |= element repository { @@ -109,17 +117,26 @@ repository_pdu |= element repository { attribute type { "offer" }, attribute handle { pubd_handle }, attribute parent_handle { object_handle }, - element bpki_ta { base64 }? + element bpki_ta { base64 } } repository_pdu |= element repository { attribute version { version }, - attribute type { "hint" }, + attribute type { "referral" }, attribute handle { pubd_handle }, attribute parent_handle { object_handle }, - attribute proposed_sia_base { uri }, + element authorization { + attribute referrer { pubd_handle }, + base64 + }, element contact_info { xsd:string }?, - element bpki_ta { base64 }? + element bpki_ta { base64 } +} + +referral_pdu = element referral { + attribute version { version }, + attribute authorized_sia_base { uri }, + base64 } # Local Variables: diff --git a/myrpki.rototill/myrpki.rng b/myrpki.rototill/myrpki.rng index 264a2c25..dda7086e 100644 --- a/myrpki.rototill/myrpki.rng +++ b/myrpki.rototill/myrpki.rng @@ -63,6 +63,9 @@ <start combine="choice"> <ref name="repository_pdu"/> </start> + <start combine="choice"> + <ref name="referral_pdu"/> + </start> <define name="myrpki_pdu"> <element name="myrpki"> <attribute name="version"> @@ -231,21 +234,15 @@ <attribute name="parent_handle"> <ref name="object_handle"/> </attribute> - <optional> - <element name="bpki_resource_ta"> - <ref name="base64"/> - </element> - </optional> - <optional> - <element name="bpki_server_ta"> - <ref name="base64"/> - </element> - </optional> - <optional> - <element name="bpki_child_ta"> - <ref name="base64"/> - </element> - </optional> + <element name="bpki_resource_ta"> + <ref name="base64"/> + </element> + <element name="bpki_server_ta"> + <ref name="base64"/> + </element> + <element name="bpki_child_ta"> + <ref name="base64"/> + </element> <optional> <element name="repository"> <choice> @@ -254,11 +251,14 @@ </attribute> <group> <attribute name="type"> - <value>hint</value> - </attribute> - <attribute name="proposed_sia_base"> - <ref name="uri"/> + <value>referral</value> </attribute> + <element name="authorization"> + <attribute name="referrer"> + <ref name="pubd_handle"/> + </attribute> + <ref name="base64"/> + </element> <element name="contact_info"> <data type="string"/> </element> @@ -291,16 +291,12 @@ <attribute name="repository_handle"> <ref name="object_handle"/> </attribute> - <optional> - <element name="bpki_server_ta"> - <ref name="base64"/> - </element> - </optional> - <optional> - <element name="bpki_client_ta"> - <ref name="base64"/> - </element> - </optional> + <element name="bpki_server_ta"> + <ref name="base64"/> + </element> + <element name="bpki_client_ta"> + <ref name="base64"/> + </element> <optional> <element name="contact_info"> <data type="string"/> @@ -322,13 +318,19 @@ <attribute name="parent_handle"> <ref name="object_handle"/> </attribute> + <element name="bpki_ta"> + <ref name="base64"/> + </element> <optional> <element name="contact_info"> <data type="string"/> </element> </optional> <optional> - <element name="bpki_ta"> + <element name="authorization"> + <attribute name="referrer"> + <ref name="pubd_handle"/> + </attribute> <ref name="base64"/> </element> </optional> @@ -348,11 +350,9 @@ <attribute name="parent_handle"> <ref name="object_handle"/> </attribute> - <optional> - <element name="bpki_ta"> - <ref name="base64"/> - </element> - </optional> + <element name="bpki_ta"> + <ref name="base64"/> + </element> </element> </define> <define name="repository_pdu" combine="choice"> @@ -361,7 +361,7 @@ <ref name="version"/> </attribute> <attribute name="type"> - <value>hint</value> + <value>referral</value> </attribute> <attribute name="handle"> <ref name="pubd_handle"/> @@ -369,19 +369,31 @@ <attribute name="parent_handle"> <ref name="object_handle"/> </attribute> - <attribute name="proposed_sia_base"> - <ref name="uri"/> - </attribute> + <element name="authorization"> + <attribute name="referrer"> + <ref name="pubd_handle"/> + </attribute> + <ref name="base64"/> + </element> <optional> <element name="contact_info"> <data type="string"/> </element> </optional> - <optional> - <element name="bpki_ta"> - <ref name="base64"/> - </element> - </optional> + <element name="bpki_ta"> + <ref name="base64"/> + </element> + </element> + </define> + <define name="referral_pdu"> + <element name="referral"> + <attribute name="version"> + <ref name="version"/> + </attribute> + <attribute name="authorized_sia_base"> + <ref name="uri"/> + </attribute> + <ref name="base64"/> </element> </define> </grammar> diff --git a/myrpki.rototill/yamltest.py b/myrpki.rototill/yamltest.py index e5bc3155..8a6890a1 100644 --- a/myrpki.rototill/yamltest.py +++ b/myrpki.rototill/yamltest.py @@ -381,7 +381,8 @@ class allocation(object): r = { ("myrpki", "handle") : self.name, ("myrpki", "run_pubd") : str(self.runs_pubd()), - ("myrpki", "run_rootd") : str(self.is_root()) } + ("myrpki", "run_rootd") : str(self.is_root()), + ("myrpki", "openssl") : prog_openssl } if not self.is_hosted(): r["irdbd", "sql-database"] = "irdb%d" % self.engine |