Add option to prune non-matching entries from cvtsudoers output with -m

option is used.
This commit is contained in:
Todd C. Miller
2018-04-04 09:51:05 -06:00
parent 5c1d9899e1
commit 7663ae7b27
7 changed files with 268 additions and 130 deletions

View File

@@ -4,7 +4,7 @@ NNAAMMEE
ccvvttssuuddooeerrss - convert between sudoers file formats ccvvttssuuddooeerrss - convert between sudoers file formats
SSYYNNOOPPSSIISS SSYYNNOOPPSSIISS
ccvvttssuuddooeerrss [--eehhMMVV] [--bb _d_n] [--cc _c_o_n_f___f_i_l_e] [--dd _d_e_f_t_y_p_e_s] ccvvttssuuddooeerrss [--eehhMMppVV] [--bb _d_n] [--cc _c_o_n_f___f_i_l_e] [--dd _d_e_f_t_y_p_e_s]
[--ff _o_u_t_p_u_t___f_o_r_m_a_t] [--ii _i_n_p_u_t___f_o_r_m_a_t] [--II _i_n_c_r_e_m_e_n_t] [--ff _o_u_t_p_u_t___f_o_r_m_a_t] [--ii _i_n_p_u_t___f_o_r_m_a_t] [--II _i_n_c_r_e_m_e_n_t]
[--mm _f_i_l_t_e_r] [--oo _o_u_t_p_u_t___f_i_l_e] [--OO _s_t_a_r_t___p_o_i_n_t] [--ss _s_e_c_t_i_o_n_s] [--mm _f_i_l_t_e_r] [--oo _o_u_t_p_u_t___f_i_l_e] [--OO _s_t_a_r_t___p_o_i_n_t] [--ss _s_e_c_t_i_o_n_s]
[_i_n_p_u_t___f_i_l_e] [_i_n_p_u_t___f_i_l_e]
@@ -147,6 +147,11 @@ DDEESSCCRRIIPPTTIIOONN
point of 0 will disable the generation of sudoOrder point of 0 will disable the generation of sudoOrder
attributes in the resulting LDIF file. attributes in the resulting LDIF file.
--pp, ----pprruunnee--mmaattcchheess
When the --mm option is also specified, ccvvttssuuddooeerrss will prune
out non-matching users, groups and hosts from matching
entries.
--ss _s_e_c_t_i_o_n_s, ----ssuupppprreessss=_s_e_c_t_i_o_n_s --ss _s_e_c_t_i_o_n_s, ----ssuupppprreessss=_s_e_c_t_i_o_n_s
Suppress the output of specific _s_e_c_t_i_o_n_s of the security Suppress the output of specific _s_e_c_t_i_o_n_s of the security
policy. One or more section names may be specified, policy. One or more section names may be specified,
@@ -182,6 +187,9 @@ DDEESSCCRRIIPPTTIIOONN
oouuttppuutt__ffoorrmmaatt == _j_s_o_n | _l_d_i_f | _s_u_d_o_e_r_s oouuttppuutt__ffoorrmmaatt == _j_s_o_n | _l_d_i_f | _s_u_d_o_e_r_s
See the description of the --ff command line option. See the description of the --ff command line option.
pprruunnee__mmaattcchheess == _y_e_s | _n_o
See the description of the --pp command line option.
ssuuddooeerrss__bbaassee == _d_n ssuuddooeerrss__bbaassee == _d_n
See the description of the --bb command line option. See the description of the --bb command line option.
@@ -223,4 +231,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or https://www.sudo.ws/license.html for file distributed with ssuuddoo or https://www.sudo.ws/license.html for
complete details. complete details.
Sudo 1.8.23 March 30, 2018 Sudo 1.8.23 Sudo 1.8.23 April 4, 2018 Sudo 1.8.23

View File

