зеркало из https://github.com/Azure/sonic-openssh.git
upstream: ssh-keygen -Y find-principals fixes based on feedback
from Markus: use "principals" instead of principal, as allowed_signers lines may list multiple. When the signing key is a certificate, emit only principals that match the certificate principal list. NB. the command -Y name changes: "find-principal" => "find-principals" ok markus@ OpenBSD-Commit-ID: ab575946ff9a55624cd4e811bfd338bf3b1d0faf
This commit is contained in:
Родитель
0585b56972
Коммит
72a8bea2d7
11
ssh-keygen.1
11
ssh-keygen.1
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: ssh-keygen.1,v 1.195 2020/01/23 07:16:38 jmc Exp $
|
||||
.\" $OpenBSD: ssh-keygen.1,v 1.196 2020/01/23 23:31:52 djm Exp $
|
||||
.\"
|
||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -138,7 +138,7 @@
|
|||
.Fl f Ar krl_file
|
||||
.Ar
|
||||
.Nm ssh-keygen
|
||||
.Fl Y Cm find-principal
|
||||
.Fl Y Cm find-principals
|
||||
.Fl s Ar signature_file
|
||||
.Fl f Ar allowed_signers_file
|
||||
.Nm ssh-keygen
|
||||
|
@ -618,8 +618,8 @@ The maximum is 3.
|
|||
Specifies a path to a library that will be used when creating
|
||||
FIDO authenticator-hosted keys, overriding the default of using
|
||||
the internal USB HID support.
|
||||
.It Fl Y Cm find-principal
|
||||
Find the principal associated with the public key of a signature,
|
||||
.It Fl Y Cm find-principals
|
||||
Find the principal(s) associated with the public key of a signature,
|
||||
provided using the
|
||||
.Fl s
|
||||
flag in an authorized signers file provided using the
|
||||
|
@ -628,7 +628,8 @@ flag.
|
|||
The format of the allowed signers file is documented in the
|
||||
.Sx ALLOWED SIGNERS
|
||||
section below.
|
||||
If a matching principal is found, it is returned on standard output.
|
||||
If one or more matching principals are found, they are returned on
|
||||
standard output.
|
||||
.It Fl Y Cm check-novalidate
|
||||
Checks that a signature generated using
|
||||
.Nm
|
||||
|
|
27
ssh-keygen.c
27
ssh-keygen.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-keygen.c,v 1.387 2020/01/23 07:54:04 djm Exp $ */
|
||||
/* $OpenBSD: ssh-keygen.c,v 1.388 2020/01/23 23:31:52 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -2758,11 +2758,11 @@ done:
|
|||
}
|
||||
|
||||
static int
|
||||
sig_find_principal(const char *signature, const char *allowed_keys) {
|
||||
sig_find_principals(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;
|
||||
char *principals = NULL;
|
||||
|
||||
if ((abuf = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new() failed", __func__);
|
||||
|
@ -2782,12 +2782,11 @@ sig_find_principal(const char *signature, const char *allowed_keys) {
|
|||
}
|
||||
if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) {
|
||||
error("%s: sshsig_get_pubkey: %s",
|
||||
__func__, ssh_err(r));
|
||||
__func__, ssh_err(r));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((r = sshsig_find_principal(allowed_keys, sign_key,
|
||||
&principal)) != 0) {
|
||||
if ((r = sshsig_find_principals(allowed_keys, sign_key,
|
||||
&principals)) != 0) {
|
||||
error("%s: sshsig_get_principal: %s",
|
||||
__func__, ssh_err(r));
|
||||
goto done;
|
||||
|
@ -2795,7 +2794,7 @@ sig_find_principal(const char *signature, const char *allowed_keys) {
|
|||
ret = 0;
|
||||
done:
|
||||
if (ret == 0 ) {
|
||||
printf("Found matching principal: %s\n", principal);
|
||||
printf("Found matching principal: %s\n", principals);
|
||||
} else {
|
||||
printf("Could not find matching principal.\n");
|
||||
}
|
||||
|
@ -2804,7 +2803,7 @@ done:
|
|||
sshbuf_free(sigbuf);
|
||||
sshbuf_free(abuf);
|
||||
sshkey_free(sign_key);
|
||||
free(principal);
|
||||
free(principals);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3093,7 +3092,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 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"
|
||||
" ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
|
||||
|
@ -3357,18 +3356,18 @@ main(int argc, char **argv)
|
|||
argc -= optind;
|
||||
|
||||
if (sign_op != NULL) {
|
||||
if (strncmp(sign_op, "find-principal", 14) == 0) {
|
||||
if (strncmp(sign_op, "find-principals", 15) == 0) {
|
||||
if (ca_key_path == NULL) {
|
||||
error("Too few arguments for find-principal:"
|
||||
error("Too few arguments for find-principals:"
|
||||
"missing signature file");
|
||||
exit(1);
|
||||
}
|
||||
if (!have_identity) {
|
||||
error("Too few arguments for find-principal:"
|
||||
error("Too few arguments for find-principals:"
|
||||
"missing allowed keys file");
|
||||
exit(1);
|
||||
}
|
||||
return sig_find_principal(ca_key_path, identity_file);
|
||||
return sig_find_principals(ca_key_path, identity_file);
|
||||
}
|
||||
if (cert_principals == NULL || *cert_principals == '\0') {
|
||||
error("Too few arguments for sign/verify: "
|
||||
|
|
74
sshsig.c
74
sshsig.c
|
@ -868,13 +868,64 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
|
|||
}
|
||||
|
||||
static int
|
||||
get_matching_principal_from_line(const char *path, u_long linenum, char *line,
|
||||
cert_filter_principals(const char *path, u_long linenum,
|
||||
char **principalsp, const struct sshkey *cert)
|
||||
{
|
||||
char *cp, *oprincipals, *principals;
|
||||
const char *reason;
|
||||
struct sshbuf *nprincipals;
|
||||
int r = SSH_ERR_INTERNAL_ERROR, success = 0;
|
||||
|
||||
oprincipals = principals = *principalsp;
|
||||
*principalsp = NULL;
|
||||
|
||||
if ((nprincipals = sshbuf_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
|
||||
while ((cp = strsep(&principals, ",")) != NULL && *cp != '\0') {
|
||||
if (strcspn(cp, "!?*") != strlen(cp)) {
|
||||
debug("%s:%lu: principal \"%s\" not authorized: "
|
||||
"contains wildcards", path, linenum, cp);
|
||||
continue;
|
||||
}
|
||||
/* Check against principals list in certificate */
|
||||
if ((r = sshkey_cert_check_authority(cert, 0, 1,
|
||||
cp, &reason)) != 0) {
|
||||
debug("%s:%lu: principal \"%s\" not authorized: %s",
|
||||
path, linenum, cp, reason);
|
||||
continue;
|
||||
}
|
||||
if ((r = sshbuf_putf(nprincipals, "%s%s",
|
||||
sshbuf_len(nprincipals) != 0 ? "," : "", cp)) != 0) {
|
||||
error("%s: buffer error", __func__);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (sshbuf_len(nprincipals) == 0) {
|
||||
error("%s:%lu: no valid principals found", path, linenum);
|
||||
r = SSH_ERR_KEY_CERT_INVALID;
|
||||
goto out;
|
||||
}
|
||||
if ((principals = sshbuf_dup_string(nprincipals)) == NULL) {
|
||||
error("%s: buffer error", __func__);
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
success = 1;
|
||||
*principalsp = principals;
|
||||
out:
|
||||
sshbuf_free(nprincipals);
|
||||
free(oprincipals);
|
||||
return success ? 0 : r;
|
||||
}
|
||||
|
||||
static int
|
||||
get_matching_principals_from_line(const char *path, u_long linenum, char *line,
|
||||
const struct sshkey *sign_key, char **principalsp)
|
||||
{
|
||||
struct sshkey *found_key = NULL;
|
||||
char *principals = NULL;
|
||||
int r, found = 0;
|
||||
const char *reason = NULL;
|
||||
struct sshsigopt *sigopts = NULL;
|
||||
|
||||
if (principalsp != NULL)
|
||||
|
@ -894,11 +945,12 @@ get_matching_principal_from_line(const char *path, u_long linenum, char *line,
|
|||
found = 1;
|
||||
} else if (sigopts->ca && sshkey_is_cert(sign_key) &&
|
||||
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
|
||||
/* Match of certificate's CA key */
|
||||
if ((r = sshkey_cert_check_authority(sign_key, 0, 1,
|
||||
principals, &reason)) != 0) {
|
||||
error("%s:%lu: certificate not authorized: %s",
|
||||
path, linenum, reason);
|
||||
/* Remove principals listed in file but not allowed by cert */
|
||||
if ((r = cert_filter_principals(path, linenum,
|
||||
&principals, sign_key)) != 0) {
|
||||
/* error already displayed */
|
||||
debug("%s:%lu: cert_filter_principals: %s",
|
||||
path, linenum, ssh_err(r));
|
||||
goto done;
|
||||
}
|
||||
debug("%s:%lu: matched certificate CA key", path, linenum);
|
||||
|
@ -920,8 +972,8 @@ get_matching_principal_from_line(const char *path, u_long linenum, char *line,
|
|||
}
|
||||
|
||||
int
|
||||
sshsig_find_principal(const char *path, const struct sshkey *sign_key,
|
||||
char **principal)
|
||||
sshsig_find_principals(const char *path, const struct sshkey *sign_key,
|
||||
char **principals)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
char *line = NULL;
|
||||
|
@ -939,8 +991,8 @@ sshsig_find_principal(const char *path, const struct sshkey *sign_key,
|
|||
|
||||
while (getline(&line, &linesize, f) != -1) {
|
||||
linenum++;
|
||||
r = get_matching_principal_from_line(path, linenum, line,
|
||||
sign_key, principal);
|
||||
r = get_matching_principals_from_line(path, linenum, line,
|
||||
sign_key, principals);
|
||||
free(line);
|
||||
line = NULL;
|
||||
if (r == SSH_ERR_KEY_NOT_FOUND)
|
||||
|
|
5
sshsig.h
5
sshsig.h
|
@ -93,13 +93,12 @@ struct sshsigopt *sshsigopt_parse(const char *opts,
|
|||
void sshsigopt_free(struct sshsigopt *opts);
|
||||
|
||||
/* Get public key from signature */
|
||||
int
|
||||
sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey);
|
||||
int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey);
|
||||
|
||||
/* Find principal in allowed_keys file, given a sshkey. Returns
|
||||
* 0 on success.
|
||||
*/
|
||||
int sshsig_find_principal(const char *path, const struct sshkey *sign_key,
|
||||
int sshsig_find_principals(const char *path, const struct sshkey *sign_key,
|
||||
char **principal);
|
||||
|
||||
#endif /* SSHSIG_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче