]> granicus.if.org Git - sudo/commitdiff
Instead of deferring setting early defaults until we have traversed
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 8 Aug 2016 23:04:20 +0000 (17:04 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 8 Aug 2016 23:04:20 +0000 (17:04 -0600)
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.

plugins/sudoers/defaults.c
plugins/sudoers/defaults.h
plugins/sudoers/ldap.c
plugins/sudoers/sssd.c

index 3292eb3857313f61b076454c314620db0df35ef0..20b93d5ab63c7f46945f568e75a8e64e273d81b1 100644 (file)
@@ -76,19 +76,9 @@ static struct strmap priorities[] = {
        { 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[] = {
 #ifdef FQDN
-    { "fqdn", NULL, true },
+    { "fqdn", &sudo_defs_table[I_FQDN] },
 #else
     { "fqdn" },
 #endif
@@ -199,8 +189,7 @@ dump_defaults(void)
 }
 
 static bool
-set_default_entry(struct sudo_defs_types *def, const char *val, int op,
-    bool quiet)
+set_default_entry(struct sudo_defs_types *def, const char *val, int op, bool quiet, bool do_callback)
 {
     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;
     }
-    if (def->callback)
+    if (do_callback && def->callback)
        debug_return_bool(def->callback(&def->sd_un));
 
     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
  * context with op == 0, disable that variable.
  * Eg. you may want to turn off logging to a file for some hosts.
  * This is only meaningful for variables that are *optional*.
  */
-bool
-set_default(const char *var, const char *val, int op, bool quiet)
+static struct sudo_defs_types *
+set_default_int(const char *var, const char *val, int op, bool quiet,
+    bool do_callback)
 {
     struct sudo_defs_types *cur;
     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++) {
        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 (!quiet)
            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
     def_insults = true;
 #endif
+#ifdef FQDN
+    def_fqdn = true;
+#endif
 #ifdef ENV_EDITOR
     def_env_editor = true;
 #endif
@@ -658,56 +720,6 @@ default_binding_matches(struct defaults *def, int what)
     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.
  * 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.
-     * We only set early Defaults once (the last instance).
      */
-    TAILQ_FOREACH(def, &defaults, entries)
-       store_early_default(def, what);
-    apply_early_defaults(quiet);
+    TAILQ_FOREACH(def, &defaults, entries) {
+       struct early_default *early = is_early_default(def->var);
+       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.
@@ -773,8 +794,7 @@ check_defaults(int what, bool quiet)
        }
        /* Don't actually set the defaults value, just checking. */
        tmp = *cur;
-       tmp.callback = NULL;
-       if (!set_default_entry(&tmp, def->val, def->op, quiet))
+       if (!set_default_entry(&tmp, def->val, def->op, quiet, false))
            rc = false;
     }
     debug_return_bool(rc);
index 2bc1481c44badd1f22f187db0124f502343322a6..ae5073e11f8128118a96caebec583c244b380f72 100644 (file)
@@ -66,6 +66,14 @@ struct sudo_defs_types {
     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.
  * 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;
 void dump_default(void);
-bool apply_early_defaults(bool quiet);
 bool check_defaults(int what, bool quiet);
 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 store_early_default(struct defaults *def, int what);
 bool update_defaults(int what, bool quiet);
 
 extern struct sudo_defs_types sudo_defs_table[];
index a1eec55c61bfe8ec2012bf2f4bed80300dfb49a9..8378c0ca19705a6779f4bc4f231a4b3881081f9d 100644 (file)
@@ -1122,15 +1122,19 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
 
     /* walk through options, early ones first */
     for (p = bv; *p != NULL; p++) {
+       struct early_default *early;
+
        if ((copy = strdup((*p)->bv_val)) == NULL) {
            sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
            goto done;
        }
        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);
     }
-    apply_early_defaults(false);
+    run_early_defaults();
 
     /* walk through options again, skipping early ones */
     for (p = bv; *p != NULL; p++) {
@@ -1139,7 +1143,7 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
            goto done;
        }
        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);
        free(copy);
     }
index f96fd2d33f446a1dca43904c1c271c5aadca6030..9d6640cac74d14f0344694e30f7b66ea664a6fa7 100644 (file)
@@ -1204,14 +1204,19 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
 
     /* walk through options, early ones first */
     for (i = 0; val_array[i] != NULL; i++) {
+       struct early_default *early;
+
        if ((copy = strdup(val_array[i])) == NULL) {
            sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
            goto done;
        }
        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);
     }
+    run_early_defaults();
 
     /* walk through options again, skipping early ones */
     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;
        }
        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);
        free(copy);
     }