]>
Commit | Line | Data |
---|---|---|
1 | diff --git a/CHANGELOG b/CHANGELOG | |
2 | index 08afa7c..c208b31 100644 | |
3 | --- a/CHANGELOG | |
4 | +++ b/CHANGELOG | |
5 | @@ -24,6 +24,7 @@ | |
6 | - fix couple of edge case parse fails of timeout option. | |
7 | - check for "*" when looking up wildcard in LDAP. | |
8 | - fix LDAP schema discovery. | |
9 | +- add SEARCH_BASE configuration option. | |
10 | ||
11 | 18/06/2007 autofs-5.0.2 | |
12 | ----------------------- | |
13 | diff --git a/include/defaults.h b/include/defaults.h | |
14 | index 9aec11a..0984b1c 100644 | |
15 | --- a/include/defaults.h | |
16 | +++ b/include/defaults.h | |
17 | @@ -37,6 +37,9 @@ | |
18 | #define DEFAULT_APPEND_OPTIONS 1 | |
19 | #define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf" | |
20 | ||
21 | +struct ldap_schema; | |
22 | +struct ldap_searchdn; | |
23 | + | |
24 | unsigned int defaults_read_config(void); | |
25 | const char *defaults_get_master_map(void); | |
26 | unsigned int defaults_get_timeout(void); | |
27 | @@ -45,6 +48,8 @@ unsigned int defaults_get_logging(void); | |
28 | const char *defaults_get_ldap_server(void); | |
29 | struct ldap_schema *defaults_get_default_schema(void); | |
30 | struct ldap_schema *defaults_get_schema(void); | |
31 | +struct ldap_searchdn *defaults_get_searchdns(void); | |
32 | +void defaults_free_searchdns(struct ldap_searchdn *); | |
33 | unsigned int defaults_get_append_options(void); | |
34 | const char *defaults_get_auth_conf_file(void); | |
35 | ||
36 | diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h | |
37 | index 1378b9e..1a924be 100644 | |
38 | --- a/include/lookup_ldap.h | |
39 | +++ b/include/lookup_ldap.h | |
40 | @@ -18,6 +18,11 @@ struct ldap_schema { | |
41 | char *value_attr; | |
42 | }; | |
43 | ||
44 | +struct ldap_searchdn { | |
45 | + char *basedn; | |
46 | + struct ldap_searchdn *next; | |
47 | +}; | |
48 | + | |
49 | struct lookup_context { | |
50 | char *mapname; | |
51 | ||
52 | @@ -32,6 +37,10 @@ struct lookup_context { | |
53 | /* LDAP lookup configuration */ | |
54 | struct ldap_schema *schema; | |
55 | ||
56 | + /* List of base dns for searching */ | |
57 | + char *cur_host; | |
58 | + struct ldap_searchdn *sdns; | |
59 | + | |
60 | /* TLS and SASL authentication information */ | |
61 | char *auth_conf; | |
62 | unsigned use_tls; | |
63 | diff --git a/lib/defaults.c b/lib/defaults.c | |
64 | index b146f13..c2f86c0 100644 | |
65 | --- a/lib/defaults.c | |
66 | +++ b/lib/defaults.c | |
67 | @@ -32,6 +32,8 @@ | |
68 | ||
69 | #define ENV_LDAP_SERVER "LDAP_SERVER" | |
70 | ||
71 | +#define SEARCH_BASE "SEARCH_BASE" | |
72 | + | |
73 | #define ENV_NAME_MAP_OBJ_CLASS "MAP_OBJECT_CLASS" | |
74 | #define ENV_NAME_ENTRY_OBJ_CLASS "ENTRY_OBJECT_CLASS" | |
75 | #define ENV_NAME_MAP_ATTR "MAP_ATTRIBUTE" | |
76 | @@ -130,6 +132,52 @@ static int check_set_config_value(const char *res, const char *name, const char | |
77 | return 0; | |
78 | } | |
79 | ||
80 | +static int parse_line(char *line, char **res, char **value) | |
81 | +{ | |
82 | + volatile char *key, *val, *trailer; | |
83 | + int len; | |
84 | + | |
85 | + key = line; | |
86 | + | |
87 | + if (*key == '#' || !isalpha(*key)) | |
88 | + return 0; | |
89 | + | |
90 | + while (*key && *key == ' ') | |
91 | + key++; | |
92 | + | |
93 | + if (!key) | |
94 | + return 0; | |
95 | + | |
96 | + if (!(val = strchr(key, '='))) | |
97 | + return 0; | |
98 | + | |
99 | + *val++ = '\0'; | |
100 | + | |
101 | + while (*val && (*val == '"' || isblank(*val))) | |
102 | + val++; | |
103 | + | |
104 | + len = strlen(val); | |
105 | + | |
106 | + if (val[len - 1] == '\n') { | |
107 | + val[len - 1] = '\0'; | |
108 | + len--; | |
109 | + } | |
110 | + | |
111 | + trailer = strchr(val, '#'); | |
112 | + if (!trailer) | |
113 | + trailer = val + len - 1; | |
114 | + else | |
115 | + trailer--; | |
116 | + | |
117 | + while (*trailer && (*trailer == '"' || isblank(*trailer))) | |
118 | + *(trailer--) = '\0';; | |
119 | + | |
120 | + *res = key; | |
121 | + *value = val; | |
122 | + | |
123 | + return 1; | |
124 | +} | |
125 | + | |
126 | /* | |
127 | * Read config env variables and check they have been set. | |
128 | * | |
129 | @@ -141,61 +189,30 @@ unsigned int defaults_read_config(void) | |
130 | { | |
131 | FILE *f; | |
132 | char buf[MAX_LINE_LEN]; | |
133 | - char *res, *value; | |
134 | + char *res; | |
135 | ||
136 | f = fopen(DEFAULTS_CONFIG_FILE, "r"); | |
137 | if (!f) | |
138 | return 0; | |
139 | ||
140 | while ((res = fgets(buf, MAX_LINE_LEN, f))) { | |
141 | - char *trailer; | |
142 | - int len; | |
143 | - | |
144 | - if (*res == '#' || !isalpha(*res)) | |
145 | - continue; | |
146 | - | |
147 | - while (*res && *res == ' ') | |
148 | - res++; | |
149 | - | |
150 | - if (!res) | |
151 | - continue; | |
152 | + char *key, *value; | |
153 | ||
154 | - if (!(value = strchr(res, '='))) | |
155 | + if (!parse_line(res, &key, &value)) | |
156 | continue; | |
157 | ||
158 | - *value++ = '\0'; | |
159 | - | |
160 | - while (*value && (*value == '"' || isblank(*value))) | |
161 | - value++; | |
162 | - | |
163 | - len = strlen(value); | |
164 | - | |
165 | - if (value[len - 1] == '\n') { | |
166 | - value[len - 1] = '\0'; | |
167 | - len--; | |
168 | - } | |
169 | - | |
170 | - trailer = strchr(value, '#'); | |
171 | - if (!trailer) | |
172 | - trailer = value + len - 1; | |
173 | - else | |
174 | - trailer--; | |
175 | - | |
176 | - while (*trailer && (*trailer == '"' || isblank(*trailer))) | |
177 | - *(trailer--) = '\0';; | |
178 | - | |
179 | - if (check_set_config_value(res, ENV_NAME_MASTER_MAP, value) || | |
180 | - check_set_config_value(res, ENV_NAME_TIMEOUT, value) || | |
181 | - check_set_config_value(res, ENV_NAME_BROWSE_MODE, value) || | |
182 | - check_set_config_value(res, ENV_NAME_LOGGING, value) || | |
183 | - check_set_config_value(res, ENV_LDAP_SERVER, value) || | |
184 | - check_set_config_value(res, ENV_NAME_MAP_OBJ_CLASS, value) || | |
185 | - check_set_config_value(res, ENV_NAME_ENTRY_OBJ_CLASS, value) || | |
186 | - check_set_config_value(res, ENV_NAME_MAP_ATTR, value) || | |
187 | - check_set_config_value(res, ENV_NAME_ENTRY_ATTR, value) || | |
188 | - check_set_config_value(res, ENV_NAME_VALUE_ATTR, value) || | |
189 | - check_set_config_value(res, ENV_APPEND_OPTIONS, value) || | |
190 | - check_set_config_value(res, ENV_AUTH_CONF_FILE, value)) | |
191 | + if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value) || | |
192 | + check_set_config_value(key, ENV_NAME_TIMEOUT, value) || | |
193 | + check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) || | |
194 | + check_set_config_value(key, ENV_NAME_LOGGING, value) || | |
195 | + check_set_config_value(key, ENV_LDAP_SERVER, value) || | |
196 | + check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) || | |
197 | + check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) || | |
198 | + check_set_config_value(key, ENV_NAME_MAP_ATTR, value) || | |
199 | + check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value) || | |
200 | + check_set_config_value(key, ENV_NAME_VALUE_ATTR, value) || | |
201 | + check_set_config_value(key, ENV_APPEND_OPTIONS, value) || | |
202 | + check_set_config_value(key, ENV_AUTH_CONF_FILE, value)) | |
203 | ; | |
204 | } | |
205 | ||
206 | @@ -336,6 +353,86 @@ struct ldap_schema *defaults_get_default_schema(void) | |
207 | return schema; | |
208 | } | |
209 | ||
210 | +static struct ldap_searchdn *alloc_searchdn(const char *value) | |
211 | +{ | |
212 | + struct ldap_searchdn *sdn; | |
213 | + char *val; | |
214 | + | |
215 | + sdn = malloc(sizeof(struct ldap_searchdn)); | |
216 | + if (!sdn) | |
217 | + return NULL; | |
218 | + | |
219 | + val = strdup(value); | |
220 | + if (!val) { | |
221 | + free(sdn); | |
222 | + return NULL; | |
223 | + } | |
224 | + | |
225 | + sdn->basedn = val; | |
226 | + sdn->next = NULL; | |
227 | + | |
228 | + return sdn; | |
229 | +} | |
230 | + | |
231 | +void defaults_free_searchdns(struct ldap_searchdn *sdn) | |
232 | +{ | |
233 | + struct ldap_searchdn *this = sdn; | |
234 | + struct ldap_searchdn *next; | |
235 | + | |
236 | + next = this; | |
237 | + while (this) { | |
238 | + next = this->next; | |
239 | + free(this->basedn); | |
240 | + free(this); | |
241 | + this = next; | |
242 | + } | |
243 | + | |
244 | + return; | |
245 | +} | |
246 | + | |
247 | +struct ldap_searchdn *defaults_get_searchdns(void) | |
248 | +{ | |
249 | + FILE *f; | |
250 | + char buf[MAX_LINE_LEN]; | |
251 | + char *res; | |
252 | + struct ldap_searchdn *sdn, *last; | |
253 | + | |
254 | + f = fopen(DEFAULTS_CONFIG_FILE, "r"); | |
255 | + if (!f) | |
256 | + return NULL; | |
257 | + | |
258 | + sdn = last = NULL; | |
259 | + | |
260 | + while ((res = fgets(buf, MAX_LINE_LEN, f))) { | |
261 | + char *key, *value; | |
262 | + | |
263 | + if (!parse_line(res, &key, &value)) | |
264 | + continue; | |
265 | + | |
266 | + if (!strcasecmp(key, SEARCH_BASE)) { | |
267 | + struct ldap_searchdn *new = alloc_searchdn(value); | |
268 | + | |
269 | + if (!new) { | |
270 | + defaults_free_searchdns(sdn); | |
271 | + return NULL; | |
272 | + } | |
273 | + | |
274 | + if (!last) | |
275 | + last = new; | |
276 | + else { | |
277 | + last->next = new; | |
278 | + last = new; | |
279 | + } | |
280 | + | |
281 | + if (!sdn) | |
282 | + sdn = new; | |
283 | + } | |
284 | + } | |
285 | + | |
286 | + fclose(f); | |
287 | + return sdn; | |
288 | +} | |
289 | + | |
290 | struct ldap_schema *defaults_get_schema(void) | |
291 | { | |
292 | struct ldap_schema *schema; | |
293 | diff --git a/man/auto.master.5.in b/man/auto.master.5.in | |
294 | index ab5ab1e..0cb2f07 100644 | |
295 | --- a/man/auto.master.5.in | |
296 | +++ b/man/auto.master.5.in | |
297 | @@ -230,6 +230,11 @@ values must be set, any partial schema specification will be ignored. | |
298 | .P | |
299 | The configuration settings available are: | |
300 | .TP | |
301 | +.B SEARCH_BASE | |
302 | +The base dn to use when searching for amap base dn. This entry may be | |
303 | +given multiple times and each will be checked for a map base dn in | |
304 | +the order they occur in the configuration. | |
305 | +.TP | |
306 | .B MAP_OBJECT_CLASS | |
307 | The map object class. In the \fBnisMap\fP schema this corresponds to the class | |
308 | \fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class | |
309 | diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c | |
310 | index 9c18ca1..da52e71 100644 | |
311 | --- a/modules/lookup_ldap.c | |
312 | +++ b/modules/lookup_ldap.c | |
313 | @@ -171,10 +171,207 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) | |
314 | return ldap; | |
315 | } | |
316 | ||
317 | +static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) | |
318 | +{ | |
319 | + char buf[PARSE_MAX_BUF]; | |
320 | + char *query, *dn; | |
321 | + LDAPMessage *result = NULL, *e; | |
322 | + struct ldap_searchdn *sdns = NULL; | |
323 | + char *attrs[2]; | |
324 | + int scope; | |
325 | + int rv, l; | |
326 | + | |
327 | + attrs[0] = LDAP_NO_ATTRS; | |
328 | + attrs[1] = NULL; | |
329 | + | |
330 | + if (!ctxt->mapname && !ctxt->base) { | |
331 | + error(LOGOPT_ANY, MODPREFIX "no master map to lookup"); | |
332 | + return 0; | |
333 | + } | |
334 | + | |
335 | + /* Build a query string. */ | |
336 | + l = strlen("(objectclass=)") + strlen(class) + 1; | |
337 | + if (ctxt->mapname) | |
338 | + l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))"); | |
339 | + | |
340 | + query = alloca(l); | |
341 | + if (query == NULL) { | |
342 | + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); | |
343 | + crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); | |
344 | + return NSS_STATUS_UNAVAIL; | |
345 | + } | |
346 | + | |
347 | + /* | |
348 | + * If we have a master mapname construct a query using it | |
349 | + * otherwise assume the base dn will catch it. | |
350 | + */ | |
351 | + if (ctxt->mapname) { | |
352 | + if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class, | |
353 | + key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) { | |
354 | + debug(LOGOPT_NONE, | |
355 | + MODPREFIX "error forming query string"); | |
356 | + return 0; | |
357 | + } | |
358 | + scope = LDAP_SCOPE_SUBTREE; | |
359 | + } else { | |
360 | + if (sprintf(query, "(objectclass=%s)", class) >= l) { | |
361 | + debug(LOGOPT_NONE, | |
362 | + MODPREFIX "error forming query string"); | |
363 | + return 0; | |
364 | + } | |
365 | + scope = LDAP_SCOPE_SUBTREE; | |
366 | + } | |
367 | + query[l] = '\0'; | |
368 | + | |
369 | + if (!ctxt->base) { | |
370 | + sdns = defaults_get_searchdns(); | |
371 | + if (sdns) | |
372 | + ctxt->sdns = sdns; | |
373 | + } | |
374 | + | |
375 | + if (!sdns) | |
376 | + rv = ldap_search_s(ldap, ctxt->base, | |
377 | + scope, query, attrs, 0, &result); | |
378 | + else { | |
379 | + struct ldap_searchdn *this = sdns; | |
380 | + | |
381 | + debug(LOGOPT_NONE, MODPREFIX | |
382 | + "check search base list"); | |
383 | + | |
384 | + while (this) { | |
385 | + rv = ldap_search_s(ldap, this->basedn, | |
386 | + scope, query, attrs, 0, &result); | |
387 | + | |
388 | + if ((rv == LDAP_SUCCESS) && result) { | |
389 | + debug(LOGOPT_NONE, MODPREFIX | |
390 | + "found search base under %s", | |
391 | + this->basedn); | |
392 | + break; | |
393 | + } | |
394 | + | |
395 | + this = this->next; | |
396 | + | |
397 | + if (result) { | |
398 | + ldap_msgfree(result); | |
399 | + result = NULL; | |
400 | + } | |
401 | + } | |
402 | + } | |
403 | + | |
404 | + if ((rv != LDAP_SUCCESS) || !result) { | |
405 | + error(LOGOPT_NONE, | |
406 | + MODPREFIX "query failed for %s: %s", | |
407 | + query, ldap_err2string(rv)); | |
408 | + return 0; | |
409 | + } | |
410 | + | |
411 | + e = ldap_first_entry(ldap, result); | |
412 | + if (e) { | |
413 | + dn = ldap_get_dn(ldap, e); | |
414 | + debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); | |
415 | + ldap_msgfree(result); | |
416 | + } else { | |
417 | + debug(LOGOPT_NONE, | |
418 | + MODPREFIX "query succeeded, no matches for %s", | |
419 | + query); | |
420 | + ldap_msgfree(result); | |
421 | + return 0; | |
422 | + } | |
423 | + | |
424 | + ctxt->qdn = dn; | |
425 | + | |
426 | + return 1; | |
427 | +} | |
428 | + | |
429 | +static struct ldap_schema *alloc_common_schema(struct ldap_schema *s) | |
430 | +{ | |
431 | + struct ldap_schema *schema; | |
432 | + char *mc, *ma, *ec, *ea, *va; | |
433 | + | |
434 | + mc = strdup(s->map_class); | |
435 | + if (!mc) | |
436 | + return NULL; | |
437 | + | |
438 | + ma = strdup(s->map_attr); | |
439 | + if (!ma) { | |
440 | + free(mc); | |
441 | + return NULL; | |
442 | + } | |
443 | + | |
444 | + ec = strdup(s->entry_class); | |
445 | + if (!ec) { | |
446 | + free(mc); | |
447 | + free(ma); | |
448 | + return NULL; | |
449 | + } | |
450 | + | |
451 | + ea = strdup(s->entry_attr); | |
452 | + if (!ea) { | |
453 | + free(mc); | |
454 | + free(ma); | |
455 | + free(ec); | |
456 | + return NULL; | |
457 | + } | |
458 | + | |
459 | + va = strdup(s->value_attr); | |
460 | + if (!va) { | |
461 | + free(mc); | |
462 | + free(ma); | |
463 | + free(ec); | |
464 | + free(ea); | |
465 | + return NULL; | |
466 | + } | |
467 | + | |
468 | + schema = malloc(sizeof(struct ldap_schema)); | |
469 | + if (!schema) { | |
470 | + free(mc); | |
471 | + free(ma); | |
472 | + free(ec); | |
473 | + free(ea); | |
474 | + free(va); | |
475 | + return NULL; | |
476 | + } | |
477 | + | |
478 | + schema->map_class = mc; | |
479 | + schema->map_attr = ma; | |
480 | + schema->entry_class = ec; | |
481 | + schema->entry_attr = ea; | |
482 | + schema->value_attr = va; | |
483 | + | |
484 | + return schema; | |
485 | +} | |
486 | + | |
487 | +static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) | |
488 | +{ | |
489 | + struct ldap_schema *schema; | |
490 | + unsigned int i; | |
491 | + | |
492 | + if (ctxt->schema) | |
493 | + return 0; | |
494 | + | |
495 | + for (i = 0; i < common_schema_count; i++) { | |
496 | + const char *class = common_schema[i].map_class; | |
497 | + const char *key = common_schema[i].map_attr; | |
498 | + if (get_query_dn(ldap, ctxt, class, key)) { | |
499 | + schema = alloc_common_schema(&common_schema[i]); | |
500 | + if (!schema) { | |
501 | + error(LOGOPT_ANY, | |
502 | + MODPREFIX "failed to allocate schema"); | |
503 | + return 0; | |
504 | + } | |
505 | + ctxt->schema = schema; | |
506 | + return 1; | |
507 | + } | |
508 | + } | |
509 | + | |
510 | + return 0; | |
511 | +} | |
512 | + | |
513 | static LDAP *do_connect(struct lookup_context *ctxt) | |
514 | { | |
515 | LDAP *ldap; | |
516 | - int rv; | |
517 | + char *host = NULL, *nhost; | |
518 | + int rv, need_base = 1; | |
519 | ||
520 | ldap = init_ldap_connection(ctxt); | |
521 | if (!ldap) | |
522 | @@ -204,6 +401,61 @@ static LDAP *do_connect(struct lookup_context *ctxt) | |
523 | return NULL; | |
524 | } | |
525 | ||
526 | + rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host); | |
527 | + if (rv != LDAP_SUCCESS || !host) { | |
528 | + unbind_ldap_connection(ldap, ctxt); | |
529 | + debug(LOGOPT_ANY, "failed to get hostname for connection"); | |
530 | + return NULL; | |
531 | + } | |
532 | + | |
533 | + nhost = strdup(host); | |
534 | + if (!nhost) { | |
535 | + unbind_ldap_connection(ldap, ctxt); | |
536 | + debug(LOGOPT_ANY, "failed to alloc context for hostname"); | |
537 | + return NULL; | |
538 | + } | |
539 | + ldap_memfree(host); | |
540 | + | |
541 | + if (!ctxt->cur_host) { | |
542 | + ctxt->cur_host = nhost; | |
543 | + /* Check if schema defined in conf first time only */ | |
544 | + ctxt->schema = defaults_get_schema(); | |
545 | + } else { | |
546 | + /* If connection host has changed update */ | |
547 | + if (strcmp(ctxt->cur_host, nhost)) { | |
548 | + free(ctxt->cur_host); | |
549 | + ctxt->cur_host = nhost; | |
550 | + } else { | |
551 | + free(nhost); | |
552 | + need_base = 0; | |
553 | + } | |
554 | + } | |
555 | + | |
556 | + if (!need_base) | |
557 | + return ldap; | |
558 | + | |
559 | + /* | |
560 | + * If the schema isn't defined in the configuration then check for | |
561 | + * presence of a map dn with a the common schema. Then calculate the | |
562 | + * base dn for searches. | |
563 | + */ | |
564 | + if (!ctxt->schema) { | |
565 | + if (!find_query_dn(ldap, ctxt)) { | |
566 | + unbind_ldap_connection(ldap, ctxt); | |
567 | + error(LOGOPT_ANY, | |
568 | + MODPREFIX "failed to find valid query dn"); | |
569 | + return NULL; | |
570 | + } | |
571 | + } else { | |
572 | + const char *class = ctxt->schema->map_class; | |
573 | + const char *key = ctxt->schema->map_attr; | |
574 | + if (!get_query_dn(ldap, ctxt, class, key)) { | |
575 | + unbind_ldap_connection(ldap, ctxt); | |
576 | + error(LOGOPT_ANY, MODPREFIX "failed to get query dn"); | |
577 | + return NULL; | |
578 | + } | |
579 | + } | |
580 | + | |
581 | return ldap; | |
582 | } | |
583 | ||
584 | @@ -769,175 +1021,17 @@ static void free_context(struct lookup_context *ctxt) | |
585 | ldap_memfree(ctxt->qdn); | |
586 | if (ctxt->server) | |
587 | free(ctxt->server); | |
588 | + if (ctxt->cur_host) | |
589 | + free(ctxt->cur_host); | |
590 | if (ctxt->base) | |
591 | free(ctxt->base); | |
592 | + if (ctxt->sdns) | |
593 | + defaults_free_searchdns(ctxt->sdns); | |
594 | free(ctxt); | |
595 | ||
596 | return; | |
597 | } | |
598 | ||
599 | -static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) | |
600 | -{ | |
601 | - char buf[PARSE_MAX_BUF]; | |
602 | - char *query, *dn; | |
603 | - LDAPMessage *result, *e; | |
604 | - char *attrs[2]; | |
605 | - int scope; | |
606 | - int rv, l; | |
607 | - | |
608 | - attrs[0] = LDAP_NO_ATTRS; | |
609 | - attrs[1] = NULL; | |
610 | - | |
611 | - if (!ctxt->mapname && !ctxt->base) { | |
612 | - error(LOGOPT_ANY, MODPREFIX "no master map to lookup"); | |
613 | - return 0; | |
614 | - } | |
615 | - | |
616 | - /* Build a query string. */ | |
617 | - l = strlen("(objectclass=)") + strlen(class) + 1; | |
618 | - if (ctxt->mapname) | |
619 | - l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))"); | |
620 | - | |
621 | - query = alloca(l); | |
622 | - if (query == NULL) { | |
623 | - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); | |
624 | - crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); | |
625 | - return NSS_STATUS_UNAVAIL; | |
626 | - } | |
627 | - | |
628 | - /* | |
629 | - * If we have a master mapname construct a query using it | |
630 | - * otherwise assume the base dn will catch it. | |
631 | - */ | |
632 | - if (ctxt->mapname) { | |
633 | - if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class, | |
634 | - key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) { | |
635 | - debug(LOGOPT_NONE, | |
636 | - MODPREFIX "error forming query string"); | |
637 | - return 0; | |
638 | - } | |
639 | - scope = LDAP_SCOPE_SUBTREE; | |
640 | - } else { | |
641 | - if (sprintf(query, "(objectclass=%s)", class) >= l) { | |
642 | - debug(LOGOPT_NONE, | |
643 | - MODPREFIX "error forming query string"); | |
644 | - return 0; | |
645 | - } | |
646 | - scope = LDAP_SCOPE_SUBTREE; | |
647 | - } | |
648 | - query[l] = '\0'; | |
649 | - | |
650 | - rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result); | |
651 | - | |
652 | - if ((rv != LDAP_SUCCESS) || !result) { | |
653 | - error(LOGOPT_NONE, | |
654 | - MODPREFIX "query failed for %s: %s", | |
655 | - query, ldap_err2string(rv)); | |
656 | - return 0; | |
657 | - } | |
658 | - | |
659 | - e = ldap_first_entry(ldap, result); | |
660 | - if (e) { | |
661 | - dn = ldap_get_dn(ldap, e); | |
662 | - debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); | |
663 | - ldap_msgfree(result); | |
664 | - } else { | |
665 | - debug(LOGOPT_NONE, | |
666 | - MODPREFIX "query succeeded, no matches for %s", | |
667 | - query); | |
668 | - ldap_msgfree(result); | |
669 | - return 0; | |
670 | - } | |
671 | - | |
672 | - ctxt->qdn = dn; | |
673 | - | |
674 | - return 1; | |
675 | -} | |
676 | - | |
677 | -static struct ldap_schema *alloc_common_schema(struct ldap_schema *s) | |
678 | -{ | |
679 | - struct ldap_schema *schema; | |
680 | - char *mc, *ma, *ec, *ea, *va; | |
681 | - | |
682 | - mc = strdup(s->map_class); | |
683 | - if (!mc) | |
684 | - return NULL; | |
685 | - | |
686 | - ma = strdup(s->map_attr); | |
687 | - if (!ma) { | |
688 | - free(mc); | |
689 | - return NULL; | |
690 | - } | |
691 | - | |
692 | - ec = strdup(s->entry_class); | |
693 | - if (!ec) { | |
694 | - free(mc); | |
695 | - free(ma); | |
696 | - return NULL; | |
697 | - } | |
698 | - | |
699 | - ea = strdup(s->entry_attr); | |
700 | - if (!ea) { | |
701 | - free(mc); | |
702 | - free(ma); | |
703 | - free(ec); | |
704 | - return NULL; | |
705 | - } | |
706 | - | |
707 | - va = strdup(s->value_attr); | |
708 | - if (!va) { | |
709 | - free(mc); | |
710 | - free(ma); | |
711 | - free(ec); | |
712 | - free(ea); | |
713 | - return NULL; | |
714 | - } | |
715 | - | |
716 | - schema = malloc(sizeof(struct ldap_schema)); | |
717 | - if (!schema) { | |
718 | - free(mc); | |
719 | - free(ma); | |
720 | - free(ec); | |
721 | - free(ea); | |
722 | - free(va); | |
723 | - return NULL; | |
724 | - } | |
725 | - | |
726 | - schema->map_class = mc; | |
727 | - schema->map_attr = ma; | |
728 | - schema->entry_class = ec; | |
729 | - schema->entry_attr = ea; | |
730 | - schema->value_attr = va; | |
731 | - | |
732 | - return schema; | |
733 | -} | |
734 | - | |
735 | -static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) | |
736 | -{ | |
737 | - struct ldap_schema *schema; | |
738 | - unsigned int i; | |
739 | - | |
740 | - if (ctxt->schema) | |
741 | - return 0; | |
742 | - | |
743 | - for (i = 0; i < common_schema_count; i++) { | |
744 | - const char *class = common_schema[i].map_class; | |
745 | - const char *key = common_schema[i].map_attr; | |
746 | - if (get_query_dn(ldap, ctxt, class, key)) { | |
747 | - schema = alloc_common_schema(&common_schema[i]); | |
748 | - if (!schema) { | |
749 | - error(LOGOPT_ANY, | |
750 | - MODPREFIX "failed to allocate schema"); | |
751 | - return 0; | |
752 | - } | |
753 | - ctxt->schema = schema; | |
754 | - return 1; | |
755 | - } | |
756 | - } | |
757 | - | |
758 | - return 0; | |
759 | -} | |
760 | - | |
761 | /* | |
762 | * This initializes a context (persistent non-global data) for queries to | |
763 | * this module. Return zero if we succeed. | |
764 | @@ -994,31 +1088,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co | |
765 | free_context(ctxt); | |
766 | return 1; | |
767 | } | |
768 | - | |
769 | - /* | |
770 | - * Get default schema for queries. | |
771 | - * If the schema isn't defined in the configuration then check for | |
772 | - * presence of a map dn in the common schemas. | |
773 | - */ | |
774 | - ctxt->schema = defaults_get_schema(); | |
775 | - if (!ctxt->schema) { | |
776 | - if (!find_query_dn(ldap, ctxt)) { | |
777 | - unbind_ldap_connection(ldap, ctxt); | |
778 | - error(LOGOPT_ANY, | |
779 | - MODPREFIX "failed to find valid query dn"); | |
780 | - free_context(ctxt); | |
781 | - return 1; | |
782 | - } | |
783 | - } else { | |
784 | - const char *class = ctxt->schema->map_class; | |
785 | - const char *key = ctxt->schema->map_attr; | |
786 | - if (!get_query_dn(ldap, ctxt, class, key)) { | |
787 | - unbind_ldap_connection(ldap, ctxt); | |
788 | - error(LOGOPT_ANY, MODPREFIX "failed to get query dn"); | |
789 | - free_context(ctxt); | |
790 | - return 1; | |
791 | - } | |
792 | - } | |
793 | unbind_ldap_connection(ldap, ctxt); | |
794 | ||
795 | /* Open the parser, if we can. */ | |
796 | diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in | |
797 | index 85f4e34..2b1e20a 100644 | |
798 | --- a/redhat/autofs.sysconfig.in | |
799 | +++ b/redhat/autofs.sysconfig.in | |
800 | @@ -21,6 +21,14 @@ BROWSE_MODE="no" | |
801 | # | |
802 | #LOGGING="none" | |
803 | # | |
804 | +# Define base dn for map dn lookup. | |
805 | +# | |
806 | +# SEARCH_BASE - base dn to use for searching for map search dn. | |
807 | +# Multiple entries can be given and they are checked | |
808 | +# in the order they occur here. | |
809 | +# | |
810 | +#SEARCH_BASE="" | |
811 | +# | |
812 | # Define the LDAP schema to used for lookups | |
813 | # | |
814 | # If no schema is set autofs will check each of the schemas | |
815 | diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in | |
816 | index 85f4e34..2b1e20a 100644 | |
817 | --- a/samples/autofs.conf.default.in | |
818 | +++ b/samples/autofs.conf.default.in | |
819 | @@ -21,6 +21,14 @@ BROWSE_MODE="no" | |
820 | # | |
821 | #LOGGING="none" | |
822 | # | |
823 | +# Define base dn for map dn lookup. | |
824 | +# | |
825 | +# SEARCH_BASE - base dn to use for searching for map search dn. | |
826 | +# Multiple entries can be given and they are checked | |
827 | +# in the order they occur here. | |
828 | +# | |
829 | +#SEARCH_BASE="" | |
830 | +# | |
831 | # Define the LDAP schema to used for lookups | |
832 | # | |
833 | # If no schema is set autofs will check each of the schemas |