]> granicus.if.org Git - sudo/commitdiff
Use non-exiting allocators in the sudoers LDAP backend.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 16 Jun 2015 19:58:45 +0000 (13:58 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 16 Jun 2015 19:58:45 +0000 (13:58 -0600)
plugins/sudoers/ldap.c

index e04855424bc09e7fb09779e9c9946ed884bf1cfe..e55b17ffa7dda9a68848a4bd5c7748681e9da89d 100644 (file)
@@ -43,6 +43,7 @@
 # include <time.h>
 #endif
 #include <ctype.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <pwd.h>
 #include <grp.h>
@@ -398,7 +399,7 @@ static struct ldap_result *sudo_ldap_result_get(struct sudo_nss *nss,
 struct sudo_ldap_handle {
     LDAP *ld;
     struct ldap_result *result;
-    char *username;
+    const char *username;
     struct group_list *grlist;
 };
 
@@ -448,9 +449,10 @@ sudo_ldap_conf_add_ports(void)
        }
     }
 
-    sudo_efree(ldap_conf.host);
-    ldap_conf.host = sudo_estrdup(hostbuf);
-    debug_return_bool(true);
+    free(ldap_conf.host);
+    if ((ldap_conf.host = strdup(hostbuf)) == NULL)
+       sudo_warnx(U_("unable to allocate memory"));
+    debug_return_bool(ldap_conf.host != NULL);
 
 overflow:
     sudo_warnx(U_("internal error, %s overflow"), __func__);
@@ -477,7 +479,11 @@ sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
 
     hostbuf[0] = '\0';
     STAILQ_FOREACH(entry, uri_list, entries) {
-       buf = sudo_estrdup(entry->val);
+       buf = strdup(entry->val);
+       if (buf == NULL) {
+           sudo_warnx(U_("unable to allocate memory"));
+           goto done;
+       }
        for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) {
            if (strncasecmp(uri, "ldap://", 7) == 0) {
                nldap++;
@@ -520,18 +526,21 @@ sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
                sudo_warnx(U_("starttls not supported when using ldaps"));
            ldap_conf.ssl_mode = SUDO_LDAP_SSL;
        }
-       sudo_efree(buf);
+       free(buf);
     }
     buf = NULL;
 
     /* Store parsed URI(s) in host for ldap_create() or ldap_init(). */
-    sudo_efree(ldap_conf.host);
-    ldap_conf.host = sudo_estrdup(hostbuf);
+    free(ldap_conf.host);
+    if ((ldap_conf.host = strdup(hostbuf)) == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       goto done;
+    }
 
     rc = LDAP_SUCCESS;
 
 done:
-    sudo_efree(buf);
+    free(buf);
     debug_return_int(rc);
 
 overflow:
@@ -544,7 +553,7 @@ sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
 {
     struct ldap_config_str *uri;
     size_t len = 0;
-    char *buf, *cp;
+    char *buf = NULL;
     debug_decl(sudo_ldap_join_uri, SUDOERS_DEBUG_LDAP)
 
     STAILQ_FOREACH(uri, uri_list, entries) {
@@ -556,13 +565,17 @@ sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
        }
        len += strlen(uri->val) + 1;
     }
-    buf = cp = sudo_emalloc(len);
-    buf[0] = '\0';
-    STAILQ_FOREACH(uri, uri_list, entries) {
-       cp += strlcpy(cp, uri->val, len - (cp - buf));
-       *cp++ = ' ';
+    if (len == 0 || (buf = malloc(len)) == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+    } else {
+       char *cp = buf;
+
+       STAILQ_FOREACH(uri, uri_list, entries) {
+           cp += strlcpy(cp, uri->val, len - (cp - buf));
+           *cp++ = ' ';
+       }
+       cp[-1] = '\0';
     }
-    cp[-1] = '\0';
     debug_return_str(buf);
 }
 #endif /* HAVE_LDAP_INITIALIZE */
@@ -867,7 +880,7 @@ sudo_ldap_extract_digest(char **cmnd, struct sudo_digest *digest)
 {
     char *ep, *cp = *cmnd;
     int digest_type = SUDO_DIGEST_INVALID;
-    debug_decl(sudo_ldap_check_command, SUDOERS_DEBUG_LDAP)
+    debug_decl(sudo_ldap_extract_digest, SUDOERS_DEBUG_LDAP)
 
     /*
      * Check for and extract a digest prefix, e.g.
@@ -903,7 +916,11 @@ sudo_ldap_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++;
@@ -959,10 +976,10 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
        /* 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 */
@@ -978,12 +995,14 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
             */
            ret = foundbang ? false : true;
        }
