]> granicus.if.org Git - sudo/commitdiff
Add long list (sudo -ll) support for printing verbose LDAP and sudoers
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 8 Feb 2008 13:18:12 +0000 (13:18 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 8 Feb 2008 13:18:12 +0000 (13:18 +0000)
file entries.  Still need to update manual.

lbuf.c
ldap.c
parse.c
sudo.c
sudo.h
sudo_nss.c

diff --git a/lbuf.c b/lbuf.c
index 71d3ce3e770d8de5f8b73d69d905ab4af3605d5c..ab50522855669751ae403c67418b232f3186c545 100644 (file)
--- a/lbuf.c
+++ b/lbuf.c
@@ -73,6 +73,10 @@ get_ttycols()
     return(cols);
 }
 
+/*
+ * TODO: add support for embedded newlines in lbufs
+ */
+
 void
 lbuf_init(lbuf, buf, indent, continuation)
     struct lbuf *lbuf;
diff --git a/ldap.c b/ldap.c
index 38c67157309fbaab337469faeb8a3ee6562dd303..49018717221318cc4bf2cc202c39e239fc5f8f6f 100644 (file)
--- a/ldap.c
+++ b/ldap.c
@@ -1155,6 +1155,168 @@ sudo_ldap_display_bound_defaults(nss, pw, lbuf)
     return(1);
 }
 
+/*
+ * Print a record in the short form, ala file sudoers.
+ */
+int
+sudo_ldap_display_entry_short(ld, entry, lbuf)
+    LDAP *ld;
+    LDAPMessage *entry;
+    struct lbuf *lbuf;
+{
+    struct berval **bv, **p;
+    int count = 0;
+
+    lbuf_append(lbuf, "    (", NULL);
+
+    /* get the RunAsUser Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
+    if (bv == NULL)
+       bv = ldap_get_values_len(ld, entry, "sudoRunAs");
+    if (bv != NULL) {
+       for (p = bv; *p != NULL; p++) {
+           if (p != bv)
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, (*p)->bv_val, NULL);
+       }
+       ldap_value_free_len(bv);
+    } else
+       lbuf_append(lbuf, def_runas_default, NULL);
+
+    /* get the RunAsGroup Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
+    if (bv != NULL) {
+       lbuf_append(lbuf, " : ", NULL);
+       for (p = bv; *p != NULL; p++) {
+           if (p != bv)
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, (*p)->bv_val, NULL);
+       }
+       ldap_value_free_len(bv);
+    }
+    lbuf_append(lbuf, ") ", NULL);
+
+    /* get the Option Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoOption");
+    if (bv != NULL) {
+       char *cp, *tag;
+
+       for (p = bv; *p != NULL; p++) {
+           cp = (*p)->bv_val;
+           if (*cp == '!')
+               cp++;
+           tag = NULL;
+           if (strcmp(cp, "authenticate") == 0)
+               tag = (*p)->bv_val[0] == '!' ?
+                   "NOPASSWD: " : "PASSWD: ";
+           else if (strcmp(cp, "noexec") == 0)
+               tag = (*p)->bv_val[0] == '!' ?
+                   "EXEC: " : "NOEXEC: ";
+           else if (strcmp(cp, "setenv") == 0)
+               tag = (*p)->bv_val[0] == '!' ?
+                   "NOSETENV: " : "SETENV: ";
+           if (tag != NULL)
+               lbuf_append(lbuf, tag, NULL);
+           /* XXX - ignores other options */
+       }
+       ldap_value_free_len(bv);
+    }
+
+    /* get the Command Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoCommand");
+    if (bv != NULL) {
+       for (p = bv; *p != NULL; p++) {
+           if (p != bv)
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, (*p)->bv_val, NULL);
+           count++;
+       }
+       ldap_value_free_len(bv);
+    }
+
+    lbuf_print(lbuf);          /* forces a newline */
+    return(count);
+}
+
+/*
+ * Print a record in the long form.
+ */
+int
+sudo_ldap_display_entry_long(ld, entry, lbuf)
+    LDAP *ld;
+    LDAPMessage *entry;
+    struct lbuf *lbuf;
+{
+    struct berval **bv, **p;
+    char *rdn;
+    int count = 0;
+
+    /* extract the dn, only show the first rdn */
+    rdn = sudo_ldap_get_first_rdn(ld, entry);
+    lbuf_print(lbuf);  /* force a newline */
+    lbuf_append(lbuf, "LDAP Role: ", rdn ? rdn : "UNKNOWN", NULL);
+    lbuf_print(lbuf);
+    if (rdn)
+       ldap_memfree(rdn);
+
+    /* get the RunAsUser Values from the entry */
+    lbuf_append(lbuf, "    RunAsUsers: ", NULL);
+    bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
+    if (bv == NULL)
+       bv = ldap_get_values_len(ld, entry, "sudoRunAs");
+    if (bv != NULL) {
+       for (p = bv; *p != NULL; p++) {
+           if (p != bv)
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, (*p)->bv_val, NULL);
+       }
+       ldap_value_free_len(bv);
+    } else
+       lbuf_append(lbuf, def_runas_default, NULL);
+    lbuf_print(lbuf);
+
+    /* get the RunAsGroup Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
+    if (bv != NULL) {
+       lbuf_append(lbuf, "    RunAsGroups: ", NULL);
+       for (p = bv; *p != NULL; p++) {
+           if (p != bv)
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, (*p)->bv_val, NULL);
+       }
+       ldap_value_free_len(bv);
+       lbuf_print(lbuf);
+    }
+
+    /* get the Option Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoOption");
+    if (bv != NULL) {
+       lbuf_append(lbuf, "    Options: ", NULL);
+       for (p = bv; *p != NULL; p++) {
+           if (p != bv)
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, (*p)->bv_val, NULL);
+       }
+       ldap_value_free_len(bv);
+       lbuf_print(lbuf);
+    }
+
+    /* get the Command Values from the entry */
+    bv = ldap_get_values_len(ld, entry, "sudoCommand");
+    if (bv != NULL) {
+       lbuf_append(lbuf, "    Commands:", NULL);
+       lbuf_print(lbuf);
+       for (p = bv; *p != NULL; p++) {
+           lbuf_append(lbuf, "\t", (*p)->bv_val, NULL);
+           lbuf_print(lbuf);
+           count++;
+       }
+       ldap_value_free_len(bv);
+    }
+
+    return(count);
+}
+
 /*
  * Like sudo_ldap_lookup(), except we just print entries.
  */
