]> granicus.if.org Git - sudo/commitdiff
Unify the -l output for file and ldap based sudoers and use lbufs for both.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 3 Feb 2008 15:43:38 +0000 (15:43 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 3 Feb 2008 15:43:38 +0000 (15:43 +0000)
The ldap output does not currently include options that cannot be represented
as tags.  This will be remedied in a long list output mode to come.

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

diff --git a/ldap.c b/ldap.c
index 9e7a1c56a07a33195c4893c64bc9ba1e2340b17f..38c67157309fbaab337469faeb8a3ee6562dd303 100644 (file)
--- a/ldap.c
+++ b/ldap.c
@@ -79,6 +79,7 @@
 
 #include "sudo.h"
 #include "parse.h"
+#include "lbuf.h"
 
 #ifndef lint
 __unused static const char rcsid[] = "$Sudo$";
@@ -236,8 +237,10 @@ struct sudo_nss sudo_nss_ldap = {
     sudo_ldap_parse,
     sudo_ldap_setdefs,
     sudo_ldap_lookup,
-    sudo_ldap_display_privs,
-    sudo_ldap_display_cmnd
+    sudo_ldap_display_cmnd,
+    sudo_ldap_display_defaults,
+    sudo_ldap_display_bound_defaults,
+    sudo_ldap_display_privs
 };
 
 #ifdef HAVE_LDAP_CREATE
@@ -1101,44 +1104,74 @@ sudo_ldap_get_first_rdn(ld, entry)
 }
 
 /*
- * Like sudo_ldap_lookup(), except we just print entries.
+ * Fetch and display the global Options.
  */
-void
-sudo_ldap_display_privs(nss, pw)
+int
+sudo_ldap_display_defaults(nss, pw, lbuf)
     struct sudo_nss *nss;
     struct passwd *pw;
+    struct lbuf *lbuf;
 {
     struct berval **bv, **p;
     LDAP *ld = (LDAP *) nss->handle;
     LDAPMessage *entry = NULL, *result = NULL;
-    char *filt, *rdn;
-    int rc, do_netgr;
+    char *prefix = NULL;
+    int rc, count = 0;
 
     if (ld == NULL)
-       return;
+       return(-1);
 
-    /*
-     * First, get (and display) the global Options.
-     */
     rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
        "cn=defaults", NULL, 0, NULL, NULL, NULL, -1, &result);
     if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
        bv = ldap_get_values_len(ld, entry, "sudoOption");
        if (bv != NULL) {
-           fputs("Global LDAP options:\n  ", stdout);
+           if (lbuf->len == 0)
+               prefix = "    ";
+           else
+               prefix = ", ";
            for (p = bv; *p != NULL; p++) {
-               if (p != bv)
-                   fputs("\n  ", stdout);
-               fputs((*p)->bv_val, stdout);
+               lbuf_append(lbuf, prefix, (*p)->bv_val, NULL);
+               prefix = ", ";
+               count++;
            }
-           putchar('\n');
            ldap_value_free_len(bv);
        }
     }
