!121 fix CVE-2023-42465

From: @qsw333 
Reviewed-by: @houmingyong, @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
This commit is contained in:
openeuler-ci-bot 2024-01-09 15:29:29 +00:00 committed by Gitee
commit d5effb837b
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 1677 additions and 1 deletions

View File

@ -0,0 +1,424 @@
From 7873f8334c8d31031f8cfa83bd97ac6029309e4f Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Sat, 9 Sep 2023 14:07:04 -0600
Subject: [PATCH] Try to make sudo less vulnerable to ROWHAMMER attacks.
We now use ROWHAMMER-resistent values for ALLOW, DENY, AUTH_SUCCESS,
AUTH_FAILURE, AUTH_ERROR and AUTH_NONINTERACTIVE. In addition, we
explicitly test for expected values instead of using a negated test
against an error value. In the parser match functions this means
explicitly checking for ALLOW or DENY instead of accepting anything
that is not set to UNSPEC.
Thanks to Andrew J. Adiletta, M. Caner Tol, Yarkin Doroz, and Berk
Sunar, all affiliated with the Vernam Applied Cryptography and
Cybersecurity Lab at Worcester Polytechnic Institute, for the report.
Paper preprint: https://arxiv.org/abs/2309.02545
Reference: https://github.com/sudo-project/sudo/commit/7873f8334c8d31031f8cfa83bd97ac6029309e4f
Conflict: passwd.c sudo_auth.h match.c parse.c
---
plugins/sudoers/auth/passwd.c | 18 ++++++-----
plugins/sudoers/auth/sudo_auth.c | 51 ++++++++++++++++++++++----------
plugins/sudoers/auth/sudo_auth.h | 10 +++----
plugins/sudoers/match.c | 25 ++++++++--------
plugins/sudoers/parse.c | 6 ++--
plugins/sudoers/parse.h | 23 ++++++++++----
6 files changed, 86 insertions(+), 47 deletions(-)
diff --git a/plugins/sudoers/auth/passwd.c b/plugins/sudoers/auth/passwd.c
index 910a510..2a9766c 100644
--- a/plugins/sudoers/auth/passwd.c
+++ b/plugins/sudoers/auth/passwd.c
@@ -61,7 +61,7 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
char des_pass[9], *epass;
char *pw_epasswd = auth->data;
size_t pw_len;
- int matched = 0;
+ int ret;
debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
/* An empty plain-text password must match an empty encrypted password. */
@@ -73,7 +73,7 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
*/
pw_len = strlen(pw_epasswd);
if (pw_len == DESLEN || HAS_AGEINFO(pw_epasswd, pw_len)) {
- strlcpy(des_pass, pass, sizeof(des_pass));
+ (void)strlcpy(des_pass, pass, sizeof(des_pass));
pass = des_pass;
}
@@ -83,16 +83,20 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
* only compare the first DESLEN characters in that case.
*/
epass = (char *) crypt(pass, pw_epasswd);
+ ret = AUTH_FAILURE;
if (epass != NULL) {
- if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN)
- matched = !strncmp(pw_epasswd, epass, DESLEN);
- else
- matched = !strcmp(pw_epasswd, epass);
+ if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN){
+ if(strncmp(pw_epasswd, epass, DESLEN) == 0)
+ ret = AUTH_SUCCESS;
+ }else{
+ if(strcmp(pw_epasswd, epass) == 0)
+ ret = AUTH_SUCCESS;
+ }
}
explicit_bzero(des_pass, sizeof(des_pass));
- debug_return_int(matched ? AUTH_SUCCESS : AUTH_FAILURE);
+ debug_return_int(ret);
}
int
diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c
index 1bdacdb..767fe26 100644
--- a/plugins/sudoers/auth/sudo_auth.c
+++ b/plugins/sudoers/auth/sudo_auth.c
@@ -112,10 +112,16 @@ sudo_auth_init(struct passwd *pw)
if (auth->init && !IS_DISABLED(auth)) {
/* Disable if it failed to init unless there was a fatal error. */
status = (auth->init)(pw, auth);
- if (status == AUTH_FAILURE)
+ switch (status) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_FAILURE:
SET(auth->flags, FLAG_DISABLED);
- else if (status == AUTH_FATAL)
- break; /* assume error msg already printed */
+ break;
+ default:
+ /*Assume error msg already printed. */
+ debug_return_int(-1);
+ }
}
}
@@ -161,7 +167,7 @@ sudo_auth_init(struct passwd *pw)
}
}
- debug_return_int(status == AUTH_FATAL ? -1 : 0);
+ debug_return_int(0);
}
/*
@@ -202,7 +208,7 @@ sudo_auth_cleanup(struct passwd *pw, bool force)
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) {
int status = (auth->cleanup)(pw, auth, force);
- if (status == AUTH_FATAL) {
+ if (status != AUTH_SUCCESS) {
/* Assume error msg already printed. */
debug_return_int(-1);
}
@@ -297,7 +303,7 @@ verify_user(struct passwd *pw, char *prompt, int validated,
status = (auth->setup)(pw, &prompt, auth);
if (status == AUTH_FAILURE)
SET(auth->flags, FLAG_DISABLED);
- else if (status == AUTH_FATAL || user_interrupted())
+ else if (status != AUTH_SUCCESS || user_interrupted())
goto done; /* assume error msg already printed */
}
}
@@ -350,7 +356,6 @@ done:
log_auth_failure(validated, ntries);
ret = false;
break;
- case AUTH_FATAL:
default:
log_auth_failure(validated, 0);
ret = -1;
@@ -362,24 +367,32 @@ done:
/*
* Call authentication method begin session hooks.
- * Returns 1 on success and -1 on error.
+ * Returns true on success, false on failure and -1 on error.
*/
int
sudo_auth_begin_session(struct passwd *pw, char **user_env[])
{
sudo_auth *auth;
+ int ret = true;
debug_decl(sudo_auth_begin_session, SUDOERS_DEBUG_AUTH);
for (auth = auth_switch; auth->name; auth++) {
if (auth->begin_session && !IS_DISABLED(auth)) {
int status = (auth->begin_session)(pw, user_env, auth);
- if (status != AUTH_SUCCESS) {
+ switch (status) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_FAILURE:
+ ret = false;
+ break;
+ default:
/* Assume error msg already printed. */
- debug_return_int(-1);
+ ret = -1;
+ break;
}
}
}
- debug_return_int(1);
+ debug_return_int(ret);
}
bool
@@ -400,25 +413,33 @@ sudo_auth_needs_end_session(void)
/*
* Call authentication method end session hooks.
- * Returns 1 on success and -1 on error.
+ * Returns true on success,false on failure and -1 on error.
*/
int
sudo_auth_end_session(struct passwd *pw)
{
sudo_auth *auth;
+ int ret = true;
int status;
debug_decl(sudo_auth_end_session, SUDOERS_DEBUG_AUTH);
for (auth = auth_switch; auth->name; auth++) {
if (auth->end_session && !IS_DISABLED(auth)) {
status = (auth->end_session)(pw, auth);
- if (status == AUTH_FATAL) {
+ switch (status) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_FAILURE:
+ ret = false;
+ break;
+ default:
/* Assume error msg already printed. */
- debug_return_int(-1);
+ ret = -1;
+ break;
}
}
}
- debug_return_int(1);
+ debug_return_int(ret);
}
/*
diff --git a/plugins/sudoers/auth/sudo_auth.h b/plugins/sudoers/auth/sudo_auth.h
index 9ee408d..585637c 100644
--- a/plugins/sudoers/auth/sudo_auth.h
+++ b/plugins/sudoers/auth/sudo_auth.h
@@ -19,11 +19,11 @@
#ifndef SUDO_AUTH_H
#define SUDO_AUTH_H
-/* Auth function return values. */
-#define AUTH_SUCCESS 0
-#define AUTH_FAILURE 1
-#define AUTH_INTR 2
-#define AUTH_FATAL 3
+/* Auth function return values(rowhammer resistent). */
+#define AUTH_SUCCESS 0x52a2925 /* 0101001010100010100100100101 */
+#define AUTH_FAILURE 0xad5d6da /* 1010110101011101011011011010 */
+#define AUTH_INTR 0x69d61fc8 /* 1101001110101100001111111001000 */
+#define AUTH_FATAL 0x1629e037 /* 0010110001010011110000000110111 */
typedef struct sudo_auth {
int flags; /* various flags, see below */
diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c
index 052e988..edf8fa1 100644
--- a/plugins/sudoers/match.c
+++ b/plugins/sudoers/match.c
@@ -93,7 +93,7 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
/* XXX */
const int rc = userlist_matches(parse_tree, pw, &a->members);
- if (rc != UNSPEC) {
+ if (SPECIFIED(rc)) {
if(m->negated) {
matched = rc == ALLOW ? DENY : ALLOW;
} else {
@@ -125,7 +125,8 @@ userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH);
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
- if ((matched = user_matches(parse_tree, pw, m)) != UNSPEC)
+ matched = user_matches(parse_tree, pw, m);
+ if (SPECIFIED(matched))
break;
}
debug_return_int(matched);
@@ -195,7 +196,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
if (a != NULL) {
rc = runaslist_matches(parse_tree, &a->members,
&empty, matching_user, NULL);
- if (rc != UNSPEC){
+ if (SPECIFIED(rc)){
if (m->negated) {
user_matched = rc == ALLOW ? DENY : ALLOW;
} else {
@@ -216,7 +217,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
user_matched = m->negated ? DENY : ALLOW;
break;
}
- if (user_matched != UNSPEC) {
+ if (SPECIFIED(user_matched)) {
if (matching_user != NULL && m->type != ALIAS)
*matching_user = m;
break;
@@ -229,7 +230,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
* Skip checking runas group if none was specified.
*/
if (ISSET(sudo_user.flags, RUNAS_GROUP_SPECIFIED)) {
- if (user_matched == UNSPEC) {
+ if (!SPECIFIED(user_matched)) {
if (strcmp(user_name, runas_pw->pw_name) == 0)
user_matched = ALLOW; /* only changing group */
}
@@ -244,7 +245,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
if (a != NULL) {
rc = runaslist_matches(parse_tree, &empty,
&a->members, NULL, matching_group);
- if (rc != UNSPEC){
+ if (SPECIFIED(rc)){
if (m->negated) {
group_matched = rc == ALLOW ? DENY : ALLOW;
} else {
@@ -260,14 +261,14 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
group_matched = m->negated ? DENY : ALLOW;
break;
}
- if (group_matched != UNSPEC) {
+ if (SPECIFIED(group_matched)) {
if (matching_group != NULL && m->type != ALIAS)
*matching_group = m;
break;
}
}
}
- if (group_matched == UNSPEC) {
+ if (!SPECIFIED(group_matched)) {
struct gid_list *runas_groups;
/*
* The runas group was not explicitly allowed by sudoers.
@@ -311,7 +312,7 @@ hostlist_matches_int(struct sudoers_parse_tree *parse_tree,
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = host_matches(parse_tree, pw, lhost, shost, m);
- if (matched != UNSPEC)
+ if (SPECIFIED(matched))
break;
}
debug_return_int(matched);
@@ -362,7 +363,7 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
/* XXX */
const int rc = hostlist_matches_int(parse_tree, pw, lhost,
shost,&a->members);
- if (rc != UNSPEC){
+ if (SPECIFIED(rc)){
if(m->negated){
matched = rc == ALLOW ? DENY : ALLOW;
} else {
@@ -395,7 +396,7 @@ cmndlist_matches(struct sudoers_parse_tree *parse_tree,
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = cmnd_matches(parse_tree, m);
- if (matched != UNSPEC)
+ if (SPECIFIED(matched))
break;
}
debug_return_int(matched);
@@ -429,7 +430,7 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
a = alias_get(parse_tree, m->name, CMNDALIAS);
if (a != NULL) {
rc = cmndlist_matches(parse_tree, &a->members);
- if (rc != UNSPEC){
+ if (SPECIFIED(rc)){
if (m->negated) {
matched = rc == ALLOW ? DENY : ALLOW;
} else {
diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c
index 6f29e0b..b5d37fb 100644
--- a/plugins/sudoers/parse.c
+++ b/plugins/sudoers/parse.c
@@ -147,7 +147,7 @@ sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw,
NULL);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(nss->parse_tree, cs->cmnd);
- if (cmnd_match != UNSPEC) {
+ if (SPECIFIED(cmnd_match)) {
/*
* If user is running command as himself,
* set runas_pw = sudo_user.pw.
@@ -301,7 +301,7 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
}
m = sudoers_lookup_check(nss, pw, &validated, &cs, &defs, now);
- if (m != UNSPEC) {
+ if (SPECIFIED(m)) {
match = m;
parse_tree = nss->parse_tree;
}
@@ -309,7 +309,7 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
if (!sudo_nss_can_continue(nss, m))
break;
}
- if (match != UNSPEC) {
+ if (SPECIFIED(match)) {
if (defs != NULL)
update_defaults(parse_tree, defs, SETDEF_GENERIC, false);
if (!apply_cmndspec(cs))
diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h
index ecc81b8..e1ba680 100644
--- a/plugins/sudoers/parse.h
+++ b/plugins/sudoers/parse.h
@@ -28,15 +28,28 @@
/* Returns true if string 's' contains meta characters. */
#define has_meta(s) (strpbrk(s, "\\?*[]") != NULL)
+/* Allowed by policy (rowhammer resistent). */
+#undef ALLOW
+#define ALLOW 0x52a2925 /* 0101001010100010100100100101 */
+
+/* Denied by policy (rowhammer resistent) */
+#undef DENY
+#define DENY 0xad5d6da /* 1010110101011101011011011010 */
+
+/* Neither allowed, nor denied. */
#undef UNSPEC
#define UNSPEC -1
-#undef DENY
-#define DENY 0
-#undef ALLOW
-#define ALLOW 1
+
+/* Tag implied by root access (SETENV only). */
#undef IMPLIED
#define IMPLIED 2
+/*
+ * We must explicitly check against ALLOW and DENY instead testing
+ * that the value is not UNSPEC to avoid potential ROWHAMMER issues.
+ */
+#define SPECIFIED(_v) ((_v) == ALLOW || (_v) == DENY)
+
/*
* Initialize all tags to UNSPEC.
*/
@@ -83,7 +96,7 @@
* Returns true if the specified tag is not UNSPEC or IMPLIED, else false.
*/
#define TAG_SET(tt) \
- ((tt) != UNSPEC && (tt) != IMPLIED)
+ ((tt) == true || (tt) == false)
/*
* Returns true if any tags set in nt differ between ot and nt, else false.
--
2.33.0

View File

@ -0,0 +1,257 @@
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 | 85 +++++++++++++++++++++++-------------
2 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c
index 111b326..12fcfd4 100644
--- a/plugins/sudoers/cvtsudoers.c
+++ b/plugins/sudoers/cvtsudoers.c
@@ -686,7 +686,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) {
@@ -712,7 +712,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);
@@ -788,7 +788,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 9051545..052e988 100644
--- a/plugins/sudoers/match.c
+++ b/plugins/sudoers/match.c
@@ -77,31 +77,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);
@@ -172,38 +177,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) {
@@ -227,22 +237,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) {
@@ -330,32 +345,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);
@@ -396,21 +416,26 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
switch (m->type) {
case ALL:
if (m->name == NULL) {
- matched = !m->negated;
+ matched = m->negated ? DENY : ALLOW;
break;
}
/* FALLTHROUGH */
case COMMAND:
c = (struct sudo_command *)m->name;
if (command_matches(c->cmnd, c->args, &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);
- 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.33.0

View File

@ -0,0 +1,989 @@
From 2ef90231a132547fa4236ff05fc0fafcd3f3d7a4 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
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 | 146 +++++++++++---------
plugins/sudoers/match_addr.c | 45 +++---
plugins/sudoers/match_command.c | 103 +++++++-------
plugins/sudoers/match_digest.c | 10 +-
plugins/sudoers/parse.h | 16 +--
plugins/sudoers/regress/parser/check_addr.c | 2 +-
plugins/sudoers/sssd.c | 6 +-
8 files changed, 171 insertions(+), 159 deletions(-)
diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c
index 5bdd488..b64a5a8 100644
--- a/plugins/sudoers/ldap.c
+++ b/plugins/sudoers/ldap.c
@@ -340,7 +340,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 edf8fa1..6fb7a2c 100644
--- a/plugins/sudoers/match.c
+++ b/plugins/sudoers/match.c
@@ -82,11 +82,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:
@@ -105,7 +105,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;
}
@@ -184,11 +184,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:
@@ -208,7 +208,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:
@@ -257,7 +257,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;
}
@@ -341,21 +341,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);
@@ -365,9 +365,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);
@@ -375,11 +375,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,
const struct member_list *list)
{
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);
if (SPECIFIED(matched))
- break;
+ debug_return_int(matched);
}
- debug_return_int(matched);
+ debug_return_int(UNSPEC);
}
/*
@@ -423,7 +423,7 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m)
/* FALLTHROUGH */
case COMMAND:
c = (struct sudo_command *)m->name;
- if (command_matches(c->cmnd, c->args, &c->digests))
+ if (command_matches(c->cmnd, c->args, &c->digests) == ALLOW)
matched = m->negated ? DENY : ALLOW;
break;
case ALIAS:
@@ -445,96 +445,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 */
@@ -547,7 +556,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;
}
@@ -562,14 +571,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;
}
}
@@ -579,8 +588,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)
@@ -656,22 +666,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
@@ -679,22 +689,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 ac942f4..d06634a 100644
--- a/plugins/sudoers/match_command.c
+++ b/plugins/sudoers/match_command.c
@@ -55,7 +55,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;
@@ -66,7 +66,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.
@@ -75,9 +75,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);
}
/*
@@ -189,7 +189,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 struct command_digest_list *digests)
{
@@ -205,11 +205,11 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
*/
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) {
@@ -250,14 +250,14 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
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);
}
-static bool
+static int
command_matches_all(const struct command_digest_list *digests)
{
struct stat sb; /* XXX - unused */
@@ -273,21 +273,21 @@ command_matches_all(const struct command_digest_list *digests)
}
/* Check digest of user_cmnd since we have no sudoers_cmnd for ALL. */
- if (!digest_matches(fd, user_cmnd, digests))
+ if (digest_matches(fd, user_cmnd, 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);
fd = -1;
}
- debug_return_bool(false);
+ debug_return_int(DENY);
}
-static bool
+static int
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
const struct command_digest_list *digests)
{
@@ -303,31 +303,31 @@ command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
* else return false.
*/
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, digests, &fd))
goto bad;
if (!do_stat(fd, user_cmnd, &sb))
goto bad;
/* Check digest of user_cmnd since sudoers_cmnd is a pattern. */
- if (!digest_matches(fd, user_cmnd, digests))
+ if (digest_matches(fd, user_cmnd, 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);
fd = -1;
}
- debug_return_bool(false);
+ debug_return_int(DENY);
}
- debug_return_bool(false);
+ debug_return_int(DENY);
}
-static bool
+static int
command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
const struct command_digest_list *digests)
{
@@ -349,19 +349,19 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
if ((base = strrchr(sudoers_cmnd, '/')) != NULL) {
base++;
if (!has_meta(base) && strcmp(user_base, base) != 0)
- debug_return_bool(false);
+ debug_return_int(DENY);
}
}
/*
- * 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] == '/') {
@@ -381,7 +381,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, digests)) {
+ if (digest_matches(fd, cp, digests) != ALLOW) {
bad_digest = true;
continue;
}
@@ -409,8 +409,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, digests))
- debug_return_bool(true);
+ if (command_matches_dir(cp, dlen,
+ digests) == ALLOW)
+ debug_return_int(ALLOW);
continue;
}
@@ -430,7 +431,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, digests))
+ if (digest_matches(fd, cp, digests) != ALLOW)
continue;
free(safe_cmnd);
if ((safe_cmnd = strdup(cp)) == NULL) {
@@ -445,18 +446,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 struct command_digest_list *digests)
{
struct stat sudoers_stat;
@@ -468,7 +469,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
/* 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, digests));
+ debug_return_int(command_matches_dir(sudoers_cmnd, dlen, digests));
/* Only proceed if user_base and basename(sudoers_cmnd) match */
if ((base = strrchr(sudoers_cmnd, '/')) == NULL)
@@ -476,7 +477,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
else
base++;
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, digests, &fd))
@@ -498,9 +499,9 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
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, digests)) {
+ if (digest_matches(fd, sudoers_cmnd, digests) != ALLOW) {
/* XXX - log functions not available but we should log very loudly */
goto bad;
}
@@ -510,25 +511,25 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
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);
}
/*
- * 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 user_cmnd names one of the inodes in path.
*/
-bool
+int
command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest_list *digests)
{
- bool rc = false;
+ int ret = DENY;
debug_decl(command_matches, SUDOERS_DEBUG_MATCH);
if (sudoers_cmnd == NULL) {
- rc = command_matches_all(digests);
+ ret = command_matches_all(digests);
goto done;
}
@@ -542,9 +543,9 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct
*/
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;
}
@@ -555,17 +556,17 @@ command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct
* use glob(3) and/or fnmatch(3) to do the matching.
*/
if (def_fast_glob)
- rc = command_matches_fnmatch(sudoers_cmnd, sudoers_args, digests);
+ ret = command_matches_fnmatch(sudoers_cmnd, sudoers_args, digests);
else
- rc = command_matches_glob(sudoers_cmnd, sudoers_args, digests);
+ ret = command_matches_glob(sudoers_cmnd, sudoers_args, digests);
} else {
- rc = command_matches_normal(sudoers_cmnd, sudoers_args, digests);
+ ret = command_matches_normal(sudoers_cmnd, sudoers_args, digests);
}
done:
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"user command \"%s%s%s\" matches sudoers command \"%s%s%s\": %s",
user_cmnd, user_args ? " " : "", user_args ? user_args : "",
sudoers_cmnd, sudoers_args ? " " : "", sudoers_args ? sudoers_args : "",
- 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 b08ba58..aa47462 100644
--- a/plugins/sudoers/match_digest.c
+++ b/plugins/sudoers/match_digest.c
@@ -37,7 +37,7 @@
#include "sudo_digest.h"
#include <gram.h>
-bool
+int
digest_matches(int fd, const char *file, const struct command_digest_list *digests)
{
unsigned int digest_type = SUDO_DIGEST_INVALID;
@@ -45,12 +45,12 @@ digest_matches(int fd, const char *file, const struct command_digest_list *diges
unsigned char *sudoers_digest = NULL;
struct command_digest *digest;
size_t digest_len = (size_t)-1;
- 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) {
@@ -100,7 +100,7 @@ digest_matches(int fd, const char *file, const struct command_digest_list *diges
}
}
if (memcmp(file_digest, sudoers_digest, digest_len) == 0) {
- matched = true;
+ matched = ALLOW;
break;
}
@@ -118,5 +118,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 e1ba680..6734eb6 100644
--- a/plugins/sudoers/parse.h
+++ b/plugins/sudoers/parse.h
@@ -318,22 +318,22 @@ void free_parse_tree(struct sudoers_parse_tree *parse_tree);
void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
/* 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 struct command_digest_list *digests);
+int command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct command_digest_list *digests);
/* match_digest.c */
-bool digest_matches(int fd, const char *file, const struct command_digest_list *digests);
+int digest_matches(int fd, const char *file, 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);
int cmndlist_matches(struct sudoers_parse_tree *parse_tree, const struct member_list *list);
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 fd0515f..135235d 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 6fe8337..e993099 100644
--- a/plugins/sudoers/sssd.c
+++ b/plugins/sudoers/sssd.c
@@ -196,20 +196,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.33.0

View File

@ -1,6 +1,6 @@
Name: sudo
Version: 1.9.2
Release: 14
Release: 15
Summary: Allows restricted root access for specified users
License: ISC
URL: http://www.courtesan.com/sudo/
@ -37,6 +37,9 @@ Patch23: backport-CVE-2023-22809.patch
Patch24: backport-CVE-2023-28486_CVE-2023-28487.patch
Patch25: Fix-compilation-error-on-sw64-arch.patch
Patch26: backport-don-t-report-a-usage-error-for-sudo-V.patch
Patch27: backport-Do-not-rely-on-the-definition-of-ALLOW-DENY-being-tr.patch
Patch28: backport-CVE-2023-42465.patch
Patch29: backport-Make-all-match-functions-return-ALLOW-DENY-not-true-.patch
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: pam
@ -177,6 +180,9 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i
%exclude %{_pkgdocdir}/ChangeLog
%changelog
* Mon Jan 8 2024 wangqingsan <wangqingsan@huawei.com> - 1.9.2-15
- fix CVE-2023-42465.
* Mon Nov 27 2023 zhangruifang <zhangruifang1@h-partners.com> - 1.9.2-14
- Don't report a usage error for "sudo -V".