mirror of
https://github.com/sudo-project/sudo.git
synced 2025-09-02 07:15:27 +00:00
Instead of deferring setting early defaults until we have traversed
the entire defaults list, just defer running the callbacks. Otherwise, if the last early default setting we see has a bad value we won't set any defaults of that type even if there was an earlier one that was valid.
This commit is contained in:
@@ -76,19 +76,9 @@ static struct strmap priorities[] = {
|
|||||||
{ NULL, -1 }
|
{ NULL, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Defaults values to apply before others.
|
|
||||||
*/
|
|
||||||
struct early_default {
|
|
||||||
const char *var;
|
|
||||||
const char *val;
|
|
||||||
short op;
|
|
||||||
short set;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct early_default early_defaults[] = {
|
static struct early_default early_defaults[] = {
|
||||||
#ifdef FQDN
|
#ifdef FQDN
|
||||||
{ "fqdn", NULL, true },
|
{ "fqdn", &sudo_defs_table[I_FQDN] },
|
||||||
#else
|
#else
|
||||||
{ "fqdn" },
|
{ "fqdn" },
|
||||||
#endif
|
#endif
|
||||||
@@ -199,8 +189,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)
|
||||||
bool quiet)
|
|
||||||
{
|
{
|
||||||
debug_decl(set_default_entry, SUDOERS_DEBUG_DEFAULTS)
|
debug_decl(set_default_entry, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
@@ -369,25 +358,39 @@ set_default_entry(struct sudo_defs_types *def, const char *val, int op,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (def->callback)
|
if (do_callback && def->callback)
|
||||||
debug_return_bool(def->callback(&def->sd_un));
|
debug_return_bool(def->callback(&def->sd_un));
|
||||||
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct early_default *
|
||||||
|
is_early_default(const char *var)
|
||||||
|
{
|
||||||
|
struct early_default *early;
|
||||||
|
debug_decl(is_early_default, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
|
for (early = early_defaults; early->var != NULL; early++) {
|
||||||
|
if (strcmp(var, early->var) == 0)
|
||||||
|
debug_return_ptr(early);
|
||||||
|
}
|
||||||
|
debug_return_ptr(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets/clears an entry in the defaults structure
|
* Sets/clears an entry in the defaults structure.
|
||||||
* If a variable that takes a value is used in a boolean
|
* If a variable that takes a value is used in a boolean
|
||||||
* context with op == 0, disable that variable.
|
* context with op == 0, disable that variable.
|
||||||
* Eg. you may want to turn off logging to a file for some hosts.
|
* Eg. you may want to turn off logging to a file for some hosts.
|
||||||
* This is only meaningful for variables that are *optional*.
|
* This is only meaningful for variables that are *optional*.
|
||||||
*/
|
*/
|
||||||
bool
|
static struct sudo_defs_types *
|
||||||
set_default(const char *var, const char *val, int op, bool quiet)
|
set_default_int(const char *var, const char *val, int op, bool quiet,
|
||||||
|
bool do_callback)
|
||||||
{
|
{
|
||||||
struct sudo_defs_types *cur;
|
struct sudo_defs_types *cur;
|
||||||
int num;
|
int num;
|
||||||
debug_decl(set_default, SUDOERS_DEBUG_DEFAULTS)
|
debug_decl(set_default_int, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
|
for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
|
||||||
if (strcmp(var, cur->name) == 0)
|
if (strcmp(var, cur->name) == 0)
|
||||||
@@ -396,10 +399,66 @@ set_default(const char *var, const char *val, int op, bool quiet)
|
|||||||
if (!cur->name) {
|
if (!cur->name) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
sudo_warnx(U_("unknown defaults entry `%s'"), var);
|
sudo_warnx(U_("unknown defaults entry `%s'"), var);
|
||||||
debug_return_bool(false);
|
debug_return_ptr(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_return_bool(set_default_entry(cur, val, op, quiet));
|
if (!set_default_entry(cur, val, op, quiet, do_callback))
|
||||||
|
debug_return_ptr(NULL);
|
||||||
|
debug_return_ptr(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets/clears an entry in the defaults structure.
|
||||||
|
* Runs the callback if present on success.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
set_default(const char *var, const char *val, int op, bool quiet)
|
||||||
|
{
|
||||||
|
const struct sudo_defs_types *def;
|
||||||
|
debug_decl(set_default, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
|
def = set_default_int(var, val, op, quiet, true);
|
||||||
|
debug_return_bool(def != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like set_default() but stores the matching default value
|
||||||
|
* and does not run callbacks.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
set_early_default(const char *var, const char *val, int op, bool quiet,
|
||||||
|
struct early_default *early)
|
||||||
|
{
|
||||||
|
const struct sudo_defs_types *def;
|
||||||
|
debug_decl(set_early_default, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
|
def = set_default_int(var, val, op, quiet, false);
|
||||||
|
if (def == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
early->def = def;
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run callbacks for early defaults.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
run_early_defaults(void)
|
||||||
|
{
|
||||||
|
struct early_default *early;
|
||||||
|
bool rc = true;
|
||||||
|
debug_decl(run_early_defaults, SUDOERS_DEBUG_DEFAULTS)
|
||||||
|
|
||||||
|
for (early = early_defaults; early->var != NULL; early++) {
|
||||||
|
if (early->def == NULL)
|
||||||
|
continue;
|
||||||
|
if (early->def->callback != NULL) {
|
||||||
|
if (!early->def->callback(&early->def->sd_un))
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
early->def = NULL;
|
||||||
|
}
|
||||||
|
debug_return_bool(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -475,6 +534,9 @@ init_defaults(void)
|
|||||||
#ifdef USE_INSULTS
|
#ifdef USE_INSULTS
|
||||||
def_insults = true;
|
def_insults = true;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FQDN
|
||||||
|
def_fqdn = true;
|
||||||
|
#endif
|
||||||
#ifdef ENV_EDITOR
|
#ifdef ENV_EDITOR
|
||||||
def_env_editor = true;
|
def_env_editor = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -658,56 +720,6 @@ default_binding_matches(struct defaults *def, int what)
|
|||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
is_early_default(const char *var)
|
|
||||||
{
|
|
||||||
struct early_default *early;
|
|
||||||
debug_decl(is_early_default, SUDOERS_DEBUG_DEFAULTS)
|
|
||||||
|
|
||||||
for (early = early_defaults; early->var != NULL; early++) {
|
|
||||||
if (strcmp(var, early->var) == 0)
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
store_early_default(struct defaults *def, int what)
|
|
||||||
{
|
|
||||||
struct early_default *early;
|
|
||||||
debug_decl(store_early_default, SUDOERS_DEBUG_DEFAULTS)
|
|
||||||
|
|
||||||
for (early = early_defaults; early->var != NULL; early++) {
|
|
||||||
if (strcmp(def->var, early->var) == 0) {
|
|
||||||
if (default_type_matches(def, what) &&
|
|
||||||
default_binding_matches(def, what)) {
|
|
||||||
early->val = def->val;
|
|
||||||
early->op = def->op;
|
|
||||||
early->set = true;
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
apply_early_defaults(bool quiet)
|
|
||||||
{
|
|
||||||
struct early_default *early;
|
|
||||||
bool rc = true;
|
|
||||||
debug_decl(apply_early_defaults, SUDOERS_DEBUG_DEFAULTS)
|
|
||||||
|
|
||||||
for (early = early_defaults; early->var != NULL; early++) {
|
|
||||||
if (early->set) {
|
|
||||||
if (!set_default(early->var, early->val, early->op, quiet))
|
|
||||||
rc = false;
|
|
||||||
early->set = false; /* clean state for next run */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_bool(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the defaults based on what was set by sudoers.
|
* Update the defaults based on what was set by sudoers.
|
||||||
* Pass in an OR'd list of which default types to update.
|
* Pass in an OR'd list of which default types to update.
|
||||||
@@ -724,11 +736,20 @@ update_defaults(int what, bool quiet)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* First apply Defaults values marked as early.
|
* First apply Defaults values marked as early.
|
||||||
* We only set early Defaults once (the last instance).
|
|
||||||
*/
|
*/
|
||||||
TAILQ_FOREACH(def, &defaults, entries)
|
TAILQ_FOREACH(def, &defaults, entries) {
|
||||||
store_early_default(def, what);
|
struct early_default *early = is_early_default(def->var);
|
||||||
apply_early_defaults(quiet);
|
if (early == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!default_type_matches(def, what) ||
|
||||||
|
!default_binding_matches(def, what))
|
||||||
|
continue;
|
||||||
|
if (!set_early_default(def->var, def->val, def->op, quiet, early))
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
if (!run_early_defaults())
|
||||||
|
rc = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Then set the rest of the defaults.
|
* Then set the rest of the defaults.
|
||||||
@@ -773,8 +794,7 @@ check_defaults(int what, bool quiet)
|
|||||||
}
|
}
|
||||||
/* Don't actually set the defaults value, just checking. */
|
/* Don't actually set the defaults value, just checking. */
|
||||||
tmp = *cur;
|
tmp = *cur;
|
||||||
tmp.callback = NULL;
|
if (!set_default_entry(&tmp, def->val, def->op, quiet, false))
|
||||||
if (!set_default_entry(&tmp, def->val, def->op, quiet))
|
|
||||||
rc = false;
|
rc = false;
|
||||||
}
|
}
|
||||||
debug_return_bool(rc);
|
debug_return_bool(rc);
|
||||||
|
@@ -66,6 +66,14 @@ struct sudo_defs_types {
|
|||||||
union sudo_defs_val sd_un;
|
union sudo_defs_val sd_un;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defaults values to apply before others.
|
||||||
|
*/
|
||||||
|
struct early_default {
|
||||||
|
const char *var;
|
||||||
|
const struct sudo_defs_types *def;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Four types of defaults: strings, integers, and flags.
|
* Four types of defaults: strings, integers, and flags.
|
||||||
* Also, T_INT, T_FLOAT or T_STR may be ANDed with T_BOOL to indicate that
|
* Also, T_INT, T_FLOAT or T_STR may be ANDed with T_BOOL to indicate that
|
||||||
@@ -113,12 +121,12 @@ struct sudo_defs_types {
|
|||||||
*/
|
*/
|
||||||
struct defaults;
|
struct defaults;
|
||||||
void dump_default(void);
|
void dump_default(void);
|
||||||
bool apply_early_defaults(bool quiet);
|
|
||||||
bool check_defaults(int what, bool quiet);
|
bool check_defaults(int what, bool quiet);
|
||||||
bool init_defaults(void);
|
bool init_defaults(void);
|
||||||
bool is_early_default(const char *var);
|
struct early_default *is_early_default(const char *var);
|
||||||
|
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_default(const char *var, const char *val, int op, bool quiet);
|
bool set_default(const char *var, const char *val, int op, bool quiet);
|
||||||
bool store_early_default(struct defaults *def, int what);
|
|
||||||
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[];
|
||||||
|
@@ -1122,15 +1122,19 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
|
|||||||
|
|
||||||
/* 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;
|
||||||
|
|
||||||
if ((copy = strdup((*p)->bv_val)) == NULL) {
|
if ((copy = strdup((*p)->bv_val)) == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sudo_ldap_parse_option(copy, &def);
|
sudo_ldap_parse_option(copy, &def);
|
||||||
store_early_default(&def, SETDEF_GENERIC);
|
early = is_early_default(def.var);
|
||||||
|
if (early != NULL)
|
||||||
|
set_early_default(def.var, def.val, def.op, false, early);
|
||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
apply_early_defaults(false);
|
run_early_defaults();
|
||||||
|
|
||||||
/* walk through options again, skipping early ones */
|
/* walk through options again, skipping early ones */
|
||||||
for (p = bv; *p != NULL; p++) {
|
for (p = bv; *p != NULL; p++) {
|
||||||
@@ -1139,7 +1143,7 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sudo_ldap_parse_option(copy, &def);
|
sudo_ldap_parse_option(copy, &def);
|
||||||
if (!is_early_default(def.var))
|
if (is_early_default(def.var) == NULL)
|
||||||
set_default(def.var, def.val, def.op, false);
|
set_default(def.var, def.val, def.op, false);
|
||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
|
@@ -1204,14 +1204,19 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
|
|||||||
|
|
||||||
/* 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;
|
||||||
|
|
||||||
if ((copy = strdup(val_array[i])) == NULL) {
|
if ((copy = strdup(val_array[i])) == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sudo_sss_parse_option(copy, &def);
|
sudo_sss_parse_option(copy, &def);
|
||||||
store_early_default(&def, SETDEF_GENERIC);
|
early = is_early_default(def.var);
|
||||||
|
if (early != NULL)
|
||||||
|
set_early_default(def.var, def.val, def.op, false, early);
|
||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
|
run_early_defaults();
|
||||||
|
|
||||||
/* walk through options again, skipping early ones */
|
/* walk through options again, skipping early ones */
|
||||||
for (i = 0; val_array[i] != NULL; i++) {
|
for (i = 0; val_array[i] != NULL; i++) {
|
||||||
@@ -1220,7 +1225,7 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sudo_sss_parse_option(copy, &def);
|
sudo_sss_parse_option(copy, &def);
|
||||||
if (!is_early_default(def.var))
|
if (is_early_default(def.var) == NULL)
|
||||||
set_default(def.var, def.val, def.op, false);
|
set_default(def.var, def.val, def.op, false);
|
||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user