]> granicus.if.org Git - sudo/commitdiff
Add support for early defaults to the ldap and sssd backends.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 27 Jul 2016 20:20:17 +0000 (14:20 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 27 Jul 2016 20:20:17 +0000 (14:20 -0600)
plugins/sudoers/defaults.c
plugins/sudoers/defaults.h
plugins/sudoers/ldap.c
plugins/sudoers/sssd.c

index d0f8c114f4f61b1bd924b1b0a3a3928b4ab2ed35..8db775a822746bce6717ace9628a60f10cbb4218 100644 (file)
@@ -656,6 +656,55 @@ 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;
+           }
+           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->val != NULL) {
+           if (!set_default(early->var, early->val, early->op, quiet))
+               rc = false;
+           early->val = NULL;          /* 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.
@@ -663,7 +712,6 @@ default_binding_matches(struct defaults *def, int what)
 bool
 update_defaults(int what, bool quiet)
 {
-    struct early_default *early;
     struct defaults *def;
     bool rc = true;
     debug_decl(update_defaults, SUDOERS_DEBUG_DEFAULTS)
@@ -672,40 +720,19 @@ update_defaults(int what, bool quiet)
        "what: 0x%02x", what);
 
     /*
-     * First set 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) {
-       /* Skip any Defaults not marked as early. */
-       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;
-               }
-               break;
-           }
-       }
-    }
-    for (early = early_defaults; early->var != NULL; early++) {
-       if (early->val != NULL) {
-           if (!set_default(early->var, early->val, early->op, quiet))
-               rc = false;
-           early->val = NULL;          /* clean state for next run */
-       }
-    }
+    TAILQ_FOREACH(def, &defaults, entries)
+       store_early_default(def, what);
+    apply_early_defaults(quiet);
 
     /*
      * Then set the rest of the defaults.
      */
     TAILQ_FOREACH(def, &defaults, entries) {
        /* Skip Defaults marked as early, we already did them. */
-       for (early = early_defaults; early->var != NULL; early++) {
-           if (strcmp(def->var, early->var) == 0)
-               break;
-       }
-       if (early->var != NULL)
+       if (is_early_default(def->var))
            continue;
 
        if (!default_type_matches(def, what) ||
index 06a5d607c163fabd4a53970286fa7d5cb58b815a..2bc1481c44badd1f22f187db0124f502343322a6 100644 (file)
@@ -111,11 +111,15 @@ struct sudo_defs_types {
 /*
  * Prototypes
  */
+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);
 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 check_defaults(int what, bool quiet);
 
 extern struct sudo_defs_types sudo_defs_table[];
 
index 400c1f421b94f830581bfae0562482db2c0778aa..a1eec55c61bfe8ec2012bf2f4bed80300dfb49a9 100644 (file)
@@ -61,6 +61,7 @@
 
 #include "sudoers.h"
 #include "parse.h"
+#include "gram.h"      /* for DEFAULTS */
 #include "sudo_lbuf.h"
 #include "sudo_dso.h"
 
@@ -1041,6 +1042,67 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
     debug_return_int(ret);
 }
 
+/*
+ * Parse an option string into a defaults structure.
+ * The members of def are pointers into optstr (which is modified).
+ */
+static void
+sudo_ldap_parse_option(char *optstr, struct defaults *def)
+{
+    char *cp, *val = NULL;
+    char *var = optstr;
+    int op;
+    debug_decl(sudo_ldap_parse_option, SUDOERS_DEBUG_LDAP)
+
+    DPRINTF2("ldap sudoOption: '%s'", optstr);
+
+    /* check for equals sign past first char */
+    cp = strchr(var, '=');
+    if (cp > var) {
+       val = cp + 1;
+       op = cp[-1];    /* peek for += or -= cases */
+       if (op == '+' || op == '-') {
+           /* case var+=val or var-=val */
+           cp--;
+       } else {
+           /* case var=val */
+           op = true;
+       }
+       /* Trim whitespace between var and operator. */
+       while (cp > var && isblank((unsigned char)cp[-1]))
+           cp--;
+       /* Truncate variable name. */
+       *cp = '\0';
+       /* Trim leading whitespace from val. */
+       while (isblank((unsigned char)*val))
+           val++;
+       /* Strip double quotes if present. */
+       if (*val == '"') {
+           char *ep = val + strlen(val);
+           if (ep != val && ep[-1] == '"') {
+               val++;
+               ep[-1] = '\0';
+           }
+       }
+    } else {
+       /* Boolean value, either true or false. */
+       op = true;
+       while (*var == '!') {
+           op = !op;
+           do {
+               var++;
+           } while (isblank((unsigned char)*var));
+       }
+    }
+    def->var = var;
+    def->val = val;
+    def->op = op;
+    def->type = DEFAULTS;
+    def->binding = NULL;
+
+    debug_return;
+}
+
 /*
  * Read sudoOption and modify the defaults as we go.  This is used once
  * from the cn=defaults entry and also once when a final sudoRole is matched.
@@ -1049,70 +1111,44 @@ static bool
 sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
 {
     struct berval **bv, **p;
-    char *copy, *cp, *var;
-    int op;
-    bool rc = false;
+    struct defaults def;
+    char *copy;
+    bool ret = false;
     debug_decl(sudo_ldap_parse_options, SUDOERS_DEBUG_LDAP)
 
     bv = ldap_get_values_len(ld, entry, "sudoOption");
     if (bv == NULL)
        debug_return_bool(true);
 
-    /* walk through options */
+    /* walk through options, early ones first */
     for (p = bv; *p != NULL; p++) {
-       if ((copy = var = strdup((*p)->bv_val)) == NULL) {
+       if ((copy = strdup((*p)->bv_val)) == NULL) {
            sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
            goto done;
        }
-       DPRINTF2("ldap sudoOption: '%s'", var);
+       sudo_ldap_parse_option(copy, &def);
+       store_early_default(&def, SETDEF_GENERIC);
+       free(copy);
+    }
+    apply_early_defaults(false);
 
-       /* check for equals sign past first char */
-       cp = strchr(var, '=');
-       if (cp > var) {
-           char *val = cp + 1;
-           op = cp[-1];        /* peek for += or -= cases */
-           if (op == '+' || op == '-') {
-               /* case var+=val or var-=val */
-               cp--;
-           } else {
-               /* case var=val */
-               op = true;
-           }
-           /* Trim whitespace between var and operator. */
-           while (cp > var && isblank((unsigned char)cp[-1]))
-               cp--;
-           /* Truncate variable name. */
-           *cp = '\0';
-           /* Trim leading whitespace from val. */
-           while (isblank((unsigned char)*val))
-               val++;
-           /* Strip double quotes if present. */
-           if (*val == '"') {
-               char *ep = val + strlen(val);
-               if (ep != val && ep[-1] == '"') {
-                   val++;
-                   ep[-1] = '\0';
-               }
-           }
-           set_default(var, val, op, false);
-       } else if (*var == '!') {
-           /* case !var Boolean False */
-           do {
-               var++;
-           } while (isblank((unsigned char)*var));
-           set_default(var, NULL, false, false);
-       } else {
-           /* case var Boolean True */
-           set_default(var, NULL, true, false);
+    /* walk through options again, skipping early ones */
+    for (p = bv; *p != NULL; p++) {
+       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);
+       if (!is_early_default(def.var))
+           set_default(def.var, def.val, def.op, false);
        free(copy);
     }
-    rc = true;
+    ret = true;
 
 done:
     ldap_value_free_len(bv);
 
-    debug_return_bool(rc);
+    debug_return_bool(ret);
 }
 
 /*
index ff3c8f95d7ffabdbee30d4b7ef9040ffba3a68ab..f96fd2d33f446a1dca43904c1c271c5aadca6030 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "sudoers.h"
 #include "parse.h"
+#include "gram.h"      /* for DEFAULTS */
 #include "sudo_lbuf.h"
 #include "sudo_dso.h"
 
@@ -1116,12 +1117,74 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
     debug_return_int(ret);
 }
 
