Add verbose version of "sudo -l command" by using an extra -l.

The output of "sudo -ll command" consists of the matching sudoers
rule (in long form) with the addition of a "Matched" entry that
shows the fully-qualfied path along with any arguments.
This commit is contained in:
Todd C. Miller
2023-08-09 10:16:10 -06:00
parent f6291bf83e
commit 60eef27e6d
6 changed files with 53 additions and 35 deletions

View File

@@ -537,7 +537,7 @@ bad:
static int
display_cmnd_check(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
time_t now)
time_t now, struct sudoers_match_info *match_info)
{
int host_match, runas_match, cmnd_match = UNSPEC;
char *saved_user_cmnd, *saved_user_base;
@@ -576,8 +576,13 @@ display_cmnd_check(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(parse_tree, cs->cmnd,
cs->runchroot, NULL);
if (cmnd_match != UNSPEC)
if (cmnd_match != UNSPEC) {
match_info->parse_tree = parse_tree;
match_info->us = us;
match_info->priv = priv;
match_info->cs = cs;
goto done;
}
}
}
}
@@ -594,8 +599,10 @@ done:
* Returns true if the command is allowed, false if not or -1 on error.
*/
int
display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
display_cmnd(struct sudo_nss_list *snl, struct passwd *pw, bool verbose)
{
struct sudoers_match_info match_info = { NULL };
struct sudo_lbuf lbuf;
struct sudo_nss *nss;
int m, match = UNSPEC;
int ret = false;
@@ -604,13 +611,14 @@ display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
/* Iterate over each source, checking for the command. */
time(&now);
sudo_lbuf_init(&lbuf, output, 0, NULL, 0);
TAILQ_FOREACH(nss, snl, entries) {
if (nss->query(nss, pw) == -1) {
/* The query function should have printed an error message. */
debug_return_int(-1);
}
m = display_cmnd_check(nss->parse_tree, pw, now);
m = display_cmnd_check(nss->parse_tree, pw, now, &match_info);
if (m != UNSPEC)
match = m;
@@ -618,9 +626,17 @@ display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
break;
}
if (match == ALLOW) {
const int len = sudo_printf(SUDO_CONV_INFO_MSG, "%s%s%s\n",
if (verbose) {
/* Append matching sudoers rule (long form). */
display_cmndspec_long(match_info.parse_tree, pw, match_info.us,
match_info.priv, match_info.cs, NULL, &lbuf);
sudo_lbuf_append(&lbuf, " Matched: ");
}
sudo_lbuf_append(&lbuf, "%s%s%s\n",
list_cmnd, user_args ? " " : "", user_args ? user_args : "");
ret = len < 0 ? -1 : true;
sudo_lbuf_print(&lbuf);
ret = sudo_lbuf_error(&lbuf) ? -1 : true;
sudo_lbuf_destroy(&lbuf);
}
debug_return_int(ret);
}

View File

@@ -99,8 +99,8 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw, time_t now,
int user_match = userlist_matches(nss->parse_tree, pw, &us->users);
if (user_match != ALLOW) {
if (callback != NULL && user_match != UNSPEC) {
callback(us, user_match, NULL, UNSPEC, NULL, UNSPEC,
UNSPEC, UNSPEC, cb_data);
callback(nss->parse_tree, us, user_match, NULL, UNSPEC,
NULL, UNSPEC, UNSPEC, UNSPEC, cb_data);
}
continue;
}
@@ -110,8 +110,8 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw, time_t now,
&priv->hostlist);
if (host_match != ALLOW) {
if (callback != NULL) {
callback(us, user_match, priv, host_match, NULL, UNSPEC,
UNSPEC, UNSPEC, cb_data);
callback(nss->parse_tree, us, user_match, priv,
host_match, NULL, UNSPEC, UNSPEC, UNSPEC, cb_data);
}
continue;
}
@@ -183,8 +183,9 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw, time_t now,
}
}
if (callback != NULL) {
callback(us, user_match, priv, host_match, cs,
date_match, runas_match, cmnd_match, cb_data);
callback(nss->parse_tree, us, user_match, priv,
host_match, cs, date_match, runas_match,
cmnd_match, cb_data);
}
if (cmnd_match != UNSPEC) {
/*
@@ -243,8 +244,8 @@ sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw,
int user_match = userlist_matches(nss->parse_tree, pw, &us->users);
if (user_match != ALLOW) {
if (callback != NULL && user_match != UNSPEC) {
callback(us, user_match, NULL, UNSPEC, NULL, UNSPEC,
UNSPEC, UNSPEC, cb_data);
callback(nss->parse_tree, us, user_match, NULL, UNSPEC, NULL,
UNSPEC, UNSPEC, UNSPEC, cb_data);
}
continue;
}
@@ -256,8 +257,8 @@ sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw,
CLR(*validated, FLAG_NO_HOST);
} else {
if (callback != NULL) {
callback(us, user_match, priv, host_match, NULL, UNSPEC,
UNSPEC, UNSPEC, cb_data);
callback(nss->parse_tree, us, user_match, priv, host_match,
NULL, UNSPEC, UNSPEC, UNSPEC, cb_data);
}
continue;
}
@@ -283,8 +284,8 @@ sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw,
}
}
if (callback != NULL) {
callback(us, user_match, priv, host_match, cs, date_match,
runas_match, cmnd_match, cb_data);
callback(nss->parse_tree, us, user_match, priv, host_match,
cs, date_match, runas_match, cmnd_match, cb_data);
}
if (cmnd_match != UNSPEC) {

View File

@@ -298,6 +298,13 @@ struct defaults {
int column; /* column number of Defaults entry */
};
struct sudoers_match_info {
struct sudoers_parse_tree *parse_tree;
struct userspec *us; /* matching userspec */
struct privilege *priv; /* matching privilege */
struct cmndspec *cs; /* matching cmndspec */
};
/*
* Parsed sudoers policy.
*/
@@ -324,7 +331,7 @@ struct cmnd_info {
/*
* Optional callback for sudoers_lookup().
*/
typedef void (*sudoers_lookup_callback_fn_t)(struct userspec *us, int user_match, struct privilege *priv, int host_match, struct cmndspec *cs, int date_match, int runas_match, int cmnd_match, void *closure);
typedef void (*sudoers_lookup_callback_fn_t)(struct sudoers_parse_tree *parse_tree, struct userspec *us, int user_match, struct privilege *priv, int host_match, struct cmndspec *cs, int date_match, int runas_match, int cmnd_match, void *closure);
/*
* Parse configuration settings, passed to init_parser().
@@ -481,7 +488,7 @@ unsigned int sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, time_t
/* display.c */
int display_privs(struct sudo_nss_list *snl, struct passwd *pw, bool verbose);
int display_cmnd(struct sudo_nss_list *snl, struct passwd *pw);
int display_cmnd(struct sudo_nss_list *snl, struct passwd *pw, bool verbose);
/* parse_ldif.c */
bool sudoers_parse_ldif(struct sudoers_parse_tree *parse_tree, FILE *fp, const char *sudoers_base, bool store_options);

View File

@@ -815,7 +815,7 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, time_t now,
/* STUB */
int
display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
display_cmnd(struct sudo_nss_list *snl, struct passwd *pw, bool verbose)
{
return true;
}

View File

@@ -325,16 +325,10 @@ done:
debug_return_str(iolog_path);
}
struct sudoers_match_info {
struct privilege *priv; /* matching privilege */
struct userspec *us; /* matching userspec */
struct cmndspec *cs; /* matching cmndspec */
};
static void
cb_lookup(struct userspec *us, int user_match, struct privilege *priv,
int host_match, struct cmndspec *cs, int date_match, int runas_match,
int cmnd_match, void *closure)
cb_lookup(struct sudoers_parse_tree *parse_tree, struct userspec *us,
int user_match, struct privilege *priv, int host_match, struct cmndspec *cs,
int date_match, int runas_match, int cmnd_match, void *closure)
{
struct sudoers_match_info *info = closure;
@@ -950,7 +944,7 @@ sudoers_list(int argc, char * const argv[], const char *list_user, bool verbose)
goto done;
if (ISSET(sudo_mode, MODE_CHECK))
ret = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
ret = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw, verbose);
else
ret = display_privs(snl, list_pw ? list_pw : sudo_user.pw, verbose);

