]> granicus.if.org Git - sudo/commitdiff
Make sudoers file long list output better match the format used by
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 20 Feb 2013 20:09:21 +0000 (15:09 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 20 Feb 2013 20:09:21 +0000 (15:09 -0500)
ldap sudoers.  Tags are now converted to options and there is a
single command per line.

plugins/sudoers/parse.c

index d0ab7a2c85d15954755d116929e17b0773941dd7..40479c58deed3a8be4d63db512b8abdd9da81274 100644 (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);
 }