]>
Commit | Line | Data |
---|---|---|
be85a188 | 1 | diff -uNr autofs-3.1.4/Makefile.conf.in autofs-3.1.4-ldap/Makefile.conf.in |
2 | --- autofs-3.1.4/Makefile.conf.in Tue Apr 11 14:18:08 2000 | |
3 | +++ autofs-3.1.4-ldap/Makefile.conf.in Tue Apr 11 14:17:49 2000 | |
4 | @@ -16,6 +16,11 @@ | |
5 | LIBHESIOD = @LIBHESIOD@ | |
6 | HESIOD_FLAGS = @HESIOD_FLAGS@ | |
7 | ||
8 | +# LDAP support: yes (1) no (0) | |
9 | +LDAP = @HAVE_LDAP@ | |
10 | +LDAP_FLAGS = @LDAP_FLAGS@ | |
11 | +LDAP_LIBS= @LDAP_LIBS@ | |
12 | + | |
13 | # NIS+ support: yes (1) no (0) | |
14 | NISPLUS = @HAVE_NISPLUS@ | |
15 | ||
16 | diff -uNr autofs-3.1.4/configure.in autofs-3.1.4-ldap/configure.in | |
17 | --- autofs-3.1.4/configure.in Tue Apr 11 14:18:08 2000 | |
18 | +++ autofs-3.1.4-ldap/configure.in Tue Apr 11 14:17:49 2000 | |
19 | @@ -85,6 +85,20 @@ | |
20 | AC_CHECK_HEADER(rpcsvc/nis.h, HAVE_NISPLUS=1) | |
21 | AC_SUBST(HAVE_NISPLUS) | |
22 | ||
23 | +AC_ARG_WITH(openldap, | |
24 | +--with-openldap=DIR enable LDAP map support (OpenLDAP libs and includes in DIR), | |
25 | + CFLAGS="$CFLAGS -I$withval/include" | |
26 | + CPPLAGS="$CPPFLAGS -I$withval/include" | |
27 | + AC_CHECK_HEADER(ldap.h) | |
28 | + AC_CHECK_LIB(ldap, ldap_init, | |
29 | + HAVE_LDAP=1 | |
30 | + LDAP_LIBS="-L$withval/lib -lldap -llber",, | |
31 | + -L$withval/lib -llber) | |
32 | +) | |
33 | +AC_SUBST(LDAP_FLAGS) | |
34 | +AC_SUBST(HAVE_LDAP) | |
35 | +AC_SUBST(LDAP_LIBS) | |
36 | + | |
37 | # | |
38 | # Location of init.d directory? | |
39 | # | |
40 | diff -uNr autofs-3.1.4/man/auto.master.5 autofs-3.1.4-ldap/man/auto.master.5 | |
41 | --- autofs-3.1.4/man/auto.master.5 Tue Apr 11 14:18:08 2000 | |
42 | +++ autofs-3.1.4-ldap/man/auto.master.5 Tue Apr 11 14:21:11 2000 | |
43 | @@ -1,6 +1,6 @@ | |
44 | .\" t | |
45 | .\" $Id$ | |
46 | -.TH AUTO.MASTER 5 "9 Sep 1997" | |
47 | +.TH AUTO.MASTER 5 "11 Apr 2000" | |
48 | .SH NAME | |
49 | /etc/auto.master \- Master Map for automounter | |
50 | .SH "DESCRIPTION" | |
51 | @@ -50,14 +50,16 @@ | |
52 | /home /etc/auto.home | |
53 | /misc /etc/auto.misc | |
54 | /mnt yp:mnt.map | |
55 | +/auto ldap:ldapserver:ou=automount,ou=services,dc=example,dc=com | |
56 | .fi | |
57 | .RE | |
58 | .sp | |
59 | -This will generate three mountpoints | |
60 | +This will generate four mountpoints | |
61 | .IR /home , | |
62 | .IR /misc , | |
63 | +.IR /mnt , | |
64 | and | |
65 | -.IR /mnt . | |
66 | +.IR /auto . | |
67 | All accesses to | |
68 | .I /home | |
69 | will lead to the consultation of the map in | |
70 | @@ -66,10 +68,14 @@ | |
71 | .I /misc | |
72 | will consult the map in | |
73 | .IR /etc/auto.misc , | |
74 | -and all accesses to | |
75 | +all accesses to | |
76 | .I /mnt | |
77 | will consult the NIS map | |
78 | -.IR mnt.map . | |
79 | +.IR mnt.map , | |
80 | +and all accesses to | |
81 | +.I /auto | |
82 | +will access the \fIautomount\fP objects in \fIldapserver\fP's subtree under | |
83 | +.IR ou=automount,ou=services,dc=example,dc=com . | |
84 | .SH "SEE ALSO" | |
85 | .BR automount (8), | |
86 | .BR autofs (5), | |
87 | diff -uNr autofs-3.1.4/man/automount.8 autofs-3.1.4-ldap/man/automount.8 | |
88 | --- autofs-3.1.4/man/automount.8 Fri Jan 21 14:08:09 2000 | |
89 | +++ autofs-3.1.4-ldap/man/automount.8 Tue Apr 11 14:17:50 2000 | |
90 | @@ -63,6 +63,16 @@ | |
91 | The map is a hesiod database whose | |
92 | .B filsys | |
93 | entries are used for maps. | |
94 | +.TP | |
95 | +.B ldap | |
96 | +map names are of the form \fB[servername:]basedn\fP, where the optional | |
97 | +\fBservername\fP is the name of the LDAP server to query, and \fBbasedn\fP is | |
98 | +the DN to do a subtree search under. Entries are \fBautomount\fP objects in | |
99 | +the specified subtree, where the \fBcn\fP attribute is the key (the wildcard | |
100 | +key is "/"), and the \fBautomounterInformation\fP attribute contains the | |
101 | +information used by the automounter. Documentation on the schema | |
102 | +used by this module is available online at | |
103 | +http://docs.iplanet.com/docs/manuals/directory/411ext/nis/mapping.htm | |
104 | .RE | |
105 | .TP | |
106 | \fBformat\fP Format of the map data; currently the only formats | |
107 | diff -uNr autofs-3.1.4/modules/Makefile autofs-3.1.4-ldap/modules/Makefile | |
108 | --- autofs-3.1.4/modules/Makefile Tue Apr 11 14:18:08 2000 | |
109 | +++ autofs-3.1.4-ldap/modules/Makefile Tue Apr 11 14:17:50 2000 | |
110 | @@ -36,6 +36,11 @@ | |
111 | MODS += lookup_nisplus.so | |
112 | endif | |
113 | ||
114 | +ifeq ($(LDAP), 1) | |
115 | + SRCS += lookup_ldap.c | |
116 | + MODS += lookup_ldap.so | |
117 | +endif | |
118 | + | |
119 | CFLAGS += -I../include -fpic -DAUTOFS_LIB_DIR=\"$(autofslibdir)\" -DPATH_AUTOMOUNT=\"$(sbindir)/automount\" | |
120 | ||
121 | all: $(MODS) | |
122 | @@ -65,3 +70,8 @@ | |
123 | $(CC) $(SOLDFLAGS) $(CFLAGS) $(HESIOD_FLAGS) -o lookup_hesiod.so \ | |
124 | lookup_hesiod.c $(LIBHESIOD) $(LIBRESOLV) | |
125 | $(STRIP) lookup_hesiod.so | |
126 | + | |
127 | +lookup_ldap.so: lookup_ldap.c | |
128 | + $(CC) $(SOLDFLAGS) $(CFLAGS) $(LDAP_FLAGS) -o lookup_ldap.so \ | |
129 | + lookup_ldap.c $(LDAP_LIBS) | |
130 | + $(STRIP) lookup_ldap.so | |
131 | diff -uNr autofs-3.1.4/modules/lookup_ldap.c autofs-3.1.4-ldap/modules/lookup_ldap.c | |
132 | --- autofs-3.1.4/modules/lookup_ldap.c Wed Dec 31 19:00:00 1969 | |
133 | +++ autofs-3.1.4-ldap/modules/lookup_ldap.c Tue Apr 11 14:28:51 2000 | |
134 | @@ -0,0 +1,238 @@ | |
135 | +/* | |
136 | + * lookup_ldap.c | |
137 | + * | |
138 | + * Module for Linux automountd to access automount maps in LDAP directories. | |
139 | + * | |
140 | + */ | |
141 | + | |
142 | +#include <sys/types.h> | |
143 | +#include <ctype.h> | |
144 | +#include <string.h> | |
145 | +#include <syslog.h> | |
146 | +#include <unistd.h> | |
147 | +#include <stdlib.h> | |
148 | +#include <netinet/in.h> | |
149 | +#include <arpa/nameser.h> | |
150 | +#include <resolv.h> | |
151 | +#include <lber.h> | |
152 | +#include <ldap.h> | |
153 | + | |
154 | +#define MODULE_LOOKUP | |
155 | +#include "automount.h" | |
156 | + | |
157 | +#define MAPFMT_DEFAULT "sun" | |
158 | + | |
159 | +#define MODPREFIX "lookup(ldap): " | |
160 | + | |
161 | +#define OBJECTCLASS "automount" | |
162 | +#define ATTRIBUTE "automountInformation" | |
163 | +#define WILDCARD "/" | |
164 | + | |
165 | +struct lookup_context { | |
166 | + char *server, *base; | |
167 | + struct parse_mod *parser; | |
168 | +}; | |
169 | + | |
170 | +int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ | |
171 | + | |
172 | +/* | |
173 | + * This initializes a context (persistent non-global data) for queries to | |
174 | + * this module. Return zero if we succeed. | |
175 | + */ | |
176 | +int lookup_init(const char *mapfmt, int argc, const char * const *argv, | |
177 | + void **context) | |
178 | +{ | |
179 | + struct lookup_context *ctxt = NULL; | |
180 | + int rv, l; | |
181 | + LDAP *ldap; | |
182 | + | |
183 | + /* If we can't build a context, bail. */ | |
184 | + ctxt = (struct lookup_context*) malloc(sizeof(struct lookup_context)); | |
185 | + *context = ctxt; | |
186 | + if( ctxt == NULL ) { | |
187 | + syslog(LOG_INFO, MODPREFIX "malloc: %m"); | |
188 | + return 1; | |
189 | + } | |
190 | + memset(ctxt, 0, sizeof(struct lookup_context)); | |
191 | + | |
192 | + /* If a map type isn't explicitly given, parse it like sun entries. */ | |
193 | + if( mapfmt == NULL ) { | |
194 | + mapfmt = MAPFMT_DEFAULT; | |
195 | + } | |
196 | + | |
197 | + /* Now we sanity-check by binding to the server temporarily. We have to be | |
198 | + * a little strange in here, because we want to provide for use of the | |
199 | + * "default" server, which is set in an ldap.conf file somewhere. */ | |
200 | + if(strchr(argv[0], ':') != NULL) { | |
201 | + l = strchr(argv[0], ':') - argv[0]; | |
202 | + /* Isolate the server's name. */ | |
203 | + ctxt->server = malloc(l + 1); | |
204 | + memset(ctxt->server, 0, l + 1); | |
205 | + memcpy(ctxt->server, argv[0], l); | |
206 | + /* Isolate the base DN. */ | |
207 | + ctxt->base = malloc(strlen(argv[0]) - l); | |
208 | + memset(ctxt->base, 0, strlen(argv[0]) - l); | |
209 | + memcpy(ctxt->base, argv[0] + l + 1, strlen(argv[0]) - l - 1); | |
210 | + } else { | |
211 | + /* Use the default server; isolate the base DN's name. */ | |
212 | + l = strlen(argv[0]); | |
213 | + ctxt->server = NULL; | |
214 | + ctxt->base = malloc(l + 1); | |
215 | + memset(ctxt->base, 0, l + 1); | |
216 | + memcpy(ctxt->base, argv[0], l); | |
217 | + } | |
218 | + | |
219 | + syslog(LOG_DEBUG, MODPREFIX "server = \"%s\", base dn = \"%s\"", | |
220 | + ctxt->server ? ctxt->server : "(default)", ctxt->base); | |
221 | + | |
222 | + /* Initialize the LDAP context. */ | |
223 | + if( ( ldap = ldap_init(ctxt->server, LDAP_PORT)) == NULL ) { | |
224 | + syslog(LOG_CRIT, MODPREFIX "couldn't initialize LDAP"); | |
225 | + return 1; | |
226 | + } | |
227 | + | |
228 | + /* Connect to the server as an anonymous user. */ | |
229 | + rv = ldap_simple_bind_s(ldap, ctxt->base, NULL); | |
230 | + if( rv != LDAP_SUCCESS ) { | |
231 | + syslog(LOG_CRIT, MODPREFIX "couldn't connect to %s", ctxt->server); | |
232 | + return 1; | |
233 | + } | |
234 | + | |
235 | + /* Okay, we're done here. */ | |
236 | + ldap_unbind(ldap); | |
237 | + | |
238 | + /* Open the parser, if we can. */ | |
239 | + return !(ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1)); | |
240 | +} | |
241 | + | |
242 | +/* Lookup by key and pass a filesystem to a parser. */ | |
243 | +int lookup_mount(const char *root, const char *name, int name_len, void *context) | |
244 | +{ | |
245 | + struct lookup_context *ctxt = (struct lookup_context *) context; | |
246 | + int rv, i, l; | |
247 | + char *query; | |
248 | + LDAPMessage *result, *e; | |
249 | + char **values; | |
250 | + char *attrs[] = {ATTRIBUTE, NULL}; | |
251 | + LDAP *ldap; | |
252 | + | |
253 | + chdir("/"); /* If this is not here the filesystem stays | |
254 | + busy, for some reason... */ | |
255 | + | |
256 | + if( ctxt == NULL ) { | |
257 | + syslog(LOG_CRIT, MODPREFIX "context was NULL"); | |
258 | + return 0; | |
259 | + } | |
260 | + | |
261 | + /* Build a query string. */ | |
262 | + l = name_len + strlen("(&(objectclass=" OBJECTCLASS ")(cn=))") + 2; | |
263 | + | |
264 | + query = malloc(l); | |
265 | + if( query == NULL ) { | |
266 | + syslog(LOG_INFO, MODPREFIX "malloc: %m"); | |
267 | + return 0; | |
268 | + } | |
269 | + | |
270 | + memset(query, '\0', l); | |
271 | + if( sprintf(query, "(&(objectclass=" OBJECTCLASS ")(cn=%s))", name) >= l ) { | |
272 | + syslog(LOG_DEBUG, MODPREFIX "error forming query string"); | |
273 | + } | |
274 | + query[l - 1] = '\0'; | |
275 | + | |
276 | + /* Initialize the LDAP context. */ | |
277 | + if( (ldap = ldap_init(ctxt->server, LDAP_PORT) ) == NULL ) { | |
278 | + syslog(LOG_CRIT, MODPREFIX "couldn't initialize LDAP connection" | |
279 | + " to %s", ctxt->server ? ctxt->server : "default server"); | |
280 | + free(query); | |
281 | + return 1; | |
282 | + } | |
283 | + | |
284 | + /* Connect to the server as an anonymous user. */ | |
285 | + rv = ldap_simple_bind_s(ldap, ctxt->base, NULL); | |
286 | + if ( rv != LDAP_SUCCESS ) { | |
287 | + syslog(LOG_CRIT, MODPREFIX "couldn't bind to %s", | |
288 | + ctxt->server ? ctxt->server : "default server"); | |
289 | + free(query); | |
290 | + return 1; | |
291 | + } | |
292 | + | |
293 | + /* Look around. */ | |
294 | + syslog(LOG_DEBUG, MODPREFIX "searching for \"%s\"", query); | |
295 | + rv = ldap_search_s(ldap, ctxt->base, LDAP_SCOPE_SUBTREE, | |
296 | + query, attrs, 0, &result); | |
297 | + | |
298 | + if( ( rv != LDAP_SUCCESS) || ( result == NULL ) ) { | |
299 | + syslog(LOG_INFO, MODPREFIX "query failed for %s", query); | |
300 | + free(query); | |
301 | + return 1; | |
302 | + } | |
303 | + | |
304 | + e = ldap_first_entry(ldap, result); | |
305 | + | |
306 | + /* If we got no answers, try it with "/" instead, which makes a better | |
307 | + * wildcard thatn "*" for LDAP, and also happens to be illegal for actual | |
308 | + * directory names. */ | |
309 | + if( e == NULL ) { | |
310 | + syslog(LOG_DEBUG, MODPREFIX "no entry for \"%s\" found, trying cn=\"/\"", | |
311 | + name); | |
312 | + | |
313 | + sprintf(query, "(&(objectclass=" OBJECTCLASS ")(cn=" WILDCARD "))"); | |
314 | + | |
315 | + syslog(LOG_DEBUG, MODPREFIX "searching for \"%s\"", query); | |
316 | + rv = ldap_search_s(ldap, ctxt->base, LDAP_SCOPE_SUBTREE, | |
317 | + query, attrs, 0, &result); | |
318 | + if( ( rv != LDAP_SUCCESS) || ( result == NULL ) ) { | |
319 | + syslog(LOG_INFO, MODPREFIX "query failed for %s", query); | |
320 | + free(query); | |
321 | + return 1; | |
322 | + } | |
323 | + | |
324 | + syslog(LOG_DEBUG, MODPREFIX "getting first entry for cn=\"/\""); | |
325 | + | |
326 | + e = ldap_first_entry(ldap, result); | |
327 | + } | |
328 | + | |
329 | + if( e == NULL ) { | |
330 | + syslog(LOG_INFO, MODPREFIX "got answer, but no first entry for %s", query); | |
331 | + free(query); | |
332 | + return 1; | |
333 | + } else { | |
334 | + syslog(LOG_DEBUG, MODPREFIX "examining first entry"); | |
335 | + } | |
336 | + | |
337 | + values = ldap_get_values(ldap, e, ATTRIBUTE); | |
338 | + if( values == NULL ) { | |
339 | + syslog(LOG_INFO, MODPREFIX "no " ATTRIBUTE " defined for %s", query); | |
340 | + free(query); | |
341 | + return 1; | |
342 | + } | |
343 | + | |
344 | + /* Try each of the answers in sucession. */ | |
345 | + rv = 1; | |
346 | + for( i = 0 ; ( values[i] != NULL ) && ( rv != 0 ) ; i++ ) { | |
347 | + rv = ctxt->parser->parse_mount(root, name, name_len, values[0], | |
348 | + ctxt->parser->context); | |
349 | + } | |
350 | + | |
351 | + /* Clean up. */ | |
352 | + ldap_value_free(values); | |
353 | + ldap_msgfree(result); | |
354 | + ldap_unbind(ldap); | |
355 | + free(query); | |
356 | + | |
357 | + return rv; | |
358 | +} | |
359 | + | |
360 | +/* | |
361 | + * This destroys a context for queries to this module. It releases the parser | |
362 | + * structure (unloading the module) and frees the memory used by the context. | |
363 | + */ | |
364 | +int lookup_done(void *context) | |
365 | +{ | |
366 | + struct lookup_context *ctxt = (struct lookup_context *) context; | |
367 | + int rv = close_parse(ctxt->parser); | |
368 | + free(ctxt->server); | |
369 | + free(ctxt->base); | |
370 | + free(ctxt); | |
371 | + return rv; | |
372 | +} |