aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2000-06-19 23:55:57 +0000
committerH. Peter Anvin <hpa@zytor.com>2000-06-19 23:55:57 +0000
commit067afb5bb1e831b96c2cab24ef4fd1811ba6b456 (patch)
tree527aff4c1318ba2a7603b377054b442d7a3a2bc5
parentfc906a8dd1b83939cdd0b6b182b4ad01e170e76a (diff)
downloadautofs3-067afb5bb1e831b96c2cab24ef4fd1811ba6b456.tar.gz
autofs3-067afb5bb1e831b96c2cab24ef4fd1811ba6b456.tar.xz
autofs3-067afb5bb1e831b96c2cab24ef4fd1811ba6b456.zip
Add LDAP support; update TODO list.
-rw-r--r--Makefile.conf.in5
-rw-r--r--NEWS4
-rw-r--r--README.options15
-rw-r--r--TODO19
-rw-r--r--configure.in55
-rw-r--r--man/auto.master.52
-rw-r--r--man/automount.812
-rw-r--r--modules/Makefile10
-rw-r--r--modules/lookup_ldap.c238
9 files changed, 345 insertions, 15 deletions
diff --git a/Makefile.conf.in b/Makefile.conf.in
index 74a5a3a..e465b1c 100644
--- a/Makefile.conf.in
+++ b/Makefile.conf.in
@@ -15,6 +15,11 @@ HESIOD = @HAVE_HESIOD@
LIBHESIOD = @LIBHESIOD@
HESIOD_FLAGS = @HESIOD_FLAGS@
+# LDAP support: yes (1) no (0)
+LDAP = @HAVE_LDAP@
+LIBLDAP= @LIBLDAP@
+LDAP_FLAGS = @LDAP_FLAGS@
+
# NIS+ support: yes (1) no (0)
NISPLUS = @HAVE_NISPLUS@
diff --git a/NEWS b/NEWS
index 54a4e82..227d1b5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Since autofs-3.1.5:
+-------------------
+* Add a lookup method for LDAP (from Nalin Dahyabhai).
+
Since autofs-3.1.4:
-------------------
* Support "bind" mounts introduced in linux-2.3.99-pre7.7 instead of
diff --git a/README.options b/README.options
index 189c18b..94f1c7b 100644
--- a/README.options
+++ b/README.options
@@ -64,3 +64,18 @@ include files in /usr/athena/include, please specify:
./configure --with-hesiod=/usr/athena
+OpenLDAP support
+----------------
+
+To enable support, if your OpenLDAP library isn't installed in
+/usr/lib with the include files in /usr/include, please specify the
+option:
+
+ --with-openldap=<openldap_root>
+
+For example, if your OpenLDAP library lives in /opt/openldap/lib and the
+include files in /opt/openldap/include, please specify:
+
+ ./configure --with-openldap=/opt/openldap
+
+
diff --git a/TODO b/TODO
index 1aab490..652d2cb 100644
--- a/TODO
+++ b/TODO
@@ -2,17 +2,26 @@ $Id$
autofs v3 TODO list
-------------------
-* The autofs v3 project is closed, except for bugfixes. I may or may
- not choose to accept feature enhancements written by other people;
- please contact me directly.
+* I am accepting minor changes to autofs v3 such as additional
+ modules. No major changes.
autofs v4 TODO list
-------------------
-* Completely rewritten kernel protocol, use multithreading rather than
- processes in the daemon.
+* autofs 4 is developed by Jeremy Fitzhardinge. It supports
+ multimounts without being quite as radical a departure
+ architecturally.
+
+autofs v5 TODO list
+-------------------
+* Completely rewritten kernel protocol, using the new VFS features
+ introduced by Alexander Viro for the 2.4 kernel series.
+* Use multithreading rather than processes in the daemon.
* Support multimount entries. (Quite messy: can't unmount the
tree as a unit, probably needs locking while constructing the tree,
and needs scaffolding if no entry for /. Appears *very* difficult
to do without threading!)
* /net support: need hostname resolver module (easy) as well as mountd
query (easy) plus all the multimount entry stuff...
+* Direct mount support.
+* (Hopefully) some kind of inode spoofing to support browsable
+ directories.
diff --git a/configure.in b/configure.in
index 1d4688e..531d0d0 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@
#
define([AC_CACHE_LOAD], )dnl
define([AC_CACHE_SAVE], )dnl
-AC_INIT(.autofs-3.1.4)
+AC_INIT(.autofs-3.1.6)
#
# autofs installs by default in /usr
@@ -54,25 +54,33 @@ AC_CHECK_LIB(resolv, res_query, LIBRESOLV="-lresolv")
AC_SUBST(LIBRESOLV)
#
-# Hesiod support? Hesiod is tricky, because it may live in /usr/athena
-# or some equally weird place; if so, have the user specify
-# --with-hesiod=/usr/athena
+# Hesiod support? Expect that this may have a special directory...
#
AF_tmp_ldflags="$LDFLAGS"
+LIBHESIOD=''
+HAVE_HESIOD=''
AC_ARG_WITH(hesiod,
--with-hesiod=DIR enable Hesiod support (libs and includes in DIR),
- if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no"
+ if test "$withval" = no
+ then
+ HAVE_HESIOD=0 # Disable
+ elif -o "$withval" = yes -o -z "$withval"
then
- LIBHESIOD=""
+ : Search for Hesiod in normal directory path
else
+ : Search for Hesiod in specific directory
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBHESIOD="-L${withval}/lib"
HESIOD_FLAGS="-I${withval}/include"
fi
)
-HAVE_HESIOD=0
-AC_CHECK_LIB(hesiod, hes_resolve, HAVE_HESIOD=1 LIBHESIOD="$LIBHESIOD -lhesiod", , $LIBRESOLV)
+if test -z "$HAVE_HESIOD"
+then
+ HAVE_HESIOD=0
+ AC_CHECK_LIB(hesiod, hes_resolve, HAVE_HESIOD=1 LIBHESIOD="$LIBHESIOD -lhesiod", ,
+ $LIBRESOLV)
+fi
AC_SUBST(HAVE_HESIOD)
AC_SUBST(LIBHESIOD)
AC_SUBST(HESIOD_FLAGS)
@@ -84,6 +92,37 @@ AC_CHECK_HEADER(rpcsvc/nis.h, HAVE_NISPLUS=1)
AC_SUBST(HAVE_NISPLUS)
#
+# OpenLDAP support? Expect that this may have a special directory...
+#
+AF_tmp_ldflags="$LDFLAGS"
+LIBLDAP=''
+HAVE_LDAP=''
+AC_ARG_WITH(openldap,
+--with-openldap=DIR enable OpenLDAP map support (libs and includes in DIR),
+ if test "$withval" = 'no'; then
+ HAVE_LDAP=0 # Disable
+ elif test -z "$withval" -o "$withval" = 'yes'
+ then
+ : Search for LDAP in normal directory path
+ else
+ : Search for LDAP in specific directory
+ LDFLAGS="$LDFLAGS -L${withval}/lib"
+ LIBLDAP="-L${withval}/lib"
+ LDAP_FLAGS="-I${withval}/include"
+ fi
+)
+if test -z "$HAVE_LDAP"; then
+ HAVE_LDAP=0
+ AC_CHECK_LIB(ldap, ldap_init, HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap -llber", ,
+ -llber)
+fi
+
+AC_SUBST(LDAP_FLAGS)
+AC_SUBST(HAVE_LDAP)
+AC_SUBST(LIBLDAP)
+LDFLAGS="${AF_tmp_ldflags}"
+
+#
# Location of init.d directory?
#
AF_INIT_D()
diff --git a/man/auto.master.5 b/man/auto.master.5
index 7e95f75..880c4a8 100644
--- a/man/auto.master.5
+++ b/man/auto.master.5
@@ -1,6 +1,6 @@
.\" t
.\" $Id$
-.TH AUTO.MASTER 5 "9 Sep 1997"
+.TH AUTO.MASTER 5 "19 Jun 2000"
.SH NAME
/etc/auto.master \- Master Map for automounter
.SH "DESCRIPTION"
diff --git a/man/automount.8 b/man/automount.8
index d7f9045..c36e9ac 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -8,7 +8,7 @@
.\"
.\" $Id$
.\"
-.TH AUTOMOUNT 8 "17 Sep 1997"
+.TH AUTOMOUNT 8 "19 Jun 2000"
.SH NAME
automount \- configure mount points for autofs
.SH SYNOPSIS
@@ -63,6 +63,16 @@ The map is a NIS+ database.
The map is a hesiod database whose
.B filsys
entries are used for maps.
+.TP
+.B ldap
+map names are of the form \fB[servername:]basedn\fP, where the optional
+\fBservername\fP is the name of the LDAP server to query, and \fBbasedn\fP is
+the DN to do a subtree search under. Entries are \fBautomount\fP objects in
+the specified subtree, where the \fBcn\fP attribute is the key (the wildcard
+key is "/"), and the \fBautomounterInformation\fP attribute contains the
+information used by the automounter. Documentation on the schema
+used by this module is available online at
+\fIhttp://docs.iplanet.com/docs/manuals/directory/411ext/nis/mapping.htm\fP.
.RE
.TP
\fBformat\fP Format of the map data; currently the only formats
diff --git a/modules/Makefile b/modules/Makefile
index 5d398a1..b5a7f6b 100644
--- a/modules/Makefile
+++ b/modules/Makefile
@@ -33,6 +33,11 @@ ifeq ($(NISPLUS), 1)
MODS += lookup_nisplus.so
endif
+ifeq ($(LDAP), 1)
+ SRCS += lookup_ldap.c
+ MODS += lookup_ldap.so
+endif
+
CFLAGS += -I../include -fpic -DAUTOFS_LIB_DIR=\"$(autofslibdir)\" -DPATH_AUTOMOUNT=\"$(sbindir)/automount\"
all: $(MODS)
@@ -62,3 +67,8 @@ lookup_hesiod.so: lookup_hesiod.c
$(CC) $(SOLDFLAGS) $(CFLAGS) $(HESIOD_FLAGS) -o lookup_hesiod.so \
lookup_hesiod.c $(LIBHESIOD) $(LIBRESOLV)
$(STRIP) lookup_hesiod.so
+
+lookup_ldap.so: lookup_ldap.c
+ $(CC) $(SOLDFLAGS) $(CFLAGS) $(LDAP_FLAGS) -o lookup_ldap.so \
+ lookup_ldap.c $(LIBLDAP)
+ $(STRIP) lookup_ldap.so
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
new file mode 100644
index 0000000..ab068a9
--- /dev/null
+++ b/modules/lookup_ldap.c
@@ -0,0 +1,238 @@
+/*
+ * lookup_ldap.c
+ *
+ * Module for Linux automountd to access automount maps in LDAP directories.
+ *
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <lber.h>
+#include <ldap.h>
+
+#define MODULE_LOOKUP
+#include "automount.h"
+
+#define MAPFMT_DEFAULT "sun"
+
+#define MODPREFIX "lookup(ldap): "
+
+#define OBJECTCLASS "automount"
+#define ATTRIBUTE "automountInformation"
+#define WILDCARD "/"
+
+struct lookup_context {
+ char *server, *base;
+ struct parse_mod *parser;
+};
+
+int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */
+
+/*
+ * This initializes a context (persistent non-global data) for queries to
+ * this module. Return zero if we succeed.
+ */
+int lookup_init(const char *mapfmt, int argc, const char * const *argv,
+ void **context)
+{
+ struct lookup_context *ctxt = NULL;
+ int rv, l;
+ LDAP *ldap;
+
+ /* If we can't build a context, bail. */
+ ctxt = (struct lookup_context*) malloc(sizeof(struct lookup_context));
+ *context = ctxt;
+ if( ctxt == NULL ) {
+ syslog(LOG_INFO, MODPREFIX "malloc: %m");
+ return 1;
+ }
+ memset(ctxt, 0, sizeof(struct lookup_context));
+
+ /* If a map type isn't explicitly given, parse it like sun entries. */
+ if( mapfmt == NULL ) {
+ mapfmt = MAPFMT_DEFAULT;
+ }
+
+ /* Now we sanity-check by binding to the server temporarily. We have to be
+ * a little strange in here, because we want to provide for use of the
+ * "default" server, which is set in an ldap.conf file somewhere. */
+ if(strchr(argv[0], ':') != NULL) {
+ l = strchr(argv[0], ':') - argv[0];
+ /* Isolate the server's name. */
+ ctxt->server = malloc(l + 1);
+ memset(ctxt->server, 0, l + 1);
+ memcpy(ctxt->server, argv[0], l);
+ /* Isolate the base DN. */
+ ctxt->base = malloc(strlen(argv[0]) - l);
+ memset(ctxt->base, 0, strlen(argv[0]) - l);
+ memcpy(ctxt->base, argv[0] + l + 1, strlen(argv[0]) - l - 1);
+ } else {
+ /* Use the default server; isolate the base DN's name. */
+ l = strlen(argv[0]);
+ ctxt->server = NULL;
+ ctxt->base = malloc(l + 1);
+ memset(ctxt->base, 0, l + 1);
+ memcpy(ctxt->base, argv[0], l);
+ }
+
+ syslog(LOG_DEBUG, MODPREFIX "server = \"%s\", base dn = \"%s\"",
+ ctxt->server ? ctxt->server : "(default)", ctxt->base);
+
+ /* Initialize the LDAP context. */
+ if( ( ldap = ldap_init(ctxt->server, LDAP_PORT)) == NULL ) {
+ syslog(LOG_CRIT, MODPREFIX "couldn't initialize LDAP");
+ return 1;
+ }
+
+ /* Connect to the server as an anonymous user. */
+ rv = ldap_simple_bind_s(ldap, ctxt->base, NULL);
+ if( rv != LDAP_SUCCESS ) {
+ syslog(LOG_CRIT, MODPREFIX "couldn't connect to %s", ctxt->server);
+ return 1;
+ }
+
+ /* Okay, we're done here. */
+ ldap_unbind(ldap);
+
+ /* Open the parser, if we can. */
+ return !(ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1));
+}
+
+/* Lookup by key and pass a filesystem to a parser. */
+int lookup_mount(const char *root, const char *name, int name_len, void *context)
+{
+ struct lookup_context *ctxt = (struct lookup_context *) context;
+ int rv, i, l;
+ char *query;
+ LDAPMessage *result, *e;
+ char **values;
+ char *attrs[] = {ATTRIBUTE, NULL};
+ LDAP *ldap;
+
+ chdir("/"); /* If this is not here the filesystem stays
+ busy, for some reason... */
+
+ if( ctxt == NULL ) {
+ syslog(LOG_CRIT, MODPREFIX "context was NULL");
+ return 0;
+ }
+
+ /* Build a query string. */
+ l = name_len + strlen("(&(objectclass=" OBJECTCLASS ")(cn=))") + 2;
+
+ query = malloc(l);
+ if( query == NULL ) {
+ syslog(LOG_INFO, MODPREFIX "malloc: %m");
+ return 0;
+ }
+
+ memset(query, '\0', l);
+ if( sprintf(query, "(&(objectclass=" OBJECTCLASS ")(cn=%s))", name) >= l ) {
+ syslog(LOG_DEBUG, MODPREFIX "error forming query string");
+ }
+ query[l - 1] = '\0';
+
+ /* Initialize the LDAP context. */
+ if( (ldap = ldap_init(ctxt->server, LDAP_PORT) ) == NULL ) {
+ syslog(LOG_CRIT, MODPREFIX "couldn't initialize LDAP connection"
+ " to %s", ctxt->server ? ctxt->server : "default server");
+ free(query);
+ return 1;
+ }
+
+ /* Connect to the server as an anonymous user. */
+ rv = ldap_simple_bind_s(ldap, ctxt->base, NULL);
+ if ( rv != LDAP_SUCCESS ) {
+ syslog(LOG_CRIT, MODPREFIX "couldn't bind to %s",
+ ctxt->server ? ctxt->server : "default server");
+ free(query);
+ return 1;
+ }
+
+ /* Look around. */
+ syslog(LOG_DEBUG, MODPREFIX "searching for \"%s\"", query);
+ rv = ldap_search_s(ldap, ctxt->base, LDAP_SCOPE_SUBTREE,
+ query, attrs, 0, &result);
+
+ if( ( rv != LDAP_SUCCESS) || ( result == NULL ) ) {
+ syslog(LOG_INFO, MODPREFIX "query failed for %s", query);
+ free(query);
+ return 1;
+ }
+
+ e = ldap_first_entry(ldap, result);
+
+ /* If we got no answers, try it with "/" instead, which makes a better
+ * wildcard thatn "*" for LDAP, and also happens to be illegal for actual
+ * directory names. */
+ if( e == NULL ) {
+ syslog(LOG_DEBUG, MODPREFIX "no entry for \"%s\" found, trying cn=\"/\"",
+ name);
+
+ sprintf(query, "(&(objectclass=" OBJECTCLASS ")(cn=" WILDCARD "))");
+
+ syslog(LOG_DEBUG, MODPREFIX "searching for \"%s\"", query);
+ rv = ldap_search_s(ldap, ctxt->base, LDAP_SCOPE_SUBTREE,
+ query, attrs, 0, &result);
+ if( ( rv != LDAP_SUCCESS) || ( result == NULL ) ) {
+ syslog(LOG_INFO, MODPREFIX "query failed for %s", query);
+ free(query);
+ return 1;
+ }
+
+ syslog(LOG_DEBUG, MODPREFIX "getting first entry for cn=\"/\"");
+
+ e = ldap_first_entry(ldap, result);
+ }
+
+ if( e == NULL ) {
+ syslog(LOG_INFO, MODPREFIX "got answer, but no first entry for %s", query);
+ free(query);
+ return 1;
+ } else {
+ syslog(LOG_DEBUG, MODPREFIX "examining first entry");
+ }
+
+ values = ldap_get_values(ldap, e, ATTRIBUTE);
+ if( values == NULL ) {
+ syslog(LOG_INFO, MODPREFIX "no " ATTRIBUTE " defined for %s", query);
+ free(query);
+ return 1;
+ }
+
+ /* Try each of the answers in sucession. */
+ rv = 1;
+ for( i = 0 ; ( values[i] != NULL ) && ( rv != 0 ) ; i++ ) {
+ rv = ctxt->parser->parse_mount(root, name, name_len, values[0],
+ ctxt->parser->context);
+ }
+
+ /* Clean up. */
+ ldap_value_free(values);
+ ldap_msgfree(result);
+ ldap_unbind(ldap);
+ free(query);
+
+ return rv;
+}
+
+/*
+ * This destroys a context for queries to this module. It releases the parser
+ * structure (unloading the module) and frees the memory used by the context.
+ */
+int lookup_done(void *context)
+{
+ struct lookup_context *ctxt = (struct lookup_context *) context;
+ int rv = close_parse(ctxt->parser);
+ free(ctxt->server);
+ free(ctxt->base);
+ free(ctxt);
+ return rv;
+}