Split set_default_entry() out of set_default() so we can call it
from check_defaults() to validate the defaults value. In visudo, suppress warnings from update_defaults() and rely on check_defaults() to provide warnings.
This commit is contained in:
@@ -197,6 +197,182 @@ dump_defaults(void)
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_default_entry(struct sudo_defs_types *def, const char *val, int op, bool quiet)
|
||||
{
|
||||
debug_decl(set_default_entry, SUDOERS_DEBUG_DEFAULTS)
|
||||
|
||||
switch (def->type & T_MASK) {
|
||||
case T_LOGFAC:
|
||||
if (!store_syslogfac(val, def, op)) {
|
||||
if (!quiet) {
|
||||
if (val)
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
else
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_LOGPRI:
|
||||
if (!store_syslogpri(val, def, op)) {
|
||||
if (!quiet) {
|
||||
if (val)
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
else
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_STR:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(def->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (ISSET(def->type, T_PATH) && val && *val != '/') {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("values for `%s' must start with a '/'"),
|
||||
def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
switch (store_str(val, def, op)) {
|
||||
case true:
|
||||
/* OK */
|
||||
break;
|
||||
case false:
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_INT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(def->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_int(val, def, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_UINT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(def->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_uint(val, def, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_FLOAT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(def->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_float(val, def, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_MODE:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(def->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_mode(val, def, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_FLAG:
|
||||
if (val) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("option `%s' does not take a value"),
|
||||
def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
def->sd_un.flag = op;
|
||||
if (def->callback)
|
||||
debug_return_bool(def->callback(&def->sd_un));
|
||||
break;
|
||||
case T_LIST:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(def->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_list(val, def, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_TUPLE:
|
||||
if (!val && !ISSET(def->type, T_BOOL)) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), def->name);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (!store_tuple(val, def, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, def->name);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets/clears an entry in the defaults structure
|
||||
* If a variable that takes a value is used in a boolean
|
||||
@@ -221,171 +397,7 @@ set_default(const char *var, const char *val, int op, bool quiet)
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
switch (cur->type & T_MASK) {
|
||||
case T_LOGFAC:
|
||||
if (!store_syslogfac(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
if (val)
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
else
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_LOGPRI:
|
||||
if (!store_syslogpri(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
if (val)
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
else
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_STR:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(cur->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (ISSET(cur->type, T_PATH) && val && *val != '/') {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("values for `%s' must start with a '/'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
switch (store_str(val, cur, op)) {
|
||||
case true:
|
||||
/* OK */
|
||||
break;
|
||||
case false:
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_INT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(cur->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_int(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_UINT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(cur->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_uint(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_FLOAT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(cur->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_float(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_MODE:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(cur->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_mode(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_FLAG:
|
||||
if (val) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("option `%s' does not take a value"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
cur->sd_un.flag = op;
|
||||
if (cur->callback)
|
||||
debug_return_bool(cur->callback(&cur->sd_un));
|
||||
break;
|
||||
case T_LIST:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!ISSET(cur->type, T_BOOL) || op != false) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (!store_list(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
case T_TUPLE:
|
||||
if (!val && !ISSET(cur->type, T_BOOL)) {
|
||||
if (!quiet)
|
||||
sudo_warnx(U_("no value specified for `%s'"), var);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (!store_tuple(val, cur, op)) {
|
||||
if (!quiet) {
|
||||
sudo_warnx(U_("value `%s' is invalid for option `%s'"),
|
||||
val, var);
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
debug_return_bool(true);
|
||||
debug_return_bool(set_default_entry(cur, val, op, quiet));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -712,7 +724,7 @@ update_defaults(int what, bool quiet)
|
||||
bool
|
||||
check_defaults(int what, bool quiet)
|
||||
{
|
||||
struct sudo_defs_types *cur;
|
||||
struct sudo_defs_types *cur, tmp;
|
||||
struct defaults *def;
|
||||
bool rc = true;
|
||||
debug_decl(check_defaults, SUDOERS_DEBUG_DEFAULTS)
|
||||
@@ -729,6 +741,11 @@ check_defaults(int what, bool quiet)
|
||||
sudo_warnx(U_("unknown defaults entry `%s'"), def->var);
|
||||
rc = false;
|
||||
}
|
||||
/* Don't actually set the defaults value, just checking. */
|
||||
tmp = *cur;
|
||||
tmp.callback = NULL;
|
||||
if (!set_default_entry(&tmp, def->val, def->op, quiet))
|
||||
rc = false;
|
||||
}
|
||||
debug_return_bool(rc);
|
||||
}
|
||||
|
@@ -554,7 +554,6 @@ reparse_sudoers(char *editor, int editor_argc, char **editor_argv,
|
||||
struct sudoersfile *sp, *last;
|
||||
FILE *fp;
|
||||
int ch, oldlocale;
|
||||
bool ok;
|
||||
debug_decl(reparse_sudoers, SUDOERS_DEBUG_UTIL)
|
||||
|
||||
/*
|
||||
@@ -581,17 +580,16 @@ reparse_sudoers(char *editor, int editor_argc, char **editor_argv,
|
||||
parse_error = true;
|
||||
errorfile = sp->path;
|
||||
}
|
||||
ok = update_defaults(SETDEF_GENERIC|SETDEF_HOST, quiet);
|
||||
if (!check_defaults(SETDEF_ALL & ~(SETDEF_GENERIC|SETDEF_HOST), quiet))
|
||||
ok = false;
|
||||
sudoers_setlocale(oldlocale, NULL);
|
||||
fclose(sudoersin);
|
||||
if (!parse_error) {
|
||||
if (!ok || check_aliases(strict, quiet) != 0) {
|
||||
(void) update_defaults(SETDEF_GENERIC|SETDEF_HOST, true);
|
||||
if (!check_defaults(SETDEF_ALL, quiet) ||
|
||||
check_aliases(strict, quiet) != 0) {
|
||||
parse_error = true;
|
||||
errorfile = NULL;
|
||||
}
|
||||
}
|
||||
sudoers_setlocale(oldlocale, NULL);
|
||||
|
||||
/*
|
||||
* Got an error, prompt the user for what to do now.
|
||||
@@ -923,9 +921,9 @@ check_syntax(const char *sudoers_file, bool quiet, bool strict, bool oldperms)
|
||||
errorfile = sudoers_file;
|
||||
}
|
||||
if (!parse_error) {
|
||||
if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST, quiet) ||
|
||||
!check_defaults(SETDEF_ALL & ~(SETDEF_GENERIC|SETDEF_HOST), quiet)
|
||||
|| check_aliases(strict, quiet) != 0) {
|
||||
(void) update_defaults(SETDEF_GENERIC|SETDEF_HOST, true);
|
||||
if (!check_defaults(SETDEF_ALL, quiet) ||
|
||||
check_aliases(strict, quiet) != 0) {
|
||||
parse_error = true;
|
||||
errorfile = NULL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user