@@ -1164,10 +1326,9 @@ sudo_ldap_display_privs(nss, pw, lbuf)
     struct passwd *pw;
     struct lbuf *lbuf;
 {
-    struct berval **bv, **p;
     LDAP *ld = (LDAP *) nss->handle;
     LDAPMessage *entry = NULL, *result = NULL;
-    char *filt, *rdn;
+    char *filt;
     int rc, do_netgr, count = 0;
 
     if (ld == NULL)
@@ -1202,82 +1363,11 @@ sudo_ldap_display_privs(nss, pw, lbuf)
                sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
                sudo_ldap_check_host(ld, entry)) {
 
-#if 0
-               /* extract the dn, only show the first rdn */
-               /* XXX - how to display the role sudo-style? */
-               rdn = sudo_ldap_get_first_rdn(ld, entry);
-               printf("LDAP Role: %s\n", rdn ? rdn : "UNKNOWN");
-               if (rdn)
-                   ldap_memfree(rdn);
-#endif
-               lbuf_append(lbuf, "    (", NULL);
-
-               /* get the RunAsUser Values from the entry */
-               bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
-               if (bv == NULL)
-                   bv = ldap_get_values_len(ld, entry, "sudoRunAs");
-               if (bv != NULL) {
-                   for (p = bv; *p != NULL; p++) {
-                       if (p != bv)
-                           lbuf_append(lbuf, ", ", NULL);
-                       lbuf_append(lbuf, (*p)->bv_val, NULL);
-                   }
-                   ldap_value_free_len(bv);
-               } else
-                   lbuf_append(lbuf, def_runas_default, NULL);
-
-               /* get the RunAsGroup Values from the entry */
-               bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
-               if (bv != NULL) {
-                   lbuf_append(lbuf, " : ", NULL);
-                   for (p = bv; *p != NULL; p++) {
-                       if (p != bv)
-                           lbuf_append(lbuf, ", ", NULL);
-                       lbuf_append(lbuf, (*p)->bv_val, NULL);
-                   }
-                   ldap_value_free_len(bv);
-               }
-               lbuf_append(lbuf, ") ", NULL);
-
-               /* get the Option Values from the entry */
-               bv = ldap_get_values_len(ld, entry, "sudoOption");
-               if (bv != NULL) {
-                   char *cp, *tag;
-
-                   for (p = bv; *p != NULL; p++) {
-                       cp = (*p)->bv_val;
-                       if (*cp == '!')
-                           cp++;
-                       tag = NULL;
-                       if (strcmp(cp, "authenticate") == 0)
-                           tag = (*p)->bv_val[0] == '!' ?
-                               "NOPASSWD: " : "PASSWD: ";
-                       else if (strcmp(cp, "noexec") == 0)
-                           tag = (*p)->bv_val[0] == '!' ?
-                               "EXEC: " : "NOEXEC: ";
-                       else if (strcmp(cp, "setenv") == 0)
-                           tag = (*p)->bv_val[0] == '!' ?
-                               "NOSETENV: " : "SETENV: ";
-                       if (tag != NULL)
-                           lbuf_append(lbuf, tag, NULL);
-                       /* XXX - ignores other options */
-                   }
-                   ldap_value_free_len(bv);
-               }
-
-               /* get the Command Values from the entry */
-               bv = ldap_get_values_len(ld, entry, "sudoCommand");
-               if (bv != NULL) {
-                   for (p = bv; *p != NULL; p++) {
-                       if (p != bv)
-                           lbuf_append(lbuf, ", ", NULL);
-                       lbuf_append(lbuf, (*p)->bv_val, NULL);
-                       count++;
-                   }
-                   ldap_value_free_len(bv);
-               }
+               if (long_list)
+                   count += sudo_ldap_display_entry_long(ld, entry, lbuf);
+               else
+                   count += sudo_ldap_display_entry_short(ld, entry, lbuf);
            }
