Imported Upstream version 1.8.4p4
[debian/sudo] / plugins / sudoers / ldap.c
index e8e63117dea93a373b91920887df9dae6de3462a..a46ba1519032eb858c2652e99cad89015edaa220 100644 (file)
 #include "parse.h"
 #include "lbuf.h"
 
+/* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */
+#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(HAVE_LDAP_SSL_H) && !defined(HAVE_MPS_LDAP_SSL_H)
+extern int ldapssl_set_strength(LDAP *ldap, int strength);
+#endif
+
 #ifndef LDAP_OPT_SUCCESS
 # define LDAP_OPT_SUCCESS LDAP_SUCCESS
 #endif
@@ -218,90 +223,90 @@ static struct ldap_config {
 } ldap_conf;
 
 static struct ldap_config_table ldap_conf_table[] = {
-    { "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug },
-    { "host", CONF_STR, FALSE, -1, &ldap_conf.host },
-    { "port", CONF_INT, FALSE, -1, &ldap_conf.port },
-    { "ssl", CONF_STR, FALSE, -1, &ldap_conf.ssl },
-    { "sslpath", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile },
-    { "uri", CONF_LIST_STR, FALSE, -1, &ldap_conf.uri },
+    { "sudoers_debug", CONF_INT, false, -1, &ldap_conf.debug },
+    { "host", CONF_STR, false, -1, &ldap_conf.host },
+    { "port", CONF_INT, false, -1, &ldap_conf.port },
+    { "ssl", CONF_STR, false, -1, &ldap_conf.ssl },
+    { "sslpath", CONF_STR, false, -1, &ldap_conf.tls_certfile },
+    { "uri", CONF_LIST_STR, false, -1, &ldap_conf.uri },
 #ifdef LDAP_OPT_DEBUG_LEVEL
-    { "debug", CONF_INT, FALSE, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
+    { "debug", CONF_INT, false, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
 #endif
 #ifdef LDAP_OPT_PROTOCOL_VERSION
-    { "ldap_version", CONF_INT, TRUE, LDAP_OPT_PROTOCOL_VERSION,
+    { "ldap_version", CONF_INT, true, LDAP_OPT_PROTOCOL_VERSION,
        &ldap_conf.version },
 #endif
 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
-    { "tls_checkpeer", CONF_BOOL, FALSE, LDAP_OPT_X_TLS_REQUIRE_CERT,
+    { "tls_checkpeer", CONF_BOOL, false, LDAP_OPT_X_TLS_REQUIRE_CERT,
        &ldap_conf.tls_checkpeer },
 #else
-    { "tls_checkpeer", CONF_BOOL, FALSE, -1, &ldap_conf.tls_checkpeer },
+    { "tls_checkpeer", CONF_BOOL, false, -1, &ldap_conf.tls_checkpeer },
 #endif
 #ifdef LDAP_OPT_X_TLS_CACERTFILE
-    { "tls_cacertfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTFILE,
+    { "tls_cacertfile", CONF_STR, false, LDAP_OPT_X_TLS_CACERTFILE,
        &ldap_conf.tls_cacertfile },
-    { "tls_cacert", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTFILE,
+    { "tls_cacert", CONF_STR, false, LDAP_OPT_X_TLS_CACERTFILE,
        &ldap_conf.tls_cacertfile },
 #endif
 #ifdef LDAP_OPT_X_TLS_CACERTDIR
-    { "tls_cacertdir", CONF_STR, FALSE, LDAP_OPT_X_TLS_CACERTDIR,
+    { "tls_cacertdir", CONF_STR, false, LDAP_OPT_X_TLS_CACERTDIR,
        &ldap_conf.tls_cacertdir },
 #endif
 #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
-    { "tls_randfile", CONF_STR, FALSE, LDAP_OPT_X_TLS_RANDOM_FILE,
+    { "tls_randfile", CONF_STR, false, LDAP_OPT_X_TLS_RANDOM_FILE,
        &ldap_conf.tls_random_file },
 #endif
 #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
-    { "tls_ciphers", CONF_STR, FALSE, LDAP_OPT_X_TLS_CIPHER_SUITE,
+    { "tls_ciphers", CONF_STR, false, LDAP_OPT_X_TLS_CIPHER_SUITE,
        &ldap_conf.tls_cipher_suite },
 #endif
 #ifdef LDAP_OPT_X_TLS_CERTFILE
-    { "tls_cert", CONF_STR, FALSE, LDAP_OPT_X_TLS_CERTFILE,
+    { "tls_cert", CONF_STR, false, LDAP_OPT_X_TLS_CERTFILE,
        &ldap_conf.tls_certfile },
 #else
-    { "tls_cert", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile },
+    { "tls_cert", CONF_STR, false, -1, &ldap_conf.tls_certfile },
 #endif
 #ifdef LDAP_OPT_X_TLS_KEYFILE
-    { "tls_key", CONF_STR, FALSE, LDAP_OPT_X_TLS_KEYFILE,
+    { "tls_key", CONF_STR, false, LDAP_OPT_X_TLS_KEYFILE,
        &ldap_conf.tls_keyfile },
 #else
-    { "tls_key", CONF_STR, FALSE, -1, &ldap_conf.tls_keyfile },
+    { "tls_key", CONF_STR, false, -1, &ldap_conf.tls_keyfile },
 #endif
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
-    { "bind_timelimit", CONF_INT, TRUE, -1 /* needs timeval, set manually */,
+    { "bind_timelimit", CONF_INT, true, -1 /* needs timeval, set manually */,
        &ldap_conf.bind_timelimit },
-    { "network_timeout", CONF_INT, TRUE, -1 /* needs timeval, set manually */,
+    { "network_timeout", CONF_INT, true, -1 /* needs timeval, set manually */,
        &ldap_conf.bind_timelimit },
 #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
-    { "bind_timelimit", CONF_INT, TRUE, LDAP_X_OPT_CONNECT_TIMEOUT,
+    { "bind_timelimit", CONF_INT, true, LDAP_X_OPT_CONNECT_TIMEOUT,
        &ldap_conf.bind_timelimit },
-    { "network_timeout", CONF_INT, TRUE, LDAP_X_OPT_CONNECT_TIMEOUT,
+    { "network_timeout", CONF_INT, true, LDAP_X_OPT_CONNECT_TIMEOUT,
        &ldap_conf.bind_timelimit },
 #endif
-    { "timelimit", CONF_INT, TRUE, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit },
+    { "timelimit", CONF_INT, true, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit },
 #ifdef LDAP_OPT_TIMEOUT
-    { "timeout", CONF_INT, TRUE, -1 /* needs timeval, set manually */,
+    { "timeout", CONF_INT, true, -1 /* needs timeval, set manually */,
        &ldap_conf.timeout },
 #endif
 #ifdef LDAP_OPT_DEREF
-    { "deref", CONF_DEREF_VAL, TRUE, LDAP_OPT_DEREF, &ldap_conf.deref },
+    { "deref", CONF_DEREF_VAL, true, LDAP_OPT_DEREF, &ldap_conf.deref },
 #endif
-    { "binddn", CONF_STR, FALSE, -1, &ldap_conf.binddn },
-    { "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw },
-    { "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn },
-    { "sudoers_base", CONF_LIST_STR, FALSE, -1, &ldap_conf.base },
-    { "sudoers_timed", CONF_BOOL, FALSE, -1, &ldap_conf.timed },
-    { "sudoers_search_filter", CONF_STR, FALSE, -1, &ldap_conf.search_filter },
+    { "binddn", CONF_STR, false, -1, &ldap_conf.binddn },
+    { "bindpw", CONF_STR, false, -1, &ldap_conf.bindpw },
+    { "rootbinddn", CONF_STR, false, -1, &ldap_conf.rootbinddn },
+    { "sudoers_base", CONF_LIST_STR, false, -1, &ldap_conf.base },
+    { "sudoers_timed", CONF_BOOL, false, -1, &ldap_conf.timed },
+    { "sudoers_search_filter", CONF_STR, false, -1, &ldap_conf.search_filter },
 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
-    { "use_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.use_sasl },
-    { "sasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.sasl_auth_id },
-    { "rootuse_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.rootuse_sasl },
-    { "rootsasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.rootsasl_auth_id },
+    { "use_sasl", CONF_BOOL, false, -1, &ldap_conf.use_sasl },
+    { "sasl_auth_id", CONF_STR, false, -1, &ldap_conf.sasl_auth_id },
+    { "rootuse_sasl", CONF_BOOL, false, -1, &ldap_conf.rootuse_sasl },
+    { "rootsasl_auth_id", CONF_STR, false, -1, &ldap_conf.rootsasl_auth_id },
 # ifdef LDAP_OPT_X_SASL_SECPROPS
-    { "sasl_secprops", CONF_STR, TRUE, LDAP_OPT_X_SASL_SECPROPS,
+    { "sasl_secprops", CONF_STR, true, LDAP_OPT_X_SASL_SECPROPS,
        &ldap_conf.sasl_secprops },
 # endif
-    { "krb5_ccname", CONF_STR, FALSE, -1, &ldap_conf.krb5_ccname },
+    { "krb5_ccname", CONF_STR, false, -1, &ldap_conf.krb5_ccname },
 #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
     { NULL }
 };
@@ -362,6 +367,7 @@ sudo_ldap_conf_add_ports(void)
 
     char *host, *port, defport[13];
     char hostbuf[LINE_MAX * 2];
+    debug_decl(sudo_ldap_conf_add_ports, SUDO_DEBUG_LDAP)
 
     hostbuf[0] = '\0';
     if (snprintf(defport, sizeof(defport), ":%d", ldap_conf.port) >= sizeof(defport))
@@ -385,7 +391,7 @@ sudo_ldap_conf_add_ports(void)
 
     efree(ldap_conf.host);
     ldap_conf.host = estrdup(hostbuf);
-    return;
+    debug_return;
 
 toobig:
     errorx(1, _("sudo_ldap_conf_add_ports: out of space expanding hostbuf"));
@@ -405,6 +411,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
     char hostbuf[LINE_MAX];
     int nldap = 0, nldaps = 0;
     int rc = -1;
+    debug_decl(sudo_ldap_parse_uri, SUDO_DEBUG_LDAP)
 
     do {
        buf = estrdup(uri_list->val);
@@ -472,7 +479,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
 
 done:
     efree(buf);
-    return rc;
+    debug_return_int(rc);
 
 toobig:
     errorx(1, _("sudo_ldap_parse_uri: out of space building hostbuf"));
@@ -484,10 +491,11 @@ sudo_ldap_join_uri(struct ldap_config_list_str *uri_list)
     struct ldap_config_list_str *uri;
     size_t len = 0;
     char *buf, *cp;
+    debug_decl(sudo_ldap_join_uri, SUDO_DEBUG_LDAP)
 
     /* Usually just a single entry. */
     if (uri_list->next == NULL)
-       return estrdup(uri_list->val);
+       debug_return_str(estrdup(uri_list->val));
 
     for (uri = uri_list; uri != NULL; uri = uri->next) {
        len += strlen(uri->val) + 1;
@@ -499,7 +507,7 @@ sudo_ldap_join_uri(struct ldap_config_list_str *uri_list)
        *cp++ = ' ';
     }
     cp[-1] = '\0';
-    return buf;
+    debug_return_str(buf);
 }
 #endif /* HAVE_LDAP_INITIALIZE */
 
@@ -508,6 +516,7 @@ sudo_ldap_init(LDAP **ldp, const char *host, int port)
 {
     LDAP *ld = NULL;
     int rc = LDAP_CONNECT_ERROR;
+    debug_decl(sudo_ldap_init, SUDO_DEBUG_LDAP)
 
 #ifdef HAVE_LDAPSSL_INIT
     if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
@@ -565,61 +574,63 @@ sudo_ldap_init(LDAP **ldp, const char *host, int port)
 
 done:
     *ldp = ld;
-    return rc;
+    debug_return_int(rc);
 }
 
 /*
- * Walk through search results and return TRUE if we have a matching
- * netgroup, else FALSE.
+ * Walk through search results and return true if we have a matching
+ * netgroup, else false.
  */
-static int
+static bool
 sudo_ldap_check_user_netgroup(LDAP *ld, LDAPMessage *entry, char *user)
 {
     struct berval **bv, **p;
     char *val;
-    int ret = FALSE;
+    int ret = false;
+    debug_decl(sudo_ldap_check_user_netgroup, SUDO_DEBUG_LDAP)
 
     if (!entry)
-       return ret;
+       debug_return_bool(ret);
 
     /* get the values from the entry */
     bv = ldap_get_values_len(ld, entry, "sudoUser");
     if (bv == NULL)
-       return ret;
+       debug_return_bool(ret);
 
     /* walk through values */
     for (p = bv; *p != NULL && !ret; p++) {
        val = (*p)->bv_val;
        /* match any */
        if (netgr_matches(val, NULL, NULL, user))
-           ret = TRUE;
+           ret = true;
        DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val,
            ret ? "MATCH!" : "not"), 2 + ((ret) ? 0 : 1));
     }
 
     ldap_value_free_len(bv);   /* cleanup */
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 /*
- * Walk through search results and return TRUE if we have a
- * host match, else FALSE.
- */
-static int
+* Walk through search results and return true if we have a
+* host match, else false.
+*/
+static bool
 sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry)
 {
     struct berval **bv, **p;
     char *val;
-    int ret = FALSE;
+    bool ret = false;
+    debug_decl(sudo_ldap_check_host, SUDO_DEBUG_LDAP)
 
     if (!entry)
-       return ret;
+       debug_return_bool(ret);
 
     /* get the values from the entry */
     bv = ldap_get_values_len(ld, entry, "sudoHost");
     if (bv == NULL)
-       return ret;
+       debug_return_bool(ret);
 
     /* walk through values */
     for (p = bv; *p != NULL && !ret; p++) {
@@ -628,14 +639,14 @@ sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry)
        if (!strcmp(val, "ALL") || addr_matches(val) ||
            netgr_matches(val, user_host, user_shost, NULL) ||
            hostname_matches(user_shost, user_host, val))
-           ret = TRUE;
+           ret = true;
        DPRINTF(("ldap sudoHost '%s' ... %s", val,
            ret ? "MATCH!" : "not"), 2);
     }
 
     ldap_value_free_len(bv);   /* cleanup */
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 static int
@@ -643,10 +654,11 @@ sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entry)
 {
     struct berval **bv, **p;
     char *val;
-    int ret = FALSE;
+    bool ret = false;
+    debug_decl(sudo_ldap_check_runas_user, SUDO_DEBUG_LDAP)
 
     if (!runas_pw)
-       return UNSPEC;
+       debug_return_bool(UNSPEC);
 
     /* get the runas user from the entry */
     bv = ldap_get_values_len(ld, entry, "sudoRunAsUser");
@@ -675,7 +687,7 @@ sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entry)
      * what the user specified on the command line.
      */
     if (bv == NULL)
-       return !strcasecmp(runas_pw->pw_name, def_runas_default);
+       debug_return_bool(!strcasecmp(runas_pw->pw_name, def_runas_default));
 
     /* walk through values returned, looking for a match */
     for (p = bv; *p != NULL && !ret; p++) {
@@ -683,21 +695,21 @@ sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entry)
        switch (val[0]) {
        case '+':
            if (netgr_matches(val, NULL, NULL, runas_pw->pw_name))
-               ret = TRUE;
+               ret = true;
            break;
        case '%':
            if (usergr_matches(val, runas_pw->pw_name, runas_pw))
-               ret = TRUE;
+               ret = true;
            break;
        case 'A':
            if (strcmp(val, "ALL") == 0) {
-               ret = TRUE;
+               ret = true;
                break;
            }
            /* FALLTHROUGH */
        default:
            if (strcasecmp(val, runas_pw->pw_name) == 0)
-               ret = TRUE;
+               ret = true;
            break;
        }
        DPRINTF(("ldap sudoRunAsUser '%s' ... %s", val,
@@ -706,7 +718,7 @@ sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entry)
 
     ldap_value_free_len(bv);   /* cleanup */
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 static int
@@ -714,84 +726,88 @@ sudo_ldap_check_runas_group(LDAP *ld, LDAPMessage *entry)
 {
     struct berval **bv, **p;
     char *val;
-    int ret = FALSE;
+    bool ret = false;
+    debug_decl(sudo_ldap_check_runas_group, SUDO_DEBUG_LDAP)
 
     /* runas_gr is only set if the user specified the -g flag */
     if (!runas_gr)
-       return UNSPEC;
+       debug_return_bool(UNSPEC);
 
     /* get the values from the entry */
     bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup");
     if (bv == NULL)
-       return ret;
+       debug_return_bool(ret);
 
     /* walk through values returned, looking for a match */
     for (p = bv; *p != NULL && !ret; p++) {
        val = (*p)->bv_val;
        if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr))
-           ret = TRUE;
+           ret = true;
        DPRINTF(("ldap sudoRunAsGroup '%s' ... %s", val,
            ret ? "MATCH!" : "not"), 2);
     }
 
     ldap_value_free_len(bv);   /* cleanup */
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 /*
- * Walk through search results and return TRUE if we have a runas match,
- * else FALSE.  RunAs info is optional.
+ * Walk through search results and return true if we have a runas match,
+ * else false.  RunAs info is optional.
  */
-static int
+static bool
 sudo_ldap_check_runas(LDAP *ld, LDAPMessage *entry)
 {
-    int ret;
+    bool ret;
+    debug_decl(sudo_ldap_check_runas, SUDO_DEBUG_LDAP)
 
     if (!entry)
-       return FALSE;
+       debug_return_bool(false);
 
-    ret = sudo_ldap_check_runas_user(ld, entry) != FALSE &&
-       sudo_ldap_check_runas_group(ld, entry) != FALSE;
+    ret = sudo_ldap_check_runas_user(ld, entry) != false &&
+       sudo_ldap_check_runas_group(ld, entry) != false;
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 /*
- * Walk through search results and return TRUE if we have a command match,
- * FALSE if disallowed and UNSPEC if not matched.
+ * Walk through search results and return true if we have a command match,
+ * false if disallowed and UNSPEC if not matched.
  */
 static int
 sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
 {
     struct berval **bv, **p;
     char *allowed_cmnd, *allowed_args, *val;
-    int foundbang, ret = UNSPEC;
+    bool foundbang;
+    int ret = UNSPEC;
+    debug_decl(sudo_ldap_check_command, SUDO_DEBUG_LDAP)
 
     if (!entry)
-       return ret;
+       debug_return_bool(ret);
 
     bv = ldap_get_values_len(ld, entry, "sudoCommand");
     if (bv == NULL)
-       return ret;
+       debug_return_bool(ret);
 
-    for (p = bv; *p != NULL && ret != FALSE; p++) {
+    for (p = bv; *p != NULL && ret != false; p++) {
        val = (*p)->bv_val;
        /* Match against ALL ? */
        if (!strcmp(val, "ALL")) {
-           ret = TRUE;
+           ret = true;
            if (setenv_implied != NULL)
-               *setenv_implied = TRUE;
+               *setenv_implied = true;
            DPRINTF(("ldap sudoCommand '%s' ... MATCH!", val), 2);
            continue;
        }
 
        /* check for !command */
        if (*val == '!') {
-           foundbang = TRUE;
+           foundbang = true;
            allowed_cmnd = estrdup(1 + val);    /* !command */
        } else {
-           foundbang = FALSE;
+           foundbang = false;
            allowed_cmnd = estrdup(val);        /* command */
        }
 
@@ -806,22 +822,22 @@ sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied)
             * If allowed (no bang) set ret but keep on checking.
             * If disallowed (bang), exit loop.
             */
-           ret = foundbang ? FALSE : TRUE;
+           ret = foundbang ? false : true;
        }
        DPRINTF(("ldap sudoCommand '%s' ... %s", val,
-           ret == TRUE ? "MATCH!" : "not"), 2);
+           ret == true ? "MATCH!" : "not"), 2);
 
        efree(allowed_cmnd);    /* cleanup */
     }
 
     ldap_value_free_len(bv);   /* more cleanup */
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 /*
  * Search for boolean "option" in sudoOption.
- * Returns TRUE if found and allowed, FALSE if negated, else UNSPEC.
+ * Returns true if found and allowed, false if negated, else UNSPEC.
  */
 static int
 sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
@@ -829,13 +845,14 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
     struct berval **bv, **p;
     char ch, *var;
     int ret = UNSPEC;
+    debug_decl(sudo_ldap_check_bool, SUDO_DEBUG_LDAP)
 
     if (entry == NULL)
-       return UNSPEC;
+       debug_return_bool(ret);
 
     bv = ldap_get_values_len(ld, entry, "sudoOption");
     if (bv == NULL)
-       return ret;
+       debug_return_bool(ret);
 
     /* walk through options */
     for (p = bv; *p != NULL; p++) {
@@ -850,7 +867,7 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option)
 
     ldap_value_free_len(bv);
 
-    return ret;
+    debug_return_bool(ret);
 }
 
 /*
@@ -862,13 +879,14 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
 {
     struct berval **bv, **p;
     char op, *var, *val;
+    debug_decl(sudo_ldap_parse_options, SUDO_DEBUG_LDAP)
 
     if (entry == NULL)
-       return;
+       debug_return;
 
     bv = ldap_get_values_len(ld, entry, "sudoOption");
     if (bv == NULL)
-       return;
+       debug_return;
 
     /* walk through options */
     for (p = bv; *p != NULL; p++) {
@@ -886,19 +904,21 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry)
                set_default(var, val, (int) op);
            } else {
                /* case var=val */
-               set_default(var, val, TRUE);
+               set_default(var, val, true);
            }
        } else if (*var == '!') {
            /* case !var Boolean False */
-           set_default(var + 1, NULL, FALSE);
+           set_default(var + 1, NULL, false);
        } else {
            /* case var Boolean True */
-           set_default(var, NULL, TRUE);
+           set_default(var, NULL, true);
        }
        efree(var);
     }
 
     ldap_value_free_len(bv);
+
+    debug_return;
 }
 
 /*
@@ -930,6 +950,7 @@ sudo_ldap_timefilter(char *buffer, size_t buffersize)
     time_t now;
     char timebuffer[16];
     int bytes = 0;
+    debug_decl(sudo_ldap_timefilter, SUDO_DEBUG_LDAP)
 
     /* Make sure we have a formatted timestamp for __now__. */
     time(&now);
@@ -953,22 +974,116 @@ sudo_ldap_timefilter(char *buffer, size_t buffersize)
     }
 
 done:
-    return bytes;
+    debug_return_int(bytes);
 }
 
 /*
  * Builds up a filter to search for default settings
  */
 static char *
-sudo_ldap_build_default_filter()
+sudo_ldap_build_default_filter(void)
 {
     char *filt;
+    debug_decl(sudo_ldap_build_default_filter, SUDO_DEBUG_LDAP)
 
     if (ldap_conf.search_filter)
        easprintf(&filt, "(&%s(cn=defaults))", ldap_conf.search_filter);
     else
        filt = estrdup("cn=defaults");
-    return filt;
+    debug_return_str(filt);
+}
+
+/*
+ * Determine length of query value after escaping characters
+ * as per RFC 4515.
+ */
+static size_t
+sudo_ldap_value_len(const char *value)
+{
+    const char *s;
+    size_t len = 0;
+
+    for (s = value; *s != '\0'; s++) {
+       switch (*s) {
+       case '\\':
+       case '(':
+       case ')':
+       case '*':
+           len += 2;
+           break;
+       }
+    }
+    len += (size_t)(s - value);
+    return len;
+}
+
+/*
+ * Like strlcat() but escapes characters as per RFC 4515.
+ */
+static size_t
+sudo_ldap_value_cat(char *dst, const char *src, size_t size)
+{
+    char *d = dst;
+    const char *s = src;
+    size_t n = size;
+    size_t dlen;
+
+    /* Find the end of dst and adjust bytes left but don't go past end */
+    while (n-- != 0 && *d != '\0')
+       d++;
+    dlen = d - dst;
+    n = size - dlen;
+
+    if (n == 0)
+       return dlen + strlen(s);
+    while (*s != '\0') {
+       switch (*s) {
+       case '\\':
+           if (n < 3)
+               goto done;
+           *d++ = '\\';
+           *d++ = '5';
+           *d++ = 'c';
+           n -= 3;
+           break;
+       case '(':
+           if (n < 3)
+               goto done;
+           *d++ = '\\';
+           *d++ = '2';
+           *d++ = '8';
+           n -= 3;
+           break;
+       case ')':
+           if (n < 3)
+               goto done;
+           *d++ = '\\';
+           *d++ = '2';
+           *d++ = '9';
+           n -= 3;
+           break;
+       case '*':
+           if (n < 3)
+               goto done;
+           *d++ = '\\';
+           *d++ = '2';
+           *d++ = 'a';
+           n -= 3;
+           break;
+       default:
+           if (n < 1)
+               goto done;
+           *d++ = *s;
+           n--;
+           break;
+       }
+       s++;
+    }
+done:
+    *d = '\0';
+    while (*s != '\0')
+       s++;
+    return dlen + (s - src);   /* count does not include NUL */
 }
 
 /*
@@ -978,27 +1093,34 @@ static char *
 sudo_ldap_build_pass1(struct passwd *pw)
 {
     struct group *grp;
-    char *buf, timebuffer[TIMEFILTER_LENGTH];
+    char *buf, timebuffer[TIMEFILTER_LENGTH], gidbuf[MAX_UID_T_LEN];
     struct group_list *grlist;
     size_t sz = 0;
     int i;
+    debug_decl(sudo_ldap_build_pass1, SUDO_DEBUG_LDAP)
 
     /* Start with LDAP search filter length + 3 */
     if (ldap_conf.search_filter)
        sz += strlen(ldap_conf.search_filter) + 3;
 
     /* Then add (|(sudoUser=USERNAME)(sudoUser=ALL)) + NUL */
-    sz += 29 + strlen(pw->pw_name);
+    sz += 29 + sudo_ldap_value_len(pw->pw_name);
 
-    /* Add space for primary and supplementary groups */
+    /* Add space for primary and supplementary groups and gids */
     if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
-       sz += 12 + strlen(grp->gr_name);
+       sz += 12 + sudo_ldap_value_len(grp->gr_name);
     }
+    sz += 13 + MAX_UID_T_LEN;
     if ((grlist = get_group_list(pw)) != NULL) {
        for (i = 0; i < grlist->ngroups; i++) {
            if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0)
                continue;
-           sz += 12 + strlen(grlist->groups[i]);
+           sz += 12 + sudo_ldap_value_len(grlist->groups[i]);
+       }
+       for (i = 0; i < grlist->ngids; i++) {
+           if (pw->pw_gid == grlist->gids[i])
+               continue;
+           sz += 13 + MAX_UID_T_LEN;
        }
     }
 
@@ -1020,23 +1142,36 @@ sudo_ldap_build_pass1(struct passwd *pw)
 
     /* Global OR + sudoUser=user_name filter */
     (void) strlcat(buf, "(|(sudoUser=", sz);
-    (void) strlcat(buf, pw->pw_name, sz);
+    (void) sudo_ldap_value_cat(buf, pw->pw_name, sz);
     (void) strlcat(buf, ")", sz);
 
-    /* Append primary group */
+    /* Append primary group and gid */
     if (grp != NULL) {
        (void) strlcat(buf, "(sudoUser=%", sz);
-       (void) strlcat(buf, grp->gr_name, sz);
+       (void) sudo_ldap_value_cat(buf, grp->gr_name, sz);
        (void) strlcat(buf, ")", sz);
     }
+    (void) snprintf(gidbuf, sizeof(gidbuf), "%u", (unsigned int)pw->pw_gid);
+    (void) strlcat(buf, "(sudoUser=%#", sz);
+    (void) strlcat(buf, gidbuf, sz);
+    (void) strlcat(buf, ")", sz);
 
-    /* Append supplementary groups */
+    /* Append supplementary groups and gids */
     if (grlist != NULL) {
        for (i = 0; i < grlist->ngroups; i++) {
            if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0)
                continue;
            (void) strlcat(buf, "(sudoUser=%", sz);
-           (void) strlcat(buf, grlist->groups[i], sz);
+           (void) sudo_ldap_value_cat(buf, grlist->groups[i], sz);
+           (void) strlcat(buf, ")", sz);
+       }
+       for (i = 0; i < grlist->ngids; i++) {
+           if (pw->pw_gid == grlist->gids[i])
+               continue;
+           (void) snprintf(gidbuf, sizeof(gidbuf), "%u",
+               (unsigned int)grlist->gids[i]);
+           (void) strlcat(buf, "(sudoUser=%#", sz);
+           (void) strlcat(buf, gidbuf, sz);
            (void) strlcat(buf, ")", sz);
        }
     }
@@ -1061,7 +1196,7 @@ sudo_ldap_build_pass1(struct passwd *pw)
     }
     strlcat(buf, ")", sz); /* closes the global OR or the global AND */
 
-    return buf;
+    debug_return_str(buf);
 }
 
 /*
@@ -1071,6 +1206,7 @@ static char *
 sudo_ldap_build_pass2(void)
 {
     char *filt, timebuffer[TIMEFILTER_LENGTH];
+    debug_decl(sudo_ldap_build_pass2, SUDO_DEBUG_LDAP)
 
     if (ldap_conf.timed)
        sudo_ldap_timefilter(timebuffer, sizeof(timebuffer));
@@ -1086,7 +1222,7 @@ sudo_ldap_build_pass2(void)
        ldap_conf.timed ? timebuffer : "",
        (ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
 
-    return filt;
+    debug_return_str(filt);
 }
 
 static void
@@ -1094,6 +1230,7 @@ sudo_ldap_read_secret(const char *path)
 {
     FILE *fp;
     char buf[LINE_MAX], *cp;
+    debug_decl(sudo_ldap_read_secret, SUDO_DEBUG_LDAP)
 
     if ((fp = fopen(_PATH_LDAP_SECRET, "r")) != NULL) {
        if (fgets(buf, sizeof(buf), fp) != NULL) {
@@ -1108,14 +1245,16 @@ sudo_ldap_read_secret(const char *path)
        }
        fclose(fp);
     }
+    debug_return;
 }
 
-static int
+static bool
 sudo_ldap_read_config(void)
 {
     FILE *fp;
     char *cp, *keyword, *value;
     struct ldap_config_table *cur;
+    debug_decl(sudo_ldap_read_config, SUDO_DEBUG_LDAP)
 
     /* defaults */
     ldap_conf.version = 3;
@@ -1129,7 +1268,7 @@ sudo_ldap_read_config(void)
     ldap_conf.deref = -1;
 
     if ((fp = fopen(_PATH_LDAP_CONF, "r")) == NULL)
-       return FALSE;
+       debug_return_bool(false);
 
     while ((cp = sudo_parseln(fp)) != NULL) {
        if (*cp == '\0')
@@ -1162,7 +1301,7 @@ sudo_ldap_read_config(void)
                        *(int *)(cur->valp) = LDAP_DEREF_NEVER;
                    break;
                case CONF_BOOL:
-                   *(int *)(cur->valp) = atobool(value) == TRUE;
+                   *(int *)(cur->valp) = atobool(value) == true;
                    break;
                case CONF_INT:
                    *(int *)(cur->valp) = atoi(value);
@@ -1294,7 +1433,7 @@ sudo_ldap_read_config(void)
        sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n");
     }
     if (!ldap_conf.base)
-       return FALSE;           /* if no base is defined, ignore LDAP */
+       debug_return_bool(false);       /* if no base is defined, ignore LDAP */
 
     if (ldap_conf.bind_timelimit > 0)
        ldap_conf.bind_timelimit *= 1000;       /* convert to ms */
@@ -1305,7 +1444,7 @@ sudo_ldap_read_config(void)
     if (ldap_conf.ssl != NULL) {
        if (strcasecmp(ldap_conf.ssl, "start_tls") == 0)
            ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS;
-       else if (atobool(ldap_conf.ssl) == TRUE)
+       else if (atobool(ldap_conf.ssl) == true)
            ldap_conf.ssl_mode = SUDO_LDAP_SSL;
     }
 
@@ -1321,7 +1460,7 @@ sudo_ldap_read_config(void)
     if (ldap_conf.uri) {
        struct ldap_config_list_str *uri = ldap_conf.uri;
        if (sudo_ldap_parse_uri(uri) != 0)
-           return FALSE;
+           debug_return_bool(false);
        do {
            ldap_conf.uri = uri->next;
            efree(uri);
@@ -1383,7 +1522,7 @@ sudo_ldap_read_config(void)
        }
     }
 #endif
-    return TRUE;
+    debug_return_bool(true);
 }
 
 /*
@@ -1395,23 +1534,25 @@ sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry)
 #ifdef HAVE_LDAP_STR2DN
     char *dn, *rdn = NULL;
     LDAPDN tmpDN;
+    debug_decl(sudo_ldap_get_first_rdn, SUDO_DEBUG_LDAP)
 
     if ((dn = ldap_get_dn(ld, entry)) == NULL)
-       return NULL;
+       debug_return_str(NULL);
     if (ldap_str2dn(dn, &tmpDN, LDAP_DN_FORMAT_LDAP) == LDAP_SUCCESS) {
        ldap_rdn2str(tmpDN[0], &rdn, LDAP_DN_FORMAT_UFN);
        ldap_dnfree(tmpDN);
     }
     ldap_memfree(dn);
-    return rdn;
+    debug_return_str(rdn);
 #else
     char *dn, **edn;
+    debug_decl(sudo_ldap_get_first_rdn, SUDO_DEBUG_LDAP)
 
     if ((dn = ldap_get_dn(ld, entry)) == NULL)
        return NULL;
     edn = ldap_explode_dn(dn, 1);
     ldap_memfree(dn);
-    return edn ? edn[0] : NULL;
+    debug_return_str(edn ? edn[0] : NULL);
 #endif
 }
 
@@ -1430,6 +1571,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
     LDAPMessage *entry, *result;
     char *prefix, *filt;
     int rc, count = 0;
+    debug_decl(sudo_ldap_display_defaults, SUDO_DEBUG_LDAP)
 
     if (handle == NULL || handle->ld == NULL)
        goto done;
@@ -1465,7 +1607,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw,
     }
     efree(filt);
 done:
-    return count;
+    debug_return_int(count);
 }
 
 /*
@@ -1475,7 +1617,8 @@ static int
 sudo_ldap_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw,
     struct lbuf *lbuf)
 {
-    return 0;
+    debug_decl(sudo_ldap_display_bound_defaults, SUDO_DEBUG_LDAP)
+    debug_return_int(0);
 }
 
 /*
@@ -1486,6 +1629,7 @@ sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *entry, struct lbuf *lbuf)
 {
     struct berval **bv, **p;
     int count = 0;
+    debug_decl(sudo_ldap_display_entry_short, SUDO_DEBUG_LDAP)
 
     lbuf_append(lbuf, "    (");
 
@@ -1543,7 +1687,7 @@ sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *entry, struct lbuf *lbuf)
     }
     lbuf_append(lbuf, "\n");
 
-    return count;
+    debug_return_int(count);
 }
 
 /*
@@ -1555,6 +1699,7 @@ sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *entry, struct lbuf *lbuf)
     struct berval **bv, **p;
     char *rdn;
     int count = 0;
+    debug_decl(sudo_ldap_display_entry_long, SUDO_DEBUG_LDAP)
 
     /* extract the dn, only show the first rdn */
     rdn = sudo_ldap_get_first_rdn(ld, entry);
@@ -1624,7 +1769,7 @@ sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *entry, struct lbuf *lbuf)
        ldap_value_free_len(bv);
     }
 
-    return count;
+    debug_return_int(count);
 }
 
 /*
@@ -1639,6 +1784,7 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
     struct ldap_result *lres;
     LDAPMessage *entry;
     int i, count = 0;
+    debug_decl(sudo_ldap_display_privs, SUDO_DEBUG_LDAP)
 
     if (handle == NULL || handle->ld == NULL)
        goto done;
@@ -1657,7 +1803,7 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw,
     }
 
 done:
-    return count;
+    debug_return_int(count);
 }
 
 static int
@@ -1667,7 +1813,9 @@ sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
     LDAP *ld;
     struct ldap_result *lres;
     LDAPMessage *entry;
-    int i, found = FALSE;
+    bool found = false;
+    int i;
+    debug_decl(sudo_ldap_display_cmnd, SUDO_DEBUG_LDAP)
 
     if (handle == NULL || handle->ld == NULL)
        goto done;
@@ -1683,7 +1831,7 @@ sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
        entry = lres->entries[i].entry;
        if (sudo_ldap_check_command(ld, entry, NULL) &&
            sudo_ldap_check_runas(ld, entry)) {
-           found = TRUE;
+           found = true;
            goto done;
        }
     }
@@ -1692,7 +1840,7 @@ done:
     if (found)
        printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd,
            user_args ? " " : "", user_args ? user_args : "");
-   return !found;
+   debug_return_bool(!found);
 }
 
 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
@@ -1702,10 +1850,11 @@ sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags, void *_auth_id,
 {
     char *auth_id = (char *)_auth_id;
     sasl_interact_t *interact = (sasl_interact_t *)_interact;
+    debug_decl(sudo_ldap_sasl_interact, SUDO_DEBUG_LDAP)
 
     for (; interact->id != SASL_CB_LIST_END; interact++) {
        if (interact->id != SASL_CB_USER)
-           return LDAP_PARAM_ERROR;
+           debug_return_int(LDAP_PARAM_ERROR);
 
        if (auth_id != NULL)
            interact->result = auth_id;
@@ -1719,7 +1868,7 @@ sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags, void *_auth_id,
        interact->result = estrdup(interact->result);
 #endif /* SASL_VERSION_MAJOR < 2 */
     }
-    return LDAP_SUCCESS;
+    debug_return_int(LDAP_SUCCESS);
 }
 #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
 
@@ -1731,6 +1880,7 @@ sudo_ldap_set_options(LDAP *ld)
 {
     struct ldap_config_table *cur;
     int rc;
+    debug_decl(sudo_ldap_set_options, SUDO_DEBUG_LDAP)
 
     /* Set ber options */
 #ifdef LBER_OPT_DEBUG_LEVEL
@@ -1757,7 +1907,7 @@ sudo_ldap_set_options(LDAP *ld)
                if (rc != LDAP_OPT_SUCCESS) {
                    warningx("ldap_set_option: %s -> %d: %s",
                        cur->conf_str, ival, ldap_err2string(rc));
-                   return -1;
+                   debug_return_int(-1);
                }
                DPRINTF(("ldap_set_option: %s -> %d", cur->conf_str, ival), 1);
            }
@@ -1769,7 +1919,7 @@ sudo_ldap_set_options(LDAP *ld)
                if (rc != LDAP_OPT_SUCCESS) {
                    warningx("ldap_set_option: %s -> %s: %s",
                        cur->conf_str, sval, ldap_err2string(rc));
-                   return -1;
+                   debug_return_int(-1);
                }
                DPRINTF(("ldap_set_option: %s -> %s", cur->conf_str, sval), 1);
            }
@@ -1787,7 +1937,7 @@ sudo_ldap_set_options(LDAP *ld)
        if (rc != LDAP_OPT_SUCCESS) {
            warningx("ldap_set_option(TIMEOUT, %ld): %s",
                (long)tv.tv_sec, ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_set_option(LDAP_OPT_TIMEOUT, %ld)",
            (long)tv.tv_sec), 1);
@@ -1803,7 +1953,7 @@ sudo_ldap_set_options(LDAP *ld)
        if (rc != LDAP_OPT_SUCCESS) {
            warningx("ldap_set_option(NETWORK_TIMEOUT, %ld): %s",
                (long)tv.tv_sec, ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)",
            (long)tv.tv_sec), 1);
