Hi,

This is another OpenSSH key revocation list (KRL) change: to support KRL
signing and verification in ssh-keygen(1).

The KRL format has supported signing of KRLs and verification of KRL
signatures for a long time, but there is currently no way to generate a
signed KRL or check the signature on one. The final patch hooks this up
for ssh-keygen(1) at least.

ok?

---
 ssh-keygen.c | 62 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/ssh-keygen.c b/ssh-keygen.c
index 869b675..29b8aec 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -2179,7 +2179,8 @@ do_show_cert(struct passwd *pw)
 }
 
 static void
-load_krl(const char *path, struct ssh_krl **krlp)
+load_krl(const char *path, struct ssh_krl **krlp,
+    struct sshkey **trusted_keys, size_t ntrusted_keys)
 {
        struct sshbuf *krlbuf;
        int r;
@@ -2187,7 +2188,8 @@ load_krl(const char *path, struct ssh_krl **krlp)
        if ((r = sshbuf_load_file(path, &krlbuf)) != 0)
                fatal_r(r, "Unable to load KRL %s", path);
        /* XXX check sigs */
-       if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 ||
+       if ((r = ssh_krl_from_blob(krlbuf, krlp,
+           trusted_keys, ntrusted_keys)) != 0 ||
            *krlp == NULL)
                fatal_r(r, "Invalid KRL file %s", path);
        sshbuf_free(krlbuf);
@@ -2378,20 +2380,54 @@ update_krl_from_file(struct passwd *pw, const char 
*file, int wild_ca,
        free(path);
 }
 
+static void
+krl_process_opts(struct passwd *pw, char * const *opts, size_t nopts,
+    struct sshkey ***sig_keys, size_t *nsig_keys)
+{
+       struct sshkey *key;
+       char *path;
+       size_t i;
+
+       for (i = 0; i < nopts; i++) {
+               if (strncasecmp(opts[i], "signing-key=", 12) == 0) {
+                       path = tilde_expand_filename(opts[i] + 12, pw->pw_uid);
+                       key = load_identity(path, NULL);
+                       free(path);
+                       *sig_keys = xrecallocarray(*sig_keys, *nsig_keys,
+                           *nsig_keys + 1, sizeof(*sig_keys));
+                       (*sig_keys)[(*nsig_keys)++] = key;
+               } else
+                       fatal("Invalid option \"%s\"", opts[i]);
+       }
+}
+
+static void
+free_sig_keys(struct sshkey **sig_keys, size_t nsig_keys)
+{
+       size_t i;
+
+       for (i = 0; i < nsig_keys; i++)
+               sshkey_free(sig_keys[i]);
+       free(sig_keys);
+}
+
 static void
 do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
     unsigned long long krl_version, const char *krl_comment,
+    char * const *opts, size_t nopts,
     int argc, char **argv)
 {
        struct ssh_krl *krl;
        struct stat sb;
-       struct sshkey *ca = NULL;
+       struct sshkey *ca = NULL, **sig_keys = NULL;
        int i, r, wild_ca = 0;
+       size_t nsig_keys = 0;
        char *tmp;
        struct sshbuf *kbuf;
 
        if (*identity_file == '\0')
                fatal("KRL generation requires an output file");
+       krl_process_opts(pw, opts, nopts, &sig_keys, &nsig_keys);
        if (stat(identity_file, &sb) == -1) {
                if (errno != ENOENT)
                        fatal("Cannot access KRL \"%s\": %s",
@@ -2411,7 +2447,7 @@ do_gen_krl(struct passwd *pw, int updating, const char 
*ca_key_path,
        }
 
        if (updating)
-               load_krl(identity_file, &krl);
+               load_krl(identity_file, &krl, NULL, 0);
        else if ((krl = ssh_krl_init()) == NULL)
                fatal("couldn't create KRL");
 
@@ -2425,26 +2461,30 @@ do_gen_krl(struct passwd *pw, int updating, const char 
*ca_key_path,
 
        if ((kbuf = sshbuf_new()) == NULL)
                fatal("sshbuf_new failed");
-       if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0)
+       if (ssh_krl_to_blob(krl, kbuf, sig_keys, nsig_keys) != 0)
                fatal("Couldn't generate KRL");
        if ((r = sshbuf_write_file(identity_file, kbuf)) != 0)
                fatal("write %s: %s", identity_file, strerror(errno));
        sshbuf_free(kbuf);
        ssh_krl_free(krl);
        sshkey_free(ca);
+       free_sig_keys(sig_keys, nsig_keys);
 }
 
 static void
-do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
+do_check_krl(struct passwd *pw, int print_krl,
+    char * const *opts, size_t nopts, int argc, char **argv)
 {
        int i, r, ret = 0;
        char *comment;
        struct ssh_krl *krl;
-       struct sshkey *k;
+       struct sshkey *k = NULL, **sig_keys = NULL;
+       size_t nsig_keys = 0;
 
        if (*identity_file == '\0')
                fatal("KRL checking requires an input file");
-       load_krl(identity_file, &krl);
+       krl_process_opts(pw, opts, nopts, &sig_keys, &nsig_keys);
+       load_krl(identity_file, &krl, sig_keys, nsig_keys);
        if (print_krl)
                krl_dump(krl, stdout);
        for (i = 0; i < argc; i++) {
@@ -2460,6 +2500,7 @@ do_check_krl(struct passwd *pw, int print_krl, int argc, 
char **argv)
                free(comment);
        }
        ssh_krl_free(krl);
+       free_sig_keys(sig_keys, nsig_keys);
        exit(ret);
 }
 
@@ -2660,7 +2701,6 @@ sig_process_opts(char * const *opts, size_t nopts, char 
**hashalgp,
        return 0;
 }
 
-
 static int
 sig_sign(const char *keypath, const char *sig_namespace, int require_agent,
     int argc, char **argv, char * const *opts, size_t nopts)
@@ -3643,11 +3683,11 @@ main(int argc, char **argv)
        }
        if (gen_krl) {
                do_gen_krl(pw, update_krl, ca_key_path,
-                   cert_serial, identity_comment, argc, argv);
+                   cert_serial, identity_comment, opts, nopts, argc, argv);
                return (0);
        }
        if (check_krl) {
-               do_check_krl(pw, print_fingerprint, argc, argv);
+               do_check_krl(pw, print_fingerprint, opts, nopts, argc, argv);
                return (0);
        }
        if (ca_key_path != NULL) {
-- 
2.39.0

Reply via email to