-           lbuf_print(lbuf);           /* forces a newline */
        }
        ldap_msgfree(result);
        result = NULL;
diff --git a/parse.c b/parse.c
index 779fa1220b51a7e32ceed442f39cfaea936d0bf3..2a0aaa46873f75b1c08659265b87241c7e3e8bf6 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -301,21 +301,147 @@ sudo_file_lookup(nss, validated, pwflag)
 }
 
 #define        TAG_CHANGED(t) \
-       (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags.t)
+       (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t)
 
-int
-sudo_file_display_privs(nss, pw, lbuf)
-    struct sudo_nss *nss;
+static void
+sudo_file_append_cmnd(cs, tags, lbuf)
+    struct cmndspec *cs;
+    struct cmndtag *tags;
+    struct lbuf *lbuf;
+{
+    struct member *m;
+
+    if (TAG_CHANGED(setenv)) {
+       lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " :
+           "NOSETENV: ", NULL);
+       tags->setenv = cs->tags.setenv;
+    }
+    if (TAG_CHANGED(noexec)) {
+       lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " :
+           "EXEC: ", NULL);
+       tags->noexec = cs->tags.noexec;
+    }
+    if (TAG_CHANGED(nopasswd)) {
+       lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " :
+           "PASSWD: ", NULL);
+       tags->nopasswd = cs->tags.nopasswd;
+    }
+    m = cs->cmnd;
+    print_member(lbuf, m->name, m->type, m->negated,
+       CMNDALIAS);
+}
+
+static int
+sudo_file_display_priv_short(pw, us, lbuf)
     struct passwd *pw;
+    struct userspec *us;
     struct lbuf *lbuf;
 {
     struct cmndspec *cs;
     struct member *m;
     struct privilege *priv;
+    struct cmndtag tags;
+    int nfound = 0;
+
+    tq_foreach_fwd(&us->privileges, priv) {
+       tags.noexec = def_noexec;
+       tags.setenv = def_setenv;
+       tags.nopasswd = !def_authenticate;
+       lbuf_append(lbuf, "    ", NULL);
+       tq_foreach_fwd(&priv->cmndlist, cs) {
+           if (cs != tq_first(&priv->cmndlist))
+               lbuf_append(lbuf, ", ", NULL);
+           lbuf_append(lbuf, "(", NULL);
+           if (!tq_empty(&cs->runasuserlist)) {
+               tq_foreach_fwd(&cs->runasuserlist, m) {
+                   if (m != tq_first(&cs->runasuserlist))
+                       lbuf_append(lbuf, ", ", NULL);
+                   print_member(lbuf, m->name, m->type, m->negated,
+                       RUNASALIAS);
+               }
+           } else {
+               lbuf_append(lbuf, def_runas_default, NULL);
+           }
+           if (!tq_empty(&cs->runasgrouplist)) {
+               lbuf_append(lbuf, " : ", NULL);
+               tq_foreach_fwd(&cs->runasgrouplist, m) {
+                   if (m != tq_first(&cs->runasgrouplist))
+                       lbuf_append(lbuf, ", ", NULL);
+                   print_member(lbuf, m->name, m->type, m->negated,
+                       RUNASALIAS);
+               }
+           }
+           lbuf_append(lbuf, ") ", NULL);
+           sudo_file_append_cmnd(cs, &tags, lbuf);
+           nfound++;
+       }
+       lbuf_print(lbuf);               /* forces a newline */
+    }
+    return(nfound);
+}
+
+static int
+sudo_file_display_priv_long(pw, us, lbuf)
+    struct passwd *pw;
     struct userspec *us;
