version 1.22, 2021/11/05 03:10:58 |
version 1.23, 2021/11/18 03:50:41 |
|
|
static int |
static int |
check_allowed_keys_line(const char *path, u_long linenum, char *line, |
check_allowed_keys_line(const char *path, u_long linenum, char *line, |
const struct sshkey *sign_key, const char *principal, |
const struct sshkey *sign_key, const char *principal, |
const char *sig_namespace, uint64_t verify_time) |
const char *sig_namespace, uint64_t verify_time, char **principalsp) |
{ |
{ |
struct sshkey *found_key = NULL; |
struct sshkey *found_key = NULL; |
|
char *principals = NULL; |
int r, success = 0; |
int r, success = 0; |
const char *reason = NULL; |
const char *reason = NULL; |
struct sshsigopt *sigopts = NULL; |
struct sshsigopt *sigopts = NULL; |
char tvalid[64], tverify[64]; |
char tvalid[64], tverify[64]; |
|
|
|
if (principalsp != NULL) |
|
*principalsp = NULL; |
|
|
/* Parse the line */ |
/* Parse the line */ |
if ((r = parse_principals_key_and_options(path, linenum, line, |
if ((r = parse_principals_key_and_options(path, linenum, line, |
principal, NULL, &found_key, &sigopts)) != 0) { |
principal, &principals, &found_key, &sigopts)) != 0) { |
/* error already logged */ |
/* error already logged */ |
goto done; |
goto done; |
} |
} |
|
|
debug("%s:%lu: matched key", path, linenum); |
debug("%s:%lu: matched key", path, linenum); |
} else if (sigopts->ca && sshkey_is_cert(sign_key) && |
} else if (sigopts->ca && sshkey_is_cert(sign_key) && |
sshkey_equal_public(sign_key->cert->signature_key, found_key)) { |
sshkey_equal_public(sign_key->cert->signature_key, found_key)) { |
/* Match of certificate's CA key */ |
if (principal) { |
if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0, |
/* Match certificate CA key with specified principal */ |
verify_time, principal, &reason)) != 0) { |
if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0, |
error("%s:%lu: certificate not authorized: %s", |
verify_time, principal, &reason)) != 0) { |
path, linenum, reason); |
error("%s:%lu: certificate not authorized: %s", |
goto done; |
path, linenum, reason); |
|
goto done; |
|
} |
|
debug("%s:%lu: matched certificate CA key", |
|
path, linenum); |
|
} else { |
|
/* No principal specified - find all matching ones */ |
|
if ((r = cert_filter_principals(path, linenum, |
|
&principals, sign_key, verify_time)) != 0) { |
|
/* error already displayed */ |
|
debug_r(r, "%s:%lu: cert_filter_principals", |
|
path, linenum); |
|
goto done; |
|
} |
|
debug("%s:%lu: matched certificate CA key", |
|
path, linenum); |
} |
} |
debug("%s:%lu: matched certificate CA key", path, linenum); |
|
} else { |
} else { |
/* Didn't match key */ |
/* Didn't match key */ |
goto done; |
goto done; |
|
|
success = 1; |
success = 1; |
|
|
done: |
done: |
|
if (success && principalsp != NULL) { |
|
*principalsp = principals; |
|
principals = NULL; /* transferred */ |
|
} |
|
free(principals); |
sshkey_free(found_key); |
sshkey_free(found_key); |
sshsigopt_free(sigopts); |
sshsigopt_free(sigopts); |
return success ? 0 : SSH_ERR_KEY_NOT_FOUND; |
return success ? 0 : SSH_ERR_KEY_NOT_FOUND; |
|
|
while (getline(&line, &linesize, f) != -1) { |
while (getline(&line, &linesize, f) != -1) { |
linenum++; |
linenum++; |
r = check_allowed_keys_line(path, linenum, line, sign_key, |
r = check_allowed_keys_line(path, linenum, line, sign_key, |
principal, sig_namespace, verify_time); |
principal, sig_namespace, verify_time, NULL); |
free(line); |
free(line); |
line = NULL; |
line = NULL; |
linesize = 0; |
linesize = 0; |
|
|
return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r; |
return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r; |
} |
} |
|
|
static int |
|
get_matching_principals_from_line(const char *path, u_long linenum, char *line, |
|
const struct sshkey *sign_key, uint64_t verify_time, char **principalsp) |
|
{ |
|
struct sshkey *found_key = NULL; |
|
char *principals = NULL; |
|
int r, found = 0; |
|
struct sshsigopt *sigopts = NULL; |
|
|
|
if (principalsp != NULL) |
|
*principalsp = NULL; |
|
|
|
/* Parse the line */ |
|
if ((r = parse_principals_key_and_options(path, linenum, line, |
|
NULL, &principals, &found_key, &sigopts)) != 0) { |
|
/* error already logged */ |
|
goto done; |
|
} |
|
|
|
if (!sigopts->ca && sshkey_equal(found_key, sign_key)) { |
|
/* Exact match of key */ |
|
debug("%s:%lu: matched key", path, linenum); |
|
/* success */ |
|
found = 1; |
|
} else if (sigopts->ca && sshkey_is_cert(sign_key) && |
|
sshkey_equal_public(sign_key->cert->signature_key, found_key)) { |
|
/* Remove principals listed in file but not allowed by cert */ |
|
if ((r = cert_filter_principals(path, linenum, |
|
&principals, sign_key, verify_time)) != 0) { |
|
/* error already displayed */ |
|
debug_r(r, "%s:%lu: cert_filter_principals", |
|
path, linenum); |
|
goto done; |
|
} |
|
debug("%s:%lu: matched certificate CA key", path, linenum); |
|
/* success */ |
|
found = 1; |
|
} else { |
|
/* Key didn't match */ |
|
goto done; |
|
} |
|
done: |
|
if (found && principalsp != NULL) { |
|
*principalsp = principals; |
|
principals = NULL; /* transferred */ |
|
} |
|
free(principals); |
|
sshkey_free(found_key); |
|
sshsigopt_free(sigopts); |
|
return found ? 0 : SSH_ERR_KEY_NOT_FOUND; |
|
} |
|
|
|
int |
int |
sshsig_find_principals(const char *path, const struct sshkey *sign_key, |
sshsig_find_principals(const char *path, const struct sshkey *sign_key, |
uint64_t verify_time, char **principals) |
uint64_t verify_time, char **principals) |
|
|
|
|
while (getline(&line, &linesize, f) != -1) { |
while (getline(&line, &linesize, f) != -1) { |
linenum++; |
linenum++; |
r = get_matching_principals_from_line(path, linenum, line, |
r = check_allowed_keys_line(path, linenum, line, |
sign_key, verify_time, principals); |
sign_key, NULL, NULL, verify_time, principals); |
free(line); |
free(line); |
line = NULL; |
line = NULL; |
linesize = 0; |
linesize = 0; |