-    if (result) {
+    if (result)
        ldap_msgfree(result);
-       result = NULL;
-    }
+    return(count);
+}
+
+/*
+ * STUB
+ */
+int
+sudo_ldap_display_bound_defaults(nss, pw, lbuf)
+    struct sudo_nss *nss;
+    struct passwd *pw;
+    struct lbuf *lbuf;
+{
+    return(1);
+}
+
+/*
+ * Like sudo_ldap_lookup(), except we just print entries.
+ */
+int
+sudo_ldap_display_privs(nss, pw, lbuf)
+    struct sudo_nss *nss;
+    struct passwd *pw;
+    struct lbuf *lbuf;
+{
+    struct berval **bv, **p;
+    LDAP *ld = (LDAP *) nss->handle;
+    LDAPMessage *entry = NULL, *result = NULL;
+    char *filt, *rdn;
+    int rc, do_netgr, count = 0;
+
+    if (ld == NULL)
+       return(-1);
 
     /*
      * Okay - time to search for anything that matches this user
@@ -1169,72 +1202,87 @@ sudo_ldap_display_privs(nss, pw)
                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("\nLDAP Role: %s\n", rdn ? rdn : "UNKNOWN");
+               printf("LDAP Role: %s\n", rdn ? rdn : "UNKNOWN");
                if (rdn)
                    ldap_memfree(rdn);
-
-               /* get the Option Values from the entry */
-               bv = ldap_get_values_len(ld, entry, "sudoOption");
-               if (bv != NULL) {
-                   fputs("  Options:\n    ", stdout);
-                   for (p = bv; *p != NULL; p++) {
-                       if (p != bv)
-                           fputs("\n    ", stdout);
-                       fputs((*p)->bv_val, stdout);
-                   }
-                   putchar('\n');
-                   ldap_value_free_len(bv);
-               }
+#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) {
-                   fputs("  RunAsUsers: ", stdout);
                    for (p = bv; *p != NULL; p++) {
                        if (p != bv)
-                           fputs(", ", stdout);
-                       fputs((*p)->bv_val, stdout);
+                           lbuf_append(lbuf, ", ", NULL);
+                       lbuf_append(lbuf, (*p)->bv_val, NULL);
                    }
-                   putchar('\n');
                    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) {
-                   fputs("  RunAsGroups: ", stdout);
+                   lbuf_append(lbuf, " : ", NULL);
                    for (p = bv; *p != NULL; p++) {
                        if (p != bv)
-                           fputs(", ", stdout);
-                       fputs((*p)->bv_val, stdout);
+                           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 */
                    }
-                   putchar('\n');
                    ldap_value_free_len(bv);
                }
 
                /* get the Command Values from the entry */
                bv = ldap_get_values_len(ld, entry, "sudoCommand");
                if (bv != NULL) {
-                   fputs("  Commands:\n    ", stdout);
                    for (p = bv; *p != NULL; p++) {
                        if (p != bv)
-                           fputs("\n    ", stdout);
-                       fputs((*p)->bv_val, stdout);
+                           lbuf_append(lbuf, ", ", NULL);
+                       lbuf_append(lbuf, (*p)->bv_val, NULL);
+                       count++;
                    }
-                   putchar('\n');
                    ldap_value_free_len(bv);
-               } else {
-                   puts("  Commands: NONE");
                }
            }
+           lbuf_print(lbuf);           /* forces a newline */
        }
        ldap_msgfree(result);
        result = NULL;
     }
+    return(count);
 }
 
 int
diff --git a/parse.c b/parse.c
index 5a50773f16f334118e2f4b94a641586975c6a812..779fa1220b51a7e32ceed442f39cfaea936d0bf3 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -64,8 +64,10 @@ struct sudo_nss sudo_nss_file = {
     sudo_file_parse,
     sudo_file_setdefs,
     sudo_file_lookup,
-    sudo_file_display_privs,
-    sudo_file_display_cmnd
+    sudo_file_display_cmnd,
+    sudo_file_display_defaults,
+    sudo_file_display_bound_defaults,
+    sudo_file_display_privs
 };
 
 /*
@@ -79,8 +81,7 @@ extern int errorlineno, parse_error;
  * Local prototypes.
  */
 static void print_member       __P((struct lbuf *, char *, int, int, int));
-static void display_defaults   __P((struct passwd *));
-static void display_bound_defaults __P((int));
+static int display_bound_defaults __P((int, struct lbuf *));
 
 int
 sudo_file_open(nss)
@@ -302,23 +303,21 @@ sudo_file_lookup(nss, validated, pwflag)
 #define        TAG_CHANGED(t) \
        (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags.t)
 
-void
-sudo_file_display_privs(nss, pw)
+int
+sudo_file_display_privs(nss, pw, lbuf)
     struct sudo_nss *nss;
     struct passwd *pw;
