#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 = {
/*
* 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)
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
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;
}
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);
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, ") ");
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)
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);
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++;
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
*/
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;
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;
}
}
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);
}