2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-02 15:25:58 +00:00

Add support for early defaults to the ldap and sssd backends.

This commit is contained in:
Todd C. Miller
2016-07-27 14:20:17 -06:00
parent cc31c2b241
commit 16551031f9
4 changed files with 224 additions and 122 deletions

View File

@@ -656,6 +656,55 @@ 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;
}
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. * 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.
@@ -663,7 +712,6 @@ default_binding_matches(struct defaults *def, int what)
bool bool
update_defaults(int what, bool quiet) update_defaults(int what, bool quiet)
{ {
struct early_default *early;
struct defaults *def; struct defaults *def;
bool rc = true; bool rc = true;
debug_decl(update_defaults, SUDOERS_DEBUG_DEFAULTS) debug_decl(update_defaults, SUDOERS_DEBUG_DEFAULTS)
@@ -672,40 +720,19 @@ update_defaults(int what, bool quiet)
"what: 0x%02x", what); "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). * We only set early Defaults once (the last instance).
*/ */
TAILQ_FOREACH(def, &defaults, entries) { TAILQ_FOREACH(def, &defaults, entries)
/* Skip any Defaults not marked as early. */ store_early_default(def, what);
for (early = early_defaults; early->var != NULL; early++) { apply_early_defaults(quiet);
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 */
}
}
/* /*
* Then set the rest of the defaults. * Then set the rest of the defaults.
*/ */
TAILQ_FOREACH(def, &defaults, entries) { TAILQ_FOREACH(def, &defaults, entries) {
/* Skip Defaults marked as early, we already did them. */ /* Skip Defaults marked as early, we already did them. */
for (early = early_defaults; early->var != NULL; early++) { if (is_early_default(def->var))
if (strcmp(def->var, early->var) == 0)
break;
}
if (early->var != NULL)
continue; continue;
if (!default_type_matches(def, what) || if (!default_type_matches(def, what) ||

View File

@@ -111,11 +111,15 @@ struct sudo_defs_types {
/* /*
* Prototypes * Prototypes
*/ */
struct defaults;
void dump_default(void); void dump_default(void);
bool init_defaults(void); bool apply_early_defaults(bool quiet);
bool set_default(const char *var, const char *val, int op, bool quiet);
bool update_defaults(int what, bool quiet);
bool check_defaults(int what, 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);
extern struct sudo_defs_types sudo_defs_table[]; extern struct sudo_defs_types sudo_defs_table[];

View File

@@ -61,6 +61,7 @@
#include "sudoers.h" #include "sudoers.h"
#include "parse.h" #include "parse.h"
#include "gram.h" /* for DEFAULTS */
#include "sudo_lbuf.h" #include "sudo_lbuf.h"
#include "sudo_dso.h" #include "sudo_dso.h"
@@ -1042,34 +1043,23 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
} }
/* /*
* Read sudoOption and modify the defaults as we go. This is used once * Parse an option string into a defaults structure.
* from the cn=defaults entry and also once when a final sudoRole is matched. * The members of def are pointers into optstr (which is modified).
*/ */
static bool static void
sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry) sudo_ldap_parse_option(char *optstr, struct defaults *def)
{ {
struct berval **bv, **p; char *cp, *val = NULL;
char *copy, *cp, *var; char *var = optstr;
int op; int op;
bool rc = false; debug_decl(sudo_ldap_parse_option, SUDOERS_DEBUG_LDAP)
debug_decl(sudo_ldap_parse_options, SUDOERS_DEBUG_LDAP)
bv = ldap_get_values_len(ld, entry, "sudoOption"); DPRINTF2("ldap sudoOption: '%s'", optstr);
if (bv == NULL)
debug_return_bool(true);
/* walk through options */
for (p = bv; *p != NULL; p++) {
if ((copy = var = strdup((*p)->bv_val)) == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto done;
}
DPRINTF2("ldap sudoOption: '%s'", var);
/* check for equals sign past first char */ /* check for equals sign past first char */
cp = strchr(var, '='); cp = strchr(var, '=');
if (cp > var) { if (cp > var) {
char *val = cp + 1; val = cp + 1;
op = cp[-1]; /* peek for += or -= cases */ op = cp[-1]; /* peek for += or -= cases */
if (op == '+' || op == '-') { if (op == '+' || op == '-') {
/* case var+=val or var-=val */ /* case var+=val or var-=val */
@@ -1094,25 +1084,71 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
ep[-1] = '\0'; ep[-1] = '\0';
} }
} }
set_default(var, val, op, false); } else {
} else if (*var == '!') { /* Boolean value, either true or false. */
/* case !var Boolean False */ op = true;
while (*var == '!') {
op = !op;
do { do {
var++; var++;
} while (isblank((unsigned char)*var)); } while (isblank((unsigned char)*var));
set_default(var, NULL, false, false);
} else {
/* case var Boolean True */
set_default(var, NULL, true, false);
} }
}
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.
*/
static bool
sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
{
struct berval **bv, **p;
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, early ones first */
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);
store_early_default(&def, SETDEF_GENERIC);
free(copy); free(copy);
} }
rc = true; apply_early_defaults(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);
}
ret = true;
done: done:
ldap_value_free_len(bv); ldap_value_free_len(bv);
debug_return_bool(rc); debug_return_bool(ret);
} }
/* /*

View File

@@ -45,6 +45,7 @@
#include "sudoers.h" #include "sudoers.h"
#include "parse.h" #include "parse.h"
#include "gram.h" /* for DEFAULTS */
#include "sudo_lbuf.h" #include "sudo_lbuf.h"
#include "sudo_dso.h" #include "sudo_dso.h"
@@ -1116,12 +1117,74 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
debug_return_int(ret); 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 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;
char *copy;
bool ret = false; bool ret = false;
char *copy, *cp, *v; struct defaults def;
char **val_array = NULL; char **val_array = NULL;
debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD); 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); debug_return_bool(false);
} }
/* walk through options */ /* walk through options, early ones first */
for (i = 0; val_array[i] != NULL; i++) { for (i = 0; val_array[i] != NULL; i++) {
sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", if ((copy = strdup(val_array[i])) == NULL) {
val_array[i]);
if ((v = 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);
store_early_default(&def, SETDEF_GENERIC);
free(copy);
}
/* check for equals sign past first char */ /* walk through options again, skipping early ones */
cp = strchr(v, '='); for (i = 0; val_array[i] != NULL; i++) {
if (cp > v) { if ((copy = strdup(val_array[i])) == NULL) {
char *val = cp + 1; sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
op = cp[-1]; /* peek for += or -= cases */ goto done;
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);
} }
sudo_sss_parse_option(copy, &def);
if (!is_early_default(def.var))
set_default(def.var, def.val, def.op, false);
free(copy); free(copy);
} }
ret = true; ret = true;