@@ -16,7 +16,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.TH "CVTSUDOERS" "1" "March 30, 2018" "Sudo @PACKAGE_VERSION@" "General Commands Manual" .TH "CVTSUDOERS" "1" "April 4, 2018" "Sudo @PACKAGE_VERSION@" "General Commands Manual"
.nh .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -25,7 +25,7 @@
.SH "SYNOPSIS" .SH "SYNOPSIS"
.HP 11n .HP 11n
\fBcvtsudoers\fR \fBcvtsudoers\fR
[\fB\-ehMV\fR] [\fB\-ehMpV\fR]
[\fB\-b\fR\ \fIdn\fR] [\fB\-b\fR\ \fIdn\fR]
[\fB\-c\fR\ \fIconf_file\fR] [\fB\-c\fR\ \fIconf_file\fR]
[\fB\-d\fR\ \fIdeftypes\fR] [\fB\-d\fR\ \fIdeftypes\fR]
@@ -277,6 +277,14 @@ Defaults to a starting point of 1.
A starting point of 0 will disable the generation of sudoOrder A starting point of 0 will disable the generation of sudoOrder
attributes in the resulting LDIF file. attributes in the resulting LDIF file.
.TP 12n .TP 12n
\fB\-p\fR, \fB\--prune-matches\fR
When the
\fB\-m\fR
option is also specified,
\fBcvtsudoers\fR
will prune out non-matching users, groups and hosts from
matching entries.
.TP 12n
\fB\-s\fR \fIsections\fR, \fB\--suppress\fR=\fIsections\fR \fB\-s\fR \fIsections\fR, \fB\--suppress\fR=\fIsections\fR
Suppress the output of specific Suppress the output of specific
\fIsections\fR \fIsections\fR
@@ -340,6 +348,11 @@ See the description of the
\fB\-f\fR \fB\-f\fR
command line option. command line option.
.TP 6n .TP 6n
\fBprune_matches =\fR \fIyes\fR | \fIno\fR
See the description of the
\fB\-p\fR
command line option.
.TP 6n
\fBsudoers_base =\fR \fIdn\fR \fBsudoers_base =\fR \fIdn\fR
See the description of the See the description of the
\fB\-b\fR \fB\-b\fR

View File

@@ -14,7 +14,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd March 30, 2018 .Dd April 4, 2018
.Dt CVTSUDOERS 1 .Dt CVTSUDOERS 1
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -22,7 +22,7 @@
.Nd convert between sudoers file formats .Nd convert between sudoers file formats
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm cvtsudoers .Nm cvtsudoers
.Op Fl ehMV .Op Fl ehMpV
.Op Fl b Ar dn .Op Fl b Ar dn
.Op Fl c Ar conf_file .Op Fl c Ar conf_file
.Op Fl d Ar deftypes .Op Fl d Ar deftypes
@@ -228,6 +228,13 @@ option for details.
Defaults to a starting point of 1. Defaults to a starting point of 1.
A starting point of 0 will disable the generation of sudoOrder A starting point of 0 will disable the generation of sudoOrder
attributes in the resulting LDIF file. attributes in the resulting LDIF file.
.It Fl p , Fl -prune-matches
When the
.Fl m
option is also specified,
.Nm
will prune out non-matching users, groups and hosts from
matching entries.
.It Fl s Ar sections , Fl -suppress Ns = Ns Ar sections .It Fl s Ar sections , Fl -suppress Ns = Ns Ar sections
Suppress the output of specific Suppress the output of specific
.Ar sections .Ar sections
@@ -284,6 +291,10 @@ command line option.
See the description of the See the description of the
.Fl f .Fl f
command line option. command line option.
.It Sy prune_matches = Ar yes | no
See the description of the
.Fl p
command line option.
.It Sy sudoers_base = Ar dn .It Sy sudoers_base = Ar dn
See the description of the See the description of the
.Fl b .Fl b

View File

