From: Todd C. Miller Date: Tue, 16 Jun 2015 21:00:47 +0000 (-0600) Subject: Use non-exiting allocators in the sudoers SSSD backend. X-Git-Tag: SUDO_1_8_14^2~87 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6da04821d75462bc765ae824c46e6353406aae8c;p=sudo Use non-exiting allocators in the sudoers SSSD backend. --- diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c index 3f8b0b6b0..1effdd684 100644 --- a/plugins/sudoers/sssd.c +++ b/plugins/sudoers/sssd.c @@ -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, "malloc: cnt=%d", src->num_values); + + 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] = strdup(src->values[i]); + if (dst->values[i] == NULL) { + dst->num_values = i; + goto oom; + } + } - 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); + debug_return_bool(true); +oom: + sudo_warnx(U_("unable to allocate memory")); + sudo_sss_attrfree(dst); + debug_return_bool(false); +} - dst->name = sudo_estrdup(src->name); - dst->num_values = src->num_values; - dst->values = sudo_emallocarray(dst->num_values, sizeof(char *)); +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 < dst->num_values; ++i) - dst->values[i] = sudo_estrdup(src->values[i]); + 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; + debug_return; } -static void +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);