Add file:linenumber prefix to all Defaults warnings so we can see

them when running sudo too.  For LDAP/SSSD we print the sudoRole
instead of the file name and omit the line number.
This commit is contained in:
Todd C. Miller
2016-11-02 17:07:32 -06:00
parent a9715211a8
commit 75e29f163e
6 changed files with 146 additions and 52 deletions

View File

@@ -90,6 +90,10 @@ static struct early_default early_defaults[] = {
{ NULL } { NULL }
}; };
/* Flags for set_default_entry() and set_default_int() */
#define FLAG_DO_CALLBACK 0x01
#define FLAG_QUIET 0x02
/* /*
* Local prototypes. * Local prototypes.
*/ */
@@ -193,7 +197,7 @@ dump_defaults(void)
static bool static bool
set_default_entry(struct sudo_defs_types *def, const char *val, int op, set_default_entry(struct sudo_defs_types *def, const char *val, int op,
bool quiet, bool do_callback) const char *file, int lineno, int flags)
{ {
int rc; int rc;
debug_decl(set_default_entry, SUDOERS_DEBUG_DEFAULTS) debug_decl(set_default_entry, SUDOERS_DEBUG_DEFAULTS)
@@ -201,8 +205,15 @@ set_default_entry(struct sudo_defs_types *def, const char *val, int op,
if (val == NULL && !ISSET(def->type, T_FLAG)) { if (val == NULL && !ISSET(def->type, T_FLAG)) {
/* Check for bogus boolean usage or missing value if non-boolean. */ /* Check for bogus boolean usage or missing value if non-boolean. */
if (!ISSET(def->type, T_BOOL) || op != false) { if (!ISSET(def->type, T_BOOL) || op != false) {
if (!quiet) if (!ISSET(flags, FLAG_QUIET)) {
sudo_warnx(U_("no value specified for `%s'"), def->name); if (lineno > 0) {
sudo_warnx(U_("%s:%d no value specified for `%s'"),
file, lineno, def->name);
} else {
sudo_warnx(U_("%s: no value specified for `%s'"),
file, def->name);
}
}
debug_return_bool(false); debug_return_bool(false);
} }
} }
@@ -216,9 +227,14 @@ set_default_entry(struct sudo_defs_types *def, const char *val, int op,
break; break;
case T_STR: case T_STR:
if (ISSET(def->type, T_PATH) && val != NULL && *val != '/') { if (ISSET(def->type, T_PATH) && val != NULL && *val != '/') {
if (!quiet) { if (!ISSET(flags, FLAG_QUIET)) {
sudo_warnx(U_("values for `%s' must start with a '/'"), if (lineno > 0) {
def->name); sudo_warnx(U_("%s:%d values for `%s' must start with a '/'"),
file, lineno, def->name);
} else {
sudo_warnx(U_("%s: values for `%s' must start with a '/'"),
file, def->name);
}
} }
rc = -1; rc = -1;
break; break;
@@ -239,9 +255,14 @@ set_default_entry(struct sudo_defs_types *def, const char *val, int op,
break; break;
case T_FLAG: case T_FLAG:
if (val != NULL) { if (val != NULL) {
if (!quiet) { if (!ISSET(flags, FLAG_QUIET)) {
sudo_warnx(U_("option `%s' does not take a value"), if (lineno > 0) {
def->name); sudo_warnx(U_("%s:%d option `%s' does not take a value"),
file, lineno, def->name);
} else {
sudo_warnx(U_("%s: option `%s' does not take a value"),
file, def->name);
}
} }
rc = -1; rc = -1;
break; break;
@@ -256,9 +277,14 @@ set_default_entry(struct sudo_defs_types *def, const char *val, int op,
rc = store_tuple(val, def); rc = store_tuple(val, def);
break; break;
default: default:
if (!quiet) { if (!ISSET(flags, FLAG_QUIET)) {
sudo_warnx(U_("invalid Defaults type 0x%x for option `%s'"), if (lineno > 0) {
def->type, def->name); sudo_warnx(U_("%s:%d invalid Defaults type 0x%x for option `%s'"),
file, lineno, def->type, def->name);
} else {
sudo_warnx(U_("%s: invalid Defaults type 0x%x for option `%s'"),
file, def->type, def->name);
}
} }
rc = -1; rc = -1;
break; break;
@@ -269,13 +295,18 @@ set_default_entry(struct sudo_defs_types *def, const char *val, int op,
rc = false; rc = false;
break; break;
case false: case false:
if (!quiet) { if (!ISSET(flags, FLAG_QUIET)) {
sudo_warnx(U_("value `%s' is invalid for option `%s'"), if (lineno > 0) {
val, def->name); sudo_warnx(U_("%s:%d value `%s' is invalid for option `%s'"),
file, lineno, val, def->name);
} else {
sudo_warnx(U_("%s: value `%s' is invalid for option `%s'"),
file, val, def->name);
}
} }
break; break;
case true: case true:
if (do_callback && def->callback) if (ISSET(flags, FLAG_DO_CALLBACK) && def->callback)
rc = def->callback(&def->sd_un); rc = def->callback(&def->sd_un);
break; break;
} }
@@ -304,8 +335,8 @@ is_early_default(const char *var)
* This is only meaningful for variables that are *optional*. * This is only meaningful for variables that are *optional*.
*/ */
static struct sudo_defs_types * static struct sudo_defs_types *
set_default_int(const char *var, const char *val, int op, bool quiet, set_default_int(const char *var, const char *val, int op, const char *file,
bool do_callback) int lineno, int flags)
{ {
struct sudo_defs_types *cur; struct sudo_defs_types *cur;
int num; int num;
@@ -316,12 +347,19 @@ set_default_int(const char *var, const char *val, int op, bool quiet,
break; break;
} }
if (!cur->name) { if (!cur->name) {
if (!quiet) if (!ISSET(flags, FLAG_QUIET)) {
sudo_warnx(U_("unknown defaults entry `%s'"), var); if (lineno > 0) {
sudo_warnx(U_("%s:%d unknown defaults entry `%s'"),
file, lineno, var);
} else {
sudo_warnx(U_("%s: unknown defaults entry `%s'"),
file, var);
}
}
debug_return_ptr(NULL); debug_return_ptr(NULL);
} }
if (!set_default_entry(cur, val, op, quiet, do_callback)) if (!set_default_entry(cur, val, op, file, lineno, flags))
debug_return_ptr(NULL); debug_return_ptr(NULL);
debug_return_ptr(cur); debug_return_ptr(cur);
} }
@@ -331,12 +369,16 @@ set_default_int(const char *var, const char *val, int op, bool quiet,
* Runs the callback if present on success. * Runs the callback if present on success.
*/ */
bool bool
set_default(const char *var, const char *val, int op, bool quiet) set_default(const char *var, const char *val, int op, const char *file,
int lineno, bool quiet)
{ {
const struct sudo_defs_types *def; const struct sudo_defs_types *def;
int flags = FLAG_DO_CALLBACK;
debug_decl(set_default, SUDOERS_DEBUG_DEFAULTS) debug_decl(set_default, SUDOERS_DEBUG_DEFAULTS)
def = set_default_int(var, val, op, quiet, true); if (quiet)
SET(flags, FLAG_QUIET);
def = set_default_int(var, val, op, file, lineno, flags);
debug_return_bool(def != NULL); debug_return_bool(def != NULL);
} }
@@ -345,13 +387,16 @@ set_default(const char *var, const char *val, int op, bool quiet)
* and does not run callbacks. * and does not run callbacks.
*/ */
bool bool
set_early_default(const char *var, const char *val, int op, bool quiet, set_early_default(const char *var, const char *val, int op, const char *file,
struct early_default *early) int lineno, bool quiet, struct early_default *early)
{ {
const struct sudo_defs_types *def; const struct sudo_defs_types *def;
int flags = 0;
debug_decl(set_early_default, SUDOERS_DEBUG_DEFAULTS) debug_decl(set_early_default, SUDOERS_DEBUG_DEFAULTS)
def = set_default_int(var, val, op, quiet, false); if (quiet)
SET(flags, FLAG_QUIET);
def = set_default_int(var, val, op, file, lineno, flags);
if (def == NULL) if (def == NULL)
debug_return_bool(false); debug_return_bool(false);
early->def = def; early->def = def;
@@ -673,7 +718,7 @@ update_defaults(int what, bool quiet)
if (!default_type_matches(def, what) || if (!default_type_matches(def, what) ||
!default_binding_matches(def, what)) !default_binding_matches(def, what))
continue; continue;
if (!set_early_default(def->var, def->val, def->op, quiet, early)) if (!set_early_default(def->var, def->val, def->op, "sudoers", 0, quiet, early))
ret = false; ret = false;
} }
if (!run_early_defaults()) if (!run_early_defaults())
@@ -690,7 +735,7 @@ update_defaults(int what, bool quiet)
if (!default_type_matches(def, what) || if (!default_type_matches(def, what) ||
!default_binding_matches(def, what)) !default_binding_matches(def, what))
continue; continue;
if (!set_default(def->var, def->val, def->op, quiet)) if (!set_default(def->var, def->val, def->op, "sudoers", 0, quiet))
ret = false; ret = false;
} }
debug_return_bool(ret); debug_return_bool(ret);
@@ -700,26 +745,37 @@ update_defaults(int what, bool quiet)
* Check a defaults entry without actually setting it. * Check a defaults entry without actually setting it.
*/ */
bool bool
check_default(struct defaults *def, bool quiet) check_default(const char *var, const char *val, int op, const char *file,
int lineno, bool quiet)
{ {
struct sudo_defs_types *cur; struct sudo_defs_types *cur;
bool ret = true; bool ret = true;
int flags = 0;
debug_decl(check_default, SUDOERS_DEBUG_DEFAULTS) debug_decl(check_default, SUDOERS_DEBUG_DEFAULTS)
if (quiet)
SET(flags, FLAG_QUIET);
for (cur = sudo_defs_table; cur->name != NULL; cur++) { for (cur = sudo_defs_table; cur->name != NULL; cur++) {
if (strcmp(def->var, cur->name) == 0) { if (strcmp(var, cur->name) == 0) {
/* Don't actually set the defaults value, just checking. */ /* Don't actually set the defaults value, just checking. */
struct sudo_defs_types tmp = *cur; struct sudo_defs_types tmp = *cur;
memset(&tmp.sd_un, 0, sizeof(tmp.sd_un)); memset(&tmp.sd_un, 0, sizeof(tmp.sd_un));
if (!set_default_entry(&tmp, def->val, def->op, quiet, false)) if (!set_default_entry(&tmp, val, op, file, lineno, flags))
ret = false; ret = false;
free_default(&tmp); free_default(&tmp);
break; break;
} }
} }
if (cur->name == NULL) { if (cur->name == NULL) {
if (!quiet) if (!quiet) {
sudo_warnx(U_("unknown defaults entry `%s'"), def->var); if (lineno > 0) {
sudo_warnx(U_("%s:%d unknown defaults entry `%s'"),
file, lineno, var);
} else {
sudo_warnx(U_("%s: unknown defaults entry `%s'"),
file, var);
}
}
ret = false; ret = false;
} }
debug_return_bool(ret); debug_return_bool(ret);

View File

@@ -122,12 +122,12 @@ struct early_default {
struct defaults; /* in parse.h */ struct defaults; /* in parse.h */
void dump_default(void); void dump_default(void);
bool check_default(struct defaults *def, bool quiet); bool check_default(const char *var, const char *val, int op, const char *file, int lineno, bool quiet);
bool init_defaults(void); bool init_defaults(void);
struct early_default *is_early_default(const char *var); struct early_default *is_early_default(const char *var);
bool run_early_defaults(void); bool run_early_defaults(void);
bool set_early_default(const char *var, const char *val, int op, bool quiet, struct early_default *early); bool set_early_default(const char *var, const char *val, int op, const char *file, int lineno, bool quiet, struct early_default *early);
bool set_default(const char *var, const char *val, int op, bool quiet); bool set_default(const char *var, const char *val, int op, const char *file, int lineno, bool quiet);
bool update_defaults(int what, bool quiet); bool update_defaults(int what, bool quiet);
extern struct sudo_defs_types sudo_defs_table[]; extern struct sudo_defs_types sudo_defs_table[];

View File

@@ -826,16 +826,16 @@ add_defaults(int type, struct member *bmem, struct defaults *defs)
* Then add to the global defaults list if it parses. * Then add to the global defaults list if it parses.
*/ */
HLTQ_FOREACH_SAFE(d, defs, entries, next) { HLTQ_FOREACH_SAFE(d, defs, entries, next) {
if (check_default(d, !sudoers_warnings)) { if (check_default(d->var, d->val, d->op, sudoers, sudolineno, !sudoers_warnings)) {
/* Append to defaults list */ /* Append to defaults list */
d->type = type; d->type = type;
d->binding = binding; d->binding = binding;
binding_used = true; binding_used = true;
TAILQ_INSERT_TAIL(&defaults, d, entries); TAILQ_INSERT_TAIL(&defaults, d, entries);
} else { } else {
/* Did not parse, warn and free it. */ /* Did not parse */
if (!allow_unknown_defaults) { if (!allow_unknown_defaults) {
sudoerserror(N_("problem with defaults entries")); sudoerserror(NULL);
ret = false; ret = false;
} }
free(d->var); free(d->var);

View File

@@ -982,16 +982,16 @@ add_defaults(int type, struct member *bmem, struct defaults *defs)
* Then add to the global defaults list if it parses. * Then add to the global defaults list if it parses.
*/ */
HLTQ_FOREACH_SAFE(d, defs, entries, next) { HLTQ_FOREACH_SAFE(d, defs, entries, next) {
if (check_default(d, !sudoers_warnings)) { if (check_default(d->var, d->val, d->op, sudoers, sudolineno, !sudoers_warnings)) {
/* Append to defaults list */ /* Append to defaults list */
d->type = type; d->type = type;
d->binding = binding; d->binding = binding;
binding_used = true; binding_used = true;
TAILQ_INSERT_TAIL(&defaults, d, entries); TAILQ_INSERT_TAIL(&defaults, d, entries);
} else { } else {
/* Did not parse, warn and free it. */ /* Did not parse */
if (!allow_unknown_defaults) { if (!allow_unknown_defaults) {
sudoerserror(N_("problem with defaults entries")); sudoerserror(NULL);
ret = false; ret = false;
} }
free(d->var); free(d->var);

View File

@@ -380,6 +380,7 @@ static int sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
struct sudo_lbuf *lbuf); struct sudo_lbuf *lbuf);
static struct ldap_result *sudo_ldap_result_get(struct sudo_nss *nss, static struct ldap_result *sudo_ldap_result_get(struct sudo_nss *nss,
struct passwd *pw); struct passwd *pw);
static char *sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry);
/* /*
* LDAP sudo_nss handle. * LDAP sudo_nss handle.
@@ -1129,7 +1130,7 @@ static bool
sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry) sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
{ {
struct berval **bv, **p; struct berval **bv, **p;
char *copy, *var, *val; char *cn, *copy, *var, *val, *source = NULL;
bool ret = false; bool ret = false;
int op; int op;
debug_decl(sudo_ldap_parse_options, SUDOERS_DEBUG_LDAP) debug_decl(sudo_ldap_parse_options, SUDOERS_DEBUG_LDAP)
@@ -1138,6 +1139,16 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
if (bv == NULL) if (bv == NULL)
debug_return_bool(true); debug_return_bool(true);
/* get the entry's dn for option error reporting */
cn = sudo_ldap_get_first_rdn(ld, entry);
if (cn != NULL) {
if (asprintf(&source, "sudoRole %s", cn) == -1) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
source = NULL;
goto done;
}
}
/* walk through options, early ones first */ /* walk through options, early ones first */
for (p = bv; *p != NULL; p++) { for (p = bv; *p != NULL; p++) {
struct early_default *early; struct early_default *early;
@@ -1148,8 +1159,10 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
} }
op = sudo_ldap_parse_option(copy, &var, &val); op = sudo_ldap_parse_option(copy, &var, &val);
early = is_early_default(var); early = is_early_default(var);
if (early != NULL) if (early != NULL) {
set_early_default(var, val, op, false, early); set_early_default(var, val, op,
source ? source : "sudoRole UNKNOWN", 0, false, early);
}
free(copy); free(copy);
} }
run_early_defaults(); run_early_defaults();
@@ -1161,13 +1174,18 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
goto done; goto done;
} }
op = sudo_ldap_parse_option(copy, &var, &val); op = sudo_ldap_parse_option(copy, &var, &val);
if (is_early_default(var) == NULL) if (is_early_default(var) == NULL) {
set_default(var, val, op, false); set_default(var, val, op,
source ? source : "sudoRole UNKNOWN", 0, false);
}
free(copy); free(copy);
} }
ret = true; ret = true;
done: done:
free(source);
if (cn)
ldap_memfree(cn);
ldap_value_free_len(bv); ldap_value_free_len(bv);
debug_return_bool(ret); debug_return_bool(ret);

View File

@@ -1196,9 +1196,10 @@ static bool
sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
{ {
int i, op; int i, op;
char *copy, *var, *val; char *copy, *var, *val, *source = NULL;
bool ret = false; bool ret = false;
char **val_array = NULL; char **val_array = NULL;
char **cn_array = NULL;
debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD); debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD);
if (rule == NULL) if (rule == NULL)
@@ -1215,6 +1216,20 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
debug_return_bool(false); debug_return_bool(false);
} }
/* get the entry's cn for option error reporting */
if (handle->fn_get_values(rule, "cn", &cn_array) == 0) {
if (cn_array[0] != NULL) {
if (asprintf(&source, "sudoRole %s", cn_array[0]) == -1) {
sudo_warnx(U_("%s: %s"), __func__,
U_("unable to allocate memory"));
source = NULL;
goto done;
}
}
handle->fn_free_values(cn_array);
cn_array = NULL;
}
/* walk through options, early ones first */ /* walk through options, early ones first */
for (i = 0; val_array[i] != NULL; i++) { for (i = 0; val_array[i] != NULL; i++) {
struct early_default *early; struct early_default *early;
@@ -1225,8 +1240,10 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
} }
op = sudo_sss_parse_option(copy, &var, &val); op = sudo_sss_parse_option(copy, &var, &val);
early = is_early_default(var); early = is_early_default(var);
if (early != NULL) if (early != NULL) {
set_early_default(var, val, op, false, early); set_early_default(var, val, op,
source ? source : "sudoRole UNKNOWN", 0, false, early);
}
free(copy); free(copy);
} }
run_early_defaults(); run_early_defaults();
@@ -1238,13 +1255,16 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
goto done; goto done;
} }
op = sudo_sss_parse_option(copy, &var, &val); op = sudo_sss_parse_option(copy, &var, &val);
if (is_early_default(var) == NULL) if (is_early_default(var) == NULL) {
set_default(var, val, op, false); set_default(var, val, op,
source ? source : "sudoRole UNKNOWN", 0, false);
}
free(copy); free(copy);
} }
ret = true; ret = true;
done: done:
free(source);
handle->fn_free_values(val_array); handle->fn_free_values(val_array);
debug_return_bool(ret); debug_return_bool(ret);
} }