summaryrefslogtreecommitdiffstats
path: root/sshsig.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2021-11-27 08:14:46 +0100
committerDamien Miller <djm@mindrot.org>2021-11-27 08:22:41 +0100
commit78230b3ec8cbabc1e7de68732dc5cbd4837c6675 (patch)
treee771d5586735f696454bd641b844ca2fe77f3bff /sshsig.c
parentupstream: debug("func: ...") -> debug_f("...") (diff)
downloadopenssh-78230b3ec8cbabc1e7de68732dc5cbd4837c6675.tar.xz
openssh-78230b3ec8cbabc1e7de68732dc5cbd4837c6675.zip
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
Diffstat (limited to 'sshsig.c')
-rw-r--r--sshsig.c72
1 files changed, 71 insertions, 1 deletions
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
*
@@ -1051,6 +1051,76 @@ sshsig_find_principals(const char *path, const struct sshkey *sign_key,
}
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)
{
struct sshkey *pk = NULL;