From 56cffcc09f8a2e661d2ba02e61364ae6f998b2b1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 23 Jan 2020 02:43:48 +0000 Subject: upstream: add a new signature operations "find-principal" to look up the principal associated with a signature from an allowed-signers file. Work by Sebastian Kinne; ok dtucker@ OpenBSD-Commit-ID: 6f782cc7e18e38fcfafa62af53246a1dcfe74e5d --- ssh-keygen.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 9 deletions(-) (limited to 'ssh-keygen.c') diff --git a/ssh-keygen.c b/ssh-keygen.c index 04492979b..eebd89a27 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.385 2020/01/22 04:51:51 claudio Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.386 2020/01/23 02:43:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -2599,7 +2599,7 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, } static int -sign(const char *keypath, const char *sig_namespace, int argc, char **argv) +sig_sign(const char *keypath, const char *sig_namespace, int argc, char **argv) { int i, fd = -1, r, ret = -1; int agent_fd = -1; @@ -2670,8 +2670,8 @@ done: } static int -verify(const char *signature, const char *sig_namespace, const char *principal, - const char *allowed_keys, const char *revoked_keys) +sig_verify(const char *signature, const char *sig_namespace, + const char *principal, const char *allowed_keys, const char *revoked_keys) { int r, ret = -1, sigfd = -1; struct sshbuf *sigbuf = NULL, *abuf = NULL; @@ -2694,7 +2694,7 @@ verify(const char *signature, const char *sig_namespace, const char *principal, } if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { error("%s: sshsig_armor: %s", __func__, ssh_err(r)); - return r; + goto done; } if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace, &sign_key, &sig_details)) != 0) @@ -2757,6 +2757,57 @@ done: return ret; } +static int +sig_find_principal(const char *signature, const char *allowed_keys) { + int r, ret = -1, sigfd = -1; + struct sshbuf *sigbuf = NULL, *abuf = NULL; + struct sshkey *sign_key = NULL; + char *principal = NULL; + + if ((abuf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new() failed", __func__); + + if ((sigfd = open(signature, O_RDONLY)) < 0) { + error("Couldn't open signature file %s", signature); + goto done; + } + + if ((r = sshkey_load_file(sigfd, abuf)) != 0) { + error("Couldn't read signature file: %s", ssh_err(r)); + goto done; + } + if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { + error("%s: sshsig_armor: %s", __func__, ssh_err(r)); + goto done; + } + if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) { + error("%s: sshsig_get_pubkey: %s", + __func__, ssh_err(r)); + goto done; + } + + if ((r = sshsig_find_principal(allowed_keys, sign_key, + &principal)) != 0) { + error("%s: sshsig_get_principal: %s", + __func__, ssh_err(r)); + goto done; + } + ret = 0; +done: + if (ret == 0 ) { + printf("Found matching principal: %s\n", principal); + } else { + printf("Could not find matching principal.\n"); + } + if (sigfd != -1) + close(sigfd); + sshbuf_free(sigbuf); + sshbuf_free(abuf); + sshkey_free(sign_key); + free(principal); + return ret; +} + static void do_moduli_gen(const char *out_file, char **opts, size_t nopts) { @@ -3042,6 +3093,7 @@ usage(void) " 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 -Y find-principal -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" " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n" @@ -3305,6 +3357,19 @@ main(int argc, char **argv) argc -= optind; if (sign_op != NULL) { + if (strncmp(sign_op, "find-principal", 14) == 0) { + if (ca_key_path == NULL) { + error("Too few arguments for find-principal:" + "missing signature file"); + exit(1); + } + if (!have_identity) { + error("Too few arguments for find-principal:" + "missing allowed keys file"); + exit(1); + } + return sig_find_principal(ca_key_path, identity_file); + } if (cert_principals == NULL || *cert_principals == '\0') { error("Too few arguments for sign/verify: " "missing namespace"); @@ -3316,15 +3381,16 @@ main(int argc, char **argv) "missing key"); exit(1); } - return sign(identity_file, cert_principals, argc, argv); + return sig_sign(identity_file, cert_principals, + argc, argv); } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { if (ca_key_path == NULL) { error("Too few arguments for check-novalidate: " "missing signature file"); exit(1); } - return verify(ca_key_path, cert_principals, - NULL, NULL, NULL); + return sig_verify(ca_key_path, cert_principals, + NULL, NULL, NULL); } else if (strncmp(sign_op, "verify", 6) == 0) { if (ca_key_path == NULL) { error("Too few arguments for verify: " @@ -3341,7 +3407,7 @@ main(int argc, char **argv) "missing principal ID"); exit(1); } - return verify(ca_key_path, cert_principals, + return sig_verify(ca_key_path, cert_principals, cert_key_id, identity_file, rr_hostname); } usage(); -- cgit v1.2.3