View File

@@ -74,7 +74,7 @@ static bool cb_runas_default(const char *file, int line, int column, const union
static int testsudoers_error(const char * restrict buf);
static int testsudoers_output(const char * restrict buf);
sudo_noreturn static void usage(void);
static void cb_lookup(struct userspec *us, int user_match, struct privilege *priv, int host_match, struct cmndspec *cs, int date_match, int runas_match, int cmnd_match, void *closure);
static void cb_lookup(struct sudoers_parse_tree *parse_tree, struct userspec *us, int user_match, struct privilege *priv, int host_match, struct cmndspec *cs, int date_match, int runas_match, int cmnd_match, void *closure);
static int testsudoers_query(const struct sudo_nss *nss, struct passwd *pw);
/*
@@ -626,9 +626,9 @@ set_cmnd_path(const char *runchroot)
}
static void
cb_lookup(struct userspec *us, int user_match, struct privilege *priv,
int host_match, struct cmndspec *cs, int date_match, int runas_match,
int cmnd_match, void *closure)
cb_lookup(struct sudoers_parse_tree *parse_tree, struct userspec *us,
int user_match, struct privilege *priv, int host_match, struct cmndspec *cs,
int date_match, int runas_match, int cmnd_match, void *closure)
{
static struct privilege *prev_priv;
struct sudo_lbuf lbuf;