+       if (allowed_args != NULL)
+           allowed_args[-1] = ' ';     /* restore val */
+
        DPRINTF2("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);
     }
 
     ldap_value_free_len(bv);   /* more cleanup */
@@ -1030,23 +1049,24 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
  * 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 void
+static bool
 sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
 {
     struct berval **bv, **p;
     char op, *var, *val;
+    bool rc = false;
     debug_decl(sudo_ldap_parse_options, SUDOERS_DEBUG_LDAP)
 
-    if (entry == NULL)
-       debug_return;
-
     bv = ldap_get_values_len(ld, entry, "sudoOption");
     if (bv == NULL)
-       debug_return;
+       debug_return_bool(true);
 
     /* walk through options */
     for (p = bv; *p != NULL; p++) {
-       var = sudo_estrdup((*p)->bv_val);
+       if ((var = strdup((*p)->bv_val)) == NULL) {
+           sudo_warnx(U_("unable to allocate memory"));
+           goto done;
+       }
        DPRINTF2("ldap sudoOption: '%s'", var);
 
        /* check for equals sign past first char */
@@ -1069,12 +1089,14 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
            /* case var Boolean True */
            set_default(var, NULL, true);
        }
-       sudo_efree(var);
+       free(var);
     }
+    rc = true;
 
+done:
     ldap_value_free_len(bv);
 
-    debug_return;
+    debug_return_bool(rc);
 }
 
 /*
@@ -1099,13 +1121,13 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
  * If either the sudoNotAfter or sudoNotBefore attributes are missing,
  * no time restriction shall be imposed.
  */
-static int
+static bool
 sudo_ldap_timefilter(char *buffer, size_t buffersize)
 {
     struct tm *tp;
     time_t now;
     char timebuffer[sizeof("20120727121554.0Z")];
-    int bytes = 0;
+    int len = -1;
     debug_decl(sudo_ldap_timefilter, SUDOERS_DEBUG_LDAP)
 
     /* Make sure we have a formatted timestamp for __now__. */
@@ -1122,15 +1144,15 @@ sudo_ldap_timefilter(char *buffer, size_t buffersize)
     }
 
     /* Build filter. */
-    bytes = snprintf(buffer, buffersize, "(&(|(!(sudoNotAfter=*))(sudoNotAfter>=%s))(|(!(sudoNotBefore=*))(sudoNotBefore<=%s)))",
+    len = snprintf(buffer, buffersize, "(&(|(!(sudoNotAfter=*))(sudoNotAfter>=%s))(|(!(sudoNotBefore=*))(sudoNotBefore<=%s)))",
        timebuffer, timebuffer);
-    if (bytes <= 0 || (size_t)bytes >= buffersize) {
-       sudo_warn(U_("unable to build time filter"));
-       bytes = 0;
+    if (len <= 0 || (size_t)len >= buffersize) {
+       sudo_warnx(U_("internal error, %s overflow"), __func__);
+       len = -1;
     }
 
 done:
-    debug_return_int(bytes);
+    debug_return_bool(len != -1);
 }
 
 /*
@@ -1139,13 +1161,13 @@ done:
 static char *
 sudo_ldap_build_default_filter(void)
 {
-    char *filt;
+    char *filt = NULL;
     debug_decl(sudo_ldap_build_default_filter, SUDOERS_DEBUG_LDAP)
 
     if (ldap_conf.search_filter)
-       sudo_easprintf(&filt, "(&%s(cn=defaults))", ldap_conf.search_filter);
+       (void)asprintf(&filt, "(&%s(cn=defaults))", ldap_conf.search_filter);
     else
-       filt = sudo_estrdup("cn=defaults");
+       filt = strdup("cn=defaults");
     debug_return_str(filt);
 }
 
@@ -1252,7 +1274,6 @@ static bool
 sudo_netgroup_lookup_nested(LDAP *ld, char *base, struct timeval *timeout,
     struct ldap_netgroup_list *netgroups, struct ldap_netgroup *start)
 {
-    struct ldap_netgroup *ng, *old_tail;
     LDAPMessage *entry, *result;
     size_t filt_len;
     char *filt;
@@ -1261,12 +1282,16 @@ sudo_netgroup_lookup_nested(LDAP *ld, char *base, struct timeval *timeout,
 
     DPRINTF1("Checking for nested netgroups from netgroup_base '%s'", base);
     do {
+       struct ldap_netgroup *ng, *old_tail;
+
+       result = NULL;
        old_tail = STAILQ_LAST(netgroups, ldap_netgroup, entries);
        filt_len = strlen(ldap_conf.netgroup_search_filter) + 7;
        for (ng = start; ng != NULL; ng = STAILQ_NEXT(ng, entries)) {
            filt_len += sudo_ldap_value_len(ng->name) + 20;
        }
-       filt = sudo_emalloc(filt_len);
+       if ((filt = malloc(filt_len)) == NULL)
+           goto oom;
        CHECK_STRLCPY(filt, "(&", filt_len);
        CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len);
        CHECK_STRLCAT(filt, "(|", filt_len);
@@ -1277,9 +1302,9 @@ sudo_netgroup_lookup_nested(LDAP *ld, char *base, struct timeval *timeout,
        }
        CHECK_STRLCAT(filt, "))", filt_len);
        DPRINTF1("ldap netgroup search filter: '%s'", filt);
-       result = NULL;
        rc = ldap_search_ext_s(ld, base, LDAP_SCOPE_SUBTREE, filt,
            NULL, 0, NULL, NULL, timeout, 0, &result);
+       free(filt);
        if (rc == LDAP_SUCCESS) {
            LDAP_FOREACH(entry, ld, result) {
                struct berval **bv;
@@ -1293,8 +1318,13 @@ sudo_netgroup_lookup_nested(LDAP *ld, char *base, struct timeval *timeout,
                            break;
                    }
                    if (ng == NULL) {
-                       ng = sudo_emalloc(sizeof(*ng));
-                       ng->name = sudo_estrdup((*bv)->bv_val);
+                       ng = malloc(sizeof(*ng));
+                       if (ng == NULL ||
+                           (ng->name = strdup((*bv)->bv_val)) == NULL) {
+                           free(ng);
+                           ldap_value_free_len(bv);
+                           goto oom;
+                       }
                        STAILQ_INSERT_TAIL(netgroups, ng, entries);
                        DPRINTF1("Found new netgroup %s for %s", ng->name, base);
                    }
@@ -1304,14 +1334,19 @@ sudo_netgroup_lookup_nested(LDAP *ld, char *base, struct timeval *timeout,
        }
        if (result)
            ldap_msgfree(result);
-       sudo_efree(filt);
 
        /* Check for nested netgroups in what we added. */
        start = old_tail ? STAILQ_NEXT(old_tail, entries) : STAILQ_FIRST(netgroups);
     } while (start != NULL);
 
     debug_return_bool(true);
