Hi, Ian, list,

Currently, the Linux automounter requires the specification of the
search base as a part of the map name.  Thus, entries like the
following are not uncommon:

/home ldap:foo.example.com:nisMapName=auto.mnt,dc=example,dc=com

when what is really desirable is the following:

/home ldap:auto.mnt

The patch below allows for this more desirable syntax.  Comments, as
always, are welcome.

-Jeff

diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 51edd6f..6c77b27 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -135,6 +135,95 @@ static LDAP *do_connect(struct lookup_co
        return ldap;
 }
 
+/*
+ *  Returns 1 on success, 0 on failure.
+ */
+int autofs_get_basedn_schema(LDAP *ldap, struct lookup_context *ctxt,
+                            const char *mapname, struct autofs_schema *schema)
+{
+       int l, rv;
+       char *query, *basedn;
+       char *attrs[] = { LDAP_NO_ATTRS, NULL };
+       LDAPMessage *result, *e;
+       const char *class = schema->map_object_class,
+                  *key = schema->map_name_attr;
+
+       /* Build a query string. */
+       l = strlen("(&(objectclass=)(=))") + strlen(class) + strlen(key) +
+               strlen(mapname) + 1;
+       query = alloca(l);
+       if (query == NULL) {
+               crit(MODPREFIX "malloc: %m");
+               return 0;
+       }
+
+       memset(query, '\0', l);
+       if (sprintf(query, "(&(objectclass=%s)(%s=%s))",
+                   class, key, mapname) >= l) {
+               debug(MODPREFIX "error forming query string");
+               return 0;
+       }
+       query[l - 1] = '\0';
+
+       /* Look around. */
+       debug(MODPREFIX "searching for \"%s\"", query);
+
+       rv = ldap_search_s(ldap, NULL, LDAP_SCOPE_SUBTREE,
+                          query, attrs, 0, &result);
+       if ((rv != LDAP_SUCCESS) || !result) {
+               crit(MODPREFIX "query failed for %s", query);
+               return 0;
+       }
+       e = ldap_first_entry(ldap, result);
+       if (!e) {
+               debug(MODPREFIX "query succeeded, no matches for %s", query);
+               ldap_msgfree(result);
+               return 0;
+       }
+
+       basedn = ldap_get_dn(ldap, result);
+       ldap_msgfree(result);
+       if (!basedn)
+               return 0;
+
+       ctxt->base = strdup(basedn);
+       ldap_memfree(basedn);
+       if (!ctxt->base)
+               return 0;
+
+       debug("got base dn of %s\n", ctxt->base);
+       return 1;
+}
+
+int autofs_get_basedn(struct lookup_context *ctxt, const char *mapname)
+{
+       LDAP *ldap;
+       int i, ret;
+
+       ldap = do_connect(ctxt, NULL);
+       if (!ldap) {
+               error("Unable to bind to the ldap server!\n");
+               return -1;
+       }
+
+       if (ctxt->schema)
+               ret = autofs_get_basedn_schema(ldap, ctxt, mapname,
+                                              ctxt->schema);
+       else {
+               for (i = 0; i < NR_SCHEMAS; i++) {
+                       ret = autofs_get_basedn_schema(ldap, ctxt, mapname,
+                                                      &supported_schemas[i]);
+                       if (ret == 1) {
+                               set_schema(ctxt, &supported_schemas[i]);
+                               break;
+                       }
+               }
+       }
+
+       ldap_unbind(ldap);
+       return ret;
+}
+
 struct lookup_context *context_init(const char *mapname)
 {
        struct lookup_context *ctxt = NULL;
@@ -189,10 +278,26 @@ struct lookup_context *context_init(cons
        }
 
        /* Isolate the base DN. */
-       l = strlen(ptr);
-       ctxt->base = malloc(l + 1);
-       memset(ctxt->base, 0, l + 1);
-       memcpy(ctxt->base, ptr, l);
+       if (strchr(ptr, '=') == NULL) {
+               if (!autofs_get_basedn(ctxt, mapname)) {
+                       warn(MODPREFIX "Unable to determine base dn\n");
+                       ctxt->base = NULL;
+               }
+       }
+
+       if (!ctxt->base) {
+               /*
+                *  Previous versions of autofs would simply use
+                *  whatever value was left in 'ptr' as the base dn.  So,
+                *  in order to hopefully not cause regressions, that
+                *  behaviour was preserved in the case where nothing
+                *  more clever could be done.
+                */
+               l = strlen(ptr);
+               ctxt->base = malloc(l + 1);
+               memset(ctxt->base, 0, l + 1);
+               memcpy(ctxt->base, ptr, l);
+       }
 
        debug(MODPREFIX "server = \"%s\", port = %d, base dn = \"%s\"",
              ctxt->server ? ctxt->server : "(default)",

_______________________________________________
autofs mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/autofs

Reply via email to