+    struct lbuf *lbuf;
 {
-    struct lbuf lbuf;
     struct cmndspec *cs;
     struct member *m;
     struct privilege *priv;
     struct userspec *us;
     struct cmndtag tags;
+    int nfound = 0;
 
-    display_defaults(pw);
-
-    lbuf_init(&lbuf, NULL, 8, '\\');
-    printf("User %s may run the following commands on this host:\n",
-       pw->pw_name);
+    if (nss->handle == NULL)
+       return(-1);
 
     tq_foreach_fwd(&userspecs, us) {
        /* XXX - why only check the first privilege here? */
@@ -330,69 +329,77 @@ sudo_file_display_privs(nss, pw)
            tags.noexec = def_noexec;
            tags.setenv = def_setenv;
            tags.nopasswd = !def_authenticate;
-           lbuf_append(&lbuf, "    ", NULL);
+           lbuf_append(lbuf, "    ", NULL);
            tq_foreach_fwd(&priv->cmndlist, cs) {
                if (cs != tq_first(&priv->cmndlist))
-                   lbuf_append(&lbuf, ", ", NULL);
-               lbuf_append(&lbuf, "(", NULL);
+                   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,
+                           lbuf_append(lbuf, ", ", NULL);
+                       print_member(lbuf, m->name, m->type, m->negated,
                            RUNASALIAS);
                    }
                } else {
-                   lbuf_append(&lbuf, def_runas_default, NULL);
+                   lbuf_append(lbuf, def_runas_default, NULL);
                }
                if (!tq_empty(&cs->runasgrouplist)) {
-                   lbuf_append(&lbuf, " : ", NULL);
+                   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,
+                           lbuf_append(lbuf, ", ", NULL);
+                       print_member(lbuf, m->name, m->type, m->negated,
                            RUNASALIAS);
                    }
                }
-               lbuf_append(&lbuf, ") ", NULL);
+               lbuf_append(lbuf, ") ", NULL);
                if (TAG_CHANGED(setenv)) {
-                   lbuf_append(&lbuf, cs->tags.setenv ? "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: " :
+                   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: " :
+                   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,
+               print_member(lbuf, m->name, m->type, m->negated,
                    CMNDALIAS);
+               nfound++;
            }
-           lbuf_print(&lbuf);
+           lbuf_print(lbuf);           /* forces a newline */
        }
     }
-    lbuf_destroy(&lbuf);
+    return(nfound);
 }
 
 /*
  * Display matching Defaults entries for the given user on this host.
  */
-static void
-display_defaults(pw)
+int
+sudo_file_display_defaults(nss, pw, lbuf)
+    struct sudo_nss *nss;
     struct passwd *pw;
+    struct lbuf *lbuf;
 {
     struct defaults *d;
-    struct lbuf lbuf;
     char *prefix = NULL;
-    int per_runas = 0, per_cmnd = 0;
+    int nfound = 0;
+
+    if (nss->handle == NULL)
+       return(-1);
 
-    lbuf_init(&lbuf, NULL, 4, 0);
+    if (lbuf->len == 0)
+       prefix = "    ";
+    else
+       prefix = ", ";
 
     tq_foreach_fwd(&defaults, d) {
        switch (d->type) {
@@ -405,55 +412,58 @@ display_defaults(pw)
                    continue;
                break;
            case DEFAULTS_RUNAS:
-               per_runas = 1;
-               continue;
            case DEFAULTS_CMND:
-               per_cmnd = 1;
                continue;
        }
-       if (prefix == NULL) {
-           printf("Matching Defaults entries for %s on this host:\n",
-               pw->pw_name);
-           prefix = "    ";
-       }
-       lbuf_append(&lbuf, prefix, NULL);
+       lbuf_append(lbuf, prefix, NULL);
        if (d->val != NULL) {
-           lbuf_append(&lbuf, d->var, d->op == '+' ? " += " :
-               d->op == '-' ? " -= " : " = ", NULL);
+           lbuf_append(lbuf, d->var, d->op == '+' ? "+=" :
+               d->op == '-' ? "-=" : "=", NULL);
            if (strpbrk(d->val, " \t") != NULL) {
-               lbuf_append(&lbuf, "\"", NULL);
-               lbuf_append_quoted(&lbuf, "\"", d->val, NULL);
-               lbuf_append(&lbuf, "\"", NULL);
+               lbuf_append(lbuf, "\"", NULL);
+               lbuf_append_quoted(lbuf, "\"", d->val, NULL);
+               lbuf_append(lbuf, "\"", NULL);
            } else
-               lbuf_append_quoted(&lbuf, SUDOERS_QUOTED, d->val, NULL);
+               lbuf_append_quoted(lbuf, SUDOERS_QUOTED, d->val, NULL);
        } else
-           lbuf_append(&lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
+           lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
        prefix = ", ";
+       nfound++;
     }
-    if (prefix) {
-       lbuf_print(&lbuf);
-       putchar('\n');
-    }
-    lbuf_destroy(&lbuf);
 
-    if (per_runas)
-       display_bound_defaults(DEFAULTS_RUNAS);
-    if (per_cmnd)
-       display_bound_defaults(DEFAULTS_CMND);
+    return(nfound);
+}
+
+/*
+ * Display Defaults entries that are per-runas or per-command
+ */
+int
+sudo_file_display_bound_defaults(nss, pw, lbuf)
+    struct sudo_nss *nss;
+    struct passwd *pw;
+    struct lbuf *lbuf;
+{
+    int nfound = 0;
+
+    /* XXX - should only print ones that match what the user can do. */
+    nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf);
+    nfound += display_bound_defaults(DEFAULTS_CMND, lbuf);
+
+    return(nfound);
 }
 
 /*
  * Display Defaults entries of the given type.
  */
