diff options
author | Andrew Cady <d@jerkface.net> | 2018-08-26 09:18:57 -0400 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2020-08-16 14:44:23 -0400 |
commit | 075d1a82801ad898eeb02446d0b5399c622a329d (patch) | |
tree | 06af2f513642444737b28e297c3eb024c1efd0e5 | |
parent | 0c69b8b9c83b9f6e6ff5114514a25e70a52b14ce (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 92c37accf..0e39f6abd 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c | |||
@@ -565,6 +565,42 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw, | |||
565 | return found_principal; | 565 | return found_principal; |
566 | } | 566 | } |
567 | 567 | ||
568 | static int | ||
569 | check_authkey_line_for_wildcard(struct sshkey *key, char *cp, const char *loc, struct sshauthopt **authoptsp) | ||
570 | { | ||
571 | struct sshauthopt *keyopts = NULL; | ||
572 | const char *reason = NULL; | ||
573 | char *key_options = cp; | ||
574 | |||
575 | if (advance_past_options(&cp) != 0) return -1; | ||
576 | skip_space(&cp); | ||
577 | |||
578 | if (!(*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0'))) { | ||
579 | return -1; // This is not a wildcard auth line. | ||
580 | } | ||
581 | |||
582 | if ((keyopts = sshauthopt_parse(key_options, &reason)) == NULL) { | ||
583 | debug("%s: bad key options: %s", loc, reason); | ||
584 | auth_debug_add("%s: bad key options: %s", loc, reason); | ||
585 | return -1; | ||
586 | } | ||
587 | |||
588 | if (keyopts->force_command) { /* We have a valid wildcard entry! */ | ||
589 | |||
590 | *authoptsp = keyopts; | ||
591 | return 0; | ||
592 | |||
593 | } else { | ||
594 | |||
595 | sshauthopt_free(keyopts); | ||
596 | reason = "Wildcard login is not allowed without specifying a forced command"; | ||
597 | error("%s", reason); | ||
598 | auth_debug_add("%s", reason); | ||
599 | return -1; | ||
600 | |||
601 | } | ||
602 | } | ||
603 | |||
568 | /* | 604 | /* |
569 | * Check a single line of an authorized_keys-format file. Returns 0 if key | 605 | * Check a single line of an authorized_keys-format file. Returns 0 if key |
570 | * matches, -1 otherwise. Will return key/cert options via *authoptsp | 606 | * matches, -1 otherwise. Will return key/cert options via *authoptsp |
@@ -591,8 +627,6 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, | |||
591 | 627 | ||
592 | /* XXX djm: peek at key type in line and skip if unwanted */ | 628 | /* XXX djm: peek at key type in line and skip if unwanted */ |
593 | 629 | ||
594 | int wild = 0; | ||
595 | |||
596 | if (sshkey_read(found, &cp) != 0) { | 630 | if (sshkey_read(found, &cp) != 0) { |
597 | /* no key? check for options */ | 631 | /* no key? check for options */ |
598 | debug2("%s: check options: '%s'", loc, cp); | 632 | debug2("%s: check options: '%s'", loc, cp); |
@@ -603,8 +637,8 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, | |||
603 | } | 637 | } |
604 | skip_space(&cp); | 638 | skip_space(&cp); |
605 | if (*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0')) { | 639 | if (*cp == '*' && (cp[1] == ' ' || cp[1] == '\n' || cp[1] == '\t' || cp[1] == '\0')) { |
606 | cp += 2; | 640 | /* This is a wildcard entry. Ignore it silently. */ |
607 | wild = 1; | 641 | goto out; |
608 | } else if (sshkey_read(found, &cp) != 0) { | 642 | } else if (sshkey_read(found, &cp) != 0) { |
609 | /* still no key? advance to next line*/ | 643 | /* still no key? advance to next line*/ |
610 | debug2("%s: advance: '%s'", loc, cp); | 644 | debug2("%s: advance: '%s'", loc, cp); |
@@ -617,33 +651,6 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, | |||
617 | auth_debug_add("%s: bad key options: %s", loc, reason); | 651 | auth_debug_add("%s: bad key options: %s", loc, reason); |
618 | goto out; | 652 | goto out; |
619 | } | 653 | } |
620 | |||
621 | if (wild) { | ||
622 | int r; | ||
623 | char *keytext = NULL; | ||
624 | if ((r = sshkey_to_base64(key, &keytext)) != 0) { | ||
625 | error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); | ||
626 | goto out; | ||
627 | } | ||
628 | if (!keyopts->force_command) { | ||
629 | reason = "Wildcard login is not allowed without specifying a forced command"; | ||
630 | goto fail_reason; | ||
631 | } | ||
632 | |||
633 | wildcard_remote_key = keytext; | ||
634 | wildcard_remote_key_type = sshkey_type(key); | ||
635 | wildcard_remote_key_fingerprint = sshkey_fingerprint(key, SSH_DIGEST_SHA256, SSH_FP_HEX); | ||
636 | |||
637 | verbose("Accepted wildcard authorization for %s key %s with forced_command=%s", | ||
638 | sshkey_type(key), | ||
639 | wildcard_remote_key_fingerprint, | ||
640 | keyopts->force_command); | ||
641 | |||
642 | finalopts = keyopts; | ||
643 | keyopts = NULL; | ||
644 | goto success; | ||
645 | } | ||
646 | |||
647 | /* Ignore keys that don't match or incorrectly marked as CAs */ | 654 | /* Ignore keys that don't match or incorrectly marked as CAs */ |
648 | if (sshkey_is_cert(key)) { | 655 | if (sshkey_is_cert(key)) { |
649 | /* Certificate; check signature key against CA */ | 656 | /* Certificate; check signature key against CA */ |
@@ -749,6 +756,7 @@ check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, | |||
749 | size_t linesize = 0; | 756 | size_t linesize = 0; |
750 | int found_key = 0; | 757 | int found_key = 0; |
751 | u_long linenum = 0; | 758 | u_long linenum = 0; |
759 | struct sshauthopt *wildcardoptsp = NULL; | ||
752 | 760 | ||
753 | if (authoptsp != NULL) | 761 | if (authoptsp != NULL) |
754 | *authoptsp = NULL; | 762 | *authoptsp = NULL; |
@@ -767,9 +775,32 @@ check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f, | |||
767 | snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); | 775 | snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum); |
768 | if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0) | 776 | if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0) |
769 | found_key = 1; | 777 | found_key = 1; |
778 | else if (wildcardoptsp == NULL) { | ||
779 | check_authkey_line_for_wildcard(key, cp, loc, &wildcardoptsp); | ||
780 | } | ||
770 | } | 781 | } |
771 | free(line); | 782 | free(line); |
772 | return found_key; | 783 | if (found_key) { |
784 | return 1; | ||
785 | } else if (!wildcardoptsp) { | ||
786 | return 0; | ||
787 | } else { | ||
788 | |||
789 | if (1) { // This block is obsoleted by SSH_USER_AUTH | ||
790 | int r; | ||
791 | char *keytext = NULL; | ||
792 | if ((r = sshkey_to_base64(key, &keytext)) != 0) { | ||
793 | error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); | ||
794 | return -1; | ||
795 | } | ||
796 | wildcard_remote_key = keytext; | ||
797 | wildcard_remote_key_type = sshkey_type(key); | ||
798 | wildcard_remote_key_fingerprint = sshkey_fingerprint(key, SSH_DIGEST_SHA256, SSH_FP_HEX); | ||
799 | } | ||
800 | |||
801 | *authoptsp = wildcardoptsp; | ||
802 | return 1; | ||
803 | } | ||
773 | } | 804 | } |
774 | 805 | ||
775 | /* Authenticate a certificate key against TrustedUserCAKeys */ | 806 | /* Authenticate a certificate key against TrustedUserCAKeys */ |
@@ -1072,8 +1072,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) | |||
1072 | if (s->display) | 1072 | if (s->display) |
1073 | child_set_env(&env, &envsize, "DISPLAY", s->display); | 1073 | child_set_env(&env, &envsize, "DISPLAY", s->display); |
1074 | if (wildcard_remote_key) { | 1074 | if (wildcard_remote_key) { |
1075 | /* This is basically obsolete because of SSH_USER_AUTH */ | 1075 | /* This is basically obsolete because of SSH_USER_AUTH */ |
1076 | /* I'm leaving it here only because I have code that uses these variables. */ | 1076 | /* I'm leaving it here only because I have code that uses these variables. */ |
1077 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY", | 1077 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY", |
1078 | wildcard_remote_key); | 1078 | wildcard_remote_key); |
1079 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY_TYPE", | 1079 | child_set_env(&env, &envsize, "SSH_REMOTE_KEY_TYPE", |