From 4dc8da7eea0ecc009239dff4ad8f79c9c148c142 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 26 Aug 2018 09:18:57 -0400 Subject: Restore wildcard semantics We now ignore the wildcard if we have another matching key -- even if the wildcard entry comes first in authorized_keys. This is how it worked before the forward port. --- auth2-pubkey.c | 95 ++++++++++++++++++++++++++++++++++++++-------------------- session.c | 4 +-- 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/auth2-pubkey.c b/auth2-pubkey.c index d630d43ef..1f0436ebd 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -555,6 +555,42 @@ advance_past_options(char **cpp) return (*cp == '\0' && quoted) ? -1 : 0; } +static int +check_authkey_line_for_wildcard(struct sshkey *key, char *cp, const char *loc, struct sshauthopt **authoptsp) +{ + struct sshauthopt *keyopts = NULL; + const char *reason = NULL; + char *key_options = cp; + + if (advance_past_options(&cp) != 0) return -1; + skip_space(&cp); + + if (!(*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0'))) { + return -1; // This is not a wildcard auth line. + } + + if ((keyopts = sshauthopt_parse(key_options, &reason)) == NULL) { + debug("%s: bad key options: %s", loc, reason); + auth_debug_add("%s: bad key options: %s", loc, reason); + return -1; + } + + if (keyopts->force_command) { /* We have a valid wildcard entry! */ + + *authoptsp = keyopts; + return 0; + + } else { + + sshauthopt_free(keyopts); + reason = "Wildcard login is not allowed without specifying a forced command"; + error("%s", reason); + auth_debug_add("%s", reason); + return -1; + + } +} + /* * Check a single line of an authorized_keys-format file. Returns 0 if key * matches, -1 otherwise. Will return key/cert options via *authoptsp @@ -581,8 +617,6 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, /* XXX djm: peek at key type in line and skip if unwanted */ - int wild = 0; - if (sshkey_read(found, &cp) != 0) { /* no key? check for options */ debug2("%s: check options: '%s'", loc, cp); @@ -593,8 +627,8 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, } skip_space(&cp); if (*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0')) { - cp += 2; - wild = 1; + /* This is a wildcard entry. Ignore it silently. */ + goto out; } else if (sshkey_read(found, &cp) != 0) { /* still no key? advance to next line*/ debug2("%s: advance: '%s'", loc, cp); @@ -607,33 +641,6 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, auth_debug_add("%s: bad key options: %s", loc, reason); goto out; } - - if (wild) { - int r; - char *keytext = NULL; - if ((r = sshkey_to_base64(key, &keytext)) != 0) { - error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); - goto out; - } - if (!keyopts->force_command) { - reason = "Wildcard login is not allowed without specifying a forced command"; - goto fail_reason; - } - - wildcard_remote_key = keytext; - wildcard_remote_key_type = sshkey_type(key); - wildcard_remote_key_fingerprint = sshkey_fingerprint(key, SSH_DIGEST_SHA256, SSH_FP_HEX); - - verbose("Accepted wildcard authorization for %s key %s with forced_command=%s", - sshkey_type(key), - wildcard_remote_key_fingerprint, - keyopts->force_command); - - finalopts = keyopts; - keyopts = NULL; - goto success; - } - /* Ignore keys that don't match or incorrectly marked as CAs */ if (sshkey_is_cert(key)) { /* Certificate; check signature key against CA */ @@ -739,6 +746,7 @@ check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, size_t linesize = 0; int found_key = 0; u_long linenum = 0; + struct sshauthopt *wildcardoptsp = NULL; if (authoptsp != NULL) *authoptsp = NULL; @@ -757,9 +765,32 @@ check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0) found_key = 1; + else if (wildcardoptsp == NULL) { + check_authkey_line_for_wildcard(key, cp, loc, &wildcardoptsp); + } } free(line); - return found_key; + if (found_key) { + return 1; + } else if (!wildcardoptsp) { + return 0; + } else { + + if (1) { // This block is obsoleted by SSH_USER_AUTH + int r; + char *keytext = NULL; + if ((r = sshkey_to_base64(key, &keytext)) != 0) { + error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); + return -1; + } + wildcard_remote_key = keytext; + wildcard_remote_key_type = sshkey_type(key); + wildcard_remote_key_fingerprint = sshkey_fingerprint(key, SSH_DIGEST_SHA256, SSH_FP_HEX); + } + + *authoptsp = wildcardoptsp; + return 1; + } } /* Authenticate a certificate key against TrustedUserCAKeys */ diff --git a/session.c b/session.c index fca7e4095..694c41a4c 100644 --- a/session.c +++ b/session.c @@ -1095,8 +1095,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) if (s->display) child_set_env(&env, &envsize, "DISPLAY", s->display); if (wildcard_remote_key) { - /* This is basically obsolete because of SSH_USER_AUTH */ - /* I'm leaving it here only because I have code that uses these variables. */ + /* This is basically obsolete because of SSH_USER_AUTH */ + /* I'm leaving it here only because I have code that uses these variables. */ child_set_env(&env, &envsize, "SSH_REMOTE_KEY", wildcard_remote_key); child_set_env(&env, &envsize, "SSH_REMOTE_KEY_TYPE", -- cgit v1.2.3