]> granicus.if.org Git - sudo/commitdiff
Add support for multiple sudoers_base entries in ldap.conf.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 15 Jun 2010 14:05:08 +0000 (10:05 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 15 Jun 2010 14:05:08 +0000 (10:05 -0400)
From Joachim Henke

--HG--
branch : 1.7

WHATSNEW
ldap.c
sudoers.ldap.cat
sudoers.ldap.man.in
sudoers.ldap.pod

index 1615adc1b2a3bb74e1fadf8f96e38f96e0576e1e..f0d7cc8d705b43ef77b15dc651f5a67a1f6d28f6 100644 (file)
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -14,6 +14,10 @@ What's new in Sudo 1.7.3?
    Mac OS X, and Linux systems with the devpts filesystem (pseudo-ttys
    only).
 
+ * Support for multiple 'sudoers_base' entries in ldap.conf.  When
+   multiple bases are listed, sudo will try each one in the order
+   in which they are specified.
+
  * Sudo's SELinux support should now function correctly when running
    commands as a non-root user and when one of stdin, stdout or stderr
    is not a terminal.
diff --git a/ldap.c b/ldap.c
index 56967e1a0d3ac1880d1ae4c68bb2a30cc6e2f82c..e99b75395c09735e0452b07076f7bc8a019ace92 100644 (file)
--- a/ldap.c
+++ b/ldap.c
 #define CONF_BOOL      0
 #define CONF_INT       1
 #define CONF_STR       2
+#define CONF_LIST_STR  4
 
 #define SUDO_LDAP_SSL          1
 #define SUDO_LDAP_STARTTLS     2
@@ -124,6 +125,11 @@ struct ldap_config_table {
     void *valp;                        /* pointer into ldap_conf */
 };
 
+struct ldap_config_list_str {
+    struct ldap_config_list_str *next;
+    char val[1];
+};
+
 /* ldap configuration structure */
 static struct ldap_config {
     int port;
@@ -141,7 +147,7 @@ static struct ldap_config {
     char *binddn;
     char *bindpw;
     char *rootbinddn;
-    char *base;
+    struct ldap_config_list_str *base;
     char *ssl;
     char *tls_cacertfile;
     char *tls_cacertdir;
@@ -214,7 +220,7 @@ static struct ldap_config_table ldap_conf_table[] = {
     { "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_STR, FALSE, -1, &ldap_conf.base },
+    { "sudoers_base", CONF_LIST_STR, FALSE, -1, &ldap_conf.base },
 #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 },
@@ -969,6 +975,21 @@ sudo_ldap_read_config()
                    efree(*(char **)(cur->valp));
                    *(char **)(cur->valp) = estrdup(value);
                    break;
+               case CONF_LIST_STR:
+                   {
+                       struct ldap_config_list_str **p;
+                       size_t len = strlen(value);
+
+                       if (len > 0) {
+                           p = (struct ldap_config_list_str **)cur->valp;
+                           while (*p != NULL)
+                               p = &(*p)->next;
+                           *p = emalloc(sizeof(struct ldap_config_list_str) + len);
+                           memcpy((*p)->val, value, len + 1);
+                           (*p)->next = NULL;
+                       }
+                   }
+                   break;
                }
                break;
            }
@@ -993,9 +1014,16 @@ sudo_ldap_read_config()
            fprintf(stderr, "port             %d\n", ldap_conf.port);
        }
        fprintf(stderr, "ldap_version     %d\n", ldap_conf.version);
+       if (ldap_conf.base) {
+           struct ldap_config_list_str *base = ldap_conf.base;
 
-       fprintf(stderr, "sudoers_base     %s\n", ldap_conf.base ?
-           ldap_conf.base : "(NONE) <---Sudo will ignore ldap)");
+           do {
+               fprintf(stderr, "sudoers_base     %s\n", base->val);
+           } while ((base = base->next) != NULL);
+       } else {
+           fprintf(stderr, "sudoers_base     %s\n",
+               "(NONE) <---Sudo will ignore ldap)");
+       }
        fprintf(stderr, "binddn           %s\n", ldap_conf.binddn ?
            ldap_conf.binddn : "(anonymous)");
        fprintf(stderr, "bindpw           %s\n", ldap_conf.bindpw ?
@@ -1154,30 +1182,34 @@ sudo_ldap_display_defaults(nss, pw, lbuf)
     struct lbuf *lbuf;
 {
     struct berval **bv, **p;
+    struct ldap_config_list_str *base;
     LDAP *ld = (LDAP *) nss->handle;
-    LDAPMessage *entry = NULL, *result = NULL;
-    char *prefix = NULL;
+    LDAPMessage *entry, *result;
+    char *prefix;
     int rc, count = 0;
 
     if (ld == NULL)
        return(-1);
 
-    rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
-       "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
-    if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
-       bv = ldap_get_values_len(ld, entry, "sudoOption");
-       if (bv != NULL) {
-           prefix = "    ";
-           for (p = bv; *p != NULL; p++) {
-               lbuf_append(lbuf, prefix, (*p)->bv_val, NULL);
-               prefix = ", ";
-               count++;
+    for (base = ldap_conf.base; base != NULL; base = base->next) {
+       result = NULL;
+       rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE,
+           "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
+       if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
+           bv = ldap_get_values_len(ld, entry, "sudoOption");
+           if (bv != NULL) {
+               prefix = "    ";
+               for (p = bv; *p != NULL; p++) {
+                   lbuf_append(lbuf, prefix, (*p)->bv_val, NULL);
+                   prefix = ", ";
+                   count++;
+               }
+               ldap_value_free_len(bv);
            }
-           ldap_value_free_len(bv);
        }
+       if (result)
+           ldap_msgfree(result);
     }
-    if (result)
-       ldap_msgfree(result);
     return(count);
 }
 
@@ -1360,8 +1392,9 @@ sudo_ldap_display_privs(nss, pw, lbuf)
     struct passwd *pw;
     struct lbuf *lbuf;
 {
+    struct ldap_config_list_str *base;
     LDAP *ld = (LDAP *) nss->handle;
-    LDAPMessage *entry = NULL, *result = NULL;
+    LDAPMessage *entry, *result;
     char *filt;
     int rc, do_netgr, count = 0;
 
@@ -1385,26 +1418,28 @@ sudo_ldap_display_privs(nss, pw, lbuf)
     for (do_netgr = 0; do_netgr < 2; do_netgr++) {
        filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
        DPRINTF(("ldap search '%s'", filt), 1);
-       rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
-           NULL, 0, NULL, NULL, NULL, 0, &result);
-       efree(filt);
-       if (rc != LDAP_SUCCESS)
-           continue;   /* no entries for this pass */
-
-       /* print each matching entry */
-       LDAP_FOREACH(entry, ld, result) {
-           if ((!do_netgr ||
-               sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
-               sudo_ldap_check_host(ld, entry)) {
-
-               if (long_list)
-                   count += sudo_ldap_display_entry_long(ld, entry, lbuf);
-               else
-                   count += sudo_ldap_display_entry_short(ld, entry, lbuf);
+       for (base = ldap_conf.base; base != NULL; base = base->next) {
+           result = NULL;
+           rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
+               NULL, 0, NULL, NULL, NULL, 0, &result);
+           if (rc != LDAP_SUCCESS)
+               continue;       /* no entries for this pass */
+
+           /* print each matching entry */
+           LDAP_FOREACH(entry, ld, result) {
+               if ((!do_netgr ||
+                   sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
+                   sudo_ldap_check_host(ld, entry)) {
+
+                   if (long_list)
+                       count += sudo_ldap_display_entry_long(ld, entry, lbuf);
+                   else
+                       count += sudo_ldap_display_entry_short(ld, entry, lbuf);
+               }
            }
+           ldap_msgfree(result);
        }
-       ldap_msgfree(result);
-       result = NULL;
+       efree(filt);
     }
     return(count);
 }
@@ -1414,8 +1449,9 @@ sudo_ldap_display_cmnd(nss, pw)
     struct sudo_nss *nss;
     struct passwd *pw;
 {
+    struct ldap_config_list_str *base;
     LDAP *ld = (LDAP *) nss->handle;
-    LDAPMessage *entry = NULL, *result = NULL; /* used for searches */
+    LDAPMessage *entry, *result;               /* used for searches */
     char *filt;                                        /* used to parse attributes */
     int rc, found, do_netgr;                   /* temp/final return values */
 
@@ -1439,25 +1475,27 @@ sudo_ldap_display_cmnd(nss, pw)
     for (found = FALSE, do_netgr = 0; !found && do_netgr < 2; do_netgr++) {
        filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
        DPRINTF(("ldap search '%s'", filt), 1);
-       rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
-           NULL, 0, NULL, NULL, NULL, 0, &result);
-       efree(filt);
-       if (rc != LDAP_SUCCESS)
-           continue;   /* no entries for this pass */
+       for (base = ldap_conf.base; base != NULL; base = base->next) {
+           result = NULL;
+           rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
+               NULL, 0, NULL, NULL, NULL, 0, &result);
+           if (rc != LDAP_SUCCESS)
+               continue;       /* no entries for this pass */
 
-       LDAP_FOREACH(entry, ld, result) {
-           if ((!do_netgr ||
-               sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
-               sudo_ldap_check_host(ld, entry) &&
-               sudo_ldap_check_command(ld, entry, NULL) &&
-               sudo_ldap_check_runas(ld, entry)) {
+           LDAP_FOREACH(entry, ld, result) {
+               if ((!do_netgr ||
+                   sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) &&
+                   sudo_ldap_check_host(ld, entry) &&
+                   sudo_ldap_check_command(ld, entry, NULL) &&
+                   sudo_ldap_check_runas(ld, entry)) {
 
-               found = TRUE;
-               break;
+                   found = TRUE;
+                   break;
+               }
            }
+           ldap_msgfree(result);
        }
-       ldap_msgfree(result);
-       result = NULL;
+       efree(filt);
     }
 
     if (found)
@@ -1740,23 +1778,27 @@ static int
 sudo_ldap_setdefs(nss)
     struct sudo_nss *nss;
 {
+    struct ldap_config_list_str *base;
     LDAP *ld = (LDAP *) nss->handle;
-    LDAPMessage *entry = NULL, *result = NULL;  /* used for searches */
+    LDAPMessage *entry, *result;                /* used for searches */
     int rc;                                     /* temp return value */
 
     if (ld == NULL)
        return(-1);
 
-    rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE,
-       "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
-    if (rc == 0 && (entry = ldap_first_entry(ld, result))) {
-       DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
-       sudo_ldap_parse_options(ld, entry);
-    } else
-       DPRINTF(("no default options found!"), 1);
-
-    if (result)
-       ldap_msgfree(result);
+    for (base = ldap_conf.base; base != NULL; base = base->next) {
+       result = NULL;
+       rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE,
+           "cn=defaults", NULL, 0, NULL, NULL, NULL, 0, &result);
+       if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
+           DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
+           sudo_ldap_parse_options(ld, entry);
+       } else
+           DPRINTF(("no default options found in %s", base->val), 1);
+
+       if (result)
+           ldap_msgfree(result);
+    }
 
     return(0);
 }
@@ -1770,8 +1812,9 @@ sudo_ldap_lookup(nss, ret, pwflag)
     int ret;
     int pwflag;
 {
+    struct ldap_config_list_str *base;
     LDAP *ld = (LDAP *) nss->handle;
-    LDAPMessage *entry = NULL, *result = NULL;
+    LDAPMessage *entry, *result;
     char *filt;
     int do_netgr, rc, matched;
     int setenv_implied;
@@ -1788,34 +1831,36 @@ sudo_ldap_lookup(nss, ret, pwflag)
 
        for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) {
            filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
-           rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
-               NULL, 0, NULL, NULL, NULL, 0, &result);
-           efree(filt);
-           if (rc != LDAP_SUCCESS)
-               continue;
-
-           LDAP_FOREACH(entry, ld, result) {
-               /* only verify netgroup matches in pass 2 */
-               if (do_netgr && !sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name))
+           for (base = ldap_conf.base; base != NULL; base = base->next) {
+               result = NULL;
+               rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
+                   NULL, 0, NULL, NULL, NULL, 0, &result);
+               if (rc != LDAP_SUCCESS)
                    continue;
 
-               ldap_user_matches = TRUE;
-               if (sudo_ldap_check_host(ld, entry)) {
-                   ldap_host_matches = TRUE;
-                   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 = 1;
-                       break;  /* end foreach */
+               LDAP_FOREACH(entry, ld, result) {
+                   /* only verify netgroup matches in pass 2 */
+                   if (do_netgr && !sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name))
+                       continue;
+
+                   ldap_user_matches = TRUE;
+                   if (sudo_ldap_check_host(ld, entry)) {
+                       ldap_host_matches = TRUE;
+                       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 = 1;
+                           break;      /* end foreach */
+                       }
                    }
                }
+               ldap_msgfree(result);
            }
-           ldap_msgfree(result);
-           result = NULL;
+           efree(filt);
        }
        if (matched || user_uid == 0) {
            SET(ret, VALIDATE_OK);
@@ -1859,14 +1904,16 @@ sudo_ldap_lookup(nss, ret, pwflag)
     for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) {
        filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw);
        DPRINTF(("ldap search '%s'", filt), 1);
-       rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt,
-           NULL, 0, NULL, NULL, NULL, 0, &result);
-       if (rc != LDAP_SUCCESS)
-           DPRINTF(("nothing found for '%s'", filt), 1);
-       efree(filt);
+       for (base = ldap_conf.base; base != NULL; base = base->next) {
+           result = NULL;
+           rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
+               NULL, 0, NULL, NULL, NULL, 0, &result);
+           if (rc != LDAP_SUCCESS) {
+               DPRINTF(("nothing found for '%s'", filt), 1);
+               continue;
+           }
 
-       /* parse each entry returned from this most recent search */
-       if (rc == LDAP_SUCCESS) {
+           /* parse each entry returned from this most recent search */
            LDAP_FOREACH(entry, ld, result) {
                DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1);
                if (
@@ -1910,8 +1957,8 @@ sudo_ldap_lookup(nss, ret, pwflag)
                }
            }
            ldap_msgfree(result);
-           result = NULL;
        }
+       efree(filt);
     }
 
 done:
