From 2ef90231a132547fa4236ff05fc0fafcd3f3d7a4 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 9 Sep 2023 14:07:06 -0600 Subject: [PATCH] Make all match functions return ALLOW/DENY not true/false. Reference: https://github.com/sudo-project/sudo/commit/2ef90231a132547fa4236ff05fc0fafcd3f3d7a4 Conflict: match.c match_command.c lookup.c --- plugins/sudoers/ldap.c | 2 +- plugins/sudoers/match.c | 147 +++++++++++--------- plugins/sudoers/match_addr.c | 45 +++--- plugins/sudoers/match_command.c | 131 ++++++++--------- plugins/sudoers/match_digest.c | 12 +- plugins/sudoers/parse.h | 16 +-- plugins/sudoers/regress/parser/check_addr.c | 2 +- plugins/sudoers/sssd.c | 6 +- 8 files changed, 187 insertions(+), 174 deletions(-) diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 60ffeb9..44e4693 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -341,7 +341,7 @@ sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw) val = (*p)->bv_val; if (*val == '+') { if (netgr_matches(val, def_netgroup_tuple ? user_runhost : NULL, - def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name)) + def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name) == ALLOW) ret = true; DPRINTF2("ldap sudoUser netgroup '%s' ... %s", val, ret ? "MATCH!" : "not"); diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c index 0891d63..efb596e 100644 --- a/plugins/sudoers/match.c +++ b/plugins/sudoers/match.c @@ -81,11 +81,11 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, case NETGROUP: if (netgr_matches(m->name, def_netgroup_tuple ? lhost : NULL, - def_netgroup_tuple ? shost : NULL, pw->pw_name)) + def_netgroup_tuple ? shost : NULL, pw->pw_name) == ALLOW) matched = m->negated ? DENY : ALLOW; break; case USERGROUP: - if (usergr_matches(m->name, pw->pw_name, pw)) + if (usergr_matches(m->name, pw->pw_name, pw) == ALLOW) matched = m->negated ? DENY : ALLOW; break; case ALIAS: @@ -104,7 +104,7 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, } FALLTHROUGH; case WORD: - if (userpw_matches(m->name, pw->pw_name, pw)) + if (userpw_matches(m->name, pw->pw_name, pw) == ALLOW) matched = m->negated ? DENY : ALLOW; break; } @@ -183,11 +183,11 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree, if (netgr_matches(m->name, def_netgroup_tuple ? lhost : NULL, def_netgroup_tuple ? shost : NULL, - runas_pw->pw_name)) + runas_pw->pw_name) == ALLOW) user_matched = m->negated ? DENY : ALLOW; break; case USERGROUP: - if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) + if (usergr_matches(m->name, runas_pw->pw_name, runas_pw) == ALLOW) user_matched = m->negated ? DENY : ALLOW; break; case ALIAS: @@ -207,7 +207,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree, } FALLTHROUGH; case WORD: - if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) + if (userpw_matches(m->name, runas_pw->pw_name, runas_pw) == ALLOW) user_matched = m->negated ? DENY : ALLOW; break; case MYSELF: @@ -256,7 +256,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree, } FALLTHROUGH; case WORD: - if (group_matches(m->name, runas_gr)) + if (group_matches(m->name, runas_gr) == ALLOW) group_matched = m->negated ? DENY : ALLOW; break; } @@ -340,21 +340,21 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const char *lhost, const char *shost, const struct member *m) { struct alias *a; - int matched = UNSPEC; + int ret = UNSPEC; debug_decl(host_matches, SUDOERS_DEBUG_MATCH); switch (m->type) { case ALL: - matched = m->negated ? DENY : ALLOW; + ret = m->negated ? DENY : ALLOW; break; case NETGROUP: if (netgr_matches(m->name, lhost, shost, - def_netgroup_tuple ? pw->pw_name : NULL)) - matched = m->negated ? DENY : ALLOW; + def_netgroup_tuple ? pw->pw_name : NULL) == ALLOW) + ret = m->negated ? DENY : ALLOW; break; case NTWKADDR: - if (addr_matches(m->name)) - matched = m->negated ? DENY : ALLOW; + if (addr_matches(m->name) == ALLOW) + ret = m->negated ? DENY : ALLOW; break; case ALIAS: a = alias_get(parse_tree, m->name, HOSTALIAS); @@ -364,9 +364,9 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, shost, &a->members); if (SPECIFIED(rc)) { if (m->negated) { - matched = rc == ALLOW ? DENY : ALLOW; + ret = rc == ALLOW ? DENY : ALLOW; } else { - matched = rc; + ret = rc; } } alias_put(a); @@ -374,11 +374,11 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, } FALLTHROUGH; case WORD: - if (hostname_matches(shost, lhost, m->name)) - matched = m->negated ? DENY : ALLOW; + if (hostname_matches(shost, lhost, m->name) == ALLOW) + ret = m->negated ? DENY : ALLOW; break; } - debug_return_int(matched); + debug_return_int(ret); } /* @@ -391,15 +391,15 @@ cmndlist_matches(struct sudoers_parse_tree *parse_tree, struct cmnd_info *info) { struct member *m; - int matched = UNSPEC; + int matched; debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH); TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { matched = cmnd_matches(parse_tree, m, runchroot, info); if (SPECIFIED(matched)) - break; + debug_return_int(matched); } - debug_return_int(matched); + debug_return_int(UNSPEC); } /* @@ -419,7 +419,8 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m, case ALL: case COMMAND: c = (struct sudo_command *)m->name; - if (command_matches(c->cmnd, c->args, runchroot, info, &c->digests)) + if (command_matches(c->cmnd, c->args, runchroot, + info, &c->digests) == ALLOW) matched = m->negated ? DENY : ALLOW; break; case ALIAS: @@ -441,96 +442,105 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m, } /* - * Returns true if the hostname matches the pattern, else false + * Returns ALLOW if the hostname matches the pattern, else DENY */ -bool +int hostname_matches(const char *shost, const char *lhost, const char *pattern) { const char *host; - bool rc; + int ret; debug_decl(hostname_matches, SUDOERS_DEBUG_MATCH); host = strchr(pattern, '.') != NULL ? lhost : shost; + ret = DENY; if (has_meta(pattern)) { - rc = !fnmatch(pattern, host, FNM_CASEFOLD); + if (fnmatch(pattern, host, FNM_CASEFOLD) == 0) + ret = ALLOW; } else { - rc = !strcasecmp(host, pattern); + if (strcasecmp(host, pattern) == 0) + ret = ALLOW; } sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "host %s matches sudoers pattern %s: %s", - host, pattern, rc ? "true" : "false"); - debug_return_bool(rc); + host, pattern, ret == ALLOW ? "ALLOW" : "DENY"); + debug_return_int(ret); } /* - * Returns true if the user/uid from sudoers matches the specified user/uid, - * else returns false. + * Returns ALLOW if the user/uid from sudoers matches the specified user/uid, + * else returns DENY. */ -bool +int userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw) { const char *errstr; + int ret = DENY; uid_t uid; - bool rc; debug_decl(userpw_matches, SUDOERS_DEBUG_MATCH); if (pw != NULL && *sudoers_user == '#') { uid = (uid_t) sudo_strtoid(sudoers_user + 1, &errstr); if (errstr == NULL && uid == pw->pw_uid) { - rc = true; + ret = ALLOW; goto done; } } - if (def_case_insensitive_user) - rc = strcasecmp(sudoers_user, user) == 0; - else - rc = strcmp(sudoers_user, user) == 0; + if (def_case_insensitive_user) { + if (strcasecmp(sudoers_user, user) == 0) + ret = ALLOW; + } else { + if (strcmp(sudoers_user, user) == 0) + ret = ALLOW; + } done: sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "user %s matches sudoers user %s: %s", - user, sudoers_user, rc ? "true" : "false"); - debug_return_bool(rc); + user, sudoers_user, ret == ALLOW ? "ALLOW" : "DENY"); + debug_return_int(ret); } /* - * Returns true if the group/gid from sudoers matches the specified group/gid, - * else returns false. + * Returns ALLOW if the group/gid from sudoers matches the specified group/gid, + * else returns DENY. */ -bool +int group_matches(const char *sudoers_group, const struct group *gr) { const char *errstr; + int ret = DENY; gid_t gid; - bool rc; debug_decl(group_matches, SUDOERS_DEBUG_MATCH); if (*sudoers_group == '#') { gid = (gid_t) sudo_strtoid(sudoers_group + 1, &errstr); if (errstr == NULL && gid == gr->gr_gid) { - rc = true; + ret = ALLOW; goto done; } } - if (def_case_insensitive_group) - rc = strcasecmp(sudoers_group, gr->gr_name) == 0; - else - rc = strcmp(sudoers_group, gr->gr_name) == 0; + if (def_case_insensitive_group) { + if (strcasecmp(sudoers_group, gr->gr_name) == 0) + ret = ALLOW; + } else { + if (strcmp(sudoers_group, gr->gr_name) == 0) + ret = ALLOW; + } done: sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "group %s matches sudoers group %s: %s", - gr->gr_name, sudoers_group, rc ? "true" : "false"); - debug_return_bool(rc); + gr->gr_name, sudoers_group, ret == ALLOW ? "ALLOW" : "DENY"); + debug_return_int(ret); } /* * Returns true if the given user belongs to the named group, * else returns false. */ -bool +int usergr_matches(const char *group, const char *user, const struct passwd *pw) { - bool matched = false; struct passwd *pw0 = NULL; + int ret = DENY; debug_decl(usergr_matches, SUDOERS_DEBUG_MATCH); /* Make sure we have a valid usergroup, sudo style */ @@ -543,7 +553,7 @@ usergr_matches(const char *group, const char *user, const struct passwd *pw) /* Query group plugin for %:name groups. */ if (*group == ':' && def_group_plugin) { if (group_plugin_query(user, group + 1, pw) == true) - matched = true; + ret = ALLOW; goto done; } @@ -558,14 +568,14 @@ usergr_matches(const char *group, const char *user, const struct passwd *pw) } if (user_in_group(pw, group)) { - matched = true; + ret = ALLOW; goto done; } /* Query the group plugin for Unix groups too? */ if (def_group_plugin && def_always_query_group_plugin) { if (group_plugin_query(user, group, pw) == true) { - matched = true; + ret = ALLOW; goto done; } } @@ -575,8 +585,9 @@ done: sudo_pw_delref(pw0); sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, - "user %s matches group %s: %s", user, group, matched ? "true" : "false"); - debug_return_bool(matched); + "user %s matches group %s: %s", user, group, + ret == ALLOW ? "ALLOW" : "DENY"); + debug_return_int(ret); } #if defined(HAVE_GETDOMAINNAME) || defined(SI_SRPC_DOMAIN) @@ -652,22 +663,22 @@ sudo_getdomainname(void) #endif /* HAVE_GETDOMAINNAME || SI_SRPC_DOMAIN */ /* - * Returns true if "host" and "user" belong to the netgroup "netgr", - * else return false. Either of "lhost", "shost" or "user" may be NULL + * Returns ALLOW if "host" and "user" belong to the netgroup "netgr", + * else return DENY. Either of "lhost", "shost" or "user" may be NULL * in which case that argument is not checked... */ -bool +int netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user) { #ifdef HAVE_INNETGR const char *domain; #endif - bool rc = false; + int ret = DENY; debug_decl(netgr_matches, SUDOERS_DEBUG_MATCH); if (!def_use_netgroups) { sudo_debug_printf(SUDO_DEBUG_INFO, "netgroups are disabled"); - debug_return_bool(false); + debug_return_int(DENY); } #ifdef HAVE_INNETGR @@ -675,22 +686,22 @@ netgr_matches(const char *netgr, const char *lhost, const char *shost, const cha if (*netgr++ != '+') { sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'", netgr); - debug_return_bool(false); + debug_return_int(DENY); } /* get the domain name (if any) */ domain = sudo_getdomainname(); if (innetgr(netgr, lhost, user, domain)) - rc = true; + ret = ALLOW; else if (lhost != shost && innetgr(netgr, shost, user, domain)) - rc = true; + ret = ALLOW; sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "", shost ? shost : "", user ? user : "", domain ? domain : "", - rc ? "true" : "false"); + ret == ALLOW ? "ALLOW" : "DENY"); #endif /* HAVE_INNETGR */ - debug_return_bool(rc); + debug_return_int(ret); } diff --git a/plugins/sudoers/match_addr.c b/plugins/sudoers/match_addr.c index 714c41c..3b701c9 100644 --- a/plugins/sudoers/match_addr.c +++ b/plugins/sudoers/match_addr.c @@ -44,7 +44,7 @@ #include "sudoers.h" #include "interfaces.h" -static bool +static int addr_matches_if(const char *n) { union sudo_in_addr_un addr; @@ -63,7 +63,7 @@ addr_matches_if(const char *n) if (inet_pton(AF_INET, n, &addr.ip4) == 1) { family = AF_INET; } else { - debug_return_bool(false); + debug_return_int(DENY); } SLIST_FOREACH(ifp, get_interfaces(), entries) { @@ -74,28 +74,28 @@ addr_matches_if(const char *n) if (ifp->addr.ip4.s_addr == addr.ip4.s_addr || (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr) == addr.ip4.s_addr) - debug_return_bool(true); + debug_return_int(ALLOW); break; #ifdef HAVE_STRUCT_IN6_ADDR case AF_INET6: if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr, sizeof(addr.ip6.s6_addr)) == 0) - debug_return_bool(true); + debug_return_int(ALLOW); for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) { if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j]) break; } if (j == sizeof(addr.ip6.s6_addr)) - debug_return_bool(true); + debug_return_int(ALLOW); break; #endif /* HAVE_STRUCT_IN6_ADDR */ } } - debug_return_bool(false); + debug_return_int(DENY); } -static bool +static int addr_matches_if_netmask(const char *n, const char *m) { unsigned int i; @@ -116,7 +116,7 @@ addr_matches_if_netmask(const char *n, const char *m) if (inet_pton(AF_INET, n, &addr.ip4) == 1) { family = AF_INET; } else { - debug_return_bool(false); + debug_return_int(DENY); } if (family == AF_INET) { @@ -124,14 +124,14 @@ addr_matches_if_netmask(const char *n, const char *m) if (inet_pton(AF_INET, m, &mask.ip4) != 1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "IPv4 netmask %s: %s", m, "invalid value"); - debug_return_bool(false); + debug_return_int(DENY); } } else { i = sudo_strtonum(m, 1, 32, &errstr); if (errstr != NULL) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "IPv4 netmask %s: %s", m, errstr); - debug_return_bool(false); + debug_return_int(DENY); } mask.ip4.s_addr = htonl(0xffffffffU << (32 - i)); } @@ -144,7 +144,7 @@ addr_matches_if_netmask(const char *n, const char *m) if (errstr != NULL) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "IPv6 netmask %s: %s", m, errstr); - debug_return_bool(false); + debug_return_int(DENY); } for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) { if (j < i * 8) @@ -165,7 +165,7 @@ addr_matches_if_netmask(const char *n, const char *m) switch (family) { case AF_INET: if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr) - debug_return_bool(true); + debug_return_int(ALLOW); break; #ifdef HAVE_STRUCT_IN6_ADDR case AF_INET6: @@ -174,35 +174,36 @@ addr_matches_if_netmask(const char *n, const char *m) break; } if (j == sizeof(addr.ip6.s6_addr)) - debug_return_bool(true); + debug_return_int(ALLOW); break; #endif /* HAVE_STRUCT_IN6_ADDR */ } } - debug_return_bool(false); + debug_return_int(DENY); } /* - * Returns true if "n" is one of our ip addresses or if - * "n" is a network that we are on, else returns false. + * Returns ALLOW if "n" is one of our ip addresses or if + * "n" is a network that we are on, else returns DENY. */ -bool +int addr_matches(char *n) { char *m; - bool rc; + int ret; debug_decl(addr_matches, SUDOERS_DEBUG_MATCH); /* If there's an explicit netmask, use it. */ if ((m = strchr(n, '/'))) { *m++ = '\0'; - rc = addr_matches_if_netmask(n, m); + ret = addr_matches_if_netmask(n, m); *(m - 1) = '/'; } else - rc = addr_matches_if(n); + ret = addr_matches_if(n); sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, - "IP address %s matches local host: %s", n, rc ? "true" : "false"); - debug_return_bool(rc); + "IP address %s matches local host: %s", n, + ret == ALLOW ? "ALLOW" : "DENY"); + debug_return_int(ret); } diff --git a/plugins/sudoers/match_command.c b/plugins/sudoers/match_command.c index f1c09bd..ee89741 100644 --- a/plugins/sudoers/match_command.c +++ b/plugins/sudoers/match_command.c @@ -56,7 +56,7 @@ # define O_EXEC O_PATH #endif -static bool +static int command_args_match(const char *sudoers_cmnd, const char *sudoers_args) { int flags = 0; @@ -67,7 +67,7 @@ command_args_match(const char *sudoers_cmnd, const char *sudoers_args) * If the empty string is specified in sudoers, no user args are allowed. */ if (!sudoers_args || (!user_args && !strcmp("\"\"", sudoers_args))) - debug_return_bool(true); + debug_return_int(ALLOW); /* * If args are specified in sudoers, they must match the user args. @@ -76,9 +76,9 @@ command_args_match(const char *sudoers_cmnd, const char *sudoers_args) if (strcmp(sudoers_cmnd, "sudoedit") == 0) flags = FNM_PATHNAME; if (fnmatch(sudoers_args, user_args ? user_args : "", flags) == 0) - debug_return_bool(true); + debug_return_int(ALLOW); - debug_return_bool(false); + debug_return_int(DENY); } #ifndef SUDOERS_NAME_MATCH @@ -229,7 +229,7 @@ set_cmnd_fd(int fd) /* * Return true if user_cmnd names one of the inodes in dir, else false. */ -static bool +static int command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, bool intercepted, const struct command_digest_list *digests) { @@ -247,7 +247,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, snprintf(sdbuf, sizeof(sdbuf), "%s%s", runchroot, sudoers_dir); if (len >= ssizeof(sdbuf)) { errno = ENAMETOOLONG; - debug_return_bool(false); + debug_return_int(DENY); } sudoers_dir = sdbuf; chrootlen = strlen(runchroot); @@ -258,11 +258,11 @@ command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, */ dirp = opendir(sudoers_dir); if (dirp == NULL) - debug_return_bool(false); + debug_return_int(DENY); if (strlcpy(buf, sudoers_dir, sizeof(buf)) >= sizeof(buf)) { closedir(dirp); - debug_return_bool(false); + debug_return_int(DENY); } while ((dent = readdir(dirp)) != NULL) { if (fd != -1) { @@ -289,7 +289,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, (user_stat->st_dev == sudoers_stat.st_dev && user_stat->st_ino == sudoers_stat.st_ino)) { /* buf is already relative to runchroot */ - if (!digest_matches(fd, buf, NULL, digests)) + if (digest_matches(fd, buf, NULL, digests) != ALLOW) continue; free(safe_cmnd); if ((safe_cmnd = strdup(buf + chrootlen)) == NULL) { @@ -304,17 +304,17 @@ command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, if (dent != NULL) { set_cmnd_fd(fd); - debug_return_bool(true); + debug_return_int(ALLOW); } if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } #else /* SUDOERS_NAME_MATCH */ /* * Return true if user_cmnd names one of the inodes in dir, else false. */ -static bool +static int command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, bool intercepted, const struct command_digest_list *digests) { @@ -332,19 +332,19 @@ command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot, /* Open the file for fdexec or for digest matching. */ if (!open_cmnd(user_cmnd, runchroot, digests, &fd)) goto bad; - if (!digest_matches(fd, user_cmnd, runchroot, digests)) + if (digest_matches(fd, user_cmnd, runchroot, digests) != ALLOW) goto bad; set_cmnd_fd(fd); - debug_return_bool(true); + debug_return_int(ALLOW); bad: if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } #endif /* SUDOERS_NAME_MATCH */ -static bool +static int command_matches_all(const char *runchroot, bool intercepted, const struct command_digest_list *digests) { @@ -366,19 +366,19 @@ command_matches_all(const char *runchroot, } /* Check digest of user_cmnd since we have no sudoers_cmnd for ALL. */ - if (!digest_matches(fd, user_cmnd, runchroot, digests)) + if (digest_matches(fd, user_cmnd, runchroot, digests) != ALLOW) goto bad; set_cmnd_fd(fd); /* No need to set safe_cmnd for ALL. */ - debug_return_bool(true); + debug_return_int(ALLOW); bad: if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } -static bool +static int command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, bool intercepted, const struct command_digest_list *digests) @@ -396,8 +396,8 @@ command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args, * Neither sudoers_cmnd nor user_cmnd are relative to runchroot. */ if (fnmatch(sudoers_cmnd, user_cmnd, FNM_PATHNAME) != 0) - debug_return_bool(false); - if (command_args_match(sudoers_cmnd, sudoers_args)) { + debug_return_int(DENY); + if (command_args_match(sudoers_cmnd, sudoers_args) == ALLOW) { /* Open the file for fdexec or for digest matching. */ if (!open_cmnd(user_cmnd, runchroot, digests, &fd)) goto bad; @@ -406,22 +406,22 @@ command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args, goto bad; #endif /* Check digest of user_cmnd since sudoers_cmnd is a pattern. */ - if (!digest_matches(fd, user_cmnd, runchroot, digests)) + if (digest_matches(fd, user_cmnd, runchroot, digests) != ALLOW) goto bad; set_cmnd_fd(fd); /* No need to set safe_cmnd since user_cmnd matches sudoers_cmnd */ - debug_return_bool(true); + debug_return_int(ALLOW); bad: if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } - debug_return_bool(false); + debug_return_int(DENY); } #ifndef SUDOERS_NAME_MATCH -static bool +static int command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, bool intercepted, const struct command_digest_list *digests) @@ -444,7 +444,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, if (sudoers_cmnd[dlen - 1] != '/') { base = sudo_basename(sudoers_cmnd); if (!has_meta(base) && strcmp(user_base, base) != 0) - debug_return_bool(false); + debug_return_int(DENY); } /* Make sudoers_cmnd relative to the new root, if any. */ @@ -453,22 +453,22 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, snprintf(pathbuf, sizeof(pathbuf), "%s%s", runchroot, sudoers_cmnd); if (len >= ssizeof(pathbuf)) { errno = ENAMETOOLONG; - debug_return_bool(false); + debug_return_int(DENY); } sudoers_cmnd = pathbuf; chrootlen = strlen(runchroot); } /* - * Return true if we find a match in the glob(3) results AND + * Return ALLOW if we find a match in the glob(3) results AND * a) there are no args in sudoers OR * b) there are no args on command line and none required by sudoers OR * c) there are args in sudoers and on command line and they match - * else return false. + * else return DENY. */ if (glob(sudoers_cmnd, GLOB_NOSORT, NULL, &gl) != 0 || gl.gl_pathc == 0) { globfree(&gl); - debug_return_bool(false); + debug_return_int(DENY); } /* If user_cmnd is fully-qualified, check for an exact match. */ if (user_cmnd[0] == '/') { @@ -491,7 +491,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, (user_stat->st_dev == sudoers_stat.st_dev && user_stat->st_ino == sudoers_stat.st_ino)) { /* There could be multiple matches, check digest early. */ - if (!digest_matches(fd, cp, runchroot, digests)) { + if (digest_matches(fd, cp, runchroot, digests) != ALLOW) { bad_digest = true; continue; } @@ -522,9 +522,9 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, /* If it ends in '/' it is a directory spec. */ dlen = strlen(cp); if (cp[dlen - 1] == '/') { - if (command_matches_dir(cp, dlen, runchroot, intercepted, digests)) { + if (command_matches_dir(cp, dlen, runchroot, intercepted, digests) == ALLOW) { globfree(&gl); - debug_return_bool(true); + debug_return_int(ALLOW); } continue; } @@ -542,7 +542,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, if (user_stat == NULL || (user_stat->st_dev == sudoers_stat.st_dev && user_stat->st_ino == sudoers_stat.st_ino)) { - if (!digest_matches(fd, cp, runchroot, digests)) + if (digest_matches(fd, cp, runchroot, digests) != ALLOW) continue; free(safe_cmnd); if ((safe_cmnd = strdup(cp)) == NULL) { @@ -557,18 +557,18 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, done: globfree(&gl); if (cp != NULL) { - if (command_args_match(sudoers_cmnd, sudoers_args)) { + if (command_args_match(sudoers_cmnd, sudoers_args) == ALLOW) { /* safe_cmnd was set above. */ set_cmnd_fd(fd); - debug_return_bool(true); + debug_return_int(ALLOW); } } if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } -static bool +static int command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, bool intercepted, const struct command_digest_list *digests) @@ -582,14 +582,14 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, /* If it ends in '/' it is a directory spec. */ dlen = strlen(sudoers_cmnd); if (sudoers_cmnd[dlen - 1] == '/') { - debug_return_bool(command_matches_dir(sudoers_cmnd, dlen, runchroot, + debug_return_int(command_matches_dir(sudoers_cmnd, dlen, runchroot, intercepted, digests)); } /* Only proceed if user_base and basename(sudoers_cmnd) match */ base = sudo_basename(sudoers_cmnd); if (strcmp(user_base, base) != 0) - debug_return_bool(false); + debug_return_int(DENY); /* Open the file for fdexec or for digest matching. */ if (!open_cmnd(sudoers_cmnd, runchroot, digests, &fd)) @@ -611,9 +611,9 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, if (strcmp(user_cmnd, sudoers_cmnd) != 0) goto bad; } - if (!command_args_match(sudoers_cmnd, sudoers_args)) + if (command_args_match(sudoers_cmnd, sudoers_args) != ALLOW) goto bad; - if (!digest_matches(fd, sudoers_cmnd, runchroot, digests)) { + if (digest_matches(fd, sudoers_cmnd, runchroot, digests) != ALLOW) { /* XXX - log functions not available but we should log very loudly */ goto bad; } @@ -623,14 +623,14 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, goto bad; } set_cmnd_fd(fd); - debug_return_bool(true); + debug_return_int(ALLOW); bad: if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } #else /* SUDOERS_NAME_MATCH */ -static bool +static int command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, bool intercepted, const struct command_digest_list *digests) @@ -639,7 +639,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args, intercepted, digests); } -static bool +static int command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, bool intercepted, const struct command_digest_list *digests) @@ -651,16 +651,16 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, /* If it ends in '/' it is a directory spec. */ dlen = strlen(sudoers_cmnd); if (sudoers_cmnd[dlen - 1] == '/') { - debug_return_bool(command_matches_dir(sudoers_cmnd, dlen, runchroot, + debug_return_int(command_matches_dir(sudoers_cmnd, dlen, runchroot, intercepted, digests)); } if (strcmp(user_cmnd, sudoers_cmnd) == 0) { - if (command_args_match(sudoers_cmnd, sudoers_args)) { + if (command_args_match(sudoers_cmnd, sudoers_args) == ALLOW) { /* Open the file for fdexec or for digest matching. */ if (!open_cmnd(user_cmnd, runchroot, digests, &fd)) goto bad; - if (!digest_matches(fd, user_cmnd, runchroot, digests)) + if (digest_matches(fd, user_cmnd, runchroot, digests) != ALLOW) goto bad; /* Successful match. */ @@ -671,21 +671,22 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, goto bad; } set_cmnd_fd(fd); - debug_return_bool(true); + debug_return_int(ALLOW); } } bad: if (fd != -1) close(fd); - debug_return_bool(false); + debug_return_int(DENY); } #endif /* SUDOERS_NAME_MATCH */ /* - * If path doesn't end in /, return true iff cmnd & path name the same inode; - * otherwise, return true if user_cmnd names one of the inodes in path. + * If path doesn't end in /, return ALLOW iff cmnd & path name the same inode; + * otherwise, return ALLOW if ctx->user.cmnd names one of the inodes in path. + * Returns DENY on failure. */ -bool +int command_matches(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests) @@ -693,7 +694,7 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, const bool intercepted = info ? info->intercepted : false; char *saved_user_cmnd = NULL; struct stat saved_user_stat; - bool rc = false; + int ret = DENY; debug_decl(command_matches, SUDOERS_DEBUG_MATCH); if (user_runchroot != NULL) { @@ -728,7 +729,7 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, if (sudoers_cmnd == NULL) { sudoers_cmnd = "ALL"; - rc = command_matches_all(runchroot, intercepted, digests); + ret = command_matches_all(runchroot, intercepted, digests); goto done; } @@ -742,9 +743,9 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, */ if (strcmp(sudoers_cmnd, "sudoedit") == 0 && strcmp(user_cmnd, "sudoedit") == 0 && - command_args_match(sudoers_cmnd, sudoers_args)) { + command_args_match(sudoers_cmnd, sudoers_args) == ALLOW) { /* No need to set safe_cmnd since user_cmnd matches sudoers_cmnd */ - rc = true; + ret = ALLOW; } goto done; } @@ -755,14 +756,14 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, * use glob(3) and/or fnmatch(3) to do the matching. */ if (def_fast_glob) { - rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args, runchroot, + ret = command_matches_fnmatch(sudoers_cmnd, sudoers_args, runchroot, intercepted, digests); } else { - rc = command_matches_glob(sudoers_cmnd, sudoers_args, runchroot, + ret = command_matches_glob(sudoers_cmnd, sudoers_args, runchroot, intercepted, digests); } } else { - rc = command_matches_normal(sudoers_cmnd, sudoers_args, runchroot, + ret = command_matches_normal(sudoers_cmnd, sudoers_args, runchroot, intercepted, digests); } done: @@ -783,6 +784,6 @@ done: user_cmnd, user_args ? " " : "", user_args ? user_args : "", sudoers_cmnd, sudoers_args ? " " : "", sudoers_args ? sudoers_args : "", runchroot ? ", chroot " : "", runchroot ? runchroot : "", - rc ? "true" : "false"); - debug_return_bool(rc); + ret == ALLOW ? "ALLOW" : "DENY"); + debug_return_int(ret); } diff --git a/plugins/sudoers/match_digest.c b/plugins/sudoers/match_digest.c index 5c39f52..78cfe0d 100644 --- a/plugins/sudoers/match_digest.c +++ b/plugins/sudoers/match_digest.c @@ -38,7 +38,7 @@ #include "sudo_digest.h" #include -bool +int digest_matches(int fd, const char *path, const char *runchroot, const struct command_digest_list *digests) { @@ -48,12 +48,12 @@ digest_matches(int fd, const char *path, const char *runchroot, struct command_digest *digest; size_t digest_len = (size_t)-1; char pathbuf[PATH_MAX]; - bool matched = false; + int matched = DENY; debug_decl(digest_matches, SUDOERS_DEBUG_MATCH); if (TAILQ_EMPTY(digests)) { /* No digest, no problem. */ - debug_return_bool(true); + debug_return_int(ALLOW); } if (fd == -1) { @@ -66,7 +66,7 @@ digest_matches(int fd, const char *path, const char *runchroot, snprintf(pathbuf, sizeof(pathbuf), "%s%s", runchroot, path); if (len >= ssizeof(pathbuf)) { errno = ENAMETOOLONG; - debug_return_bool(false); + debug_return_int(DENY); } path = pathbuf; } @@ -113,7 +113,7 @@ digest_matches(int fd, const char *path, const char *runchroot, } } if (memcmp(file_digest, sudoers_digest, digest_len) == 0) { - matched = true; + matched = ALLOW; break; } @@ -131,5 +131,5 @@ bad_format: done: free(sudoers_digest); free(file_digest); - debug_return_bool(matched); + debug_return_int(matched); } diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 8559849..bfc5bc8 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -384,22 +384,22 @@ bool parser_leak_remove(enum parser_leak_types type, void *v); void parser_leak_init(void); /* match_addr.c */ -bool addr_matches(char *n); +int addr_matches(char *n); /* match_command.c */ -bool command_matches(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests); +int command_matches(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests); /* match_digest.c */ -bool digest_matches(int fd, const char *path, const char *runchroot, const struct command_digest_list *digests); +int digest_matches(int fd, const char *path, const char *runchroot, const struct command_digest_list *digests); /* match.c */ struct group; struct passwd; -bool group_matches(const char *sudoers_group, const struct group *gr); -bool hostname_matches(const char *shost, const char *lhost, const char *pattern); -bool netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user); -bool usergr_matches(const char *group, const char *user, const struct passwd *pw); -bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw); +int group_matches(const char *sudoers_group, const struct group *gr); +int hostname_matches(const char *shost, const char *lhost, const char *pattern); +int netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user); +int usergr_matches(const char *group, const char *user, const struct passwd *pw); +int userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw); int cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info); int cmndlist_matches(struct sudoers_parse_tree *parse_tree, const struct member_list *list, const char *runchroot, struct cmnd_info *info); int host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const char *host, const char *shost, const struct member *m); diff --git a/plugins/sudoers/regress/parser/check_addr.c b/plugins/sudoers/regress/parser/check_addr.c index cf50226..a465d14 100644 --- a/plugins/sudoers/regress/parser/check_addr.c +++ b/plugins/sudoers/regress/parser/check_addr.c @@ -57,7 +57,7 @@ check_addr(char *input) sudo_fatalx("expecting 0 or 1, got %s", cp); input[len] = '\0'; - matched = addr_matches(input); + matched = addr_matches(input) == ALLOW; if (matched != expected) { sudo_warnx("%s %smatched: FAIL", input, matched ? "" : "not "); return 1; diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c index e396d84..8760e4c 100644 --- a/plugins/sudoers/sssd.c +++ b/plugins/sudoers/sssd.c @@ -195,20 +195,20 @@ sudo_sss_check_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) case '+': /* Netgroup spec found, check membership. */ if (netgr_matches(val, def_netgroup_tuple ? host : NULL, - def_netgroup_tuple ? shost : NULL, handle->pw->pw_name)) { + def_netgroup_tuple ? shost : NULL, handle->pw->pw_name) == ALLOW) { ret = true; } break; case '%': /* User group found, check membership. */ - if (usergr_matches(val, handle->pw->pw_name, handle->pw)) { + if (usergr_matches(val, handle->pw->pw_name, handle->pw) == ALLOW) { ret = true; } break; default: /* Not a netgroup or user group. */ if (strcmp(val, "ALL") == 0 || - userpw_matches(val, handle->pw->pw_name, handle->pw)) { + userpw_matches(val, handle->pw->pw_name, handle->pw) == ALLOW) { ret = true; } break; -- 2.42.0.windows.2