]> granicus.if.org Git - sudo/commitdiff
When querying LDAP netgroups, use the NIS domain if it is sent but
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 30 Jan 2015 21:45:22 +0000 (14:45 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 30 Jan 2015 21:45:22 +0000 (14:45 -0700)
also match nisNetgroupTriple entries that have no domain.

doc/sudoers.ldap.cat
doc/sudoers.ldap.man.in
doc/sudoers.ldap.mdoc.in
plugins/sudoers/ldap.c
plugins/sudoers/match.c
plugins/sudoers/parse.h

index 23c8ef8af82b6cc4ead01926693fe700c63a0a84..b6675b34929af163ced36414097966e22cfda6ba 100644 (file)
@@ -196,19 +196,23 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
      directive, the LDAP queries include a sub-filter that limits retrieval to
      entries that satisfy the time constraints, if any.
 
-     If the N\bNE\bET\bTG\bGR\bRO\bOU\bUP\bP_\b_B\bBA\bAS\bSE\bE 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 s\bsu\bud\bdo\bo are as follows:
+     If the N\bNE\bET\bTG\bGR\bRO\bOU\bUP\bP_\b_B\bBA\bAS\bSE\bE configuration directive is present (see _\bC_\bo_\bn_\bf_\bi_\bg_\bu_\br_\bi_\bn_\bg
+     _\bl_\bd_\ba_\bp_\b._\bc_\bo_\bn_\bf 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 s\bsu\bud\bdo\bo 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 _\bn_\bo_\bt 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 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
      file distributed with s\bsu\bud\bdo\bo 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
index 6804b45be5e3943a3e29ad6ed1fb303960f4cea1..a044bb1a013f249551be4b9a72bb40341a640a25 100644 (file)
@@ -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
index f16290e9044ea841a89b5c20a080d949ea7092a4..bf1ea1ecc2843d4d074379844ce77c1bfb3f7ef0 100644 (file)
@@ -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
index 0ede38fb0371b523be933aa23311cd01f5914946..eb7a8a7f2382b0991ed3d51b5e61f31e888ba48e 100644 (file)
@@ -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,
index fe444c62e6a7e4722b40c904d8a9f36bb0699f91..aee4f6877f004ad86a83b63925a6c9391dba630d 100644 (file)
@@ -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;
index 766da87533a6a2d3deb1dde344f5d1598c0816b6..a34f5fa4b09abc793bce2e07a9948463ecf86ec6 100644 (file)
@@ -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);