+oom:
+    sudo_warnx(U_("unable to allocate memory"));
+    if (result)
+       ldap_msgfree(result);
+    debug_return_bool(false);
 overflow:
+    free(filt);
     sudo_warnx(U_("internal error, %s overflow"), __func__);
     debug_return_bool(false);
 }
@@ -1328,7 +1363,7 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
     struct ldap_config_str *base;
     struct ldap_netgroup *ng, *old_tail;
     struct timeval tv, *tvp = NULL;
-    LDAPMessage *entry, *result;
+    LDAPMessage *entry, *result = NULL;
     const char *domain;
     size_t filt_len;
     char *filt;
@@ -1363,7 +1398,8 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
                filt_len += 3 * sudo_ldap_value_len(domain);
            }
            filt_len += 7 + strlen(ldap_conf.netgroup_search_filter);
-           filt = sudo_emalloc(filt_len);
+           if ((filt = malloc(filt_len)) == NULL)
+               goto oom;
            CHECK_STRLCPY(filt, "(&", filt_len);
            CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len);
            CHECK_STRLCAT(filt, "(|(nisNetgroupTriple=\\28,", filt_len);
@@ -1409,7 +1445,8 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
                filt_len += sudo_ldap_value_len(user_host);
            }
            filt_len += 7 + strlen(ldap_conf.netgroup_search_filter);
-           filt = sudo_emalloc(filt_len);
+           if ((filt = malloc(filt_len)) == NULL)
+               goto oom;
            CHECK_STRLCPY(filt, "(&", filt_len);
            CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len);
            CHECK_STRLCAT(filt, "(|(nisNetgroupTriple=\\28,", filt_len);
@@ -1426,18 +1463,18 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
            }
            CHECK_STRLCAT(filt, ",*\\29)))", filt_len);
        }
+       /* XXX - refactor duplicated code */
        DPRINTF1("ldap netgroup search filter: '%s'", filt);
        result = NULL;
        rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
            NULL, 0, NULL, NULL, tvp, 0, &result);
+       free(filt);
        if (rc != LDAP_SUCCESS) {
            DPRINTF1("ldap netgroup search failed: %s", ldap_err2string(rc));
            if (result)
                ldap_msgfree(result);
-           sudo_efree(filt);
            continue;
        }