index 45f7ceb88a64c28b4f9c5d04ff817d5a0b4d38b7..25281eec95ebf9a5cbf62a8bb12ff1f4963f6d1d 100644 (file)
@@ -61,7 +61,7 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
 
 
 
-1.7.3b3                   June 14, 2010                         1
+1.7.3b3                   June 15, 2010                         1
 
 
 
@@ -127,7 +127,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-1.7.3b3                   June 14, 2010                         2
+1.7.3b3                   June 15, 2010                         2
 
 
 
@@ -193,7 +193,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-1.7.3b3                   June 14, 2010                         3
+1.7.3b3                   June 15, 2010                         3
 
 
 
@@ -259,7 +259,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-1.7.3b3                   June 14, 2010                         4
+1.7.3b3                   June 15, 2010                         4
 
 
 
@@ -301,7 +301,8 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
        S\bSU\bUD\bDO\bOE\bER\bRS\bS_\b_B\bBA\bAS\bSE\bE base
            The base DN to use when performing s\bsu\bud\bdo\bo LDAP queries.  Typically
            this is of the form ou=SUDOers,dc=example,dc=com for the domain
-           example.com.
+           example.com.  Multiple S\bSU\bUD\bDO\bOE\bER\bRS\bS_\b_B\bBA\bAS\bSE\bE lines may be specified, in
+           which case they are queried in the order specified.
 
        S\bSU\bUD\bDO\bOE\bER\bRS\bS_\b_D\bDE\bEB\bBU\bUG\bG debug_level
            This sets the debug level for s\bsu\bud\bdo\bo LDAP queries.  Debugging
