diff options
author | Andrew Cady <d@jerkface.net> | 2018-08-26 09:18:57 -0400 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2019-06-06 11:52:37 -0400 |
commit | 4dc8da7eea0ecc009239dff4ad8f79c9c148c142 (patch) | |
tree | f234fef0988f63a68fa320f8bce4d40cf2c4464f | |
parent | 4738aeb85fa56865244969dee521ef7f24d4f7c1 (diff) |
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.
-rw-r--r-- | auth2-pubkey.c | 95 | ||||
-rw-r--r-- | 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) | |||
555 | return (*cp == '\0' && quoted) ? -1 : 0; | 555 | return (*cp == '\0' && quoted) ? -1 : 0; |
556 | } | 556 | } |
557 | 557 | ||
558 | static int | ||
559 | check_authkey_line_for_wildcard(struct sshkey *key, char *cp, const char *loc, struct sshauthopt **authoptsp) | ||
560 | { | ||
561 | struct sshauthopt *keyopts = NULL; | ||
562 | const char *reason = NULL; | ||
563 | char *key_options = cp; | ||
564 | |||
565 | if (advance_past_options(&cp) != 0) return -1; | ||
566 | skip_space(&cp); | ||
567 | |||
568 | if (!(*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0'))) { | ||
569 | return -1; // This is not a wildcard auth line. | ||
570 | } | ||
571 | |||
572 | if ((keyopts = sshauthopt_parse(key_options, &reason)) == NULL) { | ||
573 | debug("%s: bad key options: %s", loc, reason); | ||
574 | auth_debug_add("%s: bad key options: %s", loc, reason); | ||
575 | return -1; | ||
576 | } | ||
577 | |||
578 | if (keyopts->force_command) { /* We have a valid wildcard entry! */ | ||
579 | |||
580 | *authoptsp = keyopts; | ||
581 | return 0; | ||
582 | |||
583 | } else { | ||
584 | |||
585 | sshauthopt_free(keyopts); | ||
586 | reason = "Wildcard login is not allowed without specifying a forced command"; | ||
587 | error("%s", reason); | ||
588 | auth_debug_add("%s", reason); | ||
589 | return -1; | ||
590 | |||
591 | } | ||
592 | } | ||
593 | |||
558 | /* | 594 | /* |
559 | * Check a single line of an authorized_keys-format file. Returns 0 if key | 595 | * Check a single line of an authorized_keys-format file. Returns 0 if key |
560 | * matches, -1 otherwise. Will return key/cert options via *authoptsp | 596 | * 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, | |||
581 | 617 | ||
582 | /* XXX djm: peek at key type in line and skip if unwanted */ | 618 | /* XXX djm: peek at key type in line and skip if unwanted */ |
583 | 619 | ||
584 | int wild = 0; | ||
585 | |||
586 | if (sshkey_read(found, &cp) != 0) { | 620 | if (sshkey_read(found, &cp) != 0) { |
587 | /* no key? check for options */ | 621 | /* no key? check for options */ |
588 | debug2("%s: check options: '%s'", loc, cp); | 622 | debug2("%s: check options: '%s'", loc, cp); |
@@ -593,8 +627,8 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, | |||
593 | } | 627 | } |
594 | skip_space(&cp); | 628 | skip_space(&cp); |
595 | if (*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0')) { | 629 | if (*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0')) { |
596 | cp += 2; | 630 | /* This is a wildcard entry. Ignore it silently. */ |
597 | wild = 1; | 631 | goto out; |
598 | } else if (sshkey_read(found, &cp) != 0) { | 632 | } else if (sshkey_read(found, &cp) != 0) { |
599 | /* still no key? advance to next line*/ | 633 | /* still no key? advance to next line*/ |
600 | debug2("%s: advance: '%s'", loc, cp); | 634 | debug2("%s: advance: '%s'", loc, cp); |
@@ -607,33 +641,6 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, | |||
607 | auth_debug_add("%s: bad key options: %s", loc, reason); | 641 | auth_debug_add("%s: bad key options: %s", loc, reason); |
608 | goto out; | 642 | goto out; |
609 | } | 643 | } |
610 | |||
611 | if (wild) { | ||
612 | int r; | ||
613 | char *keytext = NULL; | ||
614 | if ((r = sshkey_to_base64(key, &keytext)) != 0) { | ||
615 | error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); | ||
616 | goto out; | ||
617 | } | ||
618 | if (!keyopts->force_command) { | ||
619 | reason = "Wildcard login is not allowed without specifying a forced command"; | ||
620 | goto fail_reason; | ||
621 | } | ||
622 | |||
623 | wildcard_remote_key = keytext; | ||
624 | wildcard_remote_key_type = sshkey_type(key); | ||
625 | wildcard_remote_key_fingerprint = sshkey_fingerprint(key, SSH_DIGEST_SHA256, SSH_FP_HEX); | ||
626 | |||
627 | verbose("Accepted wildcard authorization for %s key %s with forced_command=%s", | ||
628 | sshkey_type(key), | ||
629 | wildcard_remote_key_fingerprint, | ||
630 | keyopts->force_command); | ||
631 | |||
632 | finalopts = keyopts; | ||
633 | keyopts = NULL; | ||
634 | goto success; | ||
635 | } | ||
636 | |||
637 | /* Ignore keys that don't match or incorrectly marked as CAs */ | 644 | /* Ignore keys that don't match or incorrectly marked as CAs */ |
638 | if (sshkey_is_cert(key)) { | 645 | if (sshkey_is_cert(key)) { |
639 | /* Certificate; check signature key against CA */ | 646 | /* Certificate; check signature key against CA */ |
@@ -739,6 +746,7 @@ check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, | |||
739 | size_t linesize = 0; | 746 | size_t linesize = 0; |
740 | int found_key = 0; | 747 | int found_key = 0; |
741 | u_long linenum = 0; | 748 | u_long linenum = 0; |
749 | struct sshauthopt *wildcardoptsp = NULL; | ||
742 | 750 | ||
743 | if (authoptsp != NULL) | 751 | if (authoptsp != NULL) |
744 | *authoptsp = NULL; | 752 | *authoptsp = NULL; |
@@ -757,9 +765,32 @@ check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, | |||
757 | snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); | 765 | snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); |
758 | if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0) | 766 | if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0) |
759 | found_key = 1; | 767 | found_key = 1; |
768 | else if (wildcardoptsp == NULL) { | ||
769 | check_authkey_line_for_wildcard(key, cp, loc, &wildcardoptsp); | ||
770 | } | ||
760 | } | 771 | } |
761 | free(line); | 772 | free(line); |
762 | return found_key; | 773 | if (found_key) { |
774 | return 1; | ||
775 | } else if (!wildcardoptsp) { | ||
776 | return 0; | ||
777 | } else { | ||
778 | |||
779 | if (1) { // This block is obsoleted by SSH_USER_AUTH | ||
780 | int r; | ||
781 | char *keytext = NULL; | ||
782 | if ((r = sshkey_to_base64(key, &keytext)) != 0) { | ||
783 | error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); | ||
784 | return -1; | ||
785 | } | ||
786 | wildcard_remote_key = keytext; | ||
787 | wildcard_remote_key_type = sshkey_type(key); | ||
788 | wildcard_remote_key_fingerprint = sshkey_fingerprint(key, SSH_DIGEST_SHA256, SSH_FP_HEX); | ||
789 | } | ||
790 | |||
791 | *authoptsp = wildcardoptsp; | ||
792 | return 1; | ||
793 | } | ||
763 | } | 794 | } |
764 | 795 | ||
765 | /* Authenticate a certificate key against TrustedUserCAKeys */ | 796 | /* Authenticate a certificate key against TrustedUserCAKeys */ |
@@ -1095,8 +1095,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) | |||
1095 | if (s->display) | 1095 | if (s->display) |
1096 | child_set_env(&env, &envsize, "DISPLAY", s->display); | 1096 | child_set_env(&env, &envsize, "DISPLAY", s->display); |
1097 | if (wildcard_remote_key) { | 1097 | if (wildcard_remote_key) { |
1098 | /* This is basically obsolete because of SSH_USER_AUTH */ | 1098 | /* This is basically obsolete because of SSH_USER_AUTH */ |
1099 | /* I'm leaving it here only because I have code that uses these variables. */ | 1099 | /* I'm leaving it here only because I have code that uses these variables. */ |
1100 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY", | 1100 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY", |
1101 | wildcard_remote_key); | 1101 | wildcard_remote_key); |
1102 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY_TYPE", | 1102 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY_TYPE", |