-static void
-display_bound_defaults(dtype)
+static int
+display_bound_defaults(dtype, lbuf)
     int dtype;
+    struct lbuf *lbuf;
 {
-    struct lbuf lbuf;
     struct defaults *d;
     struct member *m, *binding = NULL;
     char *dname, *dsep;
-    int atype;
+    int atype, nfound = 0;
 
     switch (dtype) {
        case DEFAULTS_HOST:
@@ -477,34 +487,33 @@ display_bound_defaults(dtype)
            dsep = "!";
            break;
        default:
-           return;
+           return(-1);
     }
-    lbuf_init(&lbuf, NULL, 4, 0);
-    printf("Per-%s Defaults entries:\n", dname);
+    /* printf("Per-%s Defaults entries:\n", dname); */
     tq_foreach_fwd(&defaults, d) {
        if (d->type != dtype)
            continue;
 
+       nfound++;
        if (binding != tq_first(&d->binding)) {
            binding = tq_first(&d->binding);
-           lbuf_append(&lbuf, "    Defaults", dsep, NULL);
+           lbuf_append(lbuf, "    Defaults", dsep, NULL);
            for (m = binding; m != NULL; m = m->next) {
                if (m != binding)
-                   lbuf_append(&lbuf, ",", NULL);
-               print_member(&lbuf, m->name, m->type, m->negated, atype);
-               lbuf_append(&lbuf, " ", NULL);
+                   lbuf_append(lbuf, ",", NULL);
+               print_member(lbuf, m->name, m->type, m->negated, atype);
+               lbuf_append(lbuf, " ", NULL);
            }
        } else
-           lbuf_append(&lbuf, ", ", NULL);
+           lbuf_append(lbuf, ", ", NULL);
        if (d->val != NULL) {
-           lbuf_append(&lbuf, d->var, d->op == '+' ? "+=" :
+           lbuf_append(lbuf, d->var, d->op == '+' ? "+=" :
                d->op == '-' ? "-=" : "=", d->val, NULL);
        } else
-           lbuf_append(&lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
+           lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
     }
-    lbuf_print(&lbuf);
-    lbuf_destroy(&lbuf);
-    putchar('\n');
+
+    return(nfound);
 }
 
 int
diff --git a/sudo.h b/sudo.h
index b0967bc660754907798ab72d22dfd2c4bbc940c1..c8c6c0793ffeb9fb40de9c26fa3be5f660165203 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -169,6 +169,7 @@ struct sudo_user {
 #define TGP_ECHO       0x01            /* leave echo on when reading passwd */
 #define TGP_STDIN      0x02            /* read from stdin, not /dev/tty */
 
+struct lbuf;
 struct passwd;
 struct timespec;
 struct timeval;
@@ -232,8 +233,10 @@ int sudo_ldap_close        __P((struct sudo_nss *));
 int sudo_ldap_setdefs  __P((struct sudo_nss *));
 int sudo_ldap_lookup   __P((struct sudo_nss *, int, int));
 int sudo_ldap_parse    __P((struct sudo_nss *));
-void sudo_ldap_display_privs __P((struct sudo_nss *, struct passwd *));
 int sudo_ldap_display_cmnd __P((struct sudo_nss *, struct passwd *));
+int sudo_ldap_display_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *));
+int sudo_ldap_display_bound_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *));
+int sudo_ldap_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *));
 #endif
 #if 1
 int sudo_file_open     __P((struct sudo_nss *));
