]> granicus.if.org Git - sudo/commitdiff
Use non-exiting allocators in the sudoers SSSD backend.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 16 Jun 2015 21:00:47 +0000 (15:00 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 16 Jun 2015 21:00:47 +0000 (15:00 -0600)
plugins/sudoers/sssd.c

index 3f8b0b6b098a54fb30c3b463e97ea6702908b917..1effdd68430137c7962a2a0664f218411ca904c7 100644 (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, "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);