+    struct lbuf *lbuf;
+{
+    struct cmndspec *cs;
+    struct member *m;
+    struct privilege *priv;
     struct cmndtag tags;
     int nfound = 0;
 
+    tq_foreach_fwd(&us->privileges, priv) {
+       tags.noexec = def_noexec;
+       tags.setenv = def_setenv;
+       tags.nopasswd = !def_authenticate;
+       lbuf_print(lbuf);       /* force a newline */
+       lbuf_append(lbuf, "Sudoers entry:", NULL);
+       lbuf_print(lbuf);
+       tq_foreach_fwd(&priv->cmndlist, cs) {
+           lbuf_append(lbuf, "    RunAsUsers: ", NULL);
+           if (!tq_empty(&cs->runasuserlist)) {
+               tq_foreach_fwd(&cs->runasuserlist, m) {
+                   if (m != tq_first(&cs->runasuserlist))
+                       lbuf_append(lbuf, ", ", NULL);
+                   print_member(lbuf, m->name, m->type, m->negated,
+                       RUNASALIAS);
+               }
+           } else {
+               lbuf_append(lbuf, def_runas_default, NULL);
+           }
+           lbuf_print(lbuf);
+           if (!tq_empty(&cs->runasgrouplist)) {
+               lbuf_append(lbuf, "    RunAsGroups: ", NULL);
+               tq_foreach_fwd(&cs->runasgrouplist, m) {
+                   if (m != tq_first(&cs->runasgrouplist))
+                       lbuf_append(lbuf, ", ", NULL);
+                   print_member(lbuf, m->name, m->type, m->negated,
+                       RUNASALIAS);
+               }
+               lbuf_print(lbuf);
+           }
+           lbuf_append(lbuf, "    Commands: ", NULL);
+           lbuf_print(lbuf);
+           lbuf_append(lbuf, "\t", NULL);
+           sudo_file_append_cmnd(cs, &tags, lbuf);
+           lbuf_print(lbuf);
+           nfound++;
+       }
+    }
+    return(nfound);
+}
+
+int
+sudo_file_display_privs(nss, pw, lbuf)
+    struct sudo_nss *nss;
+    struct passwd *pw;
+    struct lbuf *lbuf;
+{
+    struct userspec *us;
+    int nfound = 0;
+
     if (nss->handle == NULL)
        return(-1);
 
@@ -325,57 +451,10 @@ sudo_file_display_privs(nss, pw, lbuf)
            hostlist_matches(&us->privileges.first->hostlist) != ALLOW)
            continue;
 
