From da04dd48eeebd07ec67f1ff7fa31dbbc3b9cfa02 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 30 Oct 2026 03:47:56 +0000 Subject: [PATCH] upstream: make `ssh-keygen -Q` check all pubkeys in a file, rather than bailing after it has read a single one. Anthropic ANT-2026-RIK2HMYK OpenBSD-Commit-ID: e6a6c58c19b95aecdcfe598816798cd27061a457 --- ssh-keygen.1 | 4 +++- ssh-keygen.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 5c1bc9f8b..be69bf08a 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.243 2026/10/30 02:18:03 djm Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.244 2026/10/30 03:47:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1255,6 +1255,8 @@ It is also possible, given a KRL, to test whether it revokes a particular key The .Fl Q flag will query an existing KRL, testing each key specified on the command line. +Files specified on the command line may contain multiple public keys, +listed one per line, all of which will be tested. If any key listed on the command line has been revoked (or an error encountered) then .Nm diff --git a/ssh-keygen.c b/ssh-keygen.c index 1e2c60342..2980cc27a 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.498 2026/10/30 03:24:23 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.499 2026/10/30 03:47:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -2511,6 +2511,58 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, sshkey_free(ca); } +/* Check a single key against a KRL; returns non-zero if it is revoked. */ +static int +check_krl_key(struct ssh_krl *krl, const struct sshkey *k, + const char *path, const char *comment) +{ + int r; + + r = ssh_krl_check_key(krl, k); + printf("%s%s%s%s: %s\n", path, + *comment ? " (" : "", comment, *comment ? ")" : "", + r == 0 ? "ok" : "REVOKED"); + return r != 0; +} + +/* + * Check every public key listed in a file (one per line) against a KRL, + * setting *revokedp if any is revoked. Returns the number of keys checked; + * zero if the file could not be opened or contains no public keys. + */ +static u_long +check_krl_file(struct ssh_krl *krl, const char *path, int *revokedp) +{ + FILE *f; + struct sshkey *k; + char *cp, *line = NULL; + size_t linesize = 0; + u_long lnum = 0, nkeys = 0; + + if ((f = fopen(path, "r")) == NULL) + return 0; + while (getline(&line, &linesize, f) != -1) { + lnum++; + cp = line + strspn(line, " \t"); + cp[strcspn(cp, "\r\n")] = '\0'; + if (*cp == '#' || *cp == '\0') + continue; + /* Stop if this looks like a private key */ + if (strncmp(cp, "-----BEGIN", 10) == 0) + break; + if ((k = try_read_key(&cp)) == NULL) + fatal("%s:%lu: invalid key", path, lnum); + cp += strspn(cp, " \t"); + if (check_krl_key(krl, k, path, *cp ? cp : path)) + *revokedp = 1; + sshkey_free(k); + nkeys++; + } + fclose(f); + free(line); + return nkeys; +} + static void do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) { @@ -2525,13 +2577,14 @@ do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) if (print_krl) krl_dump(krl, stdout); for (i = 0; i < argc; i++) { + /* Test every key in the file, not just the first */ + if (check_krl_file(krl, argv[i], &ret) != 0) + continue; + /* No public keys found; try the ".pub" suffix or a private key */ if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0) fatal_r(r, "Cannot load public key %s", argv[i]); - r = ssh_krl_check_key(krl, k); - printf("%s%s%s%s: %s\n", argv[i], - *comment ? " (" : "", comment, *comment ? ")" : "", - r == 0 ? "ok" : "REVOKED"); - if (r != 0) + if (check_krl_key(krl, k, argv[i], + comment == NULL ? "" : comment)) ret = 1; sshkey_free(k); free(comment);