[openssh-commits] [openssh] 01/04: upstream: factor out parsing of allowed-signers lines

git+noreply at mindrot.org git+noreply at mindrot.org
Wed Jan 22 17:17:58 AEDT 2020


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit e2031b05c74c98b141179ceab13a323cf17d01e5
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Wed Jan 22 02:25:21 2020 +0000

    upstream: factor out parsing of allowed-signers lines
    
    OpenBSD-Commit-ID: 85ee6aeff608371826019ea85e55bfa87f79d06e
---
 sshsig.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 87 insertions(+), 27 deletions(-)

diff --git a/sshsig.c b/sshsig.c
index abba3f67..6d72f92f 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -679,56 +679,116 @@ sshsigopt_free(struct sshsigopt *opts)
 }
 
 static int
-check_allowed_keys_line(const char *path, u_long linenum, char *line,
-    const struct sshkey *sign_key, const char *principal,
-    const char *sig_namespace)
+parse_principals_key_and_options(const char *path, u_long linenum, char *line,
+    const char *required_principal, char **principalsp, struct sshkey **keyp,
+    struct sshsigopt **sigoptsp)
 {
-	struct sshkey *found_key = NULL;
-	char *cp, *opts = NULL, *identities = NULL;
-	int r, found = 0;
+	char *opts = NULL, *tmp, *cp, *principals = NULL;
 	const char *reason = NULL;
 	struct sshsigopt *sigopts = NULL;
+	struct sshkey *key = NULL;
+	int r = SSH_ERR_INTERNAL_ERROR;
 
-	if ((found_key = sshkey_new(KEY_UNSPEC)) == NULL) {
-		error("%s: sshkey_new failed", __func__);
-		return SSH_ERR_ALLOC_FAIL;
-	}
+	if (principalsp != NULL)
+		*principalsp = NULL;
+	if (sigoptsp != NULL)
+		*sigoptsp = NULL;
+	if (keyp != NULL)
+		*keyp = NULL;
 
-	/* format: identity[,identity...] [option[,option...]] key */
 	cp = line;
 	cp = cp + strspn(cp, " \t"); /* skip leading whitespace */
 	if (*cp == '#' || *cp == '\0')
-		goto done;
-	if ((identities = strdelimw(&cp)) == NULL) {
+		return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */
+
+	/* format: identity[,identity...] [option[,option...]] key */
+	if ((tmp = strdelimw(&cp)) == NULL) {
 		error("%s:%lu: invalid line", path, linenum);
-		goto done;
+		r = SSH_ERR_INVALID_FORMAT;
+		goto out;
 	}
-	if (match_pattern_list(principal, identities, 0) != 1) {
-		/* principal didn't match */
-		goto done;
+	if ((principals = strdup(tmp)) == NULL) {
+		error("%s: strdup failed", __func__);
+		r = SSH_ERR_ALLOC_FAIL;
+		goto out;
+	}
+	/*
+	 * Bail out early if we're looking for a particular principal and this
+	 * line does not list it.
+	 */
+	if (required_principal != NULL) {
+		if (match_pattern_list(required_principal,
+		    principals, 0) != 1) {
+			/* principal didn't match */
+			r = SSH_ERR_KEY_NOT_FOUND;
+			goto out;
+		}
+		debug("%s: %s:%lu: matched principal \"%s\"",
+		    __func__, path, linenum, required_principal);
 	}
-	debug("%s: %s:%lu: matched principal \"%s\"",
-	    __func__, path, linenum, principal);
 
-	if (sshkey_read(found_key, &cp) != 0) {
+	if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
+		error("%s: sshkey_new failed", __func__);
+		r = SSH_ERR_ALLOC_FAIL;
+		goto out;
+	}
+	if (sshkey_read(key, &cp) != 0) {
 		/* no key? Check for options */
 		opts = cp;
 		if (sshkey_advance_past_options(&cp) != 0) {
-			error("%s:%lu: invalid options",
-			    path, linenum);
-			goto done;
+			error("%s:%lu: invalid options", path, linenum);
+			r = SSH_ERR_INVALID_FORMAT;
+			goto out;
 		}
 		*cp++ = '\0';
 		skip_space(&cp);
-		if (sshkey_read(found_key, &cp) != 0) {
-			error("%s:%lu: invalid key", path,
-			    linenum);
-			goto done;
+		if (sshkey_read(key, &cp) != 0) {
+			error("%s:%lu: invalid key", path, linenum);
+			r = SSH_ERR_INVALID_FORMAT;
+			goto out;
 		}
 	}
 	debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts);
 	if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) {
 		error("%s:%lu: bad options: %s", path, linenum, reason);
+		r = SSH_ERR_INVALID_FORMAT;
+		goto out;
+	}
+	/* success */
+	if (principalsp != NULL) {
+		*principalsp = principals;
+		principals = NULL; /* transferred */
+	}
+	if (sigoptsp != NULL) {
+		*sigoptsp = sigopts;
+		sigopts = NULL; /* transferred */
+	}
+	if (keyp != NULL) {
+		*keyp = key;
+		key = NULL; /* transferred */
+	}
+	r = 0;
+ out:
+	free(principals);
+	sshsigopt_free(sigopts);
+	sshkey_free(key);
+	return r;
+}
+
+static int
+check_allowed_keys_line(const char *path, u_long linenum, char *line,
+    const struct sshkey *sign_key, const char *principal,
+    const char *sig_namespace)
+{
+	struct sshkey *found_key = NULL;
+	int r, found = 0;
+	const char *reason = NULL;
+	struct sshsigopt *sigopts = NULL;
+
+	/* Parse the line */
+	if ((r = parse_principals_key_and_options(path, linenum, line,
+	    principal, NULL, &found_key, &sigopts)) != 0) {
+		/* error already logged */
 		goto done;
 	}
 

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list