@@ -56,7 +56,7 @@
struct cvtsudoers_filter *filters; struct cvtsudoers_filter *filters;
struct sudo_user sudo_user; struct sudo_user sudo_user;
struct passwd *list_pw; struct passwd *list_pw;
static const char short_opts[] = "b:c:d:ef:hi:I:m:Mo:O:s:V"; static const char short_opts[] = "b:c:d:ef:hi:I:m:Mo:O:ps:V";
static struct option long_opts[] = { static struct option long_opts[] = {
{ "base", required_argument, NULL, 'b' }, { "base", required_argument, NULL, 'b' },
{ "config", required_argument, NULL, 'c' }, { "config", required_argument, NULL, 'c' },
@@ -68,6 +68,7 @@ static struct option long_opts[] = {
{ "increment", required_argument, NULL, 'I' }, { "increment", required_argument, NULL, 'I' },
{ "match", required_argument, NULL, 'm' }, { "match", required_argument, NULL, 'm' },
{ "match-local", no_argument, NULL, 'M' }, { "match-local", no_argument, NULL, 'M' },
{ "prune-matches", no_argument, NULL, 'p' },
{ "order-start", required_argument, NULL, 'O' }, { "order-start", required_argument, NULL, 'O' },
{ "output", required_argument, NULL, 'o' }, { "output", required_argument, NULL, 'o' },
{ "suppress", required_argument, NULL, 's' }, { "suppress", required_argument, NULL, 's' },
@@ -85,7 +86,7 @@ static struct cvtsudoers_config *cvtsudoers_conf_read(const char *conf_file);
static void cvtsudoers_conf_free(struct cvtsudoers_config *conf); static void cvtsudoers_conf_free(struct cvtsudoers_config *conf);
static int cvtsudoers_parse_defaults(char *expression); static int cvtsudoers_parse_defaults(char *expression);
static int cvtsudoers_parse_suppression(char *expression); static int cvtsudoers_parse_suppression(char *expression);
static void filter_userspecs(void); static void filter_userspecs(struct cvtsudoers_config *conf);
static void filter_defaults(struct cvtsudoers_config *conf); static void filter_defaults(struct cvtsudoers_config *conf);
static void alias_remove_unused(void); static void alias_remove_unused(void);
@@ -207,6 +208,9 @@ main(int argc, char *argv[])
usage(1); usage(1);
} }
break; break;
case 'p':
conf->prune_matches = true;
break;
case 's': case 's':
conf->supstr = optarg; conf->supstr = optarg;
break; break;
@@ -317,7 +321,7 @@ main(int argc, char *argv[])
} }
/* Apply filters. */ /* Apply filters. */
filter_userspecs(); filter_userspecs(conf);
filter_defaults(conf); filter_defaults(conf);
if (filters != NULL || conf->defaults != CVT_DEFAULTS_ALL) if (filters != NULL || conf->defaults != CVT_DEFAULTS_ALL)
alias_remove_unused(); alias_remove_unused();
@@ -355,7 +359,8 @@ static struct cvtsudoers_conf_table cvtsudoers_conf_vars[] = {
{ "match", CONF_STR, &cvtsudoers_config.filter }, { "match", CONF_STR, &cvtsudoers_config.filter },
{ "defaults", CONF_STR, &cvtsudoers_config.defstr }, { "defaults", CONF_STR, &cvtsudoers_config.defstr },
{ "suppress", CONF_STR, &cvtsudoers_config.supstr }, { "suppress", CONF_STR, &cvtsudoers_config.supstr },
{ "expand_aliases", CONF_BOOL, &cvtsudoers_config.expand_aliases } { "expand_aliases", CONF_BOOL, &cvtsudoers_config.expand_aliases },
{ "prune_matches", CONF_BOOL, &cvtsudoers_config.prune_matches }
}; };
/* /*
@@ -669,86 +674,144 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
} }
static bool static bool
userlist_matches_filter(struct member_list *userlist) userlist_matches_filter(struct member_list *users, bool remove_nonmatching)
{ {
struct cvtsudoers_string *s; struct cvtsudoers_string *s;
bool matches = false; struct member *m, *next;
bool ret = false;
debug_decl(userlist_matches_filter, SUDOERS_DEBUG_UTIL) debug_decl(userlist_matches_filter, SUDOERS_DEBUG_UTIL)
if (filters == NULL || if (filters == NULL ||
(STAILQ_EMPTY(&filters->users) && STAILQ_EMPTY(&filters->groups))) (STAILQ_EMPTY(&filters->users) && STAILQ_EMPTY(&filters->groups)))
debug_return_bool(true); debug_return_bool(true);
if (STAILQ_EMPTY(&filters->users)) { TAILQ_FOREACH_REVERSE_SAFE(m, users, member_list, entries, next) {
struct passwd pw; bool matched = false;
/* if (STAILQ_EMPTY(&filters->users)) {
* Only groups in filter, make a dummy user so userlist_matches() struct passwd pw;
* can do its thing.
*/
memset(&pw, 0, sizeof(pw));
pw.pw_name = "_nobody";
pw.pw_uid = (uid_t)-1;
pw.pw_gid = (gid_t)-1;
if (userlist_matches(&pw, userlist) == true)
matches = true;
}
STAILQ_FOREACH(s, &filters->users, entries) { /*
struct passwd *pw = NULL; * Only groups in filter, make a dummy user so userlist_matches()
if (s->str[0] == '#') { * can do its thing.
const char *errstr; */
uid_t uid = sudo_strtoid(s->str + 1, NULL, NULL, &errstr); memset(&pw, 0, sizeof(pw));
if (errstr == NULL) pw.pw_name = "_nobody";
pw = sudo_getpwuid(uid); pw.pw_uid = (uid_t)-1;
pw.pw_gid = (gid_t)-1;
if (user_matches(&pw, m) == true) {
matched = true;
ret = true;
}
} else {
STAILQ_FOREACH(s, &filters->users, entries) {
struct passwd *pw = NULL;
if (s->str[0] == '#') {
const char *errstr;
uid_t uid = sudo_strtoid(s->str + 1, NULL, NULL, &errstr);
if (errstr == NULL)
pw = sudo_getpwuid(uid);
}
if (pw == NULL)
pw = sudo_getpwnam(s->str);
if (pw == NULL)
continue;
if (user_matches(pw, m) == true)
matched = true;
sudo_pw_delref(pw);
/* Only need one user in the filter to match. */
if (matched) {
ret = true;
break;
}
}
}
if (!matched && remove_nonmatching) {
TAILQ_REMOVE(users, m, entries);
free_member(m);
} }
if (pw == NULL)
pw = sudo_getpwnam(s->str);
if (pw == NULL)
continue;
if (userlist_matches(pw, userlist) == true)
matches = true;
sudo_pw_delref(pw);
if (matches)
break;
} }
debug_return_bool(matches); debug_return_bool(ret);
} }
static bool static bool
hostlist_matches_filter(struct member_list *hostlist) hostlist_matches_filter(struct member_list *hostlist, bool remove_nonmatching)
{ {
struct cvtsudoers_string *s; struct cvtsudoers_string *s;
bool matches = false; struct member *m, *next;
char *lhost, *shost;
bool ret = false;
char **shosts;
int n = 0;
debug_decl(hostlist_matches_filter, SUDOERS_DEBUG_UTIL) debug_decl(hostlist_matches_filter, SUDOERS_DEBUG_UTIL)
if (filters == NULL || STAILQ_EMPTY(&filters->hosts)) if (filters == NULL || STAILQ_EMPTY(&filters->hosts))
debug_return_bool(true); debug_return_bool(true);
/* Create an array of short host names. */
STAILQ_FOREACH(s, &filters->hosts, entries) { STAILQ_FOREACH(s, &filters->hosts, entries) {
user_runhost = s->str; n++;
if ((user_srunhost = strchr(user_runhost, '.')) != NULL) { }
user_srunhost = strndup(user_runhost, shosts = reallocarray(NULL, n, sizeof(char *));
(size_t)(user_srunhost - user_runhost)); if (shosts == NULL)
if (user_srunhost == NULL) { sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
n = 0;
STAILQ_FOREACH(s, &filters->hosts, entries) {
lhost = s->str;
if ((shost = strchr(lhost, '.')) != NULL) {
shost = strndup(lhost, (size_t)(shost - lhost));
if (shost == NULL) {
sudo_fatalx(U_("%s: %s"), __func__, sudo_fatalx(U_("%s: %s"), __func__,
U_("unable to allocate memory")); U_("unable to allocate memory"));
} }
} else { } else {
user_srunhost = user_runhost; shost = lhost;
} }
/* XXX - can't use netgroup_tuple with NULL pw */ shosts[n++] = shost;
if (hostlist_matches(NULL, hostlist) == true)
matches = true;
if (user_srunhost != user_runhost)
free(user_srunhost);
user_runhost = user_host;
user_srunhost = user_shost;
if (matches)
break;
} }
debug_return_bool(matches);
TAILQ_FOREACH_REVERSE_SAFE(m, hostlist, member_list, entries, next) {
bool matched = false;
n = 0;
STAILQ_FOREACH(s, &filters->hosts, entries) {
lhost = s->str;
shost = shosts[n++];
/* XXX - can't use netgroup_tuple with NULL pw */
if (host_matches(NULL, lhost, shost, m) == true)
matched = true;
/* Only need one host in the filter to match. */
if (matched) {
ret = true;
break;
}
}
/* Short-circuit unless removing non-matches. */
if (!matched && remove_nonmatching) {
TAILQ_REMOVE(hostlist, m, entries);
free_member(m);
}
}
/* Free shosts array and its contents. */
n = 0;
STAILQ_FOREACH(s, &filters->hosts, entries) {
lhost = s->str;
shost = shosts[n++];
if (shost != lhost)
free(shost);
}
free(shosts);
debug_return_bool(ret == true);
} }
/* /*
@@ -811,7 +874,7 @@ convert_sudoers_output(const char *buf)
* Apply filters to userspecs, removing non-matching entries. * Apply filters to userspecs, removing non-matching entries.
*/ */
static void static void
filter_userspecs(void) filter_userspecs(struct cvtsudoers_config *conf)
{ {
struct userspec *us, *next_us; struct userspec *us, *next_us;
struct privilege *priv, *next_priv; struct privilege *priv, *next_priv;
@@ -826,13 +889,13 @@ filter_userspecs(void)
* In the future, we may want to add a prune option. * In the future, we may want to add a prune option.
*/ */
TAILQ_FOREACH_SAFE(us, &userspecs, entries, next_us) { TAILQ_FOREACH_SAFE(us, &userspecs, entries, next_us) {
if (!userlist_matches_filter(&us->users)) { if (!userlist_matches_filter(&us->users, conf->prune_matches)) {
TAILQ_REMOVE(&userspecs, us, entries); TAILQ_REMOVE(&userspecs, us, entries);
free_userspec(us); free_userspec(us);
continue; continue;
} }
TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, next_priv) { TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, next_priv) {
if (!hostlist_matches_filter(&priv->hostlist)) { if (!hostlist_matches_filter(&priv->hostlist, conf->prune_matches)) {
TAILQ_REMOVE(&us->privileges, priv, entries); TAILQ_REMOVE(&us->privileges, priv, entries);
free_privilege(priv); free_privilege(priv);
} }
@@ -869,7 +932,7 @@ filter_defaults(struct cvtsudoers_config *conf)
break; break;
case DEFAULTS_USER: case DEFAULTS_USER:
if (!ISSET(conf->defaults, CVT_DEFAULTS_USER) || if (!ISSET(conf->defaults, CVT_DEFAULTS_USER) ||
!userlist_matches_filter(def->binding)) !userlist_matches_filter(def->binding, conf->prune_matches))
keep = false; keep = false;
break; break;
case DEFAULTS_RUNAS: case DEFAULTS_RUNAS:
@@ -878,7 +941,7 @@ filter_defaults(struct cvtsudoers_config *conf)
break; break;
case DEFAULTS_HOST: case DEFAULTS_HOST:
if (!ISSET(conf->defaults, CVT_DEFAULTS_HOST) || if (!ISSET(conf->defaults, CVT_DEFAULTS_HOST) ||
!hostlist_matches_filter(def->binding)) !hostlist_matches_filter(def->binding, conf->prune_matches))
keep = false; keep = false;
break; break;
case DEFAULTS_CMND: case DEFAULTS_CMND:
@@ -998,7 +1061,7 @@ done:
static void static void
usage(int fatal) usage(int fatal)
{ {
(void) fprintf(fatal ? stderr : stdout, "usage: %s [-ehMV] [-b dn] " (void) fprintf(fatal ? stderr : stdout, "usage: %s [-ehMpV] [-b dn] "
"[-c conf_file ] [-d deftypes] [-f output_format] [-i input_format] " "[-c conf_file ] [-d deftypes] [-f output_format] [-i input_format] "
"[-I increment] [-m filter] [-o output_file] [-O start_point] " "[-I increment] [-m filter] [-o output_file] [-O start_point] "
"[-s sections] [input_file]\n", getprogname()); "[-s sections] [input_file]\n", getprogname());
@@ -1023,6 +1086,7 @@ help(void)
" -M, --match-local match filter uses passwd and group databases\n" " -M, --match-local match filter uses passwd and group databases\n"
" -o, --output=output_file write converted sudoers to output_file\n" " -o, --output=output_file write converted sudoers to output_file\n"
" -O, --order-start=num starting point for first sudoOrder\n" " -O, --order-start=num starting point for first sudoOrder\n"
" -p, --prune-matches prune non-matching users, groups and hosts\n"
" -s, --suppress=sections suppress output of certain sections\n" " -s, --suppress=sections suppress output of certain sections\n"
" -V, --version display version information and exit")); " -V, --version display version information and exit"));
exit(0); exit(0);

View File

@@ -58,6 +58,7 @@ struct cvtsudoers_config {
short suppress; short suppress;
bool expand_aliases; bool expand_aliases;
bool store_options; bool store_options;
bool prune_matches;
char *sudoers_base; char *sudoers_base;
char *input_format; char *input_format;
char *output_format; char *output_format;
@@ -67,7 +68,7 @@ struct cvtsudoers_config {
}; };
/* Initial config settings for above. */ /* Initial config settings for above. */
#define INITIAL_CONFIG { 1, 1, CVT_DEFAULTS_ALL, 0, false, true } #define INITIAL_CONFIG { 1, 1, CVT_DEFAULTS_ALL, 0, false, true, false }
#define CONF_BOOL 0 #define CONF_BOOL 0
#define CONF_UINT 1 #define CONF_UINT 1

View File

@@ -89,6 +89,48 @@ static bool digest_matches(int fd, const char *file, const struct sudo_digest *s
*/ */
#define has_meta(s) (strpbrk(s, "\\?*[]") != NULL) #define has_meta(s) (strpbrk(s, "\\?*[]") != NULL)
/*
* Check whether user described by pw matches member.
* Returns ALLOW, DENY or UNSPEC.
*/
int
user_matches(const struct passwd *pw, const struct member *m)
{
struct alias *a;
int matched = UNSPEC;
debug_decl(user_matches, SUDOERS_DEBUG_MATCH)
switch (m->type) {
case ALL:
matched = !m->negated;
break;
case NETGROUP:
if (netgr_matches(m->name,
def_netgroup_tuple ? user_runhost : NULL,
def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name))
matched = !m->negated;
break;
case USERGROUP:
if (usergr_matches(m->name, pw->pw_name, pw))
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, USERALIAS)) != NULL) {
int rc = userlist_matches(pw, &a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (userpw_matches(m->name, pw->pw_name, pw))
matched = !m->negated;
break;
}
debug_return_int(matched);
}
/* /*
* Check for user described by pw in a list of members. * Check for user described by pw in a list of members.
* Returns ALLOW, DENY or UNSPEC. * Returns ALLOW, DENY or UNSPEC.
@@ -97,40 +139,11 @@ int
userlist_matches(const struct passwd *pw, const struct member_list *list) userlist_matches(const struct passwd *pw, const struct member_list *list)
{ {
struct member *m; struct member *m;
struct alias *a; int matched = UNSPEC;
int rc, matched = UNSPEC;
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH) debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH)
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
switch (m->type) { if ((matched = user_matches(pw, m)) != UNSPEC)
case ALL:
matched = !m->negated;
break;
case NETGROUP:
if (netgr_matches(m->name,
def_netgroup_tuple ? user_runhost : NULL,
def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name))
matched = !m->negated;
break;
case USERGROUP:
if (usergr_matches(m->name, pw->pw_name, pw))
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, USERALIAS)) != NULL) {
rc = userlist_matches(pw, &a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (userpw_matches(m->name, pw->pw_name, pw))
matched = !m->negated;
break;
}
if (matched != UNSPEC)
break; break;
} }
debug_return_int(matched); debug_return_int(matched);
@@ -256,46 +269,72 @@ runaslist_matches(const struct member_list *user_list,
} }
/* /*
* Check for host and shost in a list of members. * Check for lhost and shost in a list of members.
* Returns ALLOW, DENY or UNSPEC.
*/
static int
hostlist_matches_int(const struct passwd *pw, const char *lhost,
const char *shost, const struct member_list *list)
{
struct member *m;
int matched = UNSPEC;
debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH)
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
matched = host_matches(pw, lhost, shost, m);
if (matched != UNSPEC)
break;
}
debug_return_int(matched);
}
/*
* Check for user_runhost and user_srunhost in a list of members.
* Returns ALLOW, DENY or UNSPEC. * Returns ALLOW, DENY or UNSPEC.
*/ */
int int
hostlist_matches(const struct passwd *pw, const struct member_list *list) hostlist_matches(const struct passwd *pw, const struct member_list *list)
{ {
struct member *m; return hostlist_matches_int(pw, user_runhost, user_srunhost, list);
struct alias *a; }
int rc, matched = UNSPEC;
debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH)
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { /*
switch (m->type) { * Check whether host or shost matches member.
case ALL: * Returns ALLOW, DENY or UNSPEC.
*/
int
host_matches(const struct passwd *pw, const char *lhost, const char *shost,
const struct member *m)
{
struct alias *a;
int matched = UNSPEC;
debug_decl(host_matches, SUDOERS_DEBUG_MATCH)
switch (m->type) {
case ALL:
matched = !m->negated;
break;
case NETGROUP:
if (netgr_matches(m->name, lhost, shost,
def_netgroup_tuple ? pw->pw_name : NULL))
matched = !m->negated; matched = !m->negated;
break;
case NTWKADDR:
if (addr_matches(m->name))
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, HOSTALIAS)) != NULL) {
int rc = hostlist_matches_int(pw, lhost, shost, &a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);
break; break;
case NETGROUP: }
if (netgr_matches(m->name, user_runhost, user_srunhost, /* FALLTHROUGH */
def_netgroup_tuple ? pw->pw_name : NULL)) case WORD:
matched = !m->negated; if (hostname_matches(shost, lhost, m->name))
break; matched = !m->negated;
case NTWKADDR:
if (addr_matches(m->name))
matched = !m->negated;
break;
case ALIAS:
if ((a = alias_get(m->name, HOSTALIAS)) != NULL) {
rc = hostlist_matches(pw, &a->members);
if (rc != UNSPEC)
matched = m->negated ? !rc : rc;
alias_put(a);
break;
}
/* FALLTHROUGH */
case WORD:
if (hostname_matches(user_srunhost, user_runhost, m->name))
matched = !m->negated;
break;
}
if (matched != UNSPEC)
break; break;
} }
debug_return_int(matched); debug_return_int(matched);

View File

@@ -286,8 +286,10 @@ 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); bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
int cmnd_matches(const struct member *m); int cmnd_matches(const struct member *m);
int cmndlist_matches(const struct member_list *list); int cmndlist_matches(const struct member_list *list);
int host_matches(const struct passwd *pw, const char *host, const char *shost, const struct member *m);
int hostlist_matches(const struct passwd *pw, const struct member_list *list); int hostlist_matches(const struct passwd *pw, const struct member_list *list);
int runaslist_matches(const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group); int runaslist_matches(const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group);
int user_matches(const struct passwd *pw, const struct member *m);
int userlist_matches(const struct passwd *pw, const struct member_list *list); int userlist_matches(const struct passwd *pw, const struct member_list *list);
const char *sudo_getdomainname(void); const char *sudo_getdomainname(void);