-       sudo_efree(filt);
 
        old_tail = STAILQ_LAST(netgroups, ldap_netgroup, entries);
        LDAP_FOREACH(entry, ld, result) {
@@ -1452,8 +1489,13 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
                        break;
                }
                if (ng == NULL) {
-                   ng = sudo_emalloc(sizeof(*ng));
-                   ng->name = sudo_estrdup((*bv)->bv_val);
+                   ng = malloc(sizeof(*ng));
+                   if (ng == NULL ||
+                       (ng->name = strdup((*bv)->bv_val)) == NULL) {
+                       free(ng);
+                       ldap_value_free_len(bv);
+                       goto oom;
+                   }
                    STAILQ_INSERT_TAIL(netgroups, ng, entries);
                    DPRINTF1("Found new netgroup %s for %s", ng->name,
                        base->val);
@@ -1471,7 +1513,12 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw,
        }
     }
     debug_return_bool(true);
+oom:
+    sudo_warnx(U_("unable to allocate memory"));
+    ldap_msgfree(result);
+    debug_return_bool(false);
 overflow:
+    free(filt);
     sudo_warnx(U_("internal error, %s overflow"), __func__);
     debug_return_bool(false);
 }
@@ -1532,8 +1579,8 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
        } else {
            /* sudo_netgroup_lookup() failed, clean up. */
            STAILQ_FOREACH_SAFE(ng, &netgroups, entries, nextng) {
-               sudo_efree(ng->name);
-               sudo_efree(ng);
+               free(ng->name);
+               free(ng);
            }
            STAILQ_INIT(&netgroups);
        }
@@ -1542,7 +1589,10 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
     /* If timed, add space for time limits. */
     if (ldap_conf.timed)
        sz += TIMEFILTER_LENGTH;
-    buf = sudo_emalloc(sz);
+    if ((buf = malloc(sz)) == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       debug_return_str(NULL);
+    }
     *buf = '\0';
 
     /*
@@ -1602,8 +1652,8 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
        CHECK_STRLCAT(buf, "(sudoUser=+", sz);
        CHECK_LDAP_VCAT(buf, ng->name, sz);
        CHECK_STRLCAT(buf, ")", sz);
-       sudo_efree(ng->name);
-       sudo_efree(ng);
+       free(ng->name);
+       free(ng);
     }
 
     /* Add ALL to list and end the global OR. */
@@ -1612,7 +1662,10 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
     /* Add the time restriction, or simply end the global OR. */
     if (ldap_conf.timed) {
        CHECK_STRLCAT(buf, ")", sz); /* closes the global OR */
-       sudo_ldap_timefilter(timebuffer, sizeof(timebuffer));
+       if (!sudo_ldap_timefilter(timebuffer, sizeof(timebuffer))) {
+           free(buf);
+           debug_return_str(NULL);
+       }
        CHECK_STRLCAT(buf, timebuffer, sz);
     } else if (ldap_conf.search_filter) {
        CHECK_STRLCAT(buf, ")", sz); /* closes the global OR */
@@ -1621,6 +1674,7 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
 
     debug_return_str(buf);
 overflow:
+    free(buf);
     sudo_warnx(U_("internal error, %s overflow"), __func__);
     debug_return_str(NULL);
 }
