summaryrefslogtreecommitdiff
path: root/sshsig.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-01-22 02:25:21 +0000
committerDamien Miller <djm@mindrot.org>2020-01-22 17:17:51 +1100
commite2031b05c74c98b141179ceab13a323cf17d01e5 (patch)
treeb9a3a4b61a7a7bccbf60e75c5153a2c7dfb9b1c4 /sshsig.c
parent47160e1de8c2f638f0ef41cef42c976417b61778 (diff)
upstream: factor out parsing of allowed-signers lines
OpenBSD-Commit-ID: 85ee6aeff608371826019ea85e55bfa87f79d06e
Diffstat (limited to 'sshsig.c')
-rw-r--r--sshsig.c114
1 files changed, 87 insertions, 27 deletions
diff --git a/sshsig.c b/sshsig.c
index abba3f67b..6d72f92f5 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -679,56 +679,116 @@ sshsigopt_free(struct sshsigopt *opts)
679} 679}
680 680
681static int 681static int
682check_allowed_keys_line(const char *path, u_long linenum, char *line, 682parse_principals_key_and_options(const char *path, u_long linenum, char *line,
683 const struct sshkey *sign_key, const char *principal, 683 const char *required_principal, char **principalsp, struct sshkey **keyp,
684 const char *sig_namespace) 684 struct sshsigopt **sigoptsp)
685{ 685{
686 struct sshkey *found_key = NULL; 686 char *opts = NULL, *tmp, *cp, *principals = NULL;
687 char *cp, *opts = NULL, *identities = NULL;
688 int r, found = 0;
689 const char *reason = NULL; 687 const char *reason = NULL;
690 struct sshsigopt *sigopts = NULL; 688 struct sshsigopt *sigopts = NULL;
689 struct sshkey *key = NULL;
690 int r = SSH_ERR_INTERNAL_ERROR;
691 691
692 if ((found_key = sshkey_new(KEY_UNSPEC)) == NULL) { 692 if (principalsp != NULL)
693 error("%s: sshkey_new failed", __func__); 693 *principalsp = NULL;
694 return SSH_ERR_ALLOC_FAIL; 694 if (sigoptsp != NULL)
695 } 695 *sigoptsp = NULL;
696 if (keyp != NULL)
697 *keyp = NULL;
696 698
697 /* format: identity[,identity...] [option[,option...]] key */
698 cp = line; 699 cp = line;
699 cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ 700 cp = cp + strspn(cp, " \t"); /* skip leading whitespace */
700 if (*cp == '#' || *cp == '\0') 701 if (*cp == '#' || *cp == '\0')
701 goto done; 702 return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */
702 if ((identities = strdelimw(&cp)) == NULL) { 703
704 /* format: identity[,identity...] [option[,option...]] key */
705 if ((tmp = strdelimw(&cp)) == NULL) {
703 error("%s:%lu: invalid line", path, linenum); 706 error("%s:%lu: invalid line", path, linenum);
704 goto done; 707 r = SSH_ERR_INVALID_FORMAT;
708 goto out;
705 } 709 }
706 if (match_pattern_list(principal, identities, 0) != 1) { 710 if ((principals = strdup(tmp)) == NULL) {
707 /* principal didn't match */ 711 error("%s: strdup failed", __func__);
708 goto done; 712 r = SSH_ERR_ALLOC_FAIL;
713 goto out;
714 }
715 /*
716 * Bail out early if we're looking for a particular principal and this
717 * line does not list it.
718 */
719 if (required_principal != NULL) {
720 if (match_pattern_list(required_principal,
721 principals, 0) != 1) {
722 /* principal didn't match */
723 r = SSH_ERR_KEY_NOT_FOUND;
724 goto out;
725 }
726 debug("%s: %s:%lu: matched principal \"%s\"",
727 __func__, path, linenum, required_principal);
709 } 728 }
710 debug("%s: %s:%lu: matched principal \"%s\"",
711 __func__, path, linenum, principal);
712 729
713 if (sshkey_read(found_key, &cp) != 0) { 730 if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
731 error("%s: sshkey_new failed", __func__);
732 r = SSH_ERR_ALLOC_FAIL;
733 goto out;
734 }
735 if (sshkey_read(key, &cp) != 0) {
714 /* no key? Check for options */ 736 /* no key? Check for options */
715 opts = cp; 737 opts = cp;
716 if (sshkey_advance_past_options(&cp) != 0) { 738 if (sshkey_advance_past_options(&cp) != 0) {
717 error("%s:%lu: invalid options", 739 error("%s:%lu: invalid options", path, linenum);
718 path, linenum); 740 r = SSH_ERR_INVALID_FORMAT;
719 goto done; 741 goto out;
720 } 742 }
721 *cp++ = '\0'; 743 *cp++ = '\0';
722 skip_space(&cp); 744 skip_space(&cp);
723 if (sshkey_read(found_key, &cp) != 0) { 745 if (sshkey_read(key, &cp) != 0) {
724 error("%s:%lu: invalid key", path, 746 error("%s:%lu: invalid key", path, linenum);
725 linenum); 747 r = SSH_ERR_INVALID_FORMAT;
726 goto done; 748 goto out;
727 } 749 }
728 } 750 }
729 debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts); 751 debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts);
730 if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) { 752 if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) {
731 error("%s:%lu: bad options: %s", path, linenum, reason); 753 error("%s:%lu: bad options: %s", path, linenum, reason);
754 r = SSH_ERR_INVALID_FORMAT;
755 goto out;
756 }
757 /* success */
758 if (principalsp != NULL) {
759 *principalsp = principals;
760 principals = NULL; /* transferred */
761 }
762 if (sigoptsp != NULL) {
763 *sigoptsp = sigopts;
764 sigopts = NULL; /* transferred */
765 }
766 if (keyp != NULL) {
767 *keyp = key;
768 key = NULL; /* transferred */
769 }
770 r = 0;
771 out:
772 free(principals);
773 sshsigopt_free(sigopts);
774 sshkey_free(key);
775 return r;
776}
777
778static int
779check_allowed_keys_line(const char *path, u_long linenum, char *line,
780 const struct sshkey *sign_key, const char *principal,
781 const char *sig_namespace)
782{
783 struct sshkey *found_key = NULL;
784 int r, found = 0;
785 const char *reason = NULL;
786 struct sshsigopt *sigopts = NULL;
787
788 /* Parse the line */
789 if ((r = parse_principals_key_and_options(path, linenum, line,
790 principal, NULL, &found_key, &sigopts)) != 0) {
791 /* error already logged */
732 goto done; 792 goto done;
733 } 793 }
734 794