version 1.113, 2022/02/27 01:33:59 |
version 1.114, 2022/05/27 05:01:25 |
|
|
int req_presence = 0, req_verify = 0, authenticated = 0; |
int req_presence = 0, req_verify = 0, authenticated = 0; |
struct sshauthopt *authopts = NULL; |
struct sshauthopt *authopts = NULL; |
struct sshkey_sig_details *sig_details = NULL; |
struct sshkey_sig_details *sig_details = NULL; |
|
const char *remote_ip = ssh_remote_ipaddr(ssh); |
|
const char *remote_host = auth_get_canonical_hostname(ssh, |
|
options.use_dns); |
|
|
hostbound = strcmp(method, "publickey-hostbound-v00@openssh.com") == 0; |
hostbound = strcmp(method, "publickey-hostbound-v00@openssh.com") == 0; |
|
|
|
|
#endif |
#endif |
/* test for correct signature */ |
/* test for correct signature */ |
authenticated = 0; |
authenticated = 0; |
if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && |
if (PRIVSEP(user_key_allowed(pw, key, 1, remote_ip, |
|
remote_host, &authopts)) && |
PRIVSEP(sshkey_verify(key, sig, slen, |
PRIVSEP(sshkey_verify(key, sig, slen, |
sshbuf_ptr(b), sshbuf_len(b), |
sshbuf_ptr(b), sshbuf_len(b), |
(ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, |
(ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, |
|
|
* if a user is not allowed to login. is this an |
* if a user is not allowed to login. is this an |
* issue? -markus |
* issue? -markus |
*/ |
*/ |
if (PRIVSEP(user_key_allowed(ssh, pw, key, 0, NULL))) { |
if (PRIVSEP(user_key_allowed(pw, key, 0, remote_ip, |
|
remote_host, NULL))) { |
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK)) |
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK)) |
!= 0 || |
!= 0 || |
(r = sshpkt_put_cstring(ssh, pkalg)) != 0 || |
(r = sshpkt_put_cstring(ssh, pkalg)) != 0 || |
|
|
* log preamble for file/line information. |
* log preamble for file/line information. |
*/ |
*/ |
static int |
static int |
check_principals_line(struct ssh *ssh, char *cp, const struct sshkey_cert *cert, |
check_principals_line(char *cp, const struct sshkey_cert *cert, |
const char *loc, struct sshauthopt **authoptsp) |
const char *loc, struct sshauthopt **authoptsp) |
{ |
{ |
u_int i, found = 0; |
u_int i, found = 0; |
|
|
} |
} |
|
|
static int |
static int |
process_principals(struct ssh *ssh, FILE *f, const char *file, |
process_principals(FILE *f, const char *file, |
const struct sshkey_cert *cert, struct sshauthopt **authoptsp) |
const struct sshkey_cert *cert, struct sshauthopt **authoptsp) |
{ |
{ |
char loc[256], *line = NULL, *cp, *ep; |
char loc[256], *line = NULL, *cp, *ep; |
|
|
|
|
nonblank++; |
nonblank++; |
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); |
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); |
if (check_principals_line(ssh, cp, cert, loc, authoptsp) == 0) |
if (check_principals_line(cp, cert, loc, authoptsp) == 0) |
found_principal = 1; |
found_principal = 1; |
} |
} |
debug2_f("%s: processed %lu/%lu lines", file, nonblank, linenum); |
debug2_f("%s: processed %lu/%lu lines", file, nonblank, linenum); |
|
|
/* XXX remove pw args here and elsewhere once ssh->authctxt is guaranteed */ |
/* XXX remove pw args here and elsewhere once ssh->authctxt is guaranteed */ |
|
|
static int |
static int |
match_principals_file(struct ssh *ssh, struct passwd *pw, char *file, |
match_principals_file(struct passwd *pw, char *file, |
struct sshkey_cert *cert, struct sshauthopt **authoptsp) |
struct sshkey_cert *cert, struct sshauthopt **authoptsp) |
{ |
{ |
FILE *f; |
FILE *f; |
|
|
restore_uid(); |
restore_uid(); |
return 0; |
return 0; |
} |
} |
success = process_principals(ssh, f, file, cert, authoptsp); |
success = process_principals(f, file, cert, authoptsp); |
fclose(f); |
fclose(f); |
restore_uid(); |
restore_uid(); |
return success; |
return success; |
|
|
* returns 1 if the principal is allowed or 0 otherwise. |
* returns 1 if the principal is allowed or 0 otherwise. |
*/ |
*/ |
static int |
static int |
match_principals_command(struct ssh *ssh, struct passwd *user_pw, |
match_principals_command(struct passwd *user_pw, |
const struct sshkey *key, struct sshauthopt **authoptsp) |
const struct sshkey *key, struct sshauthopt **authoptsp) |
{ |
{ |
struct passwd *runas_pw = NULL; |
struct passwd *runas_pw = NULL; |
|
|
uid_swapped = 1; |
uid_swapped = 1; |
temporarily_use_uid(runas_pw); |
temporarily_use_uid(runas_pw); |
|
|
ok = process_principals(ssh, f, "(command)", cert, authoptsp); |
ok = process_principals(f, "(command)", cert, authoptsp); |
|
|
fclose(f); |
fclose(f); |
f = NULL; |
f = NULL; |
|
|
* on success. "loc" is used as file/line location in log messages. |
* on success. "loc" is used as file/line location in log messages. |
*/ |
*/ |
static int |
static int |
check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, |
check_authkey_line(struct passwd *pw, struct sshkey *key, |
char *cp, const char *loc, struct sshauthopt **authoptsp) |
char *cp, const char *remote_ip, const char *remote_host, const char *loc, |
|
struct sshauthopt **authoptsp) |
{ |
{ |
int want_keytype = sshkey_is_cert(key) ? KEY_UNSPEC : key->type; |
int want_keytype = sshkey_is_cert(key) ? KEY_UNSPEC : key->type; |
struct sshkey *found = NULL; |
struct sshkey *found = NULL; |
|
|
debug("%s: matching %s found: %s %s", loc, |
debug("%s: matching %s found: %s %s", loc, |
sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp); |
sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp); |
|
|
if (auth_authorise_keyopts(ssh, pw, keyopts, |
if (auth_authorise_keyopts(pw, keyopts, |
sshkey_is_cert(key), loc) != 0) { |
sshkey_is_cert(key), remote_ip, remote_host, loc) != 0) { |
reason = "Refused by key options"; |
reason = "Refused by key options"; |
goto fail_reason; |
goto fail_reason; |
} |
} |
|
|
reason = "Invalid certificate options"; |
reason = "Invalid certificate options"; |
goto fail_reason; |
goto fail_reason; |
} |
} |
if (auth_authorise_keyopts(ssh, pw, certopts, 0, loc) != 0) { |
if (auth_authorise_keyopts(pw, certopts, 0, |
|
remote_ip, remote_host, loc) != 0) { |
reason = "Refused by certificate options"; |
reason = "Refused by certificate options"; |
goto fail_reason; |
goto fail_reason; |
} |
} |
|
|
* returns 1 if the key is allowed or 0 otherwise. |
* returns 1 if the key is allowed or 0 otherwise. |
*/ |
*/ |
static int |
static int |
check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, |
check_authkeys_file(struct passwd *pw, FILE *f, char *file, |
char *file, struct sshkey *key, struct sshauthopt **authoptsp) |
struct sshkey *key, const char *remote_ip, |
|
const char *remote_host, struct sshauthopt **authoptsp) |
{ |
{ |
char *cp, *line = NULL, loc[256]; |
char *cp, *line = NULL, loc[256]; |
size_t linesize = 0; |
size_t linesize = 0; |
|
|
|
|
nonblank++; |
nonblank++; |
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); |
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); |
if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0) |
if (check_authkey_line(pw, key, cp, |
|
remote_ip, remote_host, loc, authoptsp) == 0) |
found_key = 1; |
found_key = 1; |
} |
} |
free(line); |
free(line); |
|
|
|
|
/* Authenticate a certificate key against TrustedUserCAKeys */ |
/* Authenticate a certificate key against TrustedUserCAKeys */ |
static int |
static int |
user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key, |
user_cert_trusted_ca(struct passwd *pw, struct sshkey *key, |
|
const char *remote_ip, const char *remote_host, |
struct sshauthopt **authoptsp) |
struct sshauthopt **authoptsp) |
{ |
{ |
char *ca_fp, *principals_file = NULL; |
char *ca_fp, *principals_file = NULL; |
|
|
* against the username. |
* against the username. |
*/ |
*/ |
if ((principals_file = authorized_principals_file(pw)) != NULL) { |
if ((principals_file = authorized_principals_file(pw)) != NULL) { |
if (match_principals_file(ssh, pw, principals_file, |
if (match_principals_file(pw, principals_file, |
key->cert, &principals_opts)) |
key->cert, &principals_opts)) |
found_principal = 1; |
found_principal = 1; |
} |
} |
/* Try querying command if specified */ |
/* Try querying command if specified */ |
if (!found_principal && match_principals_command(ssh, pw, key, |
if (!found_principal && match_principals_command(pw, key, |
&principals_opts)) |
&principals_opts)) |
found_principal = 1; |
found_principal = 1; |
/* If principals file or command is specified, then require a match */ |
/* If principals file or command is specified, then require a match */ |
|
|
reason = "Invalid certificate options"; |
reason = "Invalid certificate options"; |
goto fail_reason; |
goto fail_reason; |
} |
} |
if (auth_authorise_keyopts(ssh, pw, cert_opts, 0, "cert") != 0) { |
if (auth_authorise_keyopts(pw, cert_opts, 0, |
|
remote_ip, remote_host, "cert") != 0) { |
reason = "Refused by certificate options"; |
reason = "Refused by certificate options"; |
goto fail_reason; |
goto fail_reason; |
} |
} |
|
|
final_opts = cert_opts; |
final_opts = cert_opts; |
cert_opts = NULL; |
cert_opts = NULL; |
} else { |
} else { |
if (auth_authorise_keyopts(ssh, pw, principals_opts, 0, |
if (auth_authorise_keyopts(pw, principals_opts, 0, |
"principals") != 0) { |
remote_ip, remote_host, "principals") != 0) { |
reason = "Refused by certificate principals options"; |
reason = "Refused by certificate principals options"; |
goto fail_reason; |
goto fail_reason; |
} |
} |
|
|
* returns 1 if the key is allowed or 0 otherwise. |
* returns 1 if the key is allowed or 0 otherwise. |
*/ |
*/ |
static int |
static int |
user_key_allowed2(struct ssh *ssh, struct passwd *pw, struct sshkey *key, |
user_key_allowed2(struct passwd *pw, struct sshkey *key, |
char *file, struct sshauthopt **authoptsp) |
char *file, const char *remote_ip, const char *remote_host, |
|
struct sshauthopt **authoptsp) |
{ |
{ |
FILE *f; |
FILE *f; |
int found_key = 0; |
int found_key = 0; |
|
|
|
|
debug("trying public key file %s", file); |
debug("trying public key file %s", file); |
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) { |
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) { |
found_key = check_authkeys_file(ssh, pw, f, file, |
found_key = check_authkeys_file(pw, f, file, |
key, authoptsp); |
key, remote_ip, remote_host, authoptsp); |
fclose(f); |
fclose(f); |
} |
} |
|
|
|
|
* returns 1 if the key is allowed or 0 otherwise. |
* returns 1 if the key is allowed or 0 otherwise. |
*/ |
*/ |
static int |
static int |
user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, |
user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key, |
struct sshkey *key, struct sshauthopt **authoptsp) |
const char *remote_ip, const char *remote_host, |
|
struct sshauthopt **authoptsp) |
{ |
{ |
struct passwd *runas_pw = NULL; |
struct passwd *runas_pw = NULL; |
FILE *f = NULL; |
FILE *f = NULL; |
|
|
uid_swapped = 1; |
uid_swapped = 1; |
temporarily_use_uid(runas_pw); |
temporarily_use_uid(runas_pw); |
|
|
ok = check_authkeys_file(ssh, user_pw, f, |
ok = check_authkeys_file(user_pw, f, |
options.authorized_keys_command, key, authoptsp); |
options.authorized_keys_command, key, remote_ip, |
|
remote_host, authoptsp); |
|
|
fclose(f); |
fclose(f); |
f = NULL; |
f = NULL; |
|
|
* Check whether key authenticates and authorises the user. |
* Check whether key authenticates and authorises the user. |
*/ |
*/ |
int |
int |
user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, |
user_key_allowed(struct passwd *pw, struct sshkey *key, |
int auth_attempt, struct sshauthopt **authoptsp) |
int auth_attempt, const char *remote_ip, const char *remote_host, |
|
struct sshauthopt **authoptsp) |
{ |
{ |
u_int success = 0, i; |
u_int success = 0, i; |
char *file; |
char *file; |
|
|
continue; |
continue; |
file = expand_authorized_keys( |
file = expand_authorized_keys( |
options.authorized_keys_files[i], pw); |
options.authorized_keys_files[i], pw); |
success = user_key_allowed2(ssh, pw, key, file, &opts); |
success = user_key_allowed2(pw, key, file, |
|
remote_ip, remote_host, &opts); |
free(file); |
free(file); |
if (!success) { |
if (!success) { |
sshauthopt_free(opts); |
sshauthopt_free(opts); |
|
|
if (success) |
if (success) |
goto out; |
goto out; |
|
|
if ((success = user_cert_trusted_ca(ssh, pw, key, &opts)) != 0) |
if ((success = user_cert_trusted_ca(pw, key, remote_ip, remote_host, |
|
&opts)) != 0) |
goto out; |
goto out; |
sshauthopt_free(opts); |
sshauthopt_free(opts); |
opts = NULL; |
opts = NULL; |
|
|
if ((success = user_key_command_allowed2(ssh, pw, key, &opts)) != 0) |
if ((success = user_key_command_allowed2(pw, key, remote_ip, |
|
remote_host, &opts)) != 0) |
goto out; |
goto out; |
sshauthopt_free(opts); |
sshauthopt_free(opts); |
opts = NULL; |
opts = NULL; |