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:
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user