From: Todd C. Miller Date: Fri, 30 Jan 2015 21:45:22 +0000 (-0700) Subject: When querying LDAP netgroups, use the NIS domain if it is sent but X-Git-Tag: SUDO_1_8_12^2~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ec9cfb4933545ad90e4653b3f273fa9781995da;p=sudo When querying LDAP netgroups, use the NIS domain if it is sent but also match nisNetgroupTriple entries that have no domain. --- diff --git a/doc/sudoers.ldap.cat b/doc/sudoers.ldap.cat index 23c8ef8af..b6675b349 100644 --- a/doc/sudoers.ldap.cat +++ b/doc/sudoers.ldap.cat @@ -196,19 +196,23 @@ DDEESSCCRRIIPPTTIIOONN directive, the LDAP queries include a sub-filter that limits retrieval to entries that satisfy the time constraints, if any. - If the NNEETTGGRROOUUPP__BBAASSEE configuration directive is present, queries are - performed to determine the list of netgroups the user belongs to before - the sudoers query. This makes it possible to include netgroups in the - sudoers query string in the same manner as Unix groups. The third query - mentioned above is not performed unless a group provider plugin is also - configured. The actual LDAP queries performed by ssuuddoo are as follows: + If the NNEETTGGRROOUUPP__BBAASSEE configuration directive is present (see _C_o_n_f_i_g_u_r_i_n_g + _l_d_a_p_._c_o_n_f below), queries are performed to determine the list of + netgroups the user belongs to before the sudoers query. This makes it + possible to include netgroups in the sudoers query string in the same + manner as Unix groups. The third query mentioned above is not performed + unless a group provider plugin is also configured. The actual LDAP + queries performed by ssuuddoo are as follows: 1. Match all nisNetgroup records with a nisNetgroupTriple containing - the user and host. The query will match nisNetgroupTriple entries - with either the short or long form of the host name or no host name - specified in the tuple. A wildcard is used to match any domain name - but be aware that the NIS schema used by some LDAP servers may not - support wild cards for nisNetgroupTriple. + the user, host and NIS domain. The query will match + nisNetgroupTriple entries with either the short or long form of the + host name or no host name specified in the tuple. If the NIS domain + is set, the query will match only match entries that include the + domain or for which there is no domain present. If the NIS domain + is _n_o_t set, a wildcard is used to match any domain name but be aware + that the NIS schema used by some LDAP servers may not support wild + cards for nisNetgroupTriple. 2. Repeated queries are performed to find any nested nisNetgroup records with a memberNisNetgroup entry that refers to an already- @@ -888,4 +892,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or http://www.sudo.ws/license.html for complete details. -Sudo 1.8.12 January 26, 2015 Sudo 1.8.12 +Sudo 1.8.12 January 30, 2015 Sudo 1.8.12 diff --git a/doc/sudoers.ldap.man.in b/doc/sudoers.ldap.man.in index 6804b45be..a044bb1a0 100644 --- a/doc/sudoers.ldap.man.in +++ b/doc/sudoers.ldap.man.in @@ -16,7 +16,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.TH "SUDOERS.LDAP" "8" "January 26, 2015" "Sudo @PACKAGE_VERSION@" "System Manager's Manual" +.TH "SUDOERS.LDAP" "8" "January 30, 2015" "Sudo @PACKAGE_VERSION@" "System Manager's Manual" .nh .if n .ad l .SH "NAME" @@ -377,7 +377,9 @@ limits retrieval to entries that satisfy the time constraints, if any. .PP If the \fBNETGROUP_BASE\fR -configuration directive is present, queries are performed to determine +configuration directive is present (see +\fIConfiguring ldap.conf\fR +below), queries are performed to determine the list of netgroups the user belongs to before the sudoers query. This makes it possible to include netgroups in the sudoers query string in the same manner as Unix groups. @@ -392,12 +394,16 @@ Match all \fRnisNetgroup\fR records with a \fRnisNetgroupTriple\fR -containing the user and host. +containing the user, host and NIS domain. The query will match \fRnisNetgroupTriple\fR entries with either the short or long form of the host name or no host name specified in the tuple. -A wildcard is used to match any domain name but be aware that the +If the NIS domain is set, the query will match only match entries +that include the domain or for which there is no domain present. +If the NIS domain is +\fInot\fR +set, a wildcard is used to match any domain name but be aware that the NIS schema used by some LDAP servers may not support wild cards for \fRnisNetgroupTriple\fR. .TP 5n diff --git a/doc/sudoers.ldap.mdoc.in b/doc/sudoers.ldap.mdoc.in index f16290e90..bf1ea1ecc 100644 --- a/doc/sudoers.ldap.mdoc.in +++ b/doc/sudoers.ldap.mdoc.in @@ -14,7 +14,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 26, 2015 +.Dd January 30, 2015 .Dt SUDOERS.LDAP @mansectsu@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -355,7 +355,9 @@ limits retrieval to entries that satisfy the time constraints, if any. .Pp If the .Sy NETGROUP_BASE -configuration directive is present, queries are performed to determine +configuration directive is present (see +.Sx Configuring ldap.conf +below), queries are performed to determine the list of netgroups the user belongs to before the sudoers query. This makes it possible to include netgroups in the sudoers query string in the same manner as Unix groups. @@ -370,12 +372,16 @@ Match all .Li nisNetgroup records with a .Li nisNetgroupTriple -containing the user and host. +containing the user, host and NIS domain. The query will match .Li nisNetgroupTriple entries with either the short or long form of the host name or no host name specified in the tuple. -A wildcard is used to match any domain name but be aware that the +If the NIS domain is set, the query will match only match entries +that include the domain or for which there is no domain present. +If the NIS domain is +.Em not +set, a wildcard is used to match any domain name but be aware that the NIS schema used by some LDAP servers may not support wild cards for .Li nisNetgroupTriple . .It diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 0ede38fb0..eb7a8a7f2 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -1329,6 +1329,7 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw, struct ldap_netgroup *ng, *old_tail; struct timeval tv, *tvp = NULL; LDAPMessage *entry, *result; + const char *domain; size_t filt_len; char *filt; int rc; @@ -1340,33 +1341,90 @@ sudo_netgroup_lookup(LDAP *ld, struct passwd *pw, tvp = &tv; } + /* Use NIS domain if set, else wildcard match. */ + domain = sudo_getdomainname(); + STAILQ_FOREACH(base, &ldap_conf.netgroup_base, entries) { - /* Build query. */ - filt_len = 2 + strlen(ldap_conf.netgroup_search_filter) + - 24 + (2 * sudo_ldap_value_len(pw->pw_name)) + 26 + - sudo_ldap_value_len(user_shost) + 1 + 7 + 1; - if (user_host != user_shost) { - filt_len += 26 + sudo_ldap_value_len(user_host) + 1 + - sudo_ldap_value_len(pw->pw_name); - } - filt = sudo_emalloc(filt_len); DPRINTF1("searching from netgroup_base '%s'", base->val); - CHECK_STRLCPY(filt, "(&", filt_len); - CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len); - CHECK_STRLCAT(filt, "(|(nisNetgroupTriple=\\(,", filt_len); - CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); - CHECK_STRLCAT(filt, ",*\\))(nisNetgroupTriple=\\(", filt_len); - CHECK_LDAP_VCAT(filt, user_shost, filt_len); - CHECK_STRLCAT(filt, ",", filt_len); - CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); - if (user_host != user_shost) { + + /* Build query, using NIS domain if it is set. */ + if (domain != NULL) { + filt_len = sizeof("(nisNetgroupTriple=\\(,,\\))") - 1 + + sudo_ldap_value_len(pw->pw_name); + if (user_host == user_shost) { + filt_len *= 4; + filt_len += 2 * sudo_ldap_value_len(user_shost); + filt_len += 2 * sudo_ldap_value_len(domain); + } else { + filt_len *= 6; + filt_len += 2 * sudo_ldap_value_len(user_shost); + filt_len += 2 * sudo_ldap_value_len(user_host); + filt_len += 3 * sudo_ldap_value_len(domain); + } + filt_len += 7 + strlen(ldap_conf.netgroup_search_filter); + filt = sudo_emalloc(filt_len); + CHECK_STRLCPY(filt, "(&", filt_len); + CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len); + CHECK_STRLCAT(filt, "(|(nisNetgroupTriple=\\(,", 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, "\\))(nisNetgroupTriple=\\(", filt_len); + CHECK_LDAP_VCAT(filt, user_shost, filt_len); + CHECK_STRLCAT(filt, ",", filt_len); + CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); + if (user_host != user_shost) { + CHECK_STRLCAT(filt, ",", filt_len); + CHECK_LDAP_VCAT(filt, domain, filt_len); + CHECK_STRLCAT(filt, "\\))(nisNetgroupTriple=\\(", filt_len); + CHECK_LDAP_VCAT(filt, user_host, 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, "\\))(nisNetgroupTriple=\\(,", filt_len); + CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); + CHECK_STRLCAT(filt, ",\\))(nisNetgroupTriple=\\(", filt_len); + CHECK_LDAP_VCAT(filt, user_shost, filt_len); + CHECK_STRLCAT(filt, ",", filt_len); + CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); + if (user_host != user_shost) { + CHECK_STRLCAT(filt, ",\\))(nisNetgroupTriple=\\(", filt_len); + CHECK_LDAP_VCAT(filt, user_host, filt_len); + CHECK_STRLCAT(filt, ",", filt_len); + CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); + } + CHECK_STRLCAT(filt, ",\\))))", filt_len); + } else { + filt_len = sizeof("(nisNetgroupTriple=\\(,,*\\))") - 1 + + sudo_ldap_value_len(pw->pw_name); + if (user_host == user_shost) { + filt_len *= 2; + filt_len += sudo_ldap_value_len(user_shost); + } else { + filt_len *= 3; + filt_len += sudo_ldap_value_len(user_shost); + filt_len += sudo_ldap_value_len(user_host); + } + filt_len += 7 + strlen(ldap_conf.netgroup_search_filter); + filt = sudo_emalloc(filt_len); + CHECK_STRLCPY(filt, "(&", filt_len); + CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len); + CHECK_STRLCAT(filt, "(|(nisNetgroupTriple=\\(,", filt_len); + CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); CHECK_STRLCAT(filt, ",*\\))(nisNetgroupTriple=\\(", filt_len); - CHECK_LDAP_VCAT(filt, user_host, filt_len); + CHECK_LDAP_VCAT(filt, user_shost, filt_len); CHECK_STRLCAT(filt, ",", filt_len); CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); + if (user_host != user_shost) { + CHECK_STRLCAT(filt, ",*\\))(nisNetgroupTriple=\\(", filt_len); + CHECK_LDAP_VCAT(filt, user_host, filt_len); + CHECK_STRLCAT(filt, ",", filt_len); + CHECK_LDAP_VCAT(filt, pw->pw_name, filt_len); + } + CHECK_STRLCAT(filt, ",*\\))))", filt_len); } - CHECK_STRLCAT(filt, ",*\\))))", filt_len); - DPRINTF1("ldap netgroup search filter: '%s'", filt); result = NULL; rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt, diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c index fe444c62e..aee4f6877 100644 --- a/plugins/sudoers/match.c +++ b/plugins/sudoers/match.c @@ -905,19 +905,20 @@ done: debug_return_bool(matched); } -#ifdef HAVE_INNETGR /* - * Get NIS-style domain name and return a malloc()ed copy or NULL if none. + * Get NIS-style domain name and copy from static storage or NULL if none. */ -static char * +const char * sudo_getdomainname(void) { char *domain = NULL; #ifdef HAVE_GETDOMAINNAME - char *buf, *cp; + static char buf[HOST_NAME_MAX + 1]; + static bool initialized; + + if (getdomainname(buf, sizeof(buf)) == 0 && buf[0] != '\0') { + char *cp; - buf = sudo_emalloc(HOST_NAME_MAX + 1); - if (getdomainname(buf, HOST_NAME_MAX + 1) == 0 && *buf != '\0') { domain = buf; for (cp = buf; *cp != '\0'; cp++) { /* Check for illegal characters, Linux may use "(none)". */ @@ -927,12 +928,10 @@ sudo_getdomainname(void) } } } - if (domain == NULL) - sudo_efree(buf); + initialized = true; #endif /* HAVE_GETDOMAINNAME */ return domain; } -#endif /* HAVE_INNETGR */ /* * Returns true if "host" and "user" belong to the netgroup "netgr", @@ -943,8 +942,7 @@ bool netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user) { #ifdef HAVE_INNETGR - static char *domain; - static int initialized; + const char *domain; #endif bool rc = false; debug_decl(netgr_matches, SUDOERS_DEBUG_MATCH, sudoers_debug_instance) @@ -963,10 +961,7 @@ netgr_matches(const char *netgr, const char *lhost, const char *shost, const cha } /* get the domain name (if any) */ - if (!initialized) { - domain = sudo_getdomainname(); - initialized = 1; - } + domain = sudo_getdomainname(); if (innetgr(netgr, lhost, user, domain)) rc = true; diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 766da8753..a34f5fa4b 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -211,6 +211,7 @@ int cmndlist_matches(const struct member_list *list); int hostlist_matches(const struct member_list *list); int runaslist_matches(const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group); int userlist_matches(const struct passwd *pw, const struct member_list *list); +const char *sudo_getdomainname(void); /* toke.c */ void init_lexer(void);