@@ -241,8 +244,10 @@ int sudo_file_close        __P((struct sudo_nss *));
 int sudo_file_setdefs  __P((struct sudo_nss *));
 int sudo_file_lookup   __P((struct sudo_nss *, int, int));
 int sudo_file_parse    __P((struct sudo_nss *));
-void sudo_file_display_privs __P((struct sudo_nss *, struct passwd *));
 int sudo_file_display_cmnd __P((struct sudo_nss *, struct passwd *));
+int sudo_file_display_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *));
+int sudo_file_display_bound_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *));
+int sudo_file_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *));
 #endif
 void set_perms         __P((int));
 void remove_timestamp  __P((int));
index 88cd31d8fdabfb62c54d8d6e1882bda01e3c43c7..318f6d040ff4eb90b0ae32167679176d87c935f6 100644 (file)
@@ -41,6 +41,7 @@
 #include <grp.h>
 
 #include "sudo.h"
+#include "lbuf.h"
 
 #ifndef lint
 __unused static const char rcsid[] = "$Sudo$";
@@ -156,16 +157,44 @@ display_privs(snl, pw)
     struct passwd *pw;
 {
     struct sudo_nss *nss;
+    struct lbuf lbuf;
+    int count;
 
     /* Reset group vector so group matching works correctly. */
     reset_groups(pw);
 
-    /* Display privileges from all sources. */
-    tq_foreach_fwd(snl, nss) {
-       if (nss != tq_first(snl))
-           putchar('\n');
-       nss->display_privs(nss, pw);
+    lbuf_init(&lbuf, NULL, 4, 0);
+
+    /* Display defaults from all sources. */
+    count = 0;
+    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');
+    }
+
+    /* Display Runas and Cmnd-specific defaults from all sources. */
+    count = 0;
+    tq_foreach_fwd(snl, nss)
+       count += nss->display_bound_defaults(nss, pw, &lbuf);
+    if (count) {
+       printf("Runas and Command-specific defaults for %s:\n", pw->pw_name);
+       lbuf_print(&lbuf);
+       putchar('\n');
     }
+
+    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);
+    lbuf_destroy(&lbuf);
 }
 
 /*
index 46a522ce92dfc087451df39f9d28dba5b3df923a..e7d3f577a2039c970a77e7a7d59df3a075f3c798 100644 (file)
@@ -16,7 +16,9 @@
  * $Sudo$
  */
 
+struct lbuf;
 struct passwd;
+
 struct sudo_nss {
     struct sudo_nss *prev;
     struct sudo_nss *next;
@@ -25,8 +27,10 @@ struct sudo_nss {
     int (*parse) __P((struct sudo_nss *nss));
     int (*setdefs) __P((struct sudo_nss *nss));
     int (*lookup) __P((struct sudo_nss *nss, int, int));
-    void (*display_privs) __P((struct sudo_nss *nss, struct passwd *));
     int (*display_cmnd) __P((struct sudo_nss *nss, struct passwd *));
+    int (*display_defaults) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *));
+    int (*display_bound_defaults) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *));
+    int (*display_privs) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *));
     void *handle;
     int ret_notfound;
 };