+/*
+ * Parse an option string into a defaults structure.
+ * The members of def are pointers into optstr (which is modified).
+ */
+static void
+sudo_sss_parse_option(char *optstr, struct defaults *def)
+{
+    char *cp, *val = NULL;
+    char *var = optstr;
+    int op;
+    debug_decl(sudo_sss_parse_option, SUDOERS_DEBUG_SSSD)
+
+    sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", optstr);
+
+    /* check for equals sign past first char */
+    cp = strchr(var, '=');
+    if (cp > var) {
+       val = cp + 1;
+       op = cp[-1];    /* peek for += or -= cases */
+       if (op == '+' || op == '-') {
+           /* case var+=val or var-=val */
+           cp--;
+       } else {
+           /* case var=val */
+           op = true;
+       }
+       /* Trim whitespace between var and operator. */
+       while (cp > var && isblank((unsigned char)cp[-1]))
+           cp--;
+       /* Truncate variable name. */
+       *cp = '\0';
+       /* Trim leading whitespace from val. */
+       while (isblank((unsigned char)*val))
+           val++;
+       /* Strip double quotes if present. */
+       if (*val == '"') {
+           char *ep = val + strlen(val);
+           if (ep != val && ep[-1] == '"') {
+               val++;
+               ep[-1] = '\0';
+           }
+       }
+    } else {
+       /* Boolean value, either true or false. */
+       op = true;
+       while (*var == '!') {
+           op = !op;
+           do {
+               var++;
+           } while (isblank((unsigned char)*var));
+       }
+    }
+    def->var = var;
+    def->val = val;
+    def->op = op;
+    def->type = DEFAULTS;
+    def->binding = NULL;
+
+    debug_return;
+}
+
 static bool
 sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
 {
-    int i, op;
+    int i;
+    char *copy;
     bool ret = false;
-    char *copy, *cp, *v;
+    struct defaults def;
     char **val_array = NULL;
     debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD);
 