@@ -1632,7 +1686,7 @@ overflow:
 static char *
 sudo_ldap_build_pass2(void)
 {
-    char *filt, timebuffer[TIMEFILTER_LENGTH + 1];
+    char *filt = NULL, timebuffer[TIMEFILTER_LENGTH + 1];
     bool query_netgroups = def_use_netgroups;
     debug_decl(sudo_ldap_build_pass2, SUDOERS_DEBUG_LDAP)
 
@@ -1641,11 +1695,15 @@ sudo_ldap_build_pass2(void)
        query_netgroups = false;
 
     /* Short circuit if no netgroups and no non-Unix groups. */
-    if (!query_netgroups && !def_group_plugin)
+    if (!query_netgroups && !def_group_plugin) {
+       errno = ENOENT;
        debug_return_str(NULL);
+    }
 
-    if (ldap_conf.timed)
-       sudo_ldap_timefilter(timebuffer, sizeof(timebuffer));
+    if (ldap_conf.timed) {
+       if (!sudo_ldap_timefilter(timebuffer, sizeof(timebuffer)))
+           debug_return_str(NULL);
+    }
 
     /*
      * Match all sudoUsers beginning with '+' or '%:'.
@@ -1653,19 +1711,21 @@ sudo_ldap_build_pass2(void)
      * those get ANDed in to the expression.
      */
     if (query_netgroups && def_group_plugin) {
-       sudo_easprintf(&filt, "%s%s(|(sudoUser=+*)(sudoUser=%%:*))%s%s",
+       (void)asprintf(&filt, "%s%s(|(sudoUser=+*)(sudoUser=%%:*))%s%s",
            (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
            ldap_conf.search_filter ? ldap_conf.search_filter : "",
            ldap_conf.timed ? timebuffer : "",
            (ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
     } else {
-       sudo_easprintf(&filt, "%s%s(sudoUser=*)(sudoUser=%s*)%s%s",
+       (void)asprintf(&filt, "%s%s(sudoUser=*)(sudoUser=%s*)%s%s",
            (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
            ldap_conf.search_filter ? ldap_conf.search_filter : "",
            query_netgroups ? "+" : "%:",
            ldap_conf.timed ? timebuffer : "",
            (ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
     }
+    if (filt == NULL)
+       sudo_warnx(U_("unable to allocate memory"));
 
     debug_return_str(filt);
 }
@@ -1687,13 +1747,17 @@ sudo_ldap_decode_secret(const char *secret)
         */
        secret += sizeof("base64:") - 1;
        reslen = ((strlen(secret) + 3) / 4 * 3);
-       result = sudo_emalloc(reslen + 1);
-       len = base64_decode(secret, result, reslen);
-       if (len == (size_t)-1) {
-           free(result);
-           result = NULL;
+       result = malloc(reslen + 1);
+       if (result == NULL) {
+           sudo_warnx(U_("unable to allocate memory"));
        } else {
-           result[len] = '\0';
+           len = base64_decode(secret, result, reslen);
+           if (len == (size_t)-1) {
+               free(result);
+               result = NULL;
+           } else {
+               result[len] = '\0';
+           }
        }
     }
     debug_return_str((char *)result);
@@ -1706,15 +1770,18 @@ sudo_ldap_read_secret(const char *path)
     char buf[LINE_MAX];
     debug_decl(sudo_ldap_read_secret, SUDOERS_DEBUG_LDAP)
 
+    /* XXX - getline */
     if ((fp = fopen(path_ldap_secret, "r")) != NULL) {
        if (fgets(buf, sizeof(buf), fp) != NULL) {
            buf[strcspn(buf, "\n")] = '\0';
            /* copy to bindpw and binddn */
-           sudo_efree(ldap_conf.bindpw);
+           free(ldap_conf.bindpw);
            ldap_conf.bindpw = sudo_ldap_decode_secret(buf);
-           if (ldap_conf.bindpw == NULL)
-               ldap_conf.bindpw = sudo_estrdup(buf);
-           sudo_efree(ldap_conf.binddn);
+           if (ldap_conf.bindpw == NULL) {
+               if ((ldap_conf.bindpw = strdup(buf)) == NULL)
+                   sudo_warnx(U_("unable to allocate memory"));
+           }
+           free(ldap_conf.binddn);
            ldap_conf.binddn = ldap_conf.rootbinddn;
            ldap_conf.rootbinddn = NULL;
        }
@@ -1760,9 +1827,17 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
                }
                break;
            case CONF_STR:
-               sudo_efree(*(char **)(cur->valp));
-               *(char **)(cur->valp) = *value ? sudo_estrdup(value) : NULL;
-               break;
+               {
+                   char *cp = NULL;
+
+                   free(*(char **)(cur->valp));
+                   if (*value && (cp = strdup(value)) == NULL) {
+                       sudo_warnx(U_("unable to allocate memory"));
+                       debug_return_bool(false);
+                   }
+                   *(char **)(cur->valp) = cp;
+                   break;
+               }
            case CONF_LIST_STR:
                {
                    struct ldap_config_str_list *head;
@@ -1771,7 +1846,10 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
 
                    if (len > 0) {
                        head = (struct ldap_config_str_list *)cur->valp;
-                       str = sudo_emalloc(sizeof(*str) + len);
+                       if ((str = malloc(sizeof(*str) + len)) == NULL) {
+                           sudo_warnx(U_("unable to allocate memory"));
+                           debug_return_bool(false);
+                       }
                        memcpy(str->val, value, len + 1);
                        STAILQ_INSERT_TAIL(head, str, entries);
                    }
@@ -1858,12 +1936,17 @@ sudo_ldap_read_config(void)
     ldap_conf.use_sasl = -1;
     ldap_conf.rootuse_sasl = -1;
     ldap_conf.deref = -1;
-    ldap_conf.search_filter = sudo_estrdup(DEFAULT_SEARCH_FILTER);
-    ldap_conf.netgroup_search_filter = sudo_estrdup(DEFAULT_NETGROUP_SEARCH_FILTER);
+    ldap_conf.search_filter = strdup(DEFAULT_SEARCH_FILTER);
+    ldap_conf.netgroup_search_filter = strdup(DEFAULT_NETGROUP_SEARCH_FILTER);
     STAILQ_INIT(&ldap_conf.uri);
     STAILQ_INIT(&ldap_conf.base);
     STAILQ_INIT(&ldap_conf.netgroup_base);
 
+    if (ldap_conf.search_filter == NULL || ldap_conf.netgroup_search_filter == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       debug_return_bool(false);
+    }
+
     if ((fp = fopen(path_ldap_conf, "r")) == NULL)
        debug_return_bool(false);
 
@@ -1890,8 +1973,13 @@ sudo_ldap_read_config(void)
     free(line);
     fclose(fp);
 
-    if (!ldap_conf.host)
-       ldap_conf.host = sudo_estrdup("localhost");
+    if (!ldap_conf.host) {
+       ldap_conf.host = strdup("localhost");
+       if (ldap_conf.host == NULL) {
+           sudo_warnx(U_("unable to allocate memory"));
+           debug_return_bool(false);
+       }
+    }
 
     DPRINTF1("LDAP Config Summary");
     DPRINTF1("===================");
@@ -2011,7 +2099,7 @@ sudo_ldap_read_config(void)
            debug_return_bool(false);
        while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) {
            STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries);
-           sudo_efree(uri);
+           free(uri);
        }
        ldap_conf.port = LDAP_PORT;
     }
@@ -2039,12 +2127,16 @@ sudo_ldap_read_config(void)
     if (ldap_conf.search_filter && ldap_conf.search_filter[0] != '(') {
        size_t len = strlen(ldap_conf.search_filter);
        cp = ldap_conf.search_filter;
-       ldap_conf.search_filter = sudo_emalloc(len + 3);
+       ldap_conf.search_filter = malloc(len + 3);
+       if (ldap_conf.search_filter == NULL) {
+           sudo_warnx(U_("unable to allocate memory"));
+           debug_return_bool(false);
+       }
        ldap_conf.search_filter[0] = '(';
        memcpy(ldap_conf.search_filter + 1, cp, len);
        ldap_conf.search_filter[len + 1] = ')';
        ldap_conf.search_filter[len + 2] = '\0';
-       sudo_efree(cp);
+       free(cp);
     }
 
 
@@ -2054,7 +2146,7 @@ sudo_ldap_read_config(void)
     } else if (ldap_conf.bindpw) {
        cp = sudo_ldap_decode_secret(ldap_conf.bindpw);
        if (cp != NULL) {
-           sudo_efree(ldap_conf.bindpw);
+           free(ldap_conf.bindpw);
            ldap_conf.bindpw = cp;
        }
     }
@@ -2062,7 +2154,7 @@ sudo_ldap_read_config(void)
     if (ldap_conf.tls_keypw) {
        cp = sudo_ldap_decode_secret(ldap_conf.tls_keypw);
        if (cp != NULL) {
-           sudo_efree(ldap_conf.tls_keypw);
+           free(ldap_conf.tls_keypw);
            ldap_conf.tls_keypw = cp;
        }
     }
@@ -2133,6 +2225,10 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
     ld = handle->ld;
 
     filt = sudo_ldap_build_default_filter();
+    if (filt == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       goto done;
+    }
     STAILQ_FOREACH(base, &ldap_conf.base, entries) {
        if (ldap_conf.timeout > 0) {
            tv.tv_sec = ldap_conf.timeout;
@@ -2160,7 +2256,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
        if (result)
            ldap_msgfree(result);
     }
-    sudo_efree(filt);
+    free(filt);
 done:
     debug_return_int(count);
 }
@@ -2350,6 +2446,8 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
 
     DPRINTF1("ldap search for command list");
     lres = sudo_ldap_result_get(nss, pw);
+    if (lres == NULL)
+       goto done;
 
     /* Display all matching entries. */
     for (i = 0; i < lres->nentries; i++) {
@@ -2385,6 +2483,8 @@ sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
      */
     DPRINTF1("ldap search for command list");
     lres = sudo_ldap_result_get(nss, pw);
+    if (lres == NULL)
+       goto done;
     for (i = 0; i < lres->nentries; i++) {
        entry = lres->entries[i].entry;
        if (sudo_ldap_check_command(ld, entry, NULL) &&
@@ -2686,7 +2786,7 @@ sudo_ldap_result_alloc(void)
     struct ldap_result *result;
     debug_decl(sudo_ldap_result_alloc, SUDOERS_DEBUG_LDAP)
 
-    result = sudo_ecalloc(1, sizeof(*result));
+    result = calloc(1, sizeof(*result));
     STAILQ_INIT(&result->searches);
 
     debug_return_ptr(result);
@@ -2703,15 +2803,15 @@ sudo_ldap_result_free(struct ldap_result *lres)
 
     if (lres != NULL) {
        if (lres->nentries) {
-           sudo_efree(lres->entries);
+           free(lres->entries);
            lres->entries = NULL;
        }
        while ((s = STAILQ_FIRST(&lres->searches)) != NULL) {
            STAILQ_REMOVE_HEAD(&lres->searches, entries);
            ldap_msgfree(s->searchresult);
-           sudo_efree(s);
+           free(s);
        }
-       sudo_efree(lres);
+       free(lres);
     }
     debug_return;
 }
@@ -2727,10 +2827,12 @@ sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap,
     debug_decl(sudo_ldap_result_add_search, SUDOERS_DEBUG_LDAP)
 
     /* Create new entry and add it to the end of the chain. */
-    news = sudo_ecalloc(1, sizeof(*news));
-    news->ldap = ldap;
-    news->searchresult = searchresult;
-    STAILQ_INSERT_TAIL(&lres->searches, news, entries);
+    news = calloc(1, sizeof(*news));
+    if (news != NULL) {
+       news->ldap = ldap;
+       news->searchresult = searchresult;
+       STAILQ_INSERT_TAIL(&lres->searches, news, entries);
+    }
 
     debug_return_ptr(news);
 }
@@ -2868,7 +2970,7 @@ sudo_ldap_open(struct sudo_nss *nss)
            goto done;
        DPRINTF2("ldap_initialize(ld, %s)", buf);
        rc = ldap_initialize(&ld, buf);
-       sudo_efree(buf);
+       free(buf);
     } else
 #endif
        rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port);
@@ -2919,7 +3021,12 @@ sudo_ldap_open(struct sudo_nss *nss)
        goto done;
 
     /* Create a handle container. */
-    handle = sudo_ecalloc(1, sizeof(struct sudo_ldap_handle));
+    handle = calloc(1, sizeof(struct sudo_ldap_handle));
+    if (handle == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       rc = -1;
+       goto done;
+    }
     handle->ld = ld;
     /* handle->result = NULL; */
     /* handle->username = NULL; */
@@ -2938,7 +3045,7 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
     struct sudo_ldap_handle *handle = nss->handle;
     struct timeval tv, *tvp = NULL;
     LDAP *ld;
-    LDAPMessage *entry, *result;
+    LDAPMessage *entry, *result = NULL;
     char *filt;
     int rc;
     debug_decl(sudo_ldap_setdefs, SUDOERS_DEBUG_LDAP)
@@ -2948,6 +3055,10 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
     ld = handle->ld;
 
     filt = sudo_ldap_build_default_filter();
+    if (filt == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       debug_return_int(-1);
+    }
     DPRINTF1("Looking for cn=defaults: %s", filt);
 
     STAILQ_FOREACH(base, &ldap_conf.base, entries) {
@@ -2956,21 +3067,30 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
            tv.tv_usec = 0;
            tvp = &tv;
        }
-       result = NULL;
+       if (result != NULL) {
+           ldap_msgfree(result);
+           result = NULL;
+       }
        rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE,
            filt, NULL, 0, NULL, NULL, tvp, 0, &result);
        if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
            DPRINTF1("found:%s", ldap_get_dn(ld, entry));
-           sudo_ldap_parse_options(ld, entry);
+           if (!sudo_ldap_parse_options(ld, entry)) {
+               rc = -1;
+               goto done;
+           }
        } else {
            DPRINTF1("no default options found in %s", base->val);
        }
-       if (result)
-           ldap_msgfree(result);
     }
-    sudo_efree(filt);
+    rc = 0;
 
-    debug_return_int(0);
+done:
+    if (result != NULL)
+       ldap_msgfree(result);
+    free(filt);
+
+    debug_return_int(rc);
 }
 
 /*
@@ -2992,6 +3112,8 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
 
     /* Fetch list of sudoRole entries that match user and host. */
     lres = sudo_ldap_result_get(nss, sudo_user.pw);