@@ -321,11 +322,10 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
        B\bBI\bIN\bND\bDP\bPW\bW secret
            The B\bBI\bIN\bND\bDP\bPW\bW parameter specifies the password to use when performing
            LDAP operations.  This is typically used in conjunction with the
-           B\bBI\bIN\bND\bDD\bDN\bN parameter.
 
 
 
-1.7.3b3                   June 14, 2010                         5
+1.7.3b3                   June 15, 2010                         5
 
 
 
@@ -334,6 +334,8 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
+           B\bBI\bIN\bND\bDD\bDN\bN parameter.
+
        R\bRO\bOO\bOT\bTB\bBI\bIN\bND\bDD\bDN\bN DN
            The R\bRO\bOO\bOT\bTB\bBI\bIN\bND\bDD\bDN\bN parameter specifies the identity, in the form of a
            Distinguished Name (DN), to use when performing privileged LDAP
@@ -387,11 +389,9 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
            OpenLDAP:
                tls_cert /etc/ssl/client_cert.pem
 
-           Netscape-derived:
 
 
-
-1.7.3b3                   June 14, 2010                         6
+1.7.3b3                   June 15, 2010                         6
 
 
 
@@ -400,6 +400,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
+           Netscape-derived:
                tls_cert /var/ldap/cert7.db
 
            When using Netscape-derived libraries, this file may also contain