@@ -1817,12 +1967,12 @@ sudo_ldap_set_options(LDAP *ld)
        if (rc != LDAP_SUCCESS) {
            warningx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s",
                ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)"), 1);
     }
 #endif
-    return 0;
+    debug_return_int(0);
 }
 
 /*
@@ -1832,15 +1982,16 @@ static struct ldap_result *
 sudo_ldap_result_alloc(void)
 {
     struct ldap_result *result;
+    debug_decl(sudo_ldap_result_alloc, SUDO_DEBUG_LDAP)
 
     result = emalloc(sizeof(*result));
     result->searches = NULL;
     result->nentries = 0;
     result->entries = NULL;
     result->allocated_entries = 0;
-    result->user_matches = FALSE;
-    result->host_matches = FALSE;
-    return result;
+    result->user_matches = false;
+    result->host_matches = false;
+    debug_return_ptr(result);
 }
 
 /*
@@ -1850,6 +2001,7 @@ static void
 sudo_ldap_result_free(struct ldap_result *lres)
 {
     struct ldap_search_list *s;
+    debug_decl(sudo_ldap_result_free, SUDO_DEBUG_LDAP)
 
     if (lres != NULL) {
        if (lres->nentries) {
@@ -1865,6 +2017,7 @@ sudo_ldap_result_free(struct ldap_result *lres)
        }
        efree(lres);
     }
+    debug_return;
 }
 
 /*
@@ -1875,6 +2028,7 @@ sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap,
     LDAPMessage *searchresult)
 {
     struct ldap_search_list *s, *news;
+    debug_decl(sudo_ldap_result_add_search, SUDO_DEBUG_LDAP)
 
     news = emalloc(sizeof(struct ldap_search_list));
     news->next = NULL;
@@ -1889,7 +2043,7 @@ sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap,
     } else {
        lres->searches = news;
     }
-    return news;
+    debug_return_ptr(news);
 }
 
 /*
@@ -1905,10 +2059,11 @@ sudo_ldap_bind_s(LDAP *ld)
     unsigned int status;
 # endif
 #endif
+    debug_decl(sudo_ldap_bind_s, SUDO_DEBUG_LDAP)
 
 #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
-    if (ldap_conf.rootuse_sasl == TRUE ||
-       (ldap_conf.rootuse_sasl != FALSE && ldap_conf.use_sasl == TRUE)) {
+    if (ldap_conf.rootuse_sasl == true ||
+       (ldap_conf.rootuse_sasl != false && ldap_conf.use_sasl == true)) {
        void *auth_id = ldap_conf.rootsasl_auth_id ?
            ldap_conf.rootsasl_auth_id : ldap_conf.sasl_auth_id;
 
@@ -1920,7 +2075,7 @@ sudo_ldap_bind_s(LDAP *ld)
                DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1);
            }
 # else
-           setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE);
+           setenv("KRB5CCNAME", ldap_conf.krb5_ccname, true);
 # endif
        }
        rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI",
@@ -1931,7 +2086,7 @@ sudo_ldap_bind_s(LDAP *ld)
                    DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1);
 # else
            if (old_ccname != NULL)
-               setenv("KRB5CCNAME", old_ccname, TRUE);
+               setenv("KRB5CCNAME", old_ccname, true);
            else
                unsetenv("KRB5CCNAME");
 # endif
@@ -1939,7 +2094,7 @@ sudo_ldap_bind_s(LDAP *ld)
        if (rc != LDAP_SUCCESS) {
            warningx("ldap_sasl_interactive_bind_s(): %s",
                ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1);
     } else
@@ -1955,7 +2110,7 @@ sudo_ldap_bind_s(LDAP *ld)
            NULL, NULL, NULL);
        if (rc != LDAP_SUCCESS) {
            warningx("ldap_sasl_bind_s(): %s", ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_sasl_bind_s() ok"), 1);
     }
@@ -1964,12 +2119,12 @@ sudo_ldap_bind_s(LDAP *ld)
        rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw);
        if (rc != LDAP_SUCCESS) {
            warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_simple_bind_s() ok"), 1);
     }
 #endif
-    return 0;
+    debug_return_int(0);
 }
 
 /*
@@ -1980,16 +2135,18 @@ static int
 sudo_ldap_open(struct sudo_nss *nss)
 {
     LDAP *ld;
-    int rc, ldapnoinit = FALSE;
-    struct sudo_ldap_handle    *handle;
+    int rc;
+    bool ldapnoinit = false;
+    struct sudo_ldap_handle *handle;
+    debug_decl(sudo_ldap_open, SUDO_DEBUG_LDAP)
 
     if (!sudo_ldap_read_config())
-       return -1;
+       debug_return_int(-1);
 
     /* Prevent reading of user ldaprc and system defaults. */
     if (getenv("LDAPNOINIT") == NULL) {
-       ldapnoinit = TRUE;
-       setenv("LDAPNOINIT", "1", TRUE);
+       ldapnoinit = true;
+       setenv("LDAPNOINIT", "1", true);
     }
 
     /* Connect to LDAP server */
