From cf00568d888c90a8c5d06a06283bc87a45992933 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Sat, 26 Aug 2023 10:32:37 -0600
Subject: [PATCH] Do not rely on the definition of ALLOW/DENY being true/false.

We now explicitly check for ALLOW and DENY when checking return
values and negating values.

Reference: https://github.com/sudo-project/sudo/commit/cf00568d888c90a8c5d06a06283bc87a45992933
Conflict: cvtsudoers.c match.c
---
 plugins/sudoers/cvtsudoers.c |  6 +--
 plugins/sudoers/match.c      | 83 +++++++++++++++++++++++-------------
 2 files changed, 57 insertions(+), 32 deletions(-)

diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c
index 79558c3..8cedcc6 100644
--- a/plugins/sudoers/cvtsudoers.c
+++ b/plugins/sudoers/cvtsudoers.c
@@ -690,7 +690,7 @@ userlist_matches_filter(struct sudoers_parse_tree *parse_tree,
 	    pw.pw_uid = (uid_t)-1;
 	    pw.pw_gid = (gid_t)-1;
 
-	    if (user_matches(parse_tree, &pw, m) == true)
+	    if (user_matches(parse_tree, &pw, m) == ALLOW)
 		matched = true;
 	} else {
 	    STAILQ_FOREACH(s, &filters->users, entries) {
@@ -716,7 +716,7 @@ userlist_matches_filter(struct sudoers_parse_tree *parse_tree,
 		if (pw == NULL)
 		    continue;
 
-		if (user_matches(parse_tree, pw, m) == true)
+		if (user_matches(parse_tree, pw, m) == ALLOW)
 		    matched = true;
 		sudo_pw_delref(pw);
 
@@ -792,7 +792,7 @@ hostlist_matches_filter(struct sudoers_parse_tree *parse_tree,
 
 	    /* Only need one host in the filter to match. */
 	    /* XXX - can't use netgroup_tuple with NULL pw */
-	    if (host_matches(parse_tree, NULL, lhost, shost, m) == true) {
+	    if (host_matches(parse_tree, NULL, lhost, shost, m) == ALLOW) {
 		matched = true;
 		break;
 	    }
diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c
index 9801f38..9324159 100644
--- a/plugins/sudoers/match.c
+++ b/plugins/sudoers/match.c
@@ -76,31 +76,36 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
 
     switch (m->type) {
 	case ALL:
-	    matched = !m->negated;
+	    matched = m->negated ? DENY : ALLOW;
 	    break;
 	case NETGROUP:
 	    if (netgr_matches(m->name,
 		def_netgroup_tuple ? lhost : NULL,
 		def_netgroup_tuple ? shost : NULL, pw->pw_name))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
 	case USERGROUP:
 	    if (usergr_matches(m->name, pw->pw_name, pw))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
 	case ALIAS:
 	    if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
 		/* XXX */
-		int rc = userlist_matches(parse_tree, pw, &a->members);
-		if (rc != UNSPEC)
-		    matched = m->negated ? !rc : rc;
+		const int rc = userlist_matches(parse_tree, pw, &a->members);
+		if (rc != UNSPEC) {
+		    if (m->negated) {
+			matched = rc == ALLOW ? DENY : ALLOW;
+		    } else {
+			matched = rc;
+		    }
+		}
 		alias_put(a);
 		break;
 	    }
 	    FALLTHROUGH;
 	case WORD:
 	    if (userpw_matches(m->name, pw->pw_name, pw))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
     }
     debug_return_int(matched);
@@ -171,38 +176,43 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
 	    TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) {
 		switch (m->type) {
 		    case ALL:
-			user_matched = !m->negated;
+			user_matched = m->negated ? DENY : ALLOW;
 			break;
 		    case NETGROUP:
 			if (netgr_matches(m->name,
 			    def_netgroup_tuple ? lhost : NULL,
 			    def_netgroup_tuple ? shost : NULL,
 			    runas_pw->pw_name))
-			    user_matched = !m->negated;
+			    user_matched = m->negated ? DENY : ALLOW;
 			break;
 		    case USERGROUP:
 			if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
-			    user_matched = !m->negated;
+			    user_matched = m->negated ? DENY : ALLOW;
 			break;
 		    case ALIAS:
 			a = alias_get(parse_tree, m->name, RUNASALIAS);
 			if (a != NULL) {
 			    rc = runaslist_matches(parse_tree, &a->members,
 				&empty, matching_user, NULL);
-			    if (rc != UNSPEC)
-				user_matched = m->negated ? !rc : rc;
+			if (rc != UNSPEC) {
+			if (m->negated) {
+			    user_matched = rc == ALLOW ? DENY : ALLOW;
+			} else {
+			    user_matched = rc;
+			}
+		    }
 			    alias_put(a);
 			    break;
 			}
 			FALLTHROUGH;
 		    case WORD:
 			if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
-			    user_matched = !m->negated;
+			    user_matched = m->negated ? DENY : ALLOW;
 			break;
 		    case MYSELF:
 			if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
 			    strcmp(user_name, runas_pw->pw_name) == 0)
-			    user_matched = !m->negated;
+			    user_matched = m->negated ? DENY : ALLOW;
 			break;
 		}
 		if (user_matched != UNSPEC) {
@@ -226,22 +236,27 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
 	    TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) {
 		switch (m->type) {
 		    case ALL:
-			group_matched = !m->negated;
+			group_matched = m->negated ? DENY : ALLOW;
 			break;
 		    case ALIAS:
 			a = alias_get(parse_tree, m->name, RUNASALIAS);
 			if (a != NULL) {
 			    rc = runaslist_matches(parse_tree, &empty,
 				&a->members, NULL, matching_group);
-			    if (rc != UNSPEC)
-				group_matched = m->negated ? !rc : rc;
+			    if (rc != UNSPEC) {
+			    if (m->negated) {
+				group_matched = rc == ALLOW ? DENY : ALLOW;
+			    } else {
+				group_matched = rc;
+			    }
+			}
 			    alias_put(a);
 			    break;
 			}
 			FALLTHROUGH;
 		    case WORD:
 			if (group_matches(m->name, runas_gr))
-			    group_matched = !m->negated;
+			    group_matched = m->negated ? DENY : ALLOW;
 			break;
 		}
 		if (group_matched != UNSPEC) {
@@ -329,32 +344,37 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
 
     switch (m->type) {
 	case ALL:
-	    matched = !m->negated;
+	    matched = m->negated ? DENY : ALLOW;
 	    break;
 	case NETGROUP:
 	    if (netgr_matches(m->name, lhost, shost,
 		def_netgroup_tuple ? pw->pw_name : NULL))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
 	case NTWKADDR:
 	    if (addr_matches(m->name))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
 	case ALIAS:
 	    a = alias_get(parse_tree, m->name, HOSTALIAS);
 	    if (a != NULL) {
 		/* XXX */
-		int rc = hostlist_matches_int(parse_tree, pw, lhost, shost,
-		    &a->members);
-		if (rc != UNSPEC)
-		    matched = m->negated ? !rc : rc;
+		const int rc = hostlist_matches_int(parse_tree, pw, lhost,
+		    shost, &a->members);
+		if (rc != UNSPEC) {
+		    if (m->negated) {
+			matched = rc == ALLOW ? DENY : ALLOW;
+		    } else {
+			matched = rc;
+		    }
+		}
 		alias_put(a);
 		break;
 	    }
 	    FALLTHROUGH;
 	case WORD:
 	    if (hostname_matches(shost, lhost, m->name))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
     }
     debug_return_int(matched);
@@ -399,14 +419,19 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m,
 	case COMMAND:
 	    c = (struct sudo_command *)m->name;
 	    if (command_matches(c->cmnd, c->args, runchroot, info, &c->digests))
-		matched = !m->negated;
+		matched = m->negated ? DENY : ALLOW;
 	    break;
 	case ALIAS:
 	    a = alias_get(parse_tree, m->name, CMNDALIAS);
 	    if (a != NULL) {
 		rc = cmndlist_matches(parse_tree, &a->members, runchroot, info);
-		if (rc != UNSPEC)
-		    matched = m->negated ? !rc : rc;
+		if (rc != UNSPEC) {
+		    if (m->negated) {
+			matched = rc == ALLOW ? DENY : ALLOW;
+		    } else {
+			matched = rc;
+		    }
+		}
 		alias_put(a);
 	    }
 	    break;
-- 
2.42.0.windows.2

