Use non-exiting allocators in the sudoers SSSD backend.

This commit is contained in:
Todd C. Miller
2015-06-16 15:00:47 -06:00
parent 5413637ae8
commit 6da04821d7

View File

@@ -103,7 +103,7 @@ struct sudo_sss_handle {
static int sudo_sss_open(struct sudo_nss *nss);
static int sudo_sss_close(struct sudo_nss *nss);
static int sudo_sss_parse(struct sudo_nss *nss);
static void sudo_sss_parse_options(struct sudo_sss_handle *handle,
static bool sudo_sss_parse_options(struct sudo_sss_handle *handle,
struct sss_sudo_rule *rule);
static int sudo_sss_setdefs(struct sudo_nss *nss);
static int sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag);
@@ -123,40 +123,96 @@ static struct sss_sudo_result *sudo_sss_result_get(struct sudo_nss *nss,
uint32_t *state);
static void
sudo_sss_attrfree(struct sss_sudo_attr *attr)
{
unsigned int i;
debug_decl(sudo_sss_attrfree, SUDOERS_DEBUG_SSSD)
free(attr->name);
attr->name = NULL;
if (attr->values != NULL) {
for (i = 0; i < attr->num_values; ++i)
free(attr->values[i]);
free(attr->values);
attr->values = NULL;
}
attr->num_values = 0;
debug_return;
}
static bool
sudo_sss_attrcpy(struct sss_sudo_attr *dst, const struct sss_sudo_attr *src)
{
unsigned int i;
debug_decl(sudo_sss_attrcpy, SUDOERS_DEBUG_SSSD)
unsigned int i = 0;
debug_decl(sudo_sss_attrcpy, SUDOERS_DEBUG_SSSD)
sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_emalloc: cnt=%d", src->num_values);
sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
sudo_debug_printf(SUDO_DEBUG_INFO, "malloc: cnt=%d", src->num_values);
dst->name = sudo_estrdup(src->name);
dst->num_values = src->num_values;
dst->values = sudo_emallocarray(dst->num_values, sizeof(char *));
dst->name = strdup(src->name);
dst->values = reallocarray(NULL, dst->num_values, sizeof(char *));
if (dst->name == NULL || dst->values == NULL)
goto oom;
dst->num_values = src->num_values;
for (i = 0; i < dst->num_values; ++i)
dst->values[i] = sudo_estrdup(src->values[i]);
for (i = 0; i < dst->num_values; ++i) {
dst->values[i] = strdup(src->values[i]);
if (dst->values[i] == NULL) {
dst->num_values = i;
goto oom;
}
}
debug_return;
debug_return_bool(true);
oom:
sudo_warnx(U_("unable to allocate memory"));
sudo_sss_attrfree(dst);
debug_return_bool(false);
}
static void
sudo_sss_rulefree(struct sss_sudo_rule *rule)
{
unsigned int i;
debug_decl(sudo_sss_rulefree, SUDOERS_DEBUG_SSSD)
for (i = 0; i < rule->num_attrs; ++i)
sudo_sss_attrfree(rule->attrs + i);
free(rule->attrs);
rule->attrs = NULL;
rule->num_attrs = 0;
debug_return;
}
static bool
sudo_sss_rulecpy(struct sss_sudo_rule *dst, const struct sss_sudo_rule *src)
{
unsigned int i;
debug_decl(sudo_sss_rulecpy, SUDOERS_DEBUG_SSSD)
unsigned int i;
debug_decl(sudo_sss_rulecpy, SUDOERS_DEBUG_SSSD)
sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_emalloc: cnt=%d", src->num_attrs);
sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
sudo_debug_printf(SUDO_DEBUG_INFO, "malloc: cnt=%d", src->num_attrs);
dst->num_attrs = src->num_attrs;
dst->attrs = sudo_emallocarray(dst->num_attrs, sizeof(struct sss_sudo_attr));
dst->num_attrs = 0;
dst->attrs = reallocarray(NULL, src->num_attrs, sizeof(struct sss_sudo_attr));
if (dst->attrs == NULL) {
sudo_warnx(U_("unable to allocate memory"));
debug_return_bool(false);
}
for (i = 0; i < dst->num_attrs; ++i)
sudo_sss_attrcpy(dst->attrs + i, src->attrs + i);
for (i = 0; i < src->num_attrs; ++i) {
if (!sudo_sss_attrcpy(dst->attrs + i, src->attrs + i)) {
sudo_warnx(U_("unable to allocate memory"));
dst->num_attrs = i;
sudo_sss_rulefree(dst);
debug_return_bool(false);
}
}
dst->num_attrs = i;
debug_return;
debug_return_bool(true);
}
#define SUDO_SSS_FILTER_INCLUDE 0
@@ -183,12 +239,21 @@ sudo_sss_filter_result(struct sudo_sss_handle *handle,
if (in_res == NULL)
debug_return_ptr(NULL);
sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_emalloc: cnt=%d", in_res->num_rules);
sudo_debug_printf(SUDO_DEBUG_DEBUG, "malloc: cnt=%d", in_res->num_rules);
out_res = sudo_emalloc(sizeof(struct sss_sudo_result));
out_res->rules = in_res->num_rules > 0 ?
sudo_emallocarray(in_res->num_rules, sizeof(struct sss_sudo_rule)) : NULL;
out_res->num_rules = 0;
if ((out_res = calloc(1, sizeof(struct sss_sudo_result))) == NULL) {
sudo_warnx(U_("unable to allocate memory"));
debug_return_ptr(NULL);
}
if (in_res->num_rules > 0) {
out_res->rules =
reallocarray(NULL, in_res->num_rules, sizeof(struct sss_sudo_rule));
if (out_res->rules == NULL) {
sudo_warnx(U_("unable to allocate memory"));
free(out_res);
debug_return_ptr(NULL);
}
}
for (i = l = 0; i < in_res->num_rules; ++i) {
r = filterp(handle, in_res->rules + i, filterp_arg);
@@ -200,7 +265,14 @@ sudo_sss_filter_result(struct sudo_sss_handle *handle,
act == SUDO_SSS_FILTER_EXCLUDE ? "not excluded" : "included",
in_res->rules, i, out_res->rules, l, in_res->rules + i);
sudo_sss_rulecpy(out_res->rules + l, in_res->rules + i);
if (!sudo_sss_rulecpy(out_res->rules + l, in_res->rules + i)) {
while (l--) {
sudo_sss_rulefree(out_res->rules + l);
}
free(out_res->rules);
free(out_res);
debug_return_ptr(NULL);
}
++l;
}
}
@@ -210,10 +282,20 @@ sudo_sss_filter_result(struct sudo_sss_handle *handle,
"reallocating result: %p (count: %u -> %u)", out_res->rules,
in_res->num_rules, l);
if (l > 0) {
out_res->rules =
sudo_ereallocarray(out_res->rules, l, sizeof(struct sss_sudo_rule));
struct sss_sudo_rule *rules =
reallocarray(out_res->rules, l, sizeof(struct sss_sudo_rule));
if (out_res->rules == NULL) {
sudo_warnx(U_("unable to allocate memory"));
while (l--) {
sudo_sss_rulefree(out_res->rules + l);
}
free(out_res->rules);
free(out_res);
debug_return_ptr(NULL);
}
out_res->rules = rules;
} else {
sudo_efree(out_res->rules);
free(out_res->rules);
out_res->rules = NULL;
}
}
@@ -238,20 +320,26 @@ struct sudo_nss sudo_nss_sss = {
/* sudo_nss implementation */
// ok
static int sudo_sss_open(struct sudo_nss *nss)
static int
sudo_sss_open(struct sudo_nss *nss)
{
struct sudo_sss_handle *handle;
static const char path[] = _PATH_SSSD_LIB"/libsss_sudo.so";
debug_decl(sudo_sss_open, SUDOERS_DEBUG_SSSD);
/* Create a handle container. */
handle = sudo_emalloc(sizeof(struct sudo_sss_handle));
handle = malloc(sizeof(struct sudo_sss_handle));
if (handle == NULL) {
sudo_warnx(U_("unable to allocate memory"));
debug_return_int(ENOMEM);
}
/* Load symbols */
handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
if (handle->ssslib == NULL) {
sudo_warnx(U_("unable to load %s: %s"), path, sudo_dso_strerror());
sudo_warnx(U_("unable to initialize SSS source. Is SSSD installed on your machine?"));
free(handle);
debug_return_int(EFAULT);
}
@@ -260,6 +348,7 @@ static int sudo_sss_open(struct sudo_nss *nss)
if (handle->fn_send_recv == NULL) {
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
"sss_sudo_send_recv");
free(handle);
debug_return_int(EFAULT);
}
@@ -268,6 +357,7 @@ static int sudo_sss_open(struct sudo_nss *nss)
if (handle->fn_send_recv_defaults == NULL) {
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
"sss_sudo_send_recv_defaults");
free(handle);
debug_return_int(EFAULT);
}
@@ -276,6 +366,7 @@ static int sudo_sss_open(struct sudo_nss *nss)
if (handle->fn_free_result == NULL) {
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
"sss_sudo_free_result");
free(handle);
debug_return_int(EFAULT);
}
@@ -284,6 +375,7 @@ static int sudo_sss_open(struct sudo_nss *nss)
if (handle->fn_get_values == NULL) {
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
"sss_sudo_get_values");
free(handle);
debug_return_int(EFAULT);
}
@@ -292,6 +384,7 @@ static int sudo_sss_open(struct sudo_nss *nss)
if (handle->fn_free_values == NULL) {
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
"sss_sudo_free_values");
free(handle);
debug_return_int(EFAULT);
}
@@ -305,7 +398,8 @@ static int sudo_sss_open(struct sudo_nss *nss)
}
// ok
static int sudo_sss_close(struct sudo_nss *nss)
static int
sudo_sss_close(struct sudo_nss *nss)
{
struct sudo_sss_handle *handle;
debug_decl(sudo_sss_close, SUDOERS_DEBUG_SSSD);
@@ -313,22 +407,23 @@ static int sudo_sss_close(struct sudo_nss *nss)
if (nss && nss->handle) {
handle = nss->handle;
sudo_dso_unload(handle->ssslib);
sudo_efree(nss->handle);
free(nss->handle);
}
debug_return_int(0);
}
// ok
static int sudo_sss_parse(struct sudo_nss *nss)
static int
sudo_sss_parse(struct sudo_nss *nss)
{
debug_decl(sudo_sss_parse, SUDOERS_DEBUG_SSSD);
debug_return_int(0);
}
static int sudo_sss_setdefs(struct sudo_nss *nss)
static int
sudo_sss_setdefs(struct sudo_nss *nss)
{
struct sudo_sss_handle *handle = nss->handle;
struct sss_sudo_result *sss_result;
struct sss_sudo_rule *sss_rule;
uint32_t sss_error;
@@ -347,27 +442,34 @@ static int sudo_sss_setdefs(struct sudo_nss *nss)
"handle->fn_send_recv_defaults: != 0, sss_error=%u", sss_error);
debug_return_int(-1);
}
if (sss_error == ENOENT) {
sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
debug_return_int(0);
} else if(sss_error != 0) {
if (sss_error != 0) {
if (sss_error == ENOENT) {
sudo_debug_printf(SUDO_DEBUG_INFO,
"The user was not found in SSSD.");
goto done;
}
sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
debug_return_int(-1);
goto bad;
}
for (i = 0; i < sss_result->num_rules; ++i) {
sudo_debug_printf(SUDO_DEBUG_DIAG,
"Parsing cn=defaults, %d/%d", i, sss_result->num_rules);
sss_rule = sss_result->rules + i;
sudo_sss_parse_options(handle, sss_rule);
if (!sudo_sss_parse_options(handle, sss_rule))
goto bad;
}
done:
handle->fn_free_result(sss_result);
debug_return_int(0);
bad:
handle->fn_free_result(sss_result);
debug_return_int(-1);
}
static int sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw)
static int
sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw)
{
struct sudo_sss_handle *handle = nss->handle;
debug_decl(sudo_sss_checkpw, SUDOERS_DEBUG_SSSD);
@@ -818,7 +920,11 @@ sudo_sss_extract_digest(char **cmnd, struct sudo_digest *digest)
ep++;
if (*ep != '\0') {
digest->digest_type = digest_type;
digest->digest_str = sudo_estrndup(cp, (size_t)(ep - cp));
digest->digest_str = strndup(cp, (size_t)(ep - cp));
if (digest->digest_str == NULL) {
sudo_warnx(U_("unable to allocate memory"));
debug_return_ptr(NULL);
}
cp = ep + 1;
while (isblank((unsigned char)*cp))
cp++;
@@ -888,10 +994,10 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
/* check for !command */
if (*val == '!') {
foundbang = true;
allowed_cmnd = sudo_estrdup(1 + val); /* !command */
allowed_cmnd = val + 1; /* !command */
} else {
foundbang = false;
allowed_cmnd = sudo_estrdup(val); /* command */
allowed_cmnd = val; /* command */
}
/* split optional args away from command */
@@ -907,12 +1013,13 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
*/
ret = foundbang ? false : true;
}
if (allowed_args != NULL)
allowed_args[-1] = ' '; /* restore val */
sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoCommand '%s' ... %s",
val, ret == true ? "MATCH!" : "not");
sudo_efree(allowed_cmnd); /* cleanup */
if (allowed_digest != NULL)
sudo_efree(allowed_digest->digest_str);
free(allowed_digest->digest_str);
}
handle->fn_free_values(val_array); /* more cleanup */
@@ -920,33 +1027,37 @@ sudo_sss_check_command(struct sudo_sss_handle *handle,
debug_return_int(ret);
}
static void
static bool
sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
{
int i;
bool ret = false;
char op, *v, *val;
char **val_array = NULL;
debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD);
if (rule == NULL)
debug_return;
debug_return_bool(true);
switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
case 0:
break;
case ENOENT:
sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
debug_return;
debug_return_bool(true);
default:
sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0");
debug_return;
debug_return_bool(false);
}
/* walk through options */
for (i = 0; val_array[i] != NULL; i++) {
sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'",
val_array[i]);
v = sudo_estrdup(val_array[i]);
if ((v = strdup(val_array[i])) == NULL) {
sudo_warnx(U_("unable to allocate memory"));
goto done;
}
/* check for equals sign past first char */
val = strchr(v, '=');
@@ -968,11 +1079,13 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul
/* case var Boolean True */
set_default(v, NULL, true);
}
sudo_efree(v);
free(v);
}
ret = true;
done:
handle->fn_free_values(val_array);
debug_return;
debug_return_bool(ret);
}
static int
@@ -1059,16 +1172,19 @@ sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag)
/* Apply entry-specific options. */
if (setenv_implied)
def_setenv = true;
sudo_sss_parse_options(handle, rule);
if (sudo_sss_parse_options(handle, rule)) {
#ifdef HAVE_SELINUX
/* Set role and type if not specified on command line. */
if (user_role == NULL)
user_role = def_role;
if (user_type == NULL)
user_type = def_type;
/* Set role/type if not specified on command line. */
if (user_role == NULL)
user_role = def_role;
if (user_type == NULL)
user_type = def_type;
#endif /* HAVE_SELINUX */
SET(ret, VALIDATE_SUCCESS);
CLR(ret, VALIDATE_FAILURE);
SET(ret, VALIDATE_SUCCESS);
CLR(ret, VALIDATE_FAILURE);
} else {
SET(ret, VALIDATE_ERROR);
}
} else {
SET(ret, VALIDATE_FAILURE);
CLR(ret, VALIDATE_SUCCESS);