From 9d7bc0311fa831012c5be4ff5bef19d0f46a7ddf Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 12 Jan 2016 14:29:09 -0700 Subject: [PATCH] Use asprintf() to generate the netgroup filter instead of using lots of concatenation. --- plugins/sudoers/ldap.c | 130 ++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 79 deletions(-) diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 338991d59..f5f62c14a 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -1279,6 +1279,29 @@ done: 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 @@ -1378,9 +1401,9 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw, 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) { @@ -1392,86 +1415,34 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw, /* 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) { @@ -1525,13 +1496,14 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw, 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); } /* -- 2.40.0