Make all match functions return ALLOW/DENY not true/false.
This commit is contained in:
@@ -331,7 +331,7 @@ sudo_ldap_check_non_unix_group(struct sudoers_context *ctx,
|
|||||||
if (*val == '+') {
|
if (*val == '+') {
|
||||||
if (netgr_matches(nss, val,
|
if (netgr_matches(nss, val,
|
||||||
def_netgroup_tuple ? ctx->runas.host : NULL,
|
def_netgroup_tuple ? ctx->runas.host : NULL,
|
||||||
def_netgroup_tuple ? ctx->runas.shost : NULL, pw->pw_name))
|
def_netgroup_tuple ? ctx->runas.shost : NULL, pw->pw_name) == ALLOW)
|
||||||
ret = true;
|
ret = true;
|
||||||
DPRINTF2("ldap sudoUser netgroup '%s%s' ... %s",
|
DPRINTF2("ldap sudoUser netgroup '%s%s' ... %s",
|
||||||
negated ? "!" : "", val, ret ? "MATCH!" : "not");
|
negated ? "!" : "", val, ret ? "MATCH!" : "not");
|
||||||
|
@@ -43,7 +43,7 @@ runas_matches_pw(struct sudoers_parse_tree *parse_tree,
|
|||||||
|
|
||||||
if (cs->runasgrouplist == NULL) {
|
if (cs->runasgrouplist == NULL) {
|
||||||
/* No explicit runas user or group, use default. */
|
/* No explicit runas user or group, use default. */
|
||||||
if (userpw_matches(def_runas_default, pw->pw_name, pw))
|
if (userpw_matches(def_runas_default, pw->pw_name, pw) == ALLOW)
|
||||||
debug_return_int(ALLOW);
|
debug_return_int(ALLOW);
|
||||||
}
|
}
|
||||||
debug_return_int(UNSPEC);
|
debug_return_int(UNSPEC);
|
||||||
@@ -97,8 +97,8 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct sudoers_context *ctx,
|
|||||||
* to support the "pwcheck == all" case.
|
* to support the "pwcheck == all" case.
|
||||||
*/
|
*/
|
||||||
TAILQ_FOREACH(us, &nss->parse_tree->userspecs, entries) {
|
TAILQ_FOREACH(us, &nss->parse_tree->userspecs, entries) {
|
||||||
int user_match = userlist_matches(nss->parse_tree, ctx->user.pw,
|
const int user_match = userlist_matches(nss->parse_tree,
|
||||||
&us->users);
|
ctx->user.pw, &us->users);
|
||||||
if (user_match != ALLOW) {
|
if (user_match != ALLOW) {
|
||||||
if (callback != NULL && user_match == DENY) {
|
if (callback != NULL && user_match == DENY) {
|
||||||
callback(nss->parse_tree, us, user_match, NULL, UNSPEC,
|
callback(nss->parse_tree, us, user_match, NULL, UNSPEC,
|
||||||
@@ -108,8 +108,8 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct sudoers_context *ctx,
|
|||||||
}
|
}
|
||||||
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
TAILQ_FOREACH(priv, &us->privileges, entries) {
|
||||||
int priv_nopass = UNSPEC;
|
int priv_nopass = UNSPEC;
|
||||||
int host_match = hostlist_matches(nss->parse_tree, ctx->user.pw,
|
const int host_match = hostlist_matches(nss->parse_tree,
|
||||||
&priv->hostlist);
|
ctx->user.pw, &priv->hostlist);
|
||||||
if (host_match != ALLOW) {
|
if (host_match != ALLOW) {
|
||||||
if (callback != NULL) {
|
if (callback != NULL) {
|
||||||
callback(nss->parse_tree, us, user_match, priv,
|
callback(nss->parse_tree, us, user_match, priv,
|
||||||
@@ -243,7 +243,8 @@ sudoers_lookup_check(struct sudo_nss *nss, struct sudoers_context *ctx,
|
|||||||
init_cmnd_info(ctx, info);
|
init_cmnd_info(ctx, info);
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(us, &nss->parse_tree->userspecs, userspec_list, entries) {
|
TAILQ_FOREACH_REVERSE(us, &nss->parse_tree->userspecs, userspec_list, entries) {
|
||||||
int user_match = userlist_matches(nss->parse_tree, ctx->user.pw, &us->users);
|
const int user_match = userlist_matches(nss->parse_tree, ctx->user.pw,
|
||||||
|
&us->users);
|
||||||
if (user_match != ALLOW) {
|
if (user_match != ALLOW) {
|
||||||
if (callback != NULL && user_match == DENY) {
|
if (callback != NULL && user_match == DENY) {
|
||||||
callback(nss->parse_tree, us, user_match, NULL, UNSPEC, NULL,
|
callback(nss->parse_tree, us, user_match, NULL, UNSPEC, NULL,
|
||||||
@@ -253,8 +254,8 @@ sudoers_lookup_check(struct sudo_nss *nss, struct sudoers_context *ctx,
|
|||||||
}
|
}
|
||||||
CLR(*validated, FLAG_NO_USER);
|
CLR(*validated, FLAG_NO_USER);
|
||||||
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
|
TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
|
||||||
int host_match = hostlist_matches(nss->parse_tree, ctx->user.pw,
|
const int host_match = hostlist_matches(nss->parse_tree,
|
||||||
&priv->hostlist);
|
ctx->user.pw, &priv->hostlist);
|
||||||
if (host_match == ALLOW) {
|
if (host_match == ALLOW) {
|
||||||
CLR(*validated, FLAG_NO_HOST);
|
CLR(*validated, FLAG_NO_HOST);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -80,11 +80,11 @@ user_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
case NETGROUP:
|
case NETGROUP:
|
||||||
if (netgr_matches(parse_tree->nss, m->name,
|
if (netgr_matches(parse_tree->nss, m->name,
|
||||||
def_netgroup_tuple ? lhost : NULL,
|
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;
|
matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case USERGROUP:
|
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;
|
matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
@@ -103,7 +103,7 @@ user_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
}
|
}
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
case WORD:
|
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;
|
matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -173,11 +173,11 @@ runas_userlist_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
if (netgr_matches(parse_tree->nss, m->name,
|
if (netgr_matches(parse_tree->nss, m->name,
|
||||||
def_netgroup_tuple ? lhost : NULL,
|
def_netgroup_tuple ? lhost : NULL,
|
||||||
def_netgroup_tuple ? shost : NULL,
|
def_netgroup_tuple ? shost : NULL,
|
||||||
ctx->runas.pw->pw_name))
|
ctx->runas.pw->pw_name) == ALLOW)
|
||||||
user_matched = m->negated ? DENY : ALLOW;
|
user_matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case USERGROUP:
|
case USERGROUP:
|
||||||
if (usergr_matches(m->name, ctx->runas.pw->pw_name, ctx->runas.pw))
|
if (usergr_matches(m->name, ctx->runas.pw->pw_name, ctx->runas.pw) == ALLOW)
|
||||||
user_matched = m->negated ? DENY : ALLOW;
|
user_matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
@@ -197,7 +197,7 @@ runas_userlist_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
}
|
}
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
case WORD:
|
case WORD:
|
||||||
if (userpw_matches(m->name, ctx->runas.pw->pw_name, ctx->runas.pw))
|
if (userpw_matches(m->name, ctx->runas.pw->pw_name, ctx->runas.pw) == ALLOW)
|
||||||
user_matched = m->negated ? DENY : ALLOW;
|
user_matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case MYSELF:
|
case MYSELF:
|
||||||
@@ -259,7 +259,7 @@ runas_grouplist_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
}
|
}
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
case WORD:
|
case WORD:
|
||||||
if (group_matches(m->name, ctx->runas.gr))
|
if (group_matches(m->name, ctx->runas.gr) == ALLOW)
|
||||||
group_matched = m->negated ? DENY : ALLOW;
|
group_matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -381,21 +381,21 @@ host_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
const struct member *m)
|
const struct member *m)
|
||||||
{
|
{
|
||||||
struct alias *a;
|
struct alias *a;
|
||||||
int matched = UNSPEC;
|
int ret = UNSPEC;
|
||||||
debug_decl(host_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(host_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case ALL:
|
case ALL:
|
||||||
matched = m->negated ? DENY : ALLOW;
|
ret = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case NETGROUP:
|
case NETGROUP:
|
||||||
if (netgr_matches(parse_tree->nss, m->name, lhost, shost,
|
if (netgr_matches(parse_tree->nss, m->name, lhost, shost,
|
||||||
def_netgroup_tuple ? pw->pw_name : NULL))
|
def_netgroup_tuple ? pw->pw_name : NULL) == ALLOW)
|
||||||
matched = m->negated ? DENY : ALLOW;
|
ret = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case NTWKADDR:
|
case NTWKADDR:
|
||||||
if (addr_matches(m->name))
|
if (addr_matches(m->name) == ALLOW)
|
||||||
matched = m->negated ? DENY : ALLOW;
|
ret = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
a = alias_get(parse_tree, m->name, HOSTALIAS);
|
a = alias_get(parse_tree, m->name, HOSTALIAS);
|
||||||
@@ -405,9 +405,9 @@ host_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
shost, &a->members);
|
shost, &a->members);
|
||||||
if (SPECIFIED(rc)) {
|
if (SPECIFIED(rc)) {
|
||||||
if (m->negated) {
|
if (m->negated) {
|
||||||
matched = rc == ALLOW ? DENY : ALLOW;
|
ret = rc == ALLOW ? DENY : ALLOW;
|
||||||
} else {
|
} else {
|
||||||
matched = rc;
|
ret = rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
alias_put(a);
|
alias_put(a);
|
||||||
@@ -415,15 +415,15 @@ host_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
}
|
}
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
case WORD:
|
case WORD:
|
||||||
if (hostname_matches(shost, lhost, m->name))
|
if (hostname_matches(shost, lhost, m->name) == ALLOW)
|
||||||
matched = m->negated ? DENY : ALLOW;
|
ret = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG,
|
||||||
"host %s (%s) matches sudoers host %s%s: %s", lhost, shost,
|
"host %s (%s) matches sudoers host %s%s: %s", lhost, shost,
|
||||||
m->negated ? "!" : "", m->name ? m->name : "ALL",
|
m->negated ? "!" : "", m->name ? m->name : "ALL",
|
||||||
matched == true ? "true" : "false");
|
ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
debug_return_int(matched);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -436,15 +436,15 @@ cmndlist_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
struct cmnd_info *info)
|
struct cmnd_info *info)
|
||||||
{
|
{
|
||||||
struct member *m;
|
struct member *m;
|
||||||
int matched = UNSPEC;
|
int matched;
|
||||||
debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||||
matched = cmnd_matches(parse_tree, m, runchroot, info);
|
matched = cmnd_matches(parse_tree, m, runchroot, info);
|
||||||
if (SPECIFIED(matched))
|
if (SPECIFIED(matched))
|
||||||
break;
|
debug_return_int(matched);
|
||||||
}
|
}
|
||||||
debug_return_int(matched);
|
debug_return_int(UNSPEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -465,7 +465,7 @@ cmnd_matches(const struct sudoers_parse_tree *parse_tree,
|
|||||||
case COMMAND:
|
case COMMAND:
|
||||||
c = (struct sudo_command *)m->name;
|
c = (struct sudo_command *)m->name;
|
||||||
if (command_matches(parse_tree->ctx, c->cmnd, c->args, runchroot,
|
if (command_matches(parse_tree->ctx, c->cmnd, c->args, runchroot,
|
||||||
info, &c->digests))
|
info, &c->digests) == ALLOW)
|
||||||
matched = m->negated ? DENY : ALLOW;
|
matched = m->negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
@@ -504,7 +504,7 @@ cmnd_matches_all(const struct sudoers_parse_tree *parse_tree,
|
|||||||
case ALL:
|
case ALL:
|
||||||
c = (struct sudo_command *)m->name;
|
c = (struct sudo_command *)m->name;
|
||||||
if (command_matches(parse_tree->ctx, c->cmnd, c->args, runchroot,
|
if (command_matches(parse_tree->ctx, c->cmnd, c->args, runchroot,
|
||||||
info, &c->digests))
|
info, &c->digests) == ALLOW)
|
||||||
matched = negated ? DENY : ALLOW;
|
matched = negated ? DENY : ALLOW;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
@@ -526,93 +526,102 @@ cmnd_matches_all(const struct sudoers_parse_tree *parse_tree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
hostname_matches(const char *shost, const char *lhost, const char *pattern)
|
||||||
{
|
{
|
||||||
const char *host;
|
const char *host;
|
||||||
bool rc;
|
int ret;
|
||||||
debug_decl(hostname_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(hostname_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
host = strchr(pattern, '.') != NULL ? lhost : shost;
|
host = strchr(pattern, '.') != NULL ? lhost : shost;
|
||||||
|
ret = DENY;
|
||||||
if (has_meta(pattern)) {
|
if (has_meta(pattern)) {
|
||||||
rc = !fnmatch(pattern, host, FNM_CASEFOLD);
|
if (fnmatch(pattern, host, FNM_CASEFOLD) == 0)
|
||||||
|
ret = ALLOW;
|
||||||
} else {
|
} else {
|
||||||
rc = !strcasecmp(host, pattern);
|
if (strcasecmp(host, pattern) == 0)
|
||||||
|
ret = ALLOW;
|
||||||
}
|
}
|
||||||
debug_return_bool(rc);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the user/uid from sudoers matches the specified user/uid,
|
* Returns ALLOW if the user/uid from sudoers matches the specified user/uid,
|
||||||
* else returns false.
|
* else returns DENY.
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw)
|
userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw)
|
||||||
{
|
{
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
|
int ret = DENY;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
bool rc;
|
|
||||||
debug_decl(userpw_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(userpw_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
if (pw != NULL && *sudoers_user == '#') {
|
if (pw != NULL && *sudoers_user == '#') {
|
||||||
uid = (uid_t) sudo_strtoid(sudoers_user + 1, &errstr);
|
uid = (uid_t) sudo_strtoid(sudoers_user + 1, &errstr);
|
||||||
if (errstr == NULL && uid == pw->pw_uid) {
|
if (errstr == NULL && uid == pw->pw_uid) {
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def_case_insensitive_user)
|
if (def_case_insensitive_user) {
|
||||||
rc = strcasecmp(sudoers_user, user) == 0;
|
if (strcasecmp(sudoers_user, user) == 0)
|
||||||
else
|
ret = ALLOW;
|
||||||
rc = strcmp(sudoers_user, user) == 0;
|
} else {
|
||||||
|
if (strcmp(sudoers_user, user) == 0)
|
||||||
|
ret = ALLOW;
|
||||||
|
}
|
||||||
done:
|
done:
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||||
"user %s matches sudoers user %s: %s",
|
"user %s matches sudoers user %s: %s",
|
||||||
user, sudoers_user, rc ? "true" : "false");
|
user, sudoers_user, ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
debug_return_bool(rc);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the group/gid from sudoers matches the specified group/gid,
|
* Returns ALLOW if the group/gid from sudoers matches the specified group/gid,
|
||||||
* else returns false.
|
* else returns DENY.
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
group_matches(const char *sudoers_group, const struct group *gr)
|
group_matches(const char *sudoers_group, const struct group *gr)
|
||||||
{
|
{
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
|
int ret = DENY;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
bool rc;
|
|
||||||
debug_decl(group_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(group_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
if (*sudoers_group == '#') {
|
if (*sudoers_group == '#') {
|
||||||
gid = (gid_t) sudo_strtoid(sudoers_group + 1, &errstr);
|
gid = (gid_t) sudo_strtoid(sudoers_group + 1, &errstr);
|
||||||
if (errstr == NULL && gid == gr->gr_gid) {
|
if (errstr == NULL && gid == gr->gr_gid) {
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def_case_insensitive_group)
|
if (def_case_insensitive_group) {
|
||||||
rc = strcasecmp(sudoers_group, gr->gr_name) == 0;
|
if (strcasecmp(sudoers_group, gr->gr_name) == 0)
|
||||||
else
|
ret = ALLOW;
|
||||||
rc = strcmp(sudoers_group, gr->gr_name) == 0;
|
} else {
|
||||||
|
if (strcmp(sudoers_group, gr->gr_name) == 0)
|
||||||
|
ret = ALLOW;
|
||||||
|
}
|
||||||
done:
|
done:
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||||
"group %s matches sudoers group %s: %s",
|
"group %s matches sudoers group %s: %s",
|
||||||
gr->gr_name, sudoers_group, rc ? "true" : "false");
|
gr->gr_name, sudoers_group, ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
debug_return_bool(rc);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the given user belongs to the named group,
|
* Returns true if the given user belongs to the named group,
|
||||||
* else returns false.
|
* else returns false.
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
usergr_matches(const char *group, const char *user, const struct passwd *pw)
|
usergr_matches(const char *group, const char *user, const struct passwd *pw)
|
||||||
{
|
{
|
||||||
bool matched = false;
|
|
||||||
struct passwd *pw0 = NULL;
|
struct passwd *pw0 = NULL;
|
||||||
|
int ret = DENY;
|
||||||
debug_decl(usergr_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(usergr_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
/* Make sure we have a valid usergroup, sudo style */
|
/* Make sure we have a valid usergroup, sudo style */
|
||||||
@@ -625,7 +634,7 @@ usergr_matches(const char *group, const char *user, const struct passwd *pw)
|
|||||||
/* Query group plugin for %:name groups. */
|
/* Query group plugin for %:name groups. */
|
||||||
if (*group == ':' && def_group_plugin) {
|
if (*group == ':' && def_group_plugin) {
|
||||||
if (group_plugin_query(user, group + 1, pw) == true)
|
if (group_plugin_query(user, group + 1, pw) == true)
|
||||||
matched = true;
|
ret = ALLOW;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,14 +649,14 @@ usergr_matches(const char *group, const char *user, const struct passwd *pw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user_in_group(pw, group)) {
|
if (user_in_group(pw, group)) {
|
||||||
matched = true;
|
ret = ALLOW;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Query the group plugin for Unix groups too? */
|
/* Query the group plugin for Unix groups too? */
|
||||||
if (def_group_plugin && def_always_query_group_plugin) {
|
if (def_group_plugin && def_always_query_group_plugin) {
|
||||||
if (group_plugin_query(user, group, pw) == true) {
|
if (group_plugin_query(user, group, pw) == true) {
|
||||||
matched = true;
|
ret = ALLOW;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -657,8 +666,9 @@ done:
|
|||||||
sudo_pw_delref(pw0);
|
sudo_pw_delref(pw0);
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||||
"user %s matches group %s: %s", user, group, matched ? "true" : "false");
|
"user %s matches group %s: %s", user, group,
|
||||||
debug_return_bool(matched);
|
ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_GETDOMAINNAME) || defined(SI_SRPC_DOMAIN)
|
#if defined(HAVE_GETDOMAINNAME) || defined(SI_SRPC_DOMAIN)
|
||||||
@@ -734,28 +744,28 @@ sudo_getdomainname(void)
|
|||||||
#endif /* HAVE_GETDOMAINNAME || SI_SRPC_DOMAIN */
|
#endif /* HAVE_GETDOMAINNAME || SI_SRPC_DOMAIN */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if "host" and "user" belong to the netgroup "netgr",
|
* Returns ALLOW if "host" and "user" belong to the netgroup "netgr",
|
||||||
* else return false. Either of "lhost", "shost" or "user" may be NULL
|
* else return DENY. Either of "lhost", "shost" or "user" may be NULL
|
||||||
* in which case that argument is not checked...
|
* in which case that argument is not checked...
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
netgr_matches(const struct sudo_nss *nss, const char *netgr,
|
netgr_matches(const struct sudo_nss *nss, const char *netgr,
|
||||||
const char *lhost, const char *shost, const char *user)
|
const char *lhost, const char *shost, const char *user)
|
||||||
{
|
{
|
||||||
const char *domain;
|
const char *domain;
|
||||||
bool rc = false;
|
int ret = DENY;
|
||||||
debug_decl(netgr_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(netgr_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
if (!def_use_netgroups) {
|
if (!def_use_netgroups) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "netgroups are disabled");
|
sudo_debug_printf(SUDO_DEBUG_INFO, "netgroups are disabled");
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure we have a valid netgroup, sudo style */
|
/* make sure we have a valid netgroup, sudo style */
|
||||||
if (*netgr++ != '+') {
|
if (*netgr++ != '+') {
|
||||||
sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'",
|
sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'",
|
||||||
netgr);
|
netgr);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the domain name (if any) */
|
/* get the domain name (if any) */
|
||||||
@@ -767,11 +777,11 @@ netgr_matches(const struct sudo_nss *nss, const char *netgr,
|
|||||||
case 0:
|
case 0:
|
||||||
if (lhost != shost) {
|
if (lhost != shost) {
|
||||||
if (nss->innetgr(nss, netgr, shost, user, domain) == 1)
|
if (nss->innetgr(nss, netgr, shost, user, domain) == 1)
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
case 1:
|
case 1:
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
goto done;
|
goto done;
|
||||||
default:
|
default:
|
||||||
/* Not supported, use system innetgr(3). */
|
/* Not supported, use system innetgr(3). */
|
||||||
@@ -782,10 +792,10 @@ netgr_matches(const struct sudo_nss *nss, const char *netgr,
|
|||||||
#ifdef HAVE_INNETGR
|
#ifdef HAVE_INNETGR
|
||||||
/* Use system innetgr() function. */
|
/* Use system innetgr() function. */
|
||||||
if (innetgr(netgr, lhost, user, domain) == 1) {
|
if (innetgr(netgr, lhost, user, domain) == 1) {
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
} else if (lhost != shost) {
|
} else if (lhost != shost) {
|
||||||
if (innetgr(netgr, shost, user, domain) == 1)
|
if (innetgr(netgr, shost, user, domain) == 1)
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
@@ -796,7 +806,7 @@ done:
|
|||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||||
"netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
|
"netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
|
||||||
shost ? shost : "", user ? user : "", domain ? domain : "",
|
shost ? shost : "", user ? user : "", domain ? domain : "",
|
||||||
rc ? "true" : "false");
|
ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
|
|
||||||
debug_return_bool(rc);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
#include "sudoers.h"
|
#include "sudoers.h"
|
||||||
#include "interfaces.h"
|
#include "interfaces.h"
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
addr_matches_if(const char *n)
|
addr_matches_if(const char *n)
|
||||||
{
|
{
|
||||||
union sudo_in_addr_un addr;
|
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) {
|
if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
|
||||||
family = AF_INET;
|
family = AF_INET;
|
||||||
} else {
|
} else {
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLIST_FOREACH(ifp, get_interfaces(), entries) {
|
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 ||
|
if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
|
||||||
(ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
|
(ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
|
||||||
== addr.ip4.s_addr)
|
== addr.ip4.s_addr)
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_STRUCT_IN6_ADDR
|
#ifdef HAVE_STRUCT_IN6_ADDR
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
|
if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
|
||||||
sizeof(addr.ip6.s6_addr)) == 0)
|
sizeof(addr.ip6.s6_addr)) == 0)
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
|
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])
|
if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (j == sizeof(addr.ip6.s6_addr))
|
if (j == sizeof(addr.ip6.s6_addr))
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
break;
|
break;
|
||||||
#endif /* HAVE_STRUCT_IN6_ADDR */
|
#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)
|
addr_matches_if_netmask(const char *n, const char *m)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@@ -116,7 +116,7 @@ addr_matches_if_netmask(const char *n, const char *m)
|
|||||||
if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
|
if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
|
||||||
family = AF_INET;
|
family = AF_INET;
|
||||||
} else {
|
} else {
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (family == AF_INET) {
|
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) {
|
if (inet_pton(AF_INET, m, &mask.ip4) != 1) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"IPv4 netmask %s: %s", m, "invalid value");
|
"IPv4 netmask %s: %s", m, "invalid value");
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i = (size_t)sudo_strtonum(m, 1, 32, &errstr);
|
i = (size_t)sudo_strtonum(m, 1, 32, &errstr);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"IPv4 netmask %s: %s", m, errstr);
|
"IPv4 netmask %s: %s", m, errstr);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
mask.ip4.s_addr = htonl(0xffffffffU << (32 - i));
|
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) {
|
if (errstr != NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"IPv6 netmask %s: %s", m, errstr);
|
"IPv6 netmask %s: %s", m, errstr);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
|
for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
|
||||||
if (j < i * 8)
|
if (j < i * 8)
|
||||||
@@ -165,7 +165,7 @@ addr_matches_if_netmask(const char *n, const char *m)
|
|||||||
switch (family) {
|
switch (family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
|
if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_STRUCT_IN6_ADDR
|
#ifdef HAVE_STRUCT_IN6_ADDR
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
@@ -174,35 +174,36 @@ addr_matches_if_netmask(const char *n, const char *m)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (j == sizeof(addr.ip6.s6_addr))
|
if (j == sizeof(addr.ip6.s6_addr))
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
break;
|
break;
|
||||||
#endif /* HAVE_STRUCT_IN6_ADDR */
|
#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
|
* Returns ALLOW if "n" is one of our ip addresses or if
|
||||||
* "n" is a network that we are on, else returns false.
|
* "n" is a network that we are on, else returns DENY.
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
addr_matches(char *n)
|
addr_matches(char *n)
|
||||||
{
|
{
|
||||||
char *m;
|
char *m;
|
||||||
bool rc;
|
int ret;
|
||||||
debug_decl(addr_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(addr_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
/* If there's an explicit netmask, use it. */
|
/* If there's an explicit netmask, use it. */
|
||||||
if ((m = strchr(n, '/'))) {
|
if ((m = strchr(n, '/'))) {
|
||||||
*m++ = '\0';
|
*m++ = '\0';
|
||||||
rc = addr_matches_if_netmask(n, m);
|
ret = addr_matches_if_netmask(n, m);
|
||||||
*(m - 1) = '/';
|
*(m - 1) = '/';
|
||||||
} else
|
} else
|
||||||
rc = addr_matches_if(n);
|
ret = addr_matches_if(n);
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
|
||||||
"IP address %s matches local host: %s", n, rc ? "true" : "false");
|
"IP address %s matches local host: %s", n,
|
||||||
debug_return_bool(rc);
|
ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
@@ -57,28 +57,31 @@
|
|||||||
# define O_EXEC O_PATH
|
# define O_EXEC O_PATH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
regex_matches(const char *pattern, const char *str)
|
regex_matches(const char *pattern, const char *str)
|
||||||
{
|
{
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
int errcode;
|
|
||||||
regex_t re;
|
regex_t re;
|
||||||
|
int ret;
|
||||||
debug_decl(regex_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(regex_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
if (!sudo_regex_compile(&re, pattern, &errstr)) {
|
if (!sudo_regex_compile(&re, pattern, &errstr)) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"unable to compile regular expression \"%s\": %s",
|
"unable to compile regular expression \"%s\": %s",
|
||||||
pattern, errstr);
|
pattern, errstr);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
errcode = regexec(&re, str, 0, NULL, 0);
|
if (regexec(&re, str, 0, NULL, 0) == 0)
|
||||||
|
ret = ALLOW;
|
||||||
|
else
|
||||||
|
ret = DENY;
|
||||||
regfree(&re);
|
regfree(&re);
|
||||||
|
|
||||||
debug_return_bool(errcode == 0);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
command_args_match(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_args_match(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args)
|
const char *sudoers_args)
|
||||||
{
|
{
|
||||||
@@ -91,9 +94,9 @@ command_args_match(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
* If the empty string is specified in sudoers, no user args are allowed.
|
* If the empty string is specified in sudoers, no user args are allowed.
|
||||||
*/
|
*/
|
||||||
if (sudoers_args == NULL)
|
if (sudoers_args == NULL)
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
if (strcmp("\"\"", sudoers_args) == 0)
|
if (strcmp("\"\"", sudoers_args) == 0)
|
||||||
debug_return_bool(ctx->user.cmnd_args ? false : true);
|
debug_return_int(ctx->user.cmnd_args ? DENY : ALLOW);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If args are specified in sudoers, they must match the user args.
|
* If args are specified in sudoers, they must match the user args.
|
||||||
@@ -102,13 +105,15 @@ command_args_match(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
if (sudoers_args[0] == '^') {
|
if (sudoers_args[0] == '^') {
|
||||||
size_t len = strlen(sudoers_args);
|
size_t len = strlen(sudoers_args);
|
||||||
if (len > 0 && sudoers_args[len - 1] == '$')
|
if (len > 0 && sudoers_args[len - 1] == '$')
|
||||||
debug_return_bool(regex_matches(sudoers_args, args));
|
debug_return_int(regex_matches(sudoers_args, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If running as sudoedit, all args are assumed to be paths. */
|
/* If running as sudoedit, all args are assumed to be paths. */
|
||||||
if (strcmp(sudoers_cmnd, "sudoedit") == 0)
|
if (strcmp(sudoers_cmnd, "sudoedit") == 0)
|
||||||
flags = FNM_PATHNAME;
|
flags = FNM_PATHNAME;
|
||||||
debug_return_bool(fnmatch(sudoers_args, args, flags) == 0);
|
if (fnmatch(sudoers_args, args, flags) == 0)
|
||||||
|
debug_return_int(ALLOW);
|
||||||
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SUDOERS_NAME_MATCH
|
#ifndef SUDOERS_NAME_MATCH
|
||||||
@@ -250,14 +255,14 @@ set_cmnd_fd(struct sudoers_context *ctx, int fd, int rootfd)
|
|||||||
/*
|
/*
|
||||||
* Return true if ctx->user.cmnd names one of the inodes in dir, else false.
|
* Return true if ctx->user.cmnd names one of the inodes in dir, else false.
|
||||||
*/
|
*/
|
||||||
static bool
|
static int
|
||||||
command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
|
command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
|
||||||
size_t dlen, int rootfd, bool intercepted, const struct command_digest_list *digests)
|
size_t dlen, int rootfd, bool intercepted, const struct command_digest_list *digests)
|
||||||
{
|
{
|
||||||
struct stat sudoers_stat;
|
struct stat sudoers_stat;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
int len, fd = -1;
|
int len, fd = -1;
|
||||||
bool ret = false;
|
int ret = DENY;
|
||||||
debug_decl(command_matches_dir, SUDOERS_DEBUG_MATCH);
|
debug_decl(command_matches_dir, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
/* Compare the canonicalized directories, if possible. */
|
/* Compare the canonicalized directories, if possible. */
|
||||||
@@ -288,26 +293,28 @@ command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
|
|||||||
if (ctx->user.cmnd_stat == NULL ||
|
if (ctx->user.cmnd_stat == NULL ||
|
||||||
(ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
|
(ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
|
||||||
ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
|
ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
|
||||||
if (!digest_matches(fd, path, digests))
|
if (digest_matches(fd, path, digests) != ALLOW)
|
||||||
goto done;
|
goto done;
|
||||||
free(ctx->runas.cmnd);
|
free(ctx->runas.cmnd);
|
||||||
if ((ctx->runas.cmnd = strdup(path)) == NULL) {
|
if ((ctx->runas.cmnd = strdup(path)) == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__,
|
sudo_warnx(U_("%s: %s"), __func__,
|
||||||
U_("unable to allocate memory"));
|
U_("unable to allocate memory"));
|
||||||
}
|
}
|
||||||
ret = true;
|
ret = ALLOW;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
ret = DENY;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(ret);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
#else /* SUDOERS_NAME_MATCH */
|
#else /* SUDOERS_NAME_MATCH */
|
||||||
/*
|
/*
|
||||||
* Return true if ctx->user.cmnd names one of the inodes in dir, else false.
|
* Return true if ctx->user.cmnd names one of the inodes in dir, else false.
|
||||||
*/
|
*/
|
||||||
static bool
|
static int
|
||||||
command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
|
command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
|
||||||
size_t dlen, int rootfd, bool intercepted,
|
size_t dlen, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -326,19 +333,19 @@ command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
|
|||||||
/* Open the file for fdexec or for digest matching. */
|
/* Open the file for fdexec or for digest matching. */
|
||||||
if (!open_cmnd(ctx->user.cmnd, digests, &fd))
|
if (!open_cmnd(ctx->user.cmnd, digests, &fd))
|
||||||
goto bad;
|
goto bad;
|
||||||
if (!digest_matches(fd, ctx->user.cmnd, digests))
|
if (digest_matches(fd, ctx->user.cmnd, digests) != ALLOW)
|
||||||
goto bad;
|
goto bad;
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
|
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
#endif /* SUDOERS_NAME_MATCH */
|
#endif /* SUDOERS_NAME_MATCH */
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
command_matches_all(struct sudoers_context *ctx, int rootfd, bool intercepted,
|
command_matches_all(struct sudoers_context *ctx, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
{
|
{
|
||||||
@@ -369,19 +376,19 @@ command_matches_all(struct sudoers_context *ctx, int rootfd, bool intercepted,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check digest of ctx->user.cmnd since we have no sudoers_cmnd for ALL. */
|
/* Check digest of ctx->user.cmnd since we have no sudoers_cmnd for ALL. */
|
||||||
if (!digest_matches(fd, ctx->user.cmnd, digests))
|
if (digest_matches(fd, ctx->user.cmnd, digests) != ALLOW)
|
||||||
goto bad;
|
goto bad;
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
|
|
||||||
/* No need to set ctx->runas.cmnd for ALL. */
|
/* No need to set ctx->runas.cmnd for ALL. */
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
command_matches_fnmatch(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches_fnmatch(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, int rootfd, bool intercepted,
|
const char *sudoers_args, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -397,25 +404,25 @@ command_matches_fnmatch(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
/* A relative ctx->user.cmnd will not match, try canonicalized version. */
|
/* A relative ctx->user.cmnd will not match, try canonicalized version. */
|
||||||
if (ctx->user.cmnd[0] != '/') {
|
if (ctx->user.cmnd[0] != '/') {
|
||||||
if (ctx->user.cmnd_dir == NULL)
|
if (ctx->user.cmnd_dir == NULL)
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
len = snprintf(buf, sizeof(buf), "%s/%s", ctx->user.cmnd_dir,
|
len = snprintf(buf, sizeof(buf), "%s/%s", ctx->user.cmnd_dir,
|
||||||
ctx->user.cmnd_base);
|
ctx->user.cmnd_base);
|
||||||
if (len < 0 || len >= ssizeof(buf))
|
if (len < 0 || len >= ssizeof(buf))
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
cmnd = buf;
|
cmnd = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if fnmatch(3) succeeds AND
|
* Return ALLOW if fnmatch(3) succeeds AND
|
||||||
* a) there are no args in sudoers OR
|
* a) there are no args in sudoers OR
|
||||||
* b) there are no args on command line and none required by 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
|
* c) there are args in sudoers and on command line and they match
|
||||||
* else return false.
|
* else return DENY.
|
||||||
*/
|
*/
|
||||||
if (fnmatch(sudoers_cmnd, cmnd, FNM_PATHNAME) != 0)
|
if (fnmatch(sudoers_cmnd, cmnd, FNM_PATHNAME) != 0)
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
|
|
||||||
if (command_args_match(ctx, sudoers_cmnd, sudoers_args)) {
|
if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
|
||||||
/* Open the file for fdexec or for digest matching. */
|
/* Open the file for fdexec or for digest matching. */
|
||||||
if (!open_cmnd(cmnd, digests, &fd))
|
if (!open_cmnd(cmnd, digests, &fd))
|
||||||
goto bad;
|
goto bad;
|
||||||
@@ -426,21 +433,20 @@ command_matches_fnmatch(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
goto bad;
|
goto bad;
|
||||||
#endif
|
#endif
|
||||||
/* Check digest of cmnd since sudoers_cmnd is a pattern. */
|
/* Check digest of cmnd since sudoers_cmnd is a pattern. */
|
||||||
if (!digest_matches(fd, cmnd, digests))
|
if (digest_matches(fd, cmnd, digests) != ALLOW)
|
||||||
goto bad;
|
goto bad;
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
|
|
||||||
/* No need to set ctx->runas.cmnd since cmnd matches sudoers_cmnd */
|
/* No need to set ctx->runas.cmnd since cmnd matches sudoers_cmnd */
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
}
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
command_matches_regex(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches_regex(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, int rootfd, bool intercepted,
|
const char *sudoers_args, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -456,25 +462,25 @@ command_matches_regex(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
/* A relative ctx->user.cmnd will not match, try canonicalized version. */
|
/* A relative ctx->user.cmnd will not match, try canonicalized version. */
|
||||||
if (ctx->user.cmnd[0] != '/') {
|
if (ctx->user.cmnd[0] != '/') {
|
||||||
if (ctx->user.cmnd_dir == NULL)
|
if (ctx->user.cmnd_dir == NULL)
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
len = snprintf(buf, sizeof(buf), "%s/%s", ctx->user.cmnd_dir,
|
len = snprintf(buf, sizeof(buf), "%s/%s", ctx->user.cmnd_dir,
|
||||||
ctx->user.cmnd_base);
|
ctx->user.cmnd_base);
|
||||||
if (len < 0 || len >= ssizeof(buf))
|
if (len < 0 || len >= ssizeof(buf))
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
cmnd = buf;
|
cmnd = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if sudoers_cmnd regex matches cmnd AND
|
* Return ALLOW if sudoers_cmnd regex matches cmnd AND
|
||||||
* a) there are no args in sudoers OR
|
* a) there are no args in sudoers OR
|
||||||
* b) there are no args on command line and none required by 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
|
* c) there are args in sudoers and on command line and they match
|
||||||
* else return false.
|
* else return DENY.
|
||||||
*/
|
*/
|
||||||
if (!regex_matches(sudoers_cmnd, cmnd))
|
if (regex_matches(sudoers_cmnd, cmnd) != ALLOW)
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
|
|
||||||
if (command_args_match(ctx, sudoers_cmnd, sudoers_args)) {
|
if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
|
||||||
/* Open the file for fdexec or for digest matching. */
|
/* Open the file for fdexec or for digest matching. */
|
||||||
if (!open_cmnd(cmnd, digests, &fd))
|
if (!open_cmnd(cmnd, digests, &fd))
|
||||||
goto bad;
|
goto bad;
|
||||||
@@ -485,22 +491,21 @@ command_matches_regex(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
goto bad;
|
goto bad;
|
||||||
#endif
|
#endif
|
||||||
/* Check digest of cmnd since sudoers_cmnd is a pattern. */
|
/* Check digest of cmnd since sudoers_cmnd is a pattern. */
|
||||||
if (!digest_matches(fd, cmnd, digests))
|
if (digest_matches(fd, cmnd, digests) != ALLOW)
|
||||||
goto bad;
|
goto bad;
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
|
|
||||||
/* No need to set ctx->runas.cmnd since cmnd matches sudoers_cmnd */
|
/* No need to set ctx->runas.cmnd since cmnd matches sudoers_cmnd */
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
}
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SUDOERS_NAME_MATCH
|
#ifndef SUDOERS_NAME_MATCH
|
||||||
static bool
|
static int
|
||||||
command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, int rootfd, bool intercepted,
|
const char *sudoers_args, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -522,19 +527,19 @@ command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
if (sudoers_cmnd[dlen - 1] != '/') {
|
if (sudoers_cmnd[dlen - 1] != '/') {
|
||||||
base = sudo_basename(sudoers_cmnd);
|
base = sudo_basename(sudoers_cmnd);
|
||||||
if (!has_meta(base) && strcmp(ctx->user.cmnd_base, base) != 0)
|
if (!has_meta(base) && strcmp(ctx->user.cmnd_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
|
* a) there are no args in sudoers OR
|
||||||
* b) there are no args on command line and none required by 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
|
* 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) {
|
if (glob(sudoers_cmnd, GLOB_NOSORT, NULL, &gl) != 0 || gl.gl_pathc == 0) {
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If ctx->user.cmnd is fully-qualified, check for an exact match. */
|
/* If ctx->user.cmnd is fully-qualified, check for an exact match. */
|
||||||
@@ -558,7 +563,7 @@ command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
(ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
|
(ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
|
||||||
ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
|
ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
|
||||||
/* There could be multiple matches, check digest early. */
|
/* There could be multiple matches, check digest early. */
|
||||||
if (!digest_matches(fd, cp, digests)) {
|
if (digest_matches(fd, cp, digests) != ALLOW) {
|
||||||
bad_digest = true;
|
bad_digest = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -587,9 +592,9 @@ command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
dlen = strlen(cp);
|
dlen = strlen(cp);
|
||||||
if (cp[dlen - 1] == '/') {
|
if (cp[dlen - 1] == '/') {
|
||||||
if (command_matches_dir(ctx, cp, dlen, rootfd, intercepted,
|
if (command_matches_dir(ctx, cp, dlen, rootfd, intercepted,
|
||||||
digests)) {
|
digests) == ALLOW) {
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -627,7 +632,7 @@ command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
if (ctx->user.cmnd_stat == NULL ||
|
if (ctx->user.cmnd_stat == NULL ||
|
||||||
(ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
|
(ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
|
||||||
ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
|
ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
|
||||||
if (!digest_matches(fd, cp, digests))
|
if (digest_matches(fd, cp, digests) != ALLOW)
|
||||||
continue;
|
continue;
|
||||||
free(ctx->runas.cmnd);
|
free(ctx->runas.cmnd);
|
||||||
if ((ctx->runas.cmnd = strdup(cp)) == NULL) {
|
if ((ctx->runas.cmnd = strdup(cp)) == NULL) {
|
||||||
@@ -642,18 +647,18 @@ command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
done:
|
done:
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
if (cp != NULL) {
|
if (cp != NULL) {
|
||||||
if (command_args_match(ctx, sudoers_cmnd, sudoers_args)) {
|
if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
|
||||||
/* ctx->runas.cmnd was set above. */
|
/* ctx->runas.cmnd was set above. */
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, int rootfd, bool intercepted,
|
const char *sudoers_args, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -667,14 +672,14 @@ command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
/* If it ends in '/' it is a directory spec. */
|
/* If it ends in '/' it is a directory spec. */
|
||||||
dlen = strlen(sudoers_cmnd);
|
dlen = strlen(sudoers_cmnd);
|
||||||
if (sudoers_cmnd[dlen - 1] == '/') {
|
if (sudoers_cmnd[dlen - 1] == '/') {
|
||||||
debug_return_bool(command_matches_dir(ctx, sudoers_cmnd, dlen, rootfd,
|
debug_return_int(command_matches_dir(ctx, sudoers_cmnd, dlen, rootfd,
|
||||||
intercepted, digests));
|
intercepted, digests));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only proceed if ctx->user.cmnd_base and basename(sudoers_cmnd) match */
|
/* Only proceed if ctx->user.cmnd_base and basename(sudoers_cmnd) match */
|
||||||
base = sudo_basename(sudoers_cmnd);
|
base = sudo_basename(sudoers_cmnd);
|
||||||
if (strcmp(ctx->user.cmnd_base, base) != 0)
|
if (strcmp(ctx->user.cmnd_base, base) != 0)
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
|
|
||||||
/* Compare the canonicalized parent directories, if possible. */
|
/* Compare the canonicalized parent directories, if possible. */
|
||||||
if (ctx->user.cmnd_dir != NULL) {
|
if (ctx->user.cmnd_dir != NULL) {
|
||||||
@@ -720,9 +725,9 @@ command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
if (strcmp(ctx->user.cmnd, sudoers_cmnd) != 0)
|
if (strcmp(ctx->user.cmnd, sudoers_cmnd) != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (!command_args_match(ctx, sudoers_cmnd, sudoers_args))
|
if (command_args_match(ctx, sudoers_cmnd, sudoers_args) != ALLOW)
|
||||||
goto bad;
|
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 */
|
/* XXX - log functions not available but we should log very loudly */
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -732,14 +737,14 @@ command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
#else /* SUDOERS_NAME_MATCH */
|
#else /* SUDOERS_NAME_MATCH */
|
||||||
static bool
|
static int
|
||||||
command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, int rootfd, bool intercepted,
|
const char *sudoers_args, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -748,7 +753,7 @@ command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
intercepted, digests);
|
intercepted, digests);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static int
|
||||||
command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, int rootfd, bool intercepted,
|
const char *sudoers_args, int rootfd, bool intercepted,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -760,16 +765,16 @@ command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
/* If it ends in '/' it is a directory spec. */
|
/* If it ends in '/' it is a directory spec. */
|
||||||
dlen = strlen(sudoers_cmnd);
|
dlen = strlen(sudoers_cmnd);
|
||||||
if (sudoers_cmnd[dlen - 1] == '/') {
|
if (sudoers_cmnd[dlen - 1] == '/') {
|
||||||
debug_return_bool(command_matches_dir(ctx, sudoers_cmnd, dlen, rootfd,
|
debug_return_int(command_matches_dir(ctx, sudoers_cmnd, dlen, rootfd,
|
||||||
intercepted, digests));
|
intercepted, digests));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(ctx->user.cmnd, sudoers_cmnd) == 0) {
|
if (strcmp(ctx->user.cmnd, sudoers_cmnd) == 0) {
|
||||||
if (command_args_match(ctx, sudoers_cmnd, sudoers_args)) {
|
if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
|
||||||
/* Open the file for fdexec or for digest matching. */
|
/* Open the file for fdexec or for digest matching. */
|
||||||
if (!open_cmnd(ctx->user.cmnd, digests, &fd))
|
if (!open_cmnd(ctx->user.cmnd, digests, &fd))
|
||||||
goto bad;
|
goto bad;
|
||||||
if (!digest_matches(fd, ctx->user.cmnd, digests))
|
if (digest_matches(fd, ctx->user.cmnd, digests) != ALLOW)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
/* Successful match. */
|
/* Successful match. */
|
||||||
@@ -780,21 +785,22 @@ command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
set_cmnd_fd(ctx, fd, rootfd);
|
set_cmnd_fd(ctx, fd, rootfd);
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
debug_return_bool(false);
|
debug_return_int(DENY);
|
||||||
}
|
}
|
||||||
#endif /* SUDOERS_NAME_MATCH */
|
#endif /* SUDOERS_NAME_MATCH */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If path doesn't end in /, return true iff cmnd & path name the same inode;
|
* If path doesn't end in /, return ALLOW iff cmnd & path name the same inode;
|
||||||
* otherwise, return true if ctx->user.cmnd names one of the inodes in path.
|
* otherwise, return ALLOW if ctx->user.cmnd names one of the inodes in path.
|
||||||
|
* Returns DENY on failure.
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
||||||
const char *sudoers_args, const char *runchroot, struct cmnd_info *info,
|
const char *sudoers_args, const char *runchroot, struct cmnd_info *info,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
@@ -804,7 +810,7 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
char *saved_user_cmnd = NULL;
|
char *saved_user_cmnd = NULL;
|
||||||
struct stat saved_user_stat;
|
struct stat saved_user_stat;
|
||||||
bool reset_cmnd = false;
|
bool reset_cmnd = false;
|
||||||
bool rc = false;
|
int ret = DENY;
|
||||||
debug_decl(command_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(command_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
if (ctx->runas.chroot != NULL) {
|
if (ctx->runas.chroot != NULL) {
|
||||||
@@ -850,13 +856,13 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
|
|
||||||
if (sudoers_cmnd == NULL) {
|
if (sudoers_cmnd == NULL) {
|
||||||
sudoers_cmnd = "ALL";
|
sudoers_cmnd = "ALL";
|
||||||
rc = command_matches_all(ctx, pivot_fds[0], intercepted, digests);
|
ret = command_matches_all(ctx, pivot_fds[0], intercepted, digests);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for regular expressions first. */
|
/* Check for regular expressions first. */
|
||||||
if (sudoers_cmnd[0] == '^') {
|
if (sudoers_cmnd[0] == '^') {
|
||||||
rc = command_matches_regex(ctx, sudoers_cmnd, sudoers_args,
|
ret = command_matches_regex(ctx, sudoers_cmnd, sudoers_args,
|
||||||
pivot_fds[0], intercepted, digests);
|
pivot_fds[0], intercepted, digests);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -872,9 +878,9 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
if (strcmp(sudoers_cmnd, "list") == 0 ||
|
if (strcmp(sudoers_cmnd, "list") == 0 ||
|
||||||
strcmp(sudoers_cmnd, "sudoedit") == 0) {
|
strcmp(sudoers_cmnd, "sudoedit") == 0) {
|
||||||
if (strcmp(ctx->user.cmnd, sudoers_cmnd) == 0 &&
|
if (strcmp(ctx->user.cmnd, sudoers_cmnd) == 0 &&
|
||||||
command_args_match(ctx, sudoers_cmnd, sudoers_args)) {
|
command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
|
||||||
/* No need to set ctx->user.cmnd since cmnd == sudoers_cmnd */
|
/* No need to set ctx->user.cmnd since cmnd == sudoers_cmnd */
|
||||||
rc = true;
|
ret = ALLOW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
@@ -886,14 +892,14 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
|
|||||||
* use glob(3) and/or fnmatch(3) to do the matching.
|
* use glob(3) and/or fnmatch(3) to do the matching.
|
||||||
*/
|
*/
|
||||||
if (def_fast_glob) {
|
if (def_fast_glob) {
|
||||||
rc = command_matches_fnmatch(ctx, sudoers_cmnd, sudoers_args,
|
ret = command_matches_fnmatch(ctx, sudoers_cmnd, sudoers_args,
|
||||||
pivot_fds[0], intercepted, digests);
|
pivot_fds[0], intercepted, digests);
|
||||||
} else {
|
} else {
|
||||||
rc = command_matches_glob(ctx, sudoers_cmnd, sudoers_args,
|
ret = command_matches_glob(ctx, sudoers_cmnd, sudoers_args,
|
||||||
pivot_fds[0], intercepted, digests);
|
pivot_fds[0], intercepted, digests);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = command_matches_normal(ctx, sudoers_cmnd, sudoers_args,
|
ret = command_matches_normal(ctx, sudoers_cmnd, sudoers_args,
|
||||||
pivot_fds[0], intercepted, digests);
|
pivot_fds[0], intercepted, digests);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
@@ -921,6 +927,6 @@ done:
|
|||||||
ctx->user.cmnd_args ? ctx->user.cmnd_args : "", sudoers_cmnd,
|
ctx->user.cmnd_args ? ctx->user.cmnd_args : "", sudoers_cmnd,
|
||||||
sudoers_args ? " " : "", sudoers_args ? sudoers_args : "",
|
sudoers_args ? " " : "", sudoers_args ? sudoers_args : "",
|
||||||
runchroot ? ", chroot " : "", runchroot ? runchroot : "",
|
runchroot ? ", chroot " : "", runchroot ? runchroot : "",
|
||||||
rc ? "true" : "false");
|
ret == ALLOW ? "ALLOW" : "DENY");
|
||||||
debug_return_bool(rc);
|
debug_return_int(ret);
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,7 @@
|
|||||||
#include "sudo_digest.h"
|
#include "sudo_digest.h"
|
||||||
#include <gram.h>
|
#include <gram.h>
|
||||||
|
|
||||||
bool
|
int
|
||||||
digest_matches(int fd, const char *path,
|
digest_matches(int fd, const char *path,
|
||||||
const struct command_digest_list *digests)
|
const struct command_digest_list *digests)
|
||||||
{
|
{
|
||||||
@@ -47,12 +47,12 @@ digest_matches(int fd, const char *path,
|
|||||||
unsigned char *sudoers_digest = NULL;
|
unsigned char *sudoers_digest = NULL;
|
||||||
struct command_digest *digest;
|
struct command_digest *digest;
|
||||||
size_t digest_len = (size_t)-1;
|
size_t digest_len = (size_t)-1;
|
||||||
bool matched = false;
|
int matched = DENY;
|
||||||
debug_decl(digest_matches, SUDOERS_DEBUG_MATCH);
|
debug_decl(digest_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
if (TAILQ_EMPTY(digests)) {
|
if (TAILQ_EMPTY(digests)) {
|
||||||
/* No digest, no problem. */
|
/* No digest, no problem. */
|
||||||
debug_return_bool(true);
|
debug_return_int(ALLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@@ -104,7 +104,7 @@ digest_matches(int fd, const char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memcmp(file_digest, sudoers_digest, digest_len) == 0) {
|
if (memcmp(file_digest, sudoers_digest, digest_len) == 0) {
|
||||||
matched = true;
|
matched = ALLOW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,5 +122,5 @@ bad_format:
|
|||||||
done:
|
done:
|
||||||
free(sudoers_digest);
|
free(sudoers_digest);
|
||||||
free(file_digest);
|
free(file_digest);
|
||||||
debug_return_bool(matched);
|
debug_return_int(matched);
|
||||||
}
|
}
|
||||||
|
@@ -425,22 +425,22 @@ bool sudoers_error_recovery(void);
|
|||||||
bool sudoers_strict(void);
|
bool sudoers_strict(void);
|
||||||
|
|
||||||
/* match_addr.c */
|
/* match_addr.c */
|
||||||
bool addr_matches(char *n);
|
int addr_matches(char *n);
|
||||||
|
|
||||||
/* match_command.c */
|
/* match_command.c */
|
||||||
bool command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests);
|
int command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests);
|
||||||
|
|
||||||
/* match_digest.c */
|
/* match_digest.c */
|
||||||
bool digest_matches(int fd, const char *path, const struct command_digest_list *digests);
|
int digest_matches(int fd, const char *path, const struct command_digest_list *digests);
|
||||||
|
|
||||||
/* match.c */
|
/* match.c */
|
||||||
struct group;
|
struct group;
|
||||||
struct passwd;
|
struct passwd;
|
||||||
bool group_matches(const char *sudoers_group, const struct group *gr);
|
int group_matches(const char *sudoers_group, const struct group *gr);
|
||||||
bool hostname_matches(const char *shost, const char *lhost, const char *pattern);
|
int hostname_matches(const char *shost, const char *lhost, const char *pattern);
|
||||||
bool netgr_matches(const struct sudo_nss *nss, const char *netgr, const char *lhost, const char *shost, const char *user);
|
int netgr_matches(const struct sudo_nss *nss, 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);
|
int 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 userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
|
||||||
int cmnd_matches(const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
|
int cmnd_matches(const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
|
||||||
int cmnd_matches_all(const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
|
int cmnd_matches_all(const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
|
||||||
int cmndlist_matches(const struct sudoers_parse_tree *parse_tree, const struct member_list *list, const char *runchroot, struct cmnd_info *info);
|
int cmndlist_matches(const struct sudoers_parse_tree *parse_tree, const struct member_list *list, const char *runchroot, struct cmnd_info *info);
|
||||||
|
@@ -57,7 +57,7 @@ check_addr(char *input)
|
|||||||
sudo_fatalx("expecting 0 or 1, got %s", cp);
|
sudo_fatalx("expecting 0 or 1, got %s", cp);
|
||||||
input[len] = '\0';
|
input[len] = '\0';
|
||||||
|
|
||||||
matched = addr_matches(input);
|
matched = addr_matches(input) == ALLOW;
|
||||||
if (matched != expected) {
|
if (matched != expected) {
|
||||||
sudo_warnx("%s %smatched: FAIL", input, matched ? "" : "not ");
|
sudo_warnx("%s %smatched: FAIL", input, matched ? "" : "not ");
|
||||||
return 1;
|
return 1;
|
||||||
|
@@ -205,20 +205,20 @@ sudo_sss_check_user(struct sudoers_context *ctx, struct sudo_sss_handle *handle,
|
|||||||
case '+':
|
case '+':
|
||||||
/* Netgroup spec found, check membership. */
|
/* Netgroup spec found, check membership. */
|
||||||
if (netgr_matches(NULL, val, def_netgroup_tuple ? host : NULL,
|
if (netgr_matches(NULL, 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;
|
ret = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
/* User group found, check membership. */
|
/* 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;
|
ret = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Not a netgroup or user group. */
|
/* Not a netgroup or user group. */
|
||||||
if (strcmp(val, "ALL") == 0 ||
|
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;
|
ret = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user