diff options
author | djm@openbsd.org <djm@openbsd.org> | 2021-11-27 08:14:46 +0100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2021-11-27 08:22:41 +0100 |
commit | 78230b3ec8cbabc1e7de68732dc5cbd4837c6675 (patch) | |
tree | e771d5586735f696454bd641b844ca2fe77f3bff /sshsig.c | |
parent | upstream: debug("func: ...") -> debug_f("...") (diff) | |
download | openssh-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.c | 72 |
1 files changed, 71 insertions, 1 deletions
@@ -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; |