From 6ec7457171468da2bbd908b8cd63d298b0e049ea Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 3 Apr 2020 02:26:56 +0000 Subject: [PATCH] upstream: give ssh-keygen the ability to dump the contents of a binary key revocation list: ssh-keygen -lQf /path bz#3132; ok dtucker OpenBSD-Commit-ID: b76afc4e3b74ab735dbde4e5f0cfa1f02356033b --- krl.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++- krl.h | 3 +- ssh-keygen.1 | 8 +++-- ssh-keygen.c | 10 +++--- 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/krl.c b/krl.c index 03476dedd..9da7126e2 100644 --- a/krl.c +++ b/krl.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.47 2020/01/25 23:02:13 djm Exp $ */ +/* $OpenBSD: krl.c,v 1.48 2020/04/03 02:26:56 djm Exp $ */ #include "includes.h" @@ -38,6 +38,7 @@ #include "log.h" #include "digest.h" #include "bitmap.h" +#include "utf8.h" #include "krl.h" @@ -1355,3 +1356,94 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key) errno = oerrno; return r; } + +int +krl_dump(struct ssh_krl *krl, FILE *f) +{ + struct sshkey *key = NULL; + struct revoked_blob *rb; + struct revoked_certs *rc; + struct revoked_serial *rs; + struct revoked_key_id *rki; + int r, ret = 0; + char *fp, timestamp[64]; + + /* Try to print in a KRL spec-compatible format */ + format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); + fprintf(f, "# KRL version %lld\n", krl->krl_version); + fprintf(f, "# Generated at %s\n", timestamp); + if (krl->comment != NULL && *krl->comment != '\0') { + r = INT_MAX; + asmprintf(&fp, INT_MAX, &r, "%s", krl->comment); + fprintf(f, "# Comment: %s\n", fp); + free(fp); + } + fputc('\n', f); + + RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { + if ((r = sshkey_from_blob(rb->blob, rb->len, &key)) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + error("Parse key in KRL: %s", ssh_err(r)); + continue; + } + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) { + ret = SSH_ERR_INVALID_FORMAT; + error("sshkey_fingerprint failed"); + continue; + } + fprintf(f, "hash: SHA256:%s # %s\n", fp, sshkey_ssh_name(key)); + free(fp); + free(key); + } + RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) { + fp = tohex(rb->blob, rb->len); + fprintf(f, "hash: SHA256:%s\n", fp); + free(fp); + } + RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { + /* + * There is not KRL spec keyword for raw SHA1 hashes, so + * print them as comments. + */ + fp = tohex(rb->blob, rb->len); + fprintf(f, "# hash SHA1:%s\n", fp); + free(fp); + } + + TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { + fputc('\n', f); + if (rc->ca_key == NULL) + fprintf(f, "# Wildcard CA\n"); + else { + if ((fp = sshkey_fingerprint(rc->ca_key, + SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) { + ret = SSH_ERR_INVALID_FORMAT; + error("sshkey_fingerprint failed"); + continue; + } + fprintf(f, "# CA key %s %s\n", + sshkey_ssh_name(rc->ca_key), fp); + free(fp); + } + RB_FOREACH(rs, revoked_serial_tree, &rc->revoked_serials) { + if (rs->lo == rs->hi) + fprintf(f, "serial: %lld\n", rs->lo); + else { + fprintf(f, "serial: %lld-%lld\n", + rs->lo, rs->hi); + } + } + RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { + /* + * We don't want key IDs with embedded newlines to + * mess up the display. + */ + r = INT_MAX; + asmprintf(&fp, INT_MAX, &r, "%s", rki->key_id); + fprintf(f, "id: %s\n", fp); + free(fp); + } + } + return ret; +} diff --git a/krl.h b/krl.h index ce534a111..ca6d3f284 100644 --- a/krl.h +++ b/krl.h @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.h,v 1.7 2019/06/21 04:21:04 djm Exp $ */ +/* $OpenBSD: krl.h,v 1.8 2020/04/03 02:26:56 djm Exp $ */ #ifndef _KRL_H #define _KRL_H @@ -61,6 +61,7 @@ int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, const struct sshkey **sign_ca_keys, size_t nsign_ca_keys); int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key); int ssh_krl_file_contains_key(const char *path, const struct sshkey *key); +int krl_dump(struct ssh_krl *krl, FILE *f); #endif /* _KRL_H */ diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 629430972..059c1b034 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.202 2020/02/24 04:27:58 dtucker Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.203 2020/04/03 02:26:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: February 24 2020 $ +.Dd $Mdocdate: April 3 2020 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -135,6 +135,7 @@ .Ar .Nm ssh-keygen .Fl Q +.Op Fl l .Fl f Ar krl_file .Ar .Nm ssh-keygen @@ -521,6 +522,9 @@ containing the private key, for the old passphrase, and twice for the new passphrase. .It Fl Q Test whether keys have been revoked in a KRL. +If the +.Fl l +option is also specified then the contents of the KRL will be printed. .It Fl q Silence .Nm ssh-keygen . diff --git a/ssh-keygen.c b/ssh-keygen.c index 0fa141cff..802fd25c2 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.404 2020/03/13 03:17:07 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.405 2020/04/03 02:26:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -2439,7 +2439,7 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, } static void -do_check_krl(struct passwd *pw, int argc, char **argv) +do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) { int i, r, ret = 0; char *comment; @@ -2449,6 +2449,8 @@ do_check_krl(struct passwd *pw, int argc, char **argv) if (*identity_file == '\0') fatal("KRL checking requires an input file"); load_krl(identity_file, &krl); + if (print_krl) + krl_dump(krl, stdout); for (i = 0; i < argc; i++) { if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0) fatal("Cannot load public key %s: %s", @@ -3086,7 +3088,7 @@ usage(void) " ssh-keygen -A [-f prefix_path]\n" " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" " file ...\n" - " ssh-keygen -Q -f krl_file file ...\n" + " ssh-keygen -Q [-l] -f krl_file [file ...]\n" " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n" " ssh-keygen -Y sign -f key_file -n namespace file ...\n" @@ -3441,7 +3443,7 @@ main(int argc, char **argv) return (0); } if (check_krl) { - do_check_krl(pw, argc, argv); + do_check_krl(pw, print_fingerprint, argc, argv); return (0); } if (ca_key_path != NULL) {