@@ -1139,54 +1202,26 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
        debug_return_bool(false);
     }
 
-    /* walk through options */
+    /* walk through options, early ones first */
     for (i = 0; val_array[i] != NULL; i++) {
-       sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'",
-        val_array[i]);
-       if ((v = copy = strdup(val_array[i])) == NULL) {
+       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);
+       free(copy);
+    }
 
-       /* check for equals sign past first char */
-       cp = strchr(v, '=');
-       if (cp > v) {
-           char *val = cp + 1;
-           op = cp[-1];        /* peek for += or -= cases */
-           if (op == '+' || op == '-') {
-               /* case var+=val or var-=val */
-               cp--;
-           } else {
-               /* case var=val */
-               op = true;
-           }
-           /* Trim whitespace between var and operator. */
-           while (cp > v && isblank((unsigned char)cp[-1]))
-               cp--;
-           /* Truncate variable name. */
-           *cp = '\0';
-           /* Trim leading whitespace from val. */
-           while (isblank((unsigned char)*val))
-               val++;
-           /* Strip double quotes if present. */
-           if (*val == '"') {
-               char *ep = val + strlen(val);
-               if (ep != val && ep[-1] == '"') {
-                   val++;
-                   ep[-1] = '\0';
-               }
-           }
-           set_default(v, val, op, false);
-       } else if (*v == '!') {
-           /* case !var Boolean False */
-           do {
-               v++;
-           } while (isblank((unsigned char)*v));
-           set_default(v, NULL, false, false);
-       } else {
-           /* case var Boolean True */
-           set_default(v, NULL, true, false);
+    /* walk through options again, skipping early ones */
+    for (i = 0; val_array[i] != NULL; i++) {
+       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);
+       if (!is_early_default(def.var))
+           set_default(def.var, def.val, def.op, false);
        free(copy);
     }
     ret = true;