+    if (lres == NULL)
+       debug_return_int(ret);
 
     /*
      * The following queries are only determine whether or not a
@@ -3058,16 +3180,19 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
                /* Apply entry-specific options. */
                if (setenv_implied)
                    def_setenv = true;
-               sudo_ldap_parse_options(ld, entry);
+               if (sudo_ldap_parse_options(ld, entry)) {
 #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 and 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);
@@ -3155,9 +3280,13 @@ sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
      * of 100 entries to save on allocation time.
      */
     if (++lres->nentries > lres->allocated_entries) {
-       lres->allocated_entries += ALLOCATION_INCREMENT;
-       lres->entries = sudo_ereallocarray(lres->entries, lres->allocated_entries,
-           sizeof(lres->entries[0]));
+       int allocated_entries = lres->allocated_entries + ALLOCATION_INCREMENT;
+       struct ldap_entry_wrapper *entries = reallocarray(lres->entries,
+           allocated_entries, sizeof(lres->entries[0]));
+       if (entries == NULL)
+           debug_return_ptr(NULL);
+       lres->allocated_entries = allocated_entries;
+       lres->entries = entries;
     }
 
     /* Fill in the new entry and return it. */
@@ -3179,10 +3308,7 @@ sudo_ldap_result_free_nss(struct sudo_nss *nss)
     if (handle->result != NULL) {
        DPRINTF1("removing reusable search result");
        sudo_ldap_result_free(handle->result);
-       if (handle->username) {
-           sudo_efree(handle->username);
-           handle->username = NULL;
-       }
+       handle->username = NULL;
        handle->grlist = NULL;
        handle->result = NULL;
     }
@@ -3242,6 +3368,10 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
      * an ldap_result object.  The results are then sorted by sudoOrder.
      */
     lres = sudo_ldap_result_alloc();
+    if (lres == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       debug_return_ptr(NULL);
+    }
     for (pass = 0; pass < 2; pass++) {
        filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(ld, pw);
        if (filt != NULL) {
@@ -3266,18 +3396,32 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
 
                /* Add the seach result to list of search results. */
                DPRINTF1("adding search result");
-               sudo_ldap_result_add_search(lres, ld, result);
+               if (sudo_ldap_result_add_search(lres, ld, result) == NULL) {
+                   sudo_warnx(U_("unable to allocate memory"));
+                   free(filt);
+                   sudo_ldap_result_free(lres);
+                   debug_return_ptr(NULL);
+               }
                LDAP_FOREACH(entry, ld, result) {
                    if ((!pass ||
                        sudo_ldap_check_non_unix_group(ld, entry, pw)) &&
                        sudo_ldap_check_host(ld, entry)) {
                        lres->host_matches = true;
-                       sudo_ldap_result_add_entry(lres, entry);
+                       if (sudo_ldap_result_add_entry(lres, entry) == NULL) {
+                           sudo_warnx(U_("unable to allocate memory"));
+                           free(filt);
+                           sudo_ldap_result_free(lres);
+                           debug_return_ptr(NULL);
+                       }
                    }
                }
                DPRINTF1("result now has %d entries", lres->nentries);
            }
-           sudo_efree(filt);
+           free(filt);
+       } else if (errno != ENOENT) {
+           /* Out of memory? */
+           sudo_ldap_result_free(lres);
+           debug_return_ptr(NULL);
        }
     }
 