@@ -2004,7 +2161,7 @@ sudo_ldap_open(struct sudo_nss *nss)
        rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port);
     if (rc != LDAP_SUCCESS) {
        warningx(_("unable to initialize LDAP: %s"), ldap_err2string(rc));
-       return -1;
+       debug_return_int(-1);
     }
 
     if (ldapnoinit)
@@ -2012,25 +2169,25 @@ sudo_ldap_open(struct sudo_nss *nss)
 
     /* Set LDAP options */
     if (sudo_ldap_set_options(ld) < 0)
-       return -1;
+       debug_return_int(-1);
 
     if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
 #if defined(HAVE_LDAP_START_TLS_S)
        rc = ldap_start_tls_s(ld, NULL, NULL);
        if (rc != LDAP_SUCCESS) {
            warningx("ldap_start_tls_s(): %s", ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_start_tls_s() ok"), 1);
 #elif defined(HAVE_LDAP_SSL_CLIENT_INIT) && defined(HAVE_LDAP_START_TLS_S_NP)
        if (ldap_ssl_client_init(NULL, NULL, 0, &rc) != LDAP_SUCCESS) {
            warningx("ldap_ssl_client_init(): %s", ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        rc = ldap_start_tls_s_np(ld, NULL);
        if (rc != LDAP_SUCCESS) {
            warningx("ldap_start_tls_s_np(): %s", ldap_err2string(rc));
-           return -1;
+           debug_return_int(-1);
        }
        DPRINTF(("ldap_start_tls_s_np() ok"), 1);
 #else
@@ -2040,7 +2197,7 @@ sudo_ldap_open(struct sudo_nss *nss)
 
     /* Actually connect */
     if (sudo_ldap_bind_s(ld) != 0)
-       return -1;
+       debug_return_int(-1);
 
     /* Create a handle container. */
     handle = emalloc(sizeof(struct sudo_ldap_handle));
@@ -2050,7 +2207,7 @@ sudo_ldap_open(struct sudo_nss *nss)
     handle->grlist = NULL;
     nss->handle = handle;
 
-    return 0;
+    debug_return_int(0);
 }
 
 static int
@@ -2063,9 +2220,10 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
     LDAPMessage *entry, *result;
     char *filt;
     int rc;
+    debug_decl(sudo_ldap_setdefs, SUDO_DEBUG_LDAP)
 
     if (handle == NULL || handle->ld == NULL)
-       return -1;
+       debug_return_int(-1);
     ld = handle->ld;
 
     filt = sudo_ldap_build_default_filter();
@@ -2091,7 +2249,7 @@ sudo_ldap_setdefs(struct sudo_nss *nss)
     }
     efree(filt);
 
-    return 0;
+    debug_return_int(0);
 }
 
 /*
@@ -2105,9 +2263,10 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
     LDAPMessage *entry;
     int i, rc, setenv_implied;
     struct ldap_result *lres = NULL;
+    debug_decl(sudo_ldap_lookup, SUDO_DEBUG_LDAP)
 
     if (handle == NULL || handle->ld == NULL)
-       return ret;
+       debug_return_int(ret);
     ld = handle->ld;
 
     /* Fetch list of sudoRole entries that match user and host. */
@@ -2126,15 +2285,15 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
        DPRINTF(("perform search for pwflag %d", pwflag), 1);
        for (i = 0; i < lres->nentries; i++) {
            entry = lres->entries[i].entry;
-           if ((pwcheck == any && doauth != FALSE) ||
-               (pwcheck == all && doauth == FALSE)) {
+           if ((pwcheck == any && doauth != false) ||
+               (pwcheck == all && doauth == false)) {
                doauth = sudo_ldap_check_bool(ld, entry, "authenticate");
            }
            /* Only check the command when listing another user. */
            if (user_uid == 0 || list_pw == NULL ||
                user_uid == list_pw->pw_uid ||
                sudo_ldap_check_command(ld, entry, NULL)) {
-               matched = TRUE;
+               matched = true;
                break;
            }
        }
@@ -2148,11 +2307,11 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
                        break;
                    case all:
                    case any:
-                       if (doauth == FALSE)
-                           def_authenticate = FALSE;
+                       if (doauth == false)
+                           def_authenticate = false;
                        break;
                    case never:
-                       def_authenticate = FALSE;
+                       def_authenticate = false;
                        break;
                    default:
                        break;
@@ -2164,7 +2323,7 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
 
     DPRINTF(("searching LDAP for sudoers entries"), 1);
 
-    setenv_implied = FALSE;
+    setenv_implied = false;
     for (i = 0; i < lres->nentries; i++) {
        entry = lres->entries[i].entry;
        if (!sudo_ldap_check_runas(ld, entry))
@@ -2172,12 +2331,12 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag)
        rc = sudo_ldap_check_command(ld, entry, &setenv_implied);
        if (rc != UNSPEC) {
            /* We have a match. */
-           DPRINTF(("Command %sallowed", rc == TRUE ? "" : "NOT "), 1);
-           if (rc == TRUE) {
+           DPRINTF(("Command %sallowed", rc == true ? "" : "NOT "), 1);
+           if (rc == true) {
                DPRINTF(("LDAP entry: %p", entry), 1);
                /* Apply entry-specific options. */
                if (setenv_implied)
-                   def_setenv = TRUE;
+                   def_setenv = true;
                sudo_ldap_parse_options(ld, entry);
 #ifdef HAVE_SELINUX
                /* Set role and type if not specified on command line. */
@@ -2212,7 +2371,7 @@ done:
        CLR(ret, FLAG_NO_HOST);
     DPRINTF(("sudo_ldap_lookup(%d)=0x%02x", pwflag, ret), 1);
 
-    return ret;
+    debug_return_int(ret);
 }
 
 /*
@@ -2223,9 +2382,10 @@ ldap_entry_compare(const void *a, const void *b)
 {
     const struct ldap_entry_wrapper *aw = a;
     const struct ldap_entry_wrapper *bw = b;
+    debug_decl(ldap_entry_compare, SUDO_DEBUG_LDAP)
 
-    return bw->order < aw->order ? -1 :
-       (bw->order > aw->order ? 1 : 0);
+    debug_return_int(bw->order < aw->order ? -1 :
+       (bw->order > aw->order ? 1 : 0));
 }
 
 /*
@@ -2237,12 +2397,13 @@ static struct ldap_search_list *
 sudo_ldap_result_last_search(struct ldap_result *lres)
 {
     struct ldap_search_list *result = lres->searches;
+    debug_decl(sudo_ldap_result_last_search, SUDO_DEBUG_LDAP)
 
     if (result) {
        while (result->next)
            result = result->next;
     }
-    return result;
+    debug_return_ptr(result);
 }
 
 /*
@@ -2255,6 +2416,7 @@ sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
     struct berval **bv;
     double order = 0.0;
     char *ep;
+    debug_decl(sudo_ldap_result_add_entry, SUDO_DEBUG_LDAP)
 
     /* Determine whether the entry has the sudoOrder attribute. */
     last = sudo_ldap_result_last_search(lres);
@@ -2287,7 +2449,7 @@ sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
     lres->entries[lres->nentries - 1].entry = entry;
     lres->entries[lres->nentries - 1].order = order;
 
-    return &lres->entries[lres->nentries - 1];
+    debug_return_ptr(&lres->entries[lres->nentries - 1]);
 }
 
 /*
@@ -2297,6 +2459,7 @@ static void
 sudo_ldap_result_free_nss(struct sudo_nss *nss)
 {
     struct sudo_ldap_handle *handle = nss->handle;
+    debug_decl(sudo_ldap_result_free_nss, SUDO_DEBUG_LDAP)
 
     if (handle->result != NULL) {
        DPRINTF(("removing reusable search result"), 1);
@@ -2308,6 +2471,7 @@ sudo_ldap_result_free_nss(struct sudo_nss *nss)
        handle->grlist = NULL;
        handle->result = NULL;
     }
+    debug_return;
 }
 
 /*
@@ -2325,6 +2489,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
     LDAP *ld = handle->ld;
     int do_netgr, rc;
     char *filt;
+    debug_decl(sudo_ldap_result_get, SUDO_DEBUG_LDAP)
 
     /*
      * If we already have a cached result, return it so we don't have to
@@ -2335,7 +2500,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
            strcmp(pw->pw_name, handle->username) == 0) {
            DPRINTF(("reusing previous result (user %s) with %d entries",
                handle->username, handle->result->nentries), 1);
-           return handle->result;
+           debug_return_ptr(handle->result);
        }
        /* User mismatch, cached result cannot be used. */
        DPRINTF(("removing result (user %s), new search (user %s)",
@@ -2379,7 +2544,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
                DPRINTF(("nothing found for '%s'", filt), 1);
                continue;
            }
-           lres->user_matches = TRUE;
+           lres->user_matches = true;
 
            /* Add the seach result to list of search results. */
            DPRINTF(("adding search result"), 1);
@@ -2388,7 +2553,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
                if ((!do_netgr ||
                    sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
                    sudo_ldap_check_host(ld, entry)) {
-                   lres->host_matches = TRUE;
+                   lres->host_matches = true;
                    sudo_ldap_result_add_entry(lres, entry);
                }
            }
@@ -2407,7 +2572,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
     handle->username = estrdup(pw->pw_name);
     handle->grlist = user_group_list;
 
-    return lres;
+    debug_return_ptr(lres);
 }
 
 /*
@@ -2417,6 +2582,7 @@ static int
 sudo_ldap_close(struct sudo_nss *nss)
 {
     struct sudo_ldap_handle *handle = nss->handle;
+    debug_decl(sudo_ldap_close, SUDO_DEBUG_LDAP)
 
     if (handle != NULL) {
        /* Free the result before unbinding; it may use the LDAP connection. */
@@ -2432,7 +2598,7 @@ sudo_ldap_close(struct sudo_nss *nss)
        efree(nss->handle);
        nss->handle = NULL;
     }
-    return 0;
+    debug_return_int(0);
 }
 
 /*