From 78230b3ec8cbabc1e7de68732dc5cbd4837c6675 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 27 Nov 2021 07:14:46 +0000 Subject: upstream: Add ssh-keygen -Y match-principals operation to perform matching of principals names against an allowed signers file. Requested by and mostly written by Fabian Stelzer, towards a TOFU model for SSH signatures in git. Some tweaks by me. "doesn't bother me" deraadt@ OpenBSD-Commit-ID: 8d1b71f5a4127bc5e10a880c8ea6053394465247 --- sshsig.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) (limited to 'sshsig.c') diff --git a/sshsig.c b/sshsig.c index 5039a0fb9..bd17d035f 100644 --- a/sshsig.c +++ b/sshsig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshsig.c,v 1.23 2021/11/18 03:50:41 djm Exp $ */ +/* $OpenBSD: sshsig.c,v 1.24 2021/11/27 07:14:46 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -1050,6 +1050,76 @@ sshsig_find_principals(const char *path, const struct sshkey *sign_key, return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r; } +int +sshsig_match_principals(const char *path, const char *principal, + char ***principalsp, size_t *nprincipalsp) +{ + FILE *f = NULL; + char *found, *line = NULL, **principals = NULL, **tmp; + size_t i, nprincipals = 0, linesize = 0; + u_long linenum = 0; + int oerrno, r, ret = 0; + + if (principalsp != NULL) + *principalsp = NULL; + if (nprincipalsp != NULL) + *nprincipalsp = 0; + + /* Check key and principal against file */ + if ((f = fopen(path, "r")) == NULL) { + oerrno = errno; + error("Unable to open allowed keys file \"%s\": %s", + path, strerror(errno)); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } + + while (getline(&line, &linesize, f) != -1) { + linenum++; + /* Parse the line */ + if ((r = parse_principals_key_and_options(path, linenum, line, + principal, &found, NULL, NULL)) != 0) { + if (r == SSH_ERR_KEY_NOT_FOUND) + continue; + ret = r; + oerrno = errno; + break; /* unexpected error */ + } + if ((tmp = recallocarray(principals, nprincipals, + nprincipals + 1, sizeof(*principals))) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + free(found); + break; + } + principals = tmp; + principals[nprincipals++] = found; /* transferred */ + free(line); + line = NULL; + linesize = 0; + } + fclose(f); + + if (ret == 0) { + if (nprincipals == 0) + ret = SSH_ERR_KEY_NOT_FOUND; + if (principalsp != NULL) { + *principalsp = principals; + principals = NULL; /* transferred */ + } + if (nprincipalsp != 0) { + *nprincipalsp = nprincipals; + nprincipals = 0; + } + } + + for (i = 0; i < nprincipals; i++) + free(principals[i]); + free(principals); + + errno = oerrno; + return ret; +} + int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey) { -- cgit v1.2.3