@@ -3287,8 +3431,9 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
        ldap_entry_compare);
 
     /* Store everything in the sudo_nss handle. */
+    /* XXX - store pw and take a reference to it. */
     handle->result = lres;
-    handle->username = sudo_estrdup(pw->pw_name);
+    handle->username = pw->pw_name;
     handle->grlist = user_group_list;
 
     debug_return_ptr(lres);
@@ -3314,7 +3459,7 @@ sudo_ldap_close(struct sudo_nss *nss)
        }
 
        /* Free the handle container. */
-       sudo_efree(nss->handle);
+       free(nss->handle);
        nss->handle = NULL;
     }
     debug_return_int(0);
@@ -3339,30 +3484,42 @@ sudo_ldap_parse(struct sudo_nss *nss)
 static struct ldap_result *
 sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *searchresult)
 {
+    struct ldap_search_result *last;
+    struct ldap_result *result;
+    LDAPMessage        *entry;
+
     /*
      * An ldap_result is built from several search results, which are
      * organized in a list. The head of the list is maintained in the
      * ldap_result structure, together with the wrappers that point
      * to individual entries, this has to be initialized first.
      */
-    struct ldap_result *result = sudo_ldap_result_alloc();
+    result = sudo_ldap_result_alloc();
+    if (result == NULL) {
+       sudo_warnx(U_("unable to allocate memory"));
+       debug_return_ptr(NULL);
+    }
 
     /*
      * Build a new list node for the search result, this creates the
      * list node.
      */
-    struct ldap_search_result *last = sudo_ldap_result_add_search(result,
-       ldap, searchresult);
+    last = sudo_ldap_result_add_search(result, ldap, searchresult);
 
     /*
      * Now add each entry in the search result to the array of of entries
      * in the ldap_result object.
      */
-    LDAPMessage        *entry;
     LDAP_FOREACH(entry, last->ldap, last->searchresult) {
-       sudo_ldap_result_add_entry(result, entry);
+       if (sudo_ldap_result_add_entry(result, entry) == NULL) {
+           sudo_warnx(U_("unable to allocate memory"));
+           sudo_ldap_result_free(result);
+           result = NULL;
+           break;
+       }
     }
-    DPRINTF1("sudo_ldap_result_from_search: %d entries found", result->nentries);
+    DPRINTF1("sudo_ldap_result_from_search: %d entries found",
+       result ? result->nentries : -1);
     return result;
 }
 #endif