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:
@@ -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) ||
|
||||||
|
@@ -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[];
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user