-       tq_foreach_fwd(&us->privileges, priv) {
-           tags.noexec = def_noexec;
-           tags.setenv = def_setenv;
-           tags.nopasswd = !def_authenticate;
-           lbuf_append(lbuf, "    ", NULL);
-           tq_foreach_fwd(&priv->cmndlist, cs) {
-               if (cs != tq_first(&priv->cmndlist))
-                   lbuf_append(lbuf, ", ", NULL);
-               lbuf_append(lbuf, "(", NULL);
-               if (!tq_empty(&cs->runasuserlist)) {
-                   tq_foreach_fwd(&cs->runasuserlist, m) {
-                       if (m != tq_first(&cs->runasuserlist))
-                           lbuf_append(lbuf, ", ", NULL);
-                       print_member(lbuf, m->name, m->type, m->negated,
-                           RUNASALIAS);
-                   }
-               } else {
-                   lbuf_append(lbuf, def_runas_default, NULL);
-               }
-               if (!tq_empty(&cs->runasgrouplist)) {
-                   lbuf_append(lbuf, " : ", NULL);
-                   tq_foreach_fwd(&cs->runasgrouplist, m) {
-                       if (m != tq_first(&cs->runasgrouplist))
-                           lbuf_append(lbuf, ", ", NULL);
-                       print_member(lbuf, m->name, m->type, m->negated,
-                           RUNASALIAS);
-                   }
-               }
-               lbuf_append(lbuf, ") ", NULL);
-               if (TAG_CHANGED(setenv)) {
-                   lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " :
-                       "NOSETENV: ", NULL);
-                   tags.setenv = cs->tags.setenv;
-               }
-               if (TAG_CHANGED(noexec)) {
-                   lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " :
-                       "EXEC: ", NULL);
-                   tags.noexec = cs->tags.noexec;
-               }
-               if (TAG_CHANGED(nopasswd)) {
-                   lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " :
-                       "PASSWD: ", NULL);
-                   tags.nopasswd = cs->tags.nopasswd;
-               }
-               m = cs->cmnd;
-               print_member(lbuf, m->name, m->type, m->negated,
-                   CMNDALIAS);
-               nfound++;
-           }
-           lbuf_print(lbuf);           /* forces a newline */
-       }
+       if (long_list)
+           nfound += sudo_file_display_priv_long(pw, us, lbuf);
+       else
+           nfound += sudo_file_display_priv_short(pw, us, lbuf);
     }
     return(nfound);
 }
diff --git a/sudo.c b/sudo.c
index 3e45c02cb3e055365e613b4e5cae3b1e483d27e1..7bd154cb5049c5e77fba17b17e162091d1b0fbdd 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -135,6 +135,7 @@ struct passwd *auth_pw, *list_pw;
 struct interface *interfaces;
 int num_interfaces;
 int tgetpass_flags;
+int long_list;
 uid_t timestamp_uid;
 extern int errorlineno;
 extern int parse_error;
@@ -793,7 +794,8 @@ parse_args(argc, argv)
 
     while (NewArgc > 0) {
        if (NewArgv[0][0] == '-') {
-           if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') {
+           if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0' &&
+               NewArgv[0][2] != 'l') {
                warningx("please use single character options");
                usage(1);
            }
@@ -910,6 +912,8 @@ parse_args(argc, argv)
                    if (excl && excl != 'l')
                        usage_excl(1);
                    excl = 'l';
+                   if (NewArgv[0][2] == 'l')
+                       long_list = 1;
                    break;
                case 'V':
                    rval = MODE_VERSION;
diff --git a/sudo.h b/sudo.h
index c8c6c0793ffeb9fb40de9c26fa3be5f660165203..ba844364608e4e9b865ae981bfbebc75db87d3d9 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -307,6 +307,7 @@ extern struct sudo_user sudo_user;
 extern struct passwd *auth_pw, *list_pw;
 
 extern int tgetpass_flags;
+extern int long_list;
 extern uid_t timestamp_uid;
 #endif
 #ifndef errno
index 318f6d040ff4eb90b0ae32167679176d87c935f6..62705a5246fdbbf3427f298699cd9ec35af6ebea 100644 (file)
@@ -150,6 +150,7 @@ reset_groups(pw)
 
 /*
  * Print out privileges for the specified user.
+ * We only get here if the user is allowed to run something on this host.
  */
 void
 display_privs(snl, pw)
@@ -170,7 +171,6 @@ display_privs(snl, pw)
     tq_foreach_fwd(snl, nss)
        count += nss->display_defaults(nss, pw, &lbuf);
     if (count) {
-       /* XXX - defer printing until we find a command the user can run? */
        printf("Matching Defaults entries for %s on this host:\n", pw->pw_name);
        lbuf_print(&lbuf);
        putchar('\n');
@@ -186,14 +186,13 @@ display_privs(snl, pw)
        putchar('\n');
     }
 
+    /* Display privileges from all sources. */
     printf("User %s may run the following commands on this host:\n",
        pw->pw_name);
-    /* Display privileges from all sources. */
-    count = 0;
     tq_foreach_fwd(snl, nss)
-       count += nss->display_privs(nss, pw, &lbuf);
-    if (count)
-       lbuf_print(&lbuf);
+       (void) nss->display_privs(nss, pw, &lbuf);
+    if (lbuf.len != 0)
+       lbuf_print(&lbuf);              /* print remainder, if any */
     lbuf_destroy(&lbuf);
 }