version 1.8, 2019/11/25 00:51:37 |
version 1.9, 2020/01/22 02:25:21 |
|
|
} |
} |
|
|
static int |
static int |
check_allowed_keys_line(const char *path, u_long linenum, char *line, |
parse_principals_key_and_options(const char *path, u_long linenum, char *line, |
const struct sshkey *sign_key, const char *principal, |
const char *required_principal, char **principalsp, struct sshkey **keyp, |
const char *sig_namespace) |
struct sshsigopt **sigoptsp) |
{ |
{ |
struct sshkey *found_key = NULL; |
char *opts = NULL, *tmp, *cp, *principals = NULL; |
char *cp, *opts = NULL, *identities = NULL; |
|
int r, found = 0; |
|
const char *reason = NULL; |
const char *reason = NULL; |
struct sshsigopt *sigopts = NULL; |
struct sshsigopt *sigopts = NULL; |
|
struct sshkey *key = NULL; |
|
int r = SSH_ERR_INTERNAL_ERROR; |
|
|
if ((found_key = sshkey_new(KEY_UNSPEC)) == NULL) { |
if (principalsp != NULL) |
error("%s: sshkey_new failed", __func__); |
*principalsp = NULL; |
return SSH_ERR_ALLOC_FAIL; |
if (sigoptsp != NULL) |
} |
*sigoptsp = NULL; |
|
if (keyp != NULL) |
|
*keyp = NULL; |
|
|
/* format: identity[,identity...] [option[,option...]] key */ |
|
cp = line; |
cp = line; |
cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ |
cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ |
if (*cp == '#' || *cp == '\0') |
if (*cp == '#' || *cp == '\0') |
goto done; |
return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */ |
if ((identities = strdelimw(&cp)) == NULL) { |
|
|
/* format: identity[,identity...] [option[,option...]] key */ |
|
if ((tmp = strdelimw(&cp)) == NULL) { |
error("%s:%lu: invalid line", path, linenum); |
error("%s:%lu: invalid line", path, linenum); |
goto done; |
r = SSH_ERR_INVALID_FORMAT; |
|
goto out; |
} |
} |
if (match_pattern_list(principal, identities, 0) != 1) { |
if ((principals = strdup(tmp)) == NULL) { |
/* principal didn't match */ |
error("%s: strdup failed", __func__); |
goto done; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
} |
} |
debug("%s: %s:%lu: matched principal \"%s\"", |
/* |
__func__, path, linenum, principal); |
* Bail out early if we're looking for a particular principal and this |
|
* line does not list it. |
|
*/ |
|
if (required_principal != NULL) { |
|
if (match_pattern_list(required_principal, |
|
principals, 0) != 1) { |
|
/* principal didn't match */ |
|
r = SSH_ERR_KEY_NOT_FOUND; |
|
goto out; |
|
} |
|
debug("%s: %s:%lu: matched principal \"%s\"", |
|
__func__, path, linenum, required_principal); |
|
} |
|
|
if (sshkey_read(found_key, &cp) != 0) { |
if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { |
|
error("%s: sshkey_new failed", __func__); |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if (sshkey_read(key, &cp) != 0) { |
/* no key? Check for options */ |
/* no key? Check for options */ |
opts = cp; |
opts = cp; |
if (sshkey_advance_past_options(&cp) != 0) { |
if (sshkey_advance_past_options(&cp) != 0) { |
error("%s:%lu: invalid options", |
error("%s:%lu: invalid options", path, linenum); |
path, linenum); |
r = SSH_ERR_INVALID_FORMAT; |
goto done; |
goto out; |
} |
} |
*cp++ = '\0'; |
*cp++ = '\0'; |
skip_space(&cp); |
skip_space(&cp); |
if (sshkey_read(found_key, &cp) != 0) { |
if (sshkey_read(key, &cp) != 0) { |
error("%s:%lu: invalid key", path, |
error("%s:%lu: invalid key", path, linenum); |
linenum); |
r = SSH_ERR_INVALID_FORMAT; |
goto done; |
goto out; |
} |
} |
} |
} |
debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts); |
debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts); |
if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) { |
if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) { |
error("%s:%lu: bad options: %s", path, linenum, reason); |
error("%s:%lu: bad options: %s", path, linenum, reason); |
|
r = SSH_ERR_INVALID_FORMAT; |
|
goto out; |
|
} |
|
/* success */ |
|
if (principalsp != NULL) { |
|
*principalsp = principals; |
|
principals = NULL; /* transferred */ |
|
} |
|
if (sigoptsp != NULL) { |
|
*sigoptsp = sigopts; |
|
sigopts = NULL; /* transferred */ |
|
} |
|
if (keyp != NULL) { |
|
*keyp = key; |
|
key = NULL; /* transferred */ |
|
} |
|
r = 0; |
|
out: |
|
free(principals); |
|
sshsigopt_free(sigopts); |
|
sshkey_free(key); |
|
return r; |
|
} |
|
|
|
static int |
|
check_allowed_keys_line(const char *path, u_long linenum, char *line, |
|
const struct sshkey *sign_key, const char *principal, |
|
const char *sig_namespace) |
|
{ |
|
struct sshkey *found_key = NULL; |
|
int r, found = 0; |
|
const char *reason = NULL; |
|
struct sshsigopt *sigopts = NULL; |
|
|
|
/* Parse the line */ |
|
if ((r = parse_principals_key_and_options(path, linenum, line, |
|
principal, NULL, &found_key, &sigopts)) != 0) { |
|
/* error already logged */ |
goto done; |
goto done; |
} |
} |
|
|