Hi,

This is the first of a few changes to krl.c and related code.

This defines and implements an extension mechanism for KRLs.

This takes the form of new (sub-)section types that contain named
extensions. These may be flagged as "critical" which causes the KRL
parser to treat them as mandatory-to implement. If they aren't flagged
as critical then they are ignored.

I honestly feel kind of stupid for not doing this when I wrote the
format...

Unfortunately KRLs with extensions are not backwards-compatible, as
the parser treats unknown section types as a fatal error. They are
forwards-compatible though.

I didn't update the KRL format version because I couldn't see any
practical difference between "KRL parsing fails because of an unknown
section type" and "KRL parsing fails because the format version is
wrong", except that the latter also makes life harder for the no-
extension case.

This doesn't add support for any extensions, just the mechanism itself.

ok?

PS. also at https://github.com/djmdjm/openssh-wip/pull/19

 PROTOCOL.krl | 49 +++++++++++++++++++++++++++++-
 krl.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 krl.h        |  2 ++
 3 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/PROTOCOL.krl b/PROTOCOL.krl
index 115f80e..0bd0a82 100644
--- a/PROTOCOL.krl
+++ b/PROTOCOL.krl
@@ -37,6 +37,7 @@ The available section types are:
 #define KRL_SECTION_FINGERPRINT_SHA1           3
 #define KRL_SECTION_SIGNATURE                  4
 #define KRL_SECTION_FINGERPRINT_SHA256         5
+#define KRL_SECTION_EXTENSION                  255
 
 2. Certificate section
 
@@ -64,6 +65,7 @@ The certificate section types are:
 #define KRL_SECTION_CERT_SERIAL_RANGE  0x21
 #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
 #define KRL_SECTION_CERT_KEY_ID                0x23
+#define KRL_SECTION_CERT_EXTENSION     0x39
 
 2.1 Certificate serial list section
 
@@ -114,6 +116,29 @@ associated with a particular identity, e.g. a host or a 
user.
 This section must contain at least one "key_id". This section may appear
 multiple times.
 
+2.5. Certificate Extension subsections
+
+This subsection type provides a generic extension mechanism to the
+certificates KRL section that may be used to provide optional or critical
+data.
+
+Extensions are stored in subsections of type
+KRL_SECTION_CERT_EXTENSION with the following contents:
+
+       string  extension_name
+       boolean is_critical
+       string  extension_contents.
+
+Where "extension_name" describes the type of extension. It is
+recommended that user extensions follow "cert-n...@domain.org" naming.
+
+The "is_critical" indicates whether this extension is mandatory or
+optional. If true, then any unsupported extension encountered should
+result in KRL parsing failure. If false, then it may be safely be
+ignored.
+
+The "extension_contents" contains the body of the extension.
+
 3. Explicit key sections
 
 These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys
@@ -144,7 +169,29 @@ as a big-endian integer.
 
 This section may appear multiple times.
 
-5. KRL signature sections
+5. Extension sections
+
+This section type provides a generic extension mechanism to the KRL
+format that may be used to provide optional or critical data.
+
+Extensions are recorded in sections of type KRL_SECTION_EXTENSION
+with the following contents:
+
+       string  extension_name
+       boolean is_critical
+       string  extension_contents.
+
+Where "extension_name" describes the type of extension. It is
+recommended that user extensions follow "n...@domain.org" naming.
+
+The "is_critical" indicates whether this extension is mandatory or
+optional. If true, then any unsupported extension encountered should
+result in KRL parsing failure. If false, then it may be safely be
+ignored.
+
+The "extension_contents" contains the body of the extension.
+
+6. KRL signature sections
 
 The KRL_SECTION_SIGNATURE section serves a different purpose to the
 preceding ones: to provide cryptographic authentication of a KRL that
diff --git a/krl.c b/krl.c
index f491c24..a8a6018 100644
--- a/krl.c
+++ b/krl.c
@@ -837,6 +837,45 @@ format_timestamp(u_int64_t timestamp, char *ts, size_t nts)
        }
 }
 
+static int
+cert_extension_subsection(struct sshbuf *subsect, struct ssh_krl *krl)
+{
+       int r = SSH_ERR_INTERNAL_ERROR;
+       u_char critical = 1;
+       struct sshbuf *value = NULL;
+       char *name = NULL;
+
+       if ((r = sshbuf_get_cstring(subsect, &name, NULL)) != 0 ||
+           (r = sshbuf_get_u8(subsect, &critical)) != 0 ||
+           (r = sshbuf_froms(subsect, &value)) != 0) {
+               debug_fr(r, "parse");
+               error("KRL has invalid certificate extension subsection");
+               r = SSH_ERR_INVALID_FORMAT;
+               goto out;
+       }
+       if (sshbuf_len(subsect) != 0) {
+               error("KRL has invalid certificate extension subsection: "
+                   "trailing data");
+               r = SSH_ERR_INVALID_FORMAT;
+               goto out;
+       }
+       debug_f("cert extension %s critical %u len %zu",
+           name, critical, sshbuf_len(value));
+       /* no extensions are currently supported */
+       if (critical) {
+               error("KRL contains unsupported critical certificate "
+                   "subsection \"%s\"", name);
+               r = SSH_ERR_FEATURE_UNSUPPORTED;
+               goto out;
+       }
+       /* success */
+       r = 0;
+ out:
+       free(name);
+       sshbuf_free(value);
+       return r;
+}
+
 static int
 parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
 {
@@ -928,6 +967,10 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl 
*krl)
                                key_id = NULL;
                        }
                        break;
+               case KRL_SECTION_CERT_EXTENSION:
+                       if ((r = cert_extension_subsection(subsect, krl)) != 0)
+                               goto out;
+                       break;
                default:
                        error("Unsupported KRL certificate section %u", type);
                        r = SSH_ERR_INVALID_FORMAT;
@@ -974,6 +1017,43 @@ blob_section(struct sshbuf *sect, struct 
revoked_blob_tree *target_tree,
        return 0;
 }
 
+static int
+extension_section(struct sshbuf *sect, struct ssh_krl *krl)
+{
+       int r = SSH_ERR_INTERNAL_ERROR;
+       u_char critical = 1;
+       struct sshbuf *value = NULL;
+       char *name = NULL;
+
+       if ((r = sshbuf_get_cstring(sect, &name, NULL)) != 0 ||
+           (r = sshbuf_get_u8(sect, &critical)) != 0 ||
+           (r = sshbuf_froms(sect, &value)) != 0) {
+               debug_fr(r, "parse");
+               error("KRL has invalid extension section");
+               r = SSH_ERR_INVALID_FORMAT;
+               goto out;
+       }
+       if (sshbuf_len(sect) != 0) {
+               error("KRL has invalid extension section: trailing data");
+               r = SSH_ERR_INVALID_FORMAT;
+               goto out;
+       }
+       debug_f("extension %s critical %u len %zu",
+           name, critical, sshbuf_len(value));
+       /* no extensions are currently supported */
+       if (critical) {
+               error("KRL contains unsupported critical section \"%s\"", name);
+               r = SSH_ERR_FEATURE_UNSUPPORTED;
+               goto out;
+       }
+       /* success */
+       r = 0;
+ out:
+       free(name);
+       sshbuf_free(value);
+       return r;
+}
+
 /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. 
*/
 int
 ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
@@ -1141,6 +1221,10 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl 
**krlp,
                            &krl->revoked_sha256s, 32)) != 0)
                                goto out;
                        break;
+               case KRL_SECTION_EXTENSION:
+                       if ((r = extension_section(sect, krl)) != 0)
+                               goto out;
+                       break;
                case KRL_SECTION_SIGNATURE:
                        /* Handled above, but still need to stay in synch */
                        sshbuf_free(sect);
diff --git a/krl.h b/krl.h
index ca6d3f2..579cfde 100644
--- a/krl.h
+++ b/krl.h
@@ -30,12 +30,14 @@
 #define KRL_SECTION_FINGERPRINT_SHA1   3
 #define KRL_SECTION_SIGNATURE          4
 #define KRL_SECTION_FINGERPRINT_SHA256 5
+#define KRL_SECTION_EXTENSION          255
 
 /* KRL_SECTION_CERTIFICATES subsection types */
 #define KRL_SECTION_CERT_SERIAL_LIST   0x20
 #define KRL_SECTION_CERT_SERIAL_RANGE  0x21
 #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
 #define KRL_SECTION_CERT_KEY_ID                0x23
+#define KRL_SECTION_CERT_EXTENSION     0x39
 
 struct sshkey;
 struct sshbuf;
-- 
2.39.0

Reply via email to