return dlen + (s - src); /* count does not include NUL */
}
+/*
+ * Like strdup() but escapes characters as per RFC 4515.
+ */
+static char *
+sudo_ldap_value_dup(const char *src)
+{
+ char *dst;
+ size_t size;
+
+ size = sudo_ldap_value_len(src) + 1;
+ dst = malloc(size);
+ if (dst == NULL)
+ return NULL;
+
+ *dst = '\0';
+ if (sudo_ldap_value_cat(dst, src, size) >= size) {
+ /* Should not be possible... */
+ free(dst);
+ dst = NULL;
+ }
+ return dst;
+}
+
/*
* Check the netgroups list beginning at "start" for nesting.
* Parent nodes with a memberNisNetgroup that match one of the
struct timeval tv, *tvp = NULL;
LDAPMessage *entry, *result = NULL;
const char *domain;
- size_t filt_len;
- char *filt;
- int rc;
+ char *escaped_domain, *escaped_host, *escaped_shost, *escaped_user;
+ char *filt = NULL;
+ int filt_len, rc;
debug_decl(sudo_netgroup_lookup, SUDOERS_DEBUG_LDAP);
if (ldap_conf.timeout > 0) {
/* Use NIS domain if set, else wildcard match. */
domain = sudo_getdomainname();
+ /* Escape the domain, host names, and user name per RFC 4515. */
+ escaped_domain = domain ? sudo_ldap_value_dup(domain) : NULL;
+ escaped_host = sudo_ldap_value_dup(user_runhost);
+ if (user_runhost == user_srunhost)
+ escaped_shost = escaped_host;
+ else
+ escaped_shost = sudo_ldap_value_dup(user_srunhost);
+ escaped_user = sudo_ldap_value_dup(pw->pw_name);
+ if (escaped_domain == NULL || escaped_host == NULL ||
+ escaped_shost == NULL || escaped_user == NULL)
+ goto oom;
+
/* Build query, using NIS domain if it is set. */
if (domain != NULL) {
- filt_len = sizeof("(nisNetgroupTriple=\\28,,\\29)") - 1 +
- sudo_ldap_value_len(pw->pw_name);
- if (user_runhost == user_srunhost) {
- filt_len *= 4;
- filt_len += 2 * sudo_ldap_value_len(user_srunhost);
- filt_len += 2 * sudo_ldap_value_len(domain);
- } else {
- filt_len *= 6;
- filt_len += 2 * sudo_ldap_value_len(user_srunhost);
- filt_len += 2 * sudo_ldap_value_len(user_runhost);
- filt_len += 3 * sudo_ldap_value_len(domain);
- }
- filt_len += 7 + strlen(ldap_conf.netgroup_search_filter);
- 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);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, domain, filt_len);
- CHECK_STRLCAT(filt, "\\29)(nisNetgroupTriple=\\28", filt_len);
- CHECK_LDAP_VCAT(filt, user_srunhost, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
- if (user_runhost != user_srunhost) {
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, domain, filt_len);
- CHECK_STRLCAT(filt, "\\29)(nisNetgroupTriple=\\28", filt_len);
- CHECK_LDAP_VCAT(filt, user_runhost, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
- }
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, domain, filt_len);
- CHECK_STRLCAT(filt, "\\29)(nisNetgroupTriple=\\28,", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
- CHECK_STRLCAT(filt, ",\\29)(nisNetgroupTriple=\\28", filt_len);
- CHECK_LDAP_VCAT(filt, user_srunhost, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
if (user_runhost != user_srunhost) {
- CHECK_STRLCAT(filt, ",\\29)(nisNetgroupTriple=\\28", filt_len);
- CHECK_LDAP_VCAT(filt, user_runhost, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
- }
- CHECK_STRLCAT(filt, ",\\29)))", filt_len);
- } else {
- filt_len = sizeof("(nisNetgroupTriple=\\28,,*\\29)") - 1 +
- sudo_ldap_value_len(pw->pw_name);
- if (user_runhost == user_srunhost) {
- filt_len *= 2;
- filt_len += sudo_ldap_value_len(user_srunhost);
+ filt_len = asprintf(&filt, "(&%s(|(nisNetgroupTriple=\\28,%s,%s\\29)(nisNetgroupTriple=\\28%s,%s,%s\\29)(nisNetgroupTriple=\\28%s,%s,%s\\29)(nisNetgroupTriple=\\28,%s,\\29)(nisNetgroupTriple=\\28%s,%s,\\29)(nisNetgroupTriple=\\28%s,%s,\\29)))", ldap_conf.netgroup_search_filter, escaped_user, escaped_domain, escaped_shost, escaped_user, escaped_domain, escaped_host, escaped_user, escaped_domain, escaped_user, escaped_shost, escaped_user, escaped_host, escaped_user);
} else {
- filt_len *= 3;
- filt_len += sudo_ldap_value_len(user_srunhost);
- filt_len += sudo_ldap_value_len(user_runhost);
+ filt_len = asprintf(&filt, "(&%s(|(nisNetgroupTriple=\\28,%s,%s\\29)(nisNetgroupTriple=\\28%s,%s,%s\\29)(nisNetgroupTriple=\\28,%s,\\29)(nisNetgroupTriple=\\28%s,%s,\\29)))", ldap_conf.netgroup_search_filter, escaped_user, escaped_domain, escaped_shost, escaped_user, escaped_domain, escaped_user, escaped_shost, escaped_user);
}
- filt_len += 7 + strlen(ldap_conf.netgroup_search_filter);
- 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);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
- CHECK_STRLCAT(filt, ",*\\29)(nisNetgroupTriple=\\28", filt_len);
- CHECK_LDAP_VCAT(filt, user_srunhost, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
+ } else {
if (user_runhost != user_srunhost) {
- CHECK_STRLCAT(filt, ",*\\29)(nisNetgroupTriple=\\28", filt_len);
- CHECK_LDAP_VCAT(filt, user_runhost, filt_len);
- CHECK_STRLCAT(filt, ",", filt_len);
- CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len);
+ filt_len = asprintf(&filt, "(&%s(|(nisNetgroupTriple=\\28,%s,*\\29)(nisNetgroupTriple=\\28%s,%s,*\\29)(nisNetgroupTriple=\\28%s,%s,*\\29)))", ldap_conf.netgroup_search_filter, escaped_user, escaped_shost, escaped_user, escaped_host, escaped_user);
+ } else {
+ filt_len = asprintf(&filt, "(&%s(|(nisNetgroupTriple=\\28,%s,*\\29)(nisNetgroupTriple=\\28%s,%s,*\\29)))", ldap_conf.netgroup_search_filter, escaped_user, escaped_shost, escaped_user);
}
- CHECK_STRLCAT(filt, ",*\\29)))", filt_len);
}
+ if (filt_len == -1)
+ goto oom;
DPRINTF1("ldap netgroup search filter: '%s'", filt);
STAILQ_FOREACH(base, &ldap_conf.netgroup_base, entries) {
debug_return_bool(true);
oom:
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(escaped_domain);
+ free(escaped_host);
+ if (escaped_host != escaped_shost)
+ free(escaped_shost);
+ free(escaped_user);
free(filt);
ldap_msgfree(result);
debug_return_bool(false);
-overflow:
- sudo_warnx(U_("internal error, %s overflow"), __func__);
- free(filt);
- debug_return_bool(false);
}
/*