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>
/* Characters that must be quoted in sudoers */
#define SUDOERS_QUOTED ":\\,=#\""
#define SUDOERS_QUOTED ":\\,=#\""
/* sudoers nsswitch routines */
struct sudo_nss sudo_nss_file = {
@@ -75,8 +75,10 @@ extern bool parse_error;
/*
* Local prototypes.
*/
static void print_member(struct lbuf *, char *, int, int, int);
static int display_bound_defaults(int, struct lbuf *);
static int display_bound_defaults(int dtype, struct lbuf *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
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);
}
#define TAG_SET(tt) \
((tt) != UNSPEC && (tt) != IMPLIED)
#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
sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
struct lbuf *lbuf)
{
struct member *m;
debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS)
#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: ");
tags->log_output = cs->tags.log_output;
}
m = cs->cmnd;
print_member(lbuf, m->name, m->type, m->negated,
CMNDALIAS);
print_member(lbuf, cs->cmnd, CMNDALIAS);
debug_return;
}
@@ -368,8 +370,7 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated,
RUNASALIAS);
print_member(lbuf, m, RUNASALIAS);
}
} else if (tq_empty(&cs->runasgrouplist)) {
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) {
if (m != tq_first(&cs->runasgrouplist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated,
RUNASALIAS);
print_member(lbuf, m, RUNASALIAS);
}
}
lbuf_append(lbuf, ") ");
@@ -403,6 +403,40 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
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
sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
struct lbuf *lbuf)
@@ -410,23 +444,22 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
struct cmndspec *cs, *prev_cs;
struct member *m;
struct privilege *priv;
struct cmndtag tags;
int nfound = 0;
int nfound = 0, olen;
debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
tq_foreach_fwd(&us->privileges, priv) {
if (hostlist_matches(&priv->hostlist) != ALLOW)
continue;
lbuf_append(lbuf, _("\nSudoers entry:\n"));
prev_cs = NULL;
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: "));
if (!tq_empty(&cs->runasuserlist)) {
tq_foreach_fwd(&cs->runasuserlist, m) {
if (m != tq_first(&cs->runasuserlist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated,
RUNASALIAS);
print_member(lbuf, m, RUNASALIAS);
}
} else if (tq_empty(&cs->runasgrouplist)) {
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) {
if (m != tq_first(&cs->runasgrouplist))
lbuf_append(lbuf, ", ");
print_member(lbuf, m->name, m->type, m->negated,
RUNASALIAS);
print_member(lbuf, m, RUNASALIAS);
}
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"));
tags.noexec = UNSPEC;
tags.setenv = UNSPEC;
tags.nopasswd = UNSPEC;
tags.log_input = UNSPEC;
tags.log_output = UNSPEC;
}
lbuf_append(lbuf, "\t");
sudo_file_append_cmnd(cs, &tags, lbuf);
print_member2(lbuf, cs->cmnd, "\n\t", CMNDALIAS);
lbuf_append(lbuf, "\n");
prev_cs = cs;
nfound++;
@@ -600,7 +657,7 @@ display_bound_defaults(int dtype, struct lbuf *lbuf)
for (m = binding; m != NULL; m = m->next) {
if (m != binding)
lbuf_append(lbuf, ",");
print_member(lbuf, m->name, m->type, m->negated, atype);
print_member(lbuf, m, atype);
lbuf_append(lbuf, " ");
}
} else
@@ -666,7 +723,7 @@ done:
*/
static void
_print_member(struct lbuf *lbuf, char *name, int type, int negated,
int alias_type)
const char *separator, int alias_type)
{
struct alias *a;
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) {
tq_foreach_fwd(&a->members, m) {
if (m != tq_first(&a->members))
lbuf_append(lbuf, ", ");
lbuf_append(lbuf, separator);
_print_member(lbuf, m->name, m->type,
negated ? !m->negated : m->negated, alias_type);
negated ? !m->negated : m->negated, separator,
alias_type);
}
break;
}
@@ -709,9 +767,16 @@ _print_member(struct lbuf *lbuf, char *name, int type, int negated,
}
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)
{
alias_seqno++;
_print_member(lbuf, name, type, negated, alias_type);
_print_member(lbuf, m->name, m->type, m->negated, separator, alias_type);
}