@@ -456,8 +457,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-
-1.7.3b3                   June 14, 2010                         7
+1.7.3b3                   June 15, 2010                         7
 
 
 
@@ -523,7 +523,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-1.7.3b3                   June 14, 2010                         8
+1.7.3b3                   June 15, 2010                         8
 
 
 
@@ -569,7 +569,7 @@ E\bEX\bXA\bAM\bMP\bPL\bLE\bES\bS
          # The amount of time, in seconds, to wait while performing an LDAP query.
          timelimit 30
          #
-         # must be set or sudo will ignore LDAP
+         # Must be set or sudo will ignore LDAP; may be specified multiple times.
          sudoers_base   ou=SUDOers,dc=example,dc=com
          #
          # verbose sudoers matching from ldap
@@ -589,7 +589,7 @@ E\bEX\bXA\bAM\bMP\bPL\bLE\bES\bS
 
 
 
-1.7.3b3                   June 14, 2010                         9
+1.7.3b3                   June 15, 2010                         9
 
 
 
@@ -655,7 +655,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-1.7.3b3                   June 14, 2010                        10
+1.7.3b3                   June 15, 2010                        10
 
 
 
@@ -721,7 +721,7 @@ SUDOERS.LDAP(4)        MAINTENANCE COMMANDS       SUDOERS.LDAP(4)
 
 
 
-1.7.3b3                   June 14, 2010                        11
+1.7.3b3                   June 15, 2010                        11
 
 
 
@@ -787,6 +787,6 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
 
 
 
-1.7.3b3                   June 14, 2010                        12
+1.7.3b3                   June 15, 2010                        12
 
 
index 3c7eb9a8578139323141d87acc33b62edb7d9c9e..0013b7f34ffe95a0ae620f4e7f3333cdfa68f0dd 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "SUDOERS.LDAP @mansectform@"
-.TH SUDOERS.LDAP @mansectform@ "June 14, 2010" "1.7.3b3" "MAINTENANCE COMMANDS"
+.TH SUDOERS.LDAP @mansectform@ "June 15, 2010" "1.7.3b3" "MAINTENANCE COMMANDS"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -401,7 +401,8 @@ to wait for a response to an \s-1LDAP\s0 query.
 .IX Item "SUDOERS_BASE base"
 The base \s-1DN\s0 to use when performing \fBsudo\fR \s-1LDAP\s0 queries.  Typically
 this is of the form \f(CW\*(C`ou=SUDOers,dc=example,dc=com\*(C'\fR for the domain
-\&\f(CW\*(C`example.com\*(C'\fR.
+\&\f(CW\*(C`example.com\*(C'\fR.  Multiple \fB\s-1SUDOERS_BASE\s0\fR lines may be specified,
+in which case they are queried in the order specified.
 .IP "\fB\s-1SUDOERS_DEBUG\s0\fR debug_level" 4
 .IX Item "SUDOERS_DEBUG debug_level"
 This sets the debug level for \fBsudo\fR \s-1LDAP\s0 queries.  Debugging
@@ -647,7 +648,7 @@ determines sudoers source order on \s-1AIX\s0
 \&  # The amount of time, in seconds, to wait while performing an LDAP query.
 \&  timelimit 30
 \&  #
-\&  # must be set or sudo will ignore LDAP
+\&  # Must be set or sudo will ignore LDAP; may be specified multiple times.
 \&  sudoers_base   ou=SUDOers,dc=example,dc=com
 \&  #
 \&  # verbose sudoers matching from ldap
index 4b4533106498466b31f49972091647e6384aaaa8..7dabfaa906d599e0e5c9f80c025b9e945c394ea8 100644 (file)
@@ -301,7 +301,8 @@ to wait for a response to an LDAP query.
 
 The base DN to use when performing B<sudo> LDAP queries.  Typically
 this is of the form C<ou=SUDOers,dc=example,dc=com> for the domain
-C<example.com>.
+C<example.com>.  Multiple B<SUDOERS_BASE> lines may be specified,
+in which case they are queried in the order specified.
 
 =item B<SUDOERS_DEBUG> debug_level
 
@@ -559,7 +560,7 @@ determines sudoers source order on AIX
   # The amount of time, in seconds, to wait while performing an LDAP query.
   timelimit 30
   #
-  # must be set or sudo will ignore LDAP
+  # Must be set or sudo will ignore LDAP; may be specified multiple times.
   sudoers_base   ou=SUDOers,dc=example,dc=com
   #
   # verbose sudoers matching from ldap