Make sudoers file long list output better match the format used by

ldap sudoers.  Tags are now converted to options and there is a
single command per line.
This commit is contained in:
Todd C. Miller
2013-02-20 15:09:21 -05:00
parent 05e53aea0f
commit fa924d09bc

View File

@@ -47,7 +47,7 @@
#include <gram.h> #include <gram.h>
/* Characters that must be quoted in sudoers */ /* Characters that must be quoted in sudoers */
#define SUDOERS_QUOTED ":\\,=#\"" #define SUDOERS_QUOTED ":\\,=#\""
/* sudoers nsswitch routines */ /* sudoers nsswitch routines */
struct sudo_nss sudo_nss_file = { struct sudo_nss sudo_nss_file = {
@@ -75,8 +75,10 @@ extern bool parse_error;
/* /*
* Local prototypes. * Local prototypes.
*/ */
static void print_member(struct lbuf *, char *, int, int, int); static int display_bound_defaults(int dtype, struct lbuf *lbuf);
static int display_bound_defaults(int, struct lbuf *); static void print_member(struct lbuf *lbuf, struct member *m, int alias_type);
static void print_member2(struct lbuf *lbuf, struct member *m,
const char *separator, int alias_type);
int int
sudo_file_open(struct sudo_nss *nss) sudo_file_open(struct sudo_nss *nss)
@@ -289,14 +291,16 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag)
debug_return_int(validated); debug_return_int(validated);
} }
#define TAG_SET(tt) \
((tt) != UNSPEC && (tt) != IMPLIED)
#define TAG_CHANGED(t) \ #define TAG_CHANGED(t) \
(cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t) (TAG_SET(cs->tags.t) && cs->tags.t != tags->t)
static void static void
sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
struct lbuf *lbuf) struct lbuf *lbuf)
{ {
struct member *m;
debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS) debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS)
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
@@ -331,9 +335,7 @@ sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: "); lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: ");
tags->log_output = cs->tags.log_output; tags->log_output = cs->tags.log_output;
} }
m = cs->cmnd; print_member(lbuf, cs->cmnd, CMNDALIAS);
print_member(lbuf, m->name, m->type, m->negated,
CMNDALIAS);
debug_return; debug_return;
} }
@@ -368,8 +370,7 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
tq_foreach_fwd(&cs->runasuserlist, m) { tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist)) if (m != tq_first(&cs->runasuserlist))
lbuf_append(lbuf, ", "); lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated, print_member(lbuf, m, RUNASALIAS);
RUNASALIAS);
} }
} else if (tq_empty(&cs->runasgrouplist)) { } else if (tq_empty(&cs->runasgrouplist)) {
lbuf_append(lbuf, "%s", def_runas_default); lbuf_append(lbuf, "%s", def_runas_default);
@@ -381,8 +382,7 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
tq_foreach_fwd(&cs->runasgrouplist, m) { tq_foreach_fwd(&cs->runasgrouplist, m) {
if (m != tq_first(&cs->runasgrouplist)) if (m != tq_first(&cs->runasgrouplist))
lbuf_append(lbuf, ", "); lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated, print_member(lbuf, m, RUNASALIAS);
RUNASALIAS);
} }
} }
lbuf_append(lbuf, ") "); lbuf_append(lbuf, ") ");
@@ -403,6 +403,40 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
debug_return_int(nfound); debug_return_int(nfound);
} }
#define TAGS_CHANGED(ot, nt) \
((TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \
(TAG_SET((nt).noexec) && (nt).noexec != (ot).noexec) || \
(TAG_SET((nt).nopasswd) && (nt).nopasswd != (ot).nopasswd) || \
(TAG_SET((nt).log_input) && (nt).log_input != (ot).log_input) || \
(TAG_SET((nt).log_output) && (nt).log_output != (ot).log_output))
/*
* Compare the current cmndspec with the previous one to determine
* whether we need to start a new long entry for "sudo -ll".
* Returns true if we should start a new long entry, else false.
*/
static bool
new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs)
{
if (prev_cs == NULL)
return true;
if (RUNAS_CHANGED(cs, prev_cs) || TAGS_CHANGED(cs->tags, prev_cs->tags))
return true;
#ifdef HAVE_PRIV_SET
if (cs->privs && (!prev_cs->privs || strcmp(cs->privs, prev_cs->privs) != 0)
return true;
if (cs->limitprivs && (!prev_cs->limitprivs || strcmp(cs->limitprivs, prev_cs->limitprivs) != 0)
return true;
#endif /* HAVE_PRIV_SET */
#ifdef HAVE_SELINUX
if (cs->role && (!prev_cs->role || strcmp(cs->role, prev_cs->role) != 0)
return true;
if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0)
return true;
#endif /* HAVE_SELINUX */
return false;
}
static int static int
sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
struct lbuf *lbuf) struct lbuf *lbuf)
@@ -410,23 +444,22 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
struct cmndspec *cs, *prev_cs; struct cmndspec *cs, *prev_cs;
struct member *m; struct member *m;
struct privilege *priv; struct privilege *priv;
struct cmndtag tags; int nfound = 0, olen;
int nfound = 0;
debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS) debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
tq_foreach_fwd(&us->privileges, priv) { tq_foreach_fwd(&us->privileges, priv) {
if (hostlist_matches(&priv->hostlist) != ALLOW) if (hostlist_matches(&priv->hostlist) != ALLOW)
continue; continue;
lbuf_append(lbuf, _("\nSudoers entry:\n")); prev_cs = NULL;
tq_foreach_fwd(&priv->cmndlist, cs) { tq_foreach_fwd(&priv->cmndlist, cs) {
if (RUNAS_CHANGED(cs, prev_cs)) { if (new_long_entry(cs, prev_cs)) {
lbuf_append(lbuf, _("\nSudoers entry:\n"));
lbuf_append(lbuf, _(" RunAsUsers: ")); lbuf_append(lbuf, _(" RunAsUsers: "));
if (!tq_empty(&cs->runasuserlist)) { if (!tq_empty(&cs->runasuserlist)) {
tq_foreach_fwd(&cs->runasuserlist, m) { tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist)) if (m != tq_first(&cs->runasuserlist))
lbuf_append(lbuf, ", "); lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated, print_member(lbuf, m, RUNASALIAS);
RUNASALIAS);
} }
} else if (tq_empty(&cs->runasgrouplist)) { } else if (tq_empty(&cs->runasgrouplist)) {
lbuf_append(lbuf, "%s", def_runas_default); lbuf_append(lbuf, "%s", def_runas_default);
@@ -439,20 +472,44 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
tq_foreach_fwd(&cs->runasgrouplist, m) { tq_foreach_fwd(&cs->runasgrouplist, m) {
if (m != tq_first(&cs->runasgrouplist)) if (m != tq_first(&cs->runasgrouplist))
lbuf_append(lbuf, ", "); lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated, print_member(lbuf, m, RUNASALIAS);
RUNASALIAS);
} }
lbuf_append(lbuf, "\n"); lbuf_append(lbuf, "\n");
} }
olen = lbuf->len;
lbuf_append(lbuf, _(" Options: "));
if (TAG_SET(cs->tags.setenv))
lbuf_append(lbuf, "%ssetenv, ", cs->tags.setenv ? "" : "!");
if (TAG_SET(cs->tags.noexec))
lbuf_append(lbuf, "%snoexec, ", cs->tags.noexec ? "" : "!");
if (TAG_SET(cs->tags.nopasswd))
lbuf_append(lbuf, "%sauthenticate, ", cs->tags.nopasswd ? "!" : "");
if (TAG_SET(cs->tags.log_input))
lbuf_append(lbuf, "%slog_input, ", cs->tags.log_input ? "" : "!");
if (TAG_SET(cs->tags.log_output))
lbuf_append(lbuf, "%slog_output, ", cs->tags.log_output ? "" : "!");
if (lbuf->buf[lbuf->len - 2] == ',') {
lbuf->len -= 2; /* remove trailing ", " */
lbuf_append(lbuf, "\n");
} else {
lbuf->len = olen; /* no options */
}
#ifdef HAVE_PRIV_SET
if (cs->privs)
lbuf_append(lbuf, " Privs: %s\n", cs->privs);
if (cs->limitprivs)
lbuf_append(lbuf, " Limitprivs: %s\n", cs->limitprivs);
#endif /* HAVE_PRIV_SET */
#ifdef HAVE_SELINUX
if (cs->role)
lbuf_append(lbuf, " Role: %s\n", cs->role);
if (cs->type)
lbuf_append(lbuf, " Type: %s\n", cs->type);
#endif /* HAVE_SELINUX */
lbuf_append(lbuf, _(" Commands:\n")); lbuf_append(lbuf, _(" Commands:\n"));
tags.noexec = UNSPEC;
tags.setenv = UNSPEC;
tags.nopasswd = UNSPEC;
tags.log_input = UNSPEC;
tags.log_output = UNSPEC;
} }
lbuf_append(lbuf, "\t"); lbuf_append(lbuf, "\t");
sudo_file_append_cmnd(cs, &tags, lbuf); print_member2(lbuf, cs->cmnd, "\n\t", CMNDALIAS);
lbuf_append(lbuf, "\n"); lbuf_append(lbuf, "\n");
prev_cs = cs; prev_cs = cs;
nfound++; nfound++;
@@ -600,7 +657,7 @@ display_bound_defaults(int dtype, struct lbuf *lbuf)
for (m = binding; m != NULL; m = m->next) { for (m = binding; m != NULL; m = m->next) {
if (m != binding) if (m != binding)
lbuf_append(lbuf, ","); lbuf_append(lbuf, ",");
print_member(lbuf, m->name, m->type, m->negated, atype); print_member(lbuf, m, atype);
lbuf_append(lbuf, " "); lbuf_append(lbuf, " ");
} }
} else } else
@@ -666,7 +723,7 @@ done:
*/ */
static void static void
_print_member(struct lbuf *lbuf, char *name, int type, int negated, _print_member(struct lbuf *lbuf, char *name, int type, int negated,
int alias_type) const char *separator, int alias_type)
{ {
struct alias *a; struct alias *a;
struct member *m; struct member *m;
@@ -694,9 +751,10 @@ _print_member(struct lbuf *lbuf, char *name, int type, int negated,
if ((a = alias_find(name, alias_type)) != NULL) { if ((a = alias_find(name, alias_type)) != NULL) {
tq_foreach_fwd(&a->members, m) { tq_foreach_fwd(&a->members, m) {
if (m != tq_first(&a->members)) if (m != tq_first(&a->members))
lbuf_append(lbuf, ", "); lbuf_append(lbuf, separator);
_print_member(lbuf, m->name, m->type, _print_member(lbuf, m->name, m->type,
negated ? !m->negated : m->negated, alias_type); negated ? !m->negated : m->negated, separator,
alias_type);
} }
break; break;
} }
@@ -709,9 +767,16 @@ _print_member(struct lbuf *lbuf, char *name, int type, int negated,
} }
static void static void
print_member(struct lbuf *lbuf, char *name, int type, int negated, print_member(struct lbuf *lbuf, struct member *m, int alias_type)
{
alias_seqno++;
_print_member(lbuf, m->name, m->type, m->negated, ", ", alias_type);
}
static void
print_member2(struct lbuf *lbuf, struct member *m, const char *separator,
int alias_type) int alias_type)
{ {
alias_seqno++; alias_seqno++;
_print_member(lbuf, name, type, negated, alias_type); _print_member(lbuf, m->name, m->type, m->negated, separator, alias_type);
} }