2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-04 00:05:11 +00:00

Unify the -l output for file and ldap based sudoers and use lbufs for both.

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.
This commit is contained in:
Todd C. Miller
2008-02-03 15:43:38 +00:00
parent 8e33f63484
commit 3c7b76bb54
5 changed files with 226 additions and 131 deletions

142
ldap.c
View File

@@ -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,45 +1104,75 @@ 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
* Lets limit it to only two queries of the LDAP server
@@ -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

157
parse.c
View File

@@ -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;
lbuf_init(&lbuf, NULL, 4, 0);
if (nss->handle == NULL)
return(-1);
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 == '+' ? " += " :
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

9
sudo.h
View File

@@ -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));

View 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))
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');
nss->display_privs(nss, pw);
}
/* 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);
}
/*

View 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;
};