Line data Source code
1 : /*
2 : SSSD
3 :
4 : Async LDAP Helper routines for autofs
5 :
6 : Authors:
7 : Jakub Hrozek <jhrozek@redhat.com>
8 :
9 : Copyright (C) 2012 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "util/util.h"
26 : #include "db/sysdb.h"
27 : #include "providers/ldap/sdap_async_private.h"
28 : #include "db/sysdb_autofs.h"
29 : #include "providers/ldap/ldap_common.h"
30 : #include "providers/ldap/sdap_autofs.h"
31 :
32 : enum autofs_map_op {
33 : AUTOFS_MAP_OP_ADD,
34 : AUTOFS_MAP_OP_DEL
35 : };
36 :
37 : /* ====== Utility functions ====== */
38 : static const char *
39 0 : get_autofs_map_name(struct sysdb_attrs *map, struct sdap_options *opts)
40 : {
41 : errno_t ret;
42 : struct ldb_message_element *el;
43 :
44 0 : ret = sysdb_attrs_get_el(map,
45 0 : opts->autofs_mobject_map[SDAP_AT_AUTOFS_MAP_NAME].sys_name,
46 : &el);
47 0 : if (ret) return NULL;
48 0 : if (el->num_values == 0) return NULL;
49 :
50 0 : return (const char *)el->values[0].data;
51 : }
52 :
53 : static const char *
54 0 : get_autofs_entry_attr(struct sysdb_attrs *entry, struct sdap_options *opts,
55 : enum sdap_autofs_entry_attrs attr)
56 : {
57 : errno_t ret;
58 : struct ldb_message_element *el;
59 :
60 0 : ret = sysdb_attrs_get_el(entry,
61 0 : opts->autofs_entry_map[attr].sys_name,
62 : &el);
63 0 : if (ret) return NULL;
64 0 : if (el->num_values != 1) {
65 0 : DEBUG(SSSDBG_CRIT_FAILURE,
66 : "Expected one entry got %d\n", el->num_values);
67 0 : return NULL;
68 : }
69 :
70 0 : return (const char *)el->values[0].data;
71 : }
72 :
73 : static const char *
74 0 : get_autofs_entry_key(struct sysdb_attrs *entry, struct sdap_options *opts)
75 : {
76 0 : return get_autofs_entry_attr(entry, opts, SDAP_AT_AUTOFS_ENTRY_KEY);
77 : }
78 :
79 : static const char *
80 0 : get_autofs_entry_value(struct sysdb_attrs *entry, struct sdap_options *opts)
81 : {
82 0 : return get_autofs_entry_attr(entry, opts, SDAP_AT_AUTOFS_ENTRY_VALUE);
83 : }
84 :
85 : static errno_t
86 0 : add_autofs_entry(struct sss_domain_info *domain,
87 : const char *map,
88 : struct sdap_options *opts,
89 : struct sysdb_attrs *entry)
90 : {
91 : const char *key;
92 : const char *value;
93 :
94 0 : key = get_autofs_entry_key(entry, opts);
95 0 : if (!key) {
96 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not get autofs entry key\n");
97 0 : return EINVAL;
98 : }
99 :
100 0 : value = get_autofs_entry_value(entry, opts);
101 0 : if (!value) {
102 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not get autofs entry value\n");
103 0 : return EINVAL;
104 : }
105 :
106 0 : return sysdb_save_autofsentry(domain, map, key, value, NULL);
107 : }
108 :
109 : static errno_t
110 0 : save_autofs_entries(struct sss_domain_info *domain,
111 : struct sdap_options *opts,
112 : const char *map,
113 : char **add_dn_list,
114 : hash_table_t *entry_hash)
115 : {
116 : hash_key_t key;
117 : hash_value_t value;
118 : size_t i;
119 : int hret;
120 : errno_t ret;
121 : struct sysdb_attrs *entry;
122 :
123 0 : if (!add_dn_list) {
124 0 : return EOK;
125 : }
126 :
127 0 : for (i=0; add_dn_list[i]; i++) {
128 0 : key.type = HASH_KEY_STRING;
129 0 : key.str = (char *) add_dn_list[i];
130 :
131 0 : hret = hash_lookup(entry_hash, &key, &value);
132 0 : if (hret != HASH_SUCCESS) {
133 0 : DEBUG(SSSDBG_MINOR_FAILURE,
134 : "Cannot retrieve entry [%s] from hash\n", add_dn_list[i]);
135 0 : continue;
136 : }
137 :
138 0 : entry = talloc_get_type(value.ptr, struct sysdb_attrs);
139 0 : if (!entry) {
140 0 : DEBUG(SSSDBG_MINOR_FAILURE,
141 : "Cannot retrieve entry [%s] from ptr\n", add_dn_list[i]);
142 0 : continue;
143 : }
144 :
145 0 : DEBUG(SSSDBG_TRACE_FUNC,
146 : "Saving autofs entry [%s]\n", add_dn_list[i]);
147 0 : ret = add_autofs_entry(domain, map, opts, entry);
148 0 : if (ret) {
149 0 : DEBUG(SSSDBG_MINOR_FAILURE,
150 : "Cannot save entry [%s] to cache\n", add_dn_list[i]);
151 0 : continue;
152 : }
153 :
154 0 : DEBUG(SSSDBG_TRACE_FUNC, "Saved entry [%s]\n", add_dn_list[i]);
155 : }
156 :
157 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "All entries saved\n");
158 0 : return EOK;
159 : }
160 :
161 : static errno_t
162 0 : del_autofs_entries(struct sss_domain_info *dom,
163 : char **del_dn_list)
164 : {
165 : size_t i;
166 : errno_t ret;
167 :
168 0 : for (i=0; del_dn_list[i]; i++) {
169 0 : DEBUG(SSSDBG_TRACE_FUNC,
170 : "Removing autofs entry [%s]\n", del_dn_list[i]);
171 :
172 0 : ret = sysdb_del_autofsentry(dom, del_dn_list[i]);
173 0 : if (ret) {
174 0 : DEBUG(SSSDBG_MINOR_FAILURE,
175 : "Cannot delete entry %s\n", del_dn_list[i]);
176 0 : continue;
177 : }
178 : }
179 :
180 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "All entries removed\n");
181 0 : return EOK;
182 : }
183 :
184 : static errno_t
185 0 : save_autofs_map(struct sss_domain_info *dom,
186 : struct sdap_options *opts,
187 : struct sysdb_attrs *map)
188 : {
189 : const char *mapname;
190 : errno_t ret;
191 : time_t now;
192 :
193 0 : mapname = get_autofs_map_name(map, opts);
194 0 : if (!mapname) return EINVAL;
195 :
196 0 : now = time(NULL);
197 :
198 0 : ret = sysdb_save_autofsmap(dom, mapname, mapname,
199 0 : NULL, dom->autofsmap_timeout, now);
200 0 : if (ret != EOK) {
201 0 : return ret;
202 : }
203 :
204 0 : return EOK;
205 : }
206 :
207 : struct automntmaps_process_members_state {
208 : struct tevent_context *ev;
209 : struct sdap_options *opts;
210 : struct sdap_handle *sh;
211 : struct sss_domain_info *dom;
212 : int timeout;
213 :
214 : const char *orig_dn;
215 : char *base_filter;
216 : char *filter;
217 : const char **attrs;
218 : size_t base_iter;
219 : struct sdap_search_base **search_bases;
220 :
221 : struct sysdb_attrs *map;
222 :
223 : struct sysdb_attrs **entries;
224 : size_t entries_count;
225 : };
226 :
227 : static void
228 : automntmaps_process_members_done(struct tevent_req *subreq);
229 : static errno_t
230 : automntmaps_process_members_next_base(struct tevent_req *req);
231 :
232 : static struct tevent_req *
233 0 : automntmaps_process_members_send(TALLOC_CTX *mem_ctx,
234 : struct tevent_context *ev,
235 : struct sdap_options *opts,
236 : struct sdap_handle *sh,
237 : struct sss_domain_info *dom,
238 : struct sdap_search_base **search_bases,
239 : int timeout,
240 : struct sysdb_attrs *map)
241 : {
242 : errno_t ret;
243 : struct tevent_req *req;
244 : struct automntmaps_process_members_state *state;
245 :
246 0 : req = tevent_req_create(mem_ctx, &state,
247 : struct automntmaps_process_members_state);
248 0 : if (!req) return NULL;
249 :
250 0 : state->ev = ev;
251 0 : state->opts = opts;
252 0 : state->dom = dom;
253 0 : state->sh = sh;
254 0 : state->timeout = timeout;
255 0 : state->base_iter = 0;
256 0 : state->map = map;
257 0 : state->search_bases = search_bases;
258 :
259 0 : state->base_filter = talloc_asprintf(state, "(&(%s=*)(objectclass=%s))",
260 0 : opts->autofs_entry_map[SDAP_AT_AUTOFS_ENTRY_KEY].name,
261 0 : opts->autofs_entry_map[SDAP_OC_AUTOFS_ENTRY].name);
262 0 : if (!state->base_filter) {
263 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build filter\n");
264 0 : ret = ENOMEM;
265 0 : goto immediate;
266 : }
267 :
268 0 : ret = build_attrs_from_map(state, opts->autofs_entry_map,
269 : SDAP_OPTS_AUTOFS_ENTRY, NULL,
270 0 : &state->attrs, NULL);
271 0 : if (ret != EOK) {
272 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build attributes from map\n");
273 0 : ret = ENOMEM;
274 0 : goto immediate;
275 : }
276 :
277 :
278 0 : ret = sysdb_attrs_get_string(state->map, SYSDB_ORIG_DN, &state->orig_dn);
279 0 : if (ret != EOK) {
280 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get originalDN\n");
281 0 : goto immediate;
282 : }
283 :
284 0 : DEBUG(SSSDBG_TRACE_FUNC,
285 : "Examining autofs map [%s]\n", state->orig_dn);
286 :
287 0 : ret = automntmaps_process_members_next_base(req);
288 0 : if (ret != EOK) {
289 0 : DEBUG(SSSDBG_OP_FAILURE,
290 : "search failed [%d]: %s\n", ret, strerror(ret));
291 0 : goto immediate;
292 : }
293 :
294 0 : return req;
295 :
296 : immediate:
297 0 : if (ret != EOK) {
298 0 : tevent_req_error(req, ret);
299 : } else {
300 0 : tevent_req_done(req);
301 : }
302 0 : tevent_req_post(req, ev);
303 0 : return req;
304 : }
305 :
306 : static errno_t
307 0 : automntmaps_process_members_next_base(struct tevent_req *req)
308 : {
309 : struct tevent_req *subreq;
310 0 : struct automntmaps_process_members_state *state =
311 0 : tevent_req_data(req, struct automntmaps_process_members_state);
312 :
313 0 : talloc_zfree(state->filter);
314 0 : state->filter = sdap_combine_filters(state, state->base_filter,
315 0 : state->search_bases[state->base_iter]->filter);
316 0 : if (!state->filter) {
317 0 : return ENOMEM;
318 : }
319 :
320 0 : DEBUG(SSSDBG_TRACE_FUNC,
321 : "Searching for automount map entries with base [%s]\n",
322 : state->search_bases[state->base_iter]->basedn);
323 :
324 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
325 : state->orig_dn,
326 0 : state->search_bases[state->base_iter]->scope,
327 0 : state->filter, state->attrs,
328 0 : state->opts->autofs_entry_map,
329 : SDAP_OPTS_AUTOFS_ENTRY,
330 : state->timeout, true);
331 0 : if (!subreq) {
332 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot start search for entries\n");
333 0 : return EIO;
334 : }
335 0 : tevent_req_set_callback(subreq, automntmaps_process_members_done, req);
336 :
337 0 : return EOK;
338 : }
339 :
340 : static void
341 0 : automntmaps_process_members_done(struct tevent_req *subreq)
342 : {
343 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
344 : struct tevent_req);
345 0 : struct automntmaps_process_members_state *state =
346 0 : tevent_req_data(req, struct automntmaps_process_members_state);
347 : errno_t ret;
348 : struct sysdb_attrs **entries;
349 : size_t entries_count, i;
350 :
351 0 : ret = sdap_get_generic_recv(subreq, state,
352 : &entries_count, &entries);
353 0 : talloc_zfree(subreq);
354 0 : if (ret) {
355 0 : tevent_req_error(req, ret);
356 0 : return;
357 : }
358 :
359 0 : if (entries_count > 0) {
360 0 : state->entries = talloc_realloc(state, state->entries,
361 : struct sysdb_attrs *,
362 : state->entries_count + entries_count + 1);
363 0 : if (state->entries == NULL) {
364 0 : tevent_req_error(req, ENOMEM);
365 0 : return;
366 : }
367 :
368 0 : for (i=0; i < entries_count; i++) {
369 0 : state->entries[state->entries_count + i] =
370 0 : talloc_steal(state->entries, entries[i]);
371 : }
372 :
373 0 : state->entries_count += entries_count;
374 0 : state->entries[state->entries_count] = NULL;
375 : }
376 :
377 0 : state->base_iter++;
378 0 : if (state->search_bases[state->base_iter]) {
379 0 : ret = automntmaps_process_members_next_base(req);
380 0 : if (ret != EOK) {
381 0 : tevent_req_error(req, ret);
382 0 : return;
383 : }
384 : }
385 :
386 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "No more search bases to try\n");
387 :
388 0 : DEBUG(SSSDBG_TRACE_FUNC,
389 : "Search for autofs entries, returned %zu results.\n",
390 : state->entries_count);
391 :
392 0 : tevent_req_done(req);
393 0 : return;
394 : }
395 :
396 : static errno_t
397 0 : automntmaps_process_members_recv(struct tevent_req *req,
398 : TALLOC_CTX *mem_ctx,
399 : size_t *entries_count,
400 : struct sysdb_attrs ***entries)
401 : {
402 : struct automntmaps_process_members_state *state;
403 0 : state = tevent_req_data(req, struct automntmaps_process_members_state);
404 :
405 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
406 :
407 0 : if (entries_count) {
408 0 : *entries_count = state->entries_count;
409 : }
410 :
411 0 : if (entries) {
412 0 : *entries = talloc_steal(mem_ctx, state->entries);
413 : }
414 :
415 0 : return EOK;
416 : }
417 :
418 : struct sdap_get_automntmap_state {
419 : struct tevent_context *ev;
420 : struct sdap_options *opts;
421 : struct sdap_handle *sh;
422 : struct sss_domain_info *dom;
423 : const char **attrs;
424 : const char *base_filter;
425 : char *filter;
426 : int timeout;
427 :
428 : char *higher_timestamp;
429 :
430 : struct sysdb_attrs **map;
431 : size_t count;
432 :
433 : struct sysdb_attrs **entries;
434 : size_t entries_count;
435 :
436 : size_t base_iter;
437 : struct sdap_search_base **search_bases;
438 : };
439 :
440 : static errno_t
441 : sdap_get_automntmap_next_base(struct tevent_req *req);
442 : static void
443 : sdap_get_automntmap_process(struct tevent_req *subreq);
444 :
445 : static struct tevent_req *
446 0 : sdap_get_automntmap_send(TALLOC_CTX *memctx,
447 : struct tevent_context *ev,
448 : struct sss_domain_info *dom,
449 : struct sdap_options *opts,
450 : struct sdap_search_base **search_bases,
451 : struct sdap_handle *sh,
452 : const char **attrs,
453 : const char *filter,
454 : int timeout)
455 : {
456 : errno_t ret;
457 : struct tevent_req *req;
458 : struct sdap_get_automntmap_state *state;
459 :
460 0 : req = tevent_req_create(memctx, &state, struct sdap_get_automntmap_state);
461 0 : if (!req) return NULL;
462 :
463 0 : state->ev = ev;
464 0 : state->opts = opts;
465 0 : state->dom = dom;
466 0 : state->sh = sh;
467 0 : state->attrs = attrs;
468 0 : state->higher_timestamp = NULL;
469 0 : state->map = NULL;
470 0 : state->count = 0;
471 0 : state->timeout = timeout;
472 0 : state->base_filter = filter;
473 0 : state->base_iter = 0;
474 0 : state->search_bases = search_bases;
475 :
476 0 : ret = sdap_get_automntmap_next_base(req);
477 0 : if (ret != EOK) {
478 0 : tevent_req_error(req, ret);
479 0 : tevent_req_post(req, state->ev);
480 : }
481 0 : return req;
482 : }
483 :
484 : static errno_t
485 0 : sdap_get_automntmap_next_base(struct tevent_req *req)
486 : {
487 : struct tevent_req *subreq;
488 : struct sdap_get_automntmap_state *state;
489 :
490 0 : state = tevent_req_data(req, struct sdap_get_automntmap_state);
491 :
492 0 : talloc_zfree(state->filter);
493 0 : state->filter = sdap_combine_filters(state, state->base_filter,
494 0 : state->search_bases[state->base_iter]->filter);
495 0 : if (!state->filter) {
496 0 : return ENOMEM;
497 : }
498 :
499 0 : DEBUG(SSSDBG_TRACE_FUNC,
500 : "Searching for automount maps with base [%s]\n",
501 : state->search_bases[state->base_iter]->basedn);
502 :
503 0 : subreq = sdap_get_generic_send(
504 : state, state->ev, state->opts, state->sh,
505 0 : state->search_bases[state->base_iter]->basedn,
506 0 : state->search_bases[state->base_iter]->scope,
507 0 : state->filter, state->attrs,
508 0 : state->opts->autofs_mobject_map, SDAP_OPTS_AUTOFS_MAP,
509 : state->timeout,
510 : false);
511 0 : if (!subreq) {
512 0 : return EIO;
513 : }
514 0 : tevent_req_set_callback(subreq, sdap_get_automntmap_process, req);
515 :
516 0 : return EOK;
517 : }
518 :
519 : static void
520 : sdap_get_automntmap_done(struct tevent_req *subreq);
521 :
522 : static void
523 0 : sdap_get_automntmap_process(struct tevent_req *subreq)
524 : {
525 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
526 : struct tevent_req);
527 0 : struct sdap_get_automntmap_state *state = tevent_req_data(req,
528 : struct sdap_get_automntmap_state);
529 : errno_t ret;
530 :
531 0 : ret = sdap_get_generic_recv(subreq, state,
532 : &state->count, &state->map);
533 0 : talloc_zfree(subreq);
534 0 : if (ret) {
535 0 : tevent_req_error(req, ret);
536 0 : return;
537 : }
538 :
539 0 : DEBUG(SSSDBG_TRACE_FUNC,
540 : "Search for autofs maps, returned %zu results.\n", state->count);
541 :
542 0 : if (state->count == 0) {
543 : /* No maps found in this search */
544 0 : state->base_iter++;
545 0 : if (state->search_bases[state->base_iter]) {
546 : /* There are more search bases to try */
547 0 : ret = sdap_get_automntmap_next_base(req);
548 0 : if (ret != EOK) {
549 0 : tevent_req_error(req, ENOENT);
550 : }
551 0 : return;
552 : }
553 :
554 0 : tevent_req_error(req, ENOENT);
555 0 : return;
556 0 : } else if (state->count > 1) {
557 0 : DEBUG(SSSDBG_OP_FAILURE,
558 : "The search yielded more than one autofs map\n");
559 0 : tevent_req_error(req, EIO);
560 0 : return;
561 : }
562 :
563 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Processing autofs maps\n");
564 0 : subreq = automntmaps_process_members_send(state, state->ev, state->opts,
565 : state->sh, state->dom,
566 : state->search_bases,
567 : state->timeout,
568 0 : state->map[0]);
569 0 : if (!subreq) {
570 0 : tevent_req_error(req, ENOMEM);
571 0 : return;
572 : }
573 0 : tevent_req_set_callback(subreq, sdap_get_automntmap_done, req);
574 :
575 0 : return;
576 : }
577 :
578 : static void
579 0 : sdap_get_automntmap_done(struct tevent_req *subreq)
580 : {
581 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
582 : struct tevent_req);
583 0 : struct sdap_get_automntmap_state *state = tevent_req_data(req,
584 : struct sdap_get_automntmap_state);
585 : errno_t ret;
586 :
587 0 : ret = automntmaps_process_members_recv(subreq, state, &state->entries_count,
588 : &state->entries);
589 0 : talloc_zfree(subreq);
590 0 : if (ret != EOK) {
591 0 : tevent_req_error(req, ret);
592 0 : return;
593 : }
594 :
595 0 : DEBUG(SSSDBG_TRACE_FUNC, "automount map members received\n");
596 0 : tevent_req_done(req);
597 0 : return;
598 : }
599 :
600 : static errno_t
601 0 : sdap_get_automntmap_recv(struct tevent_req *req,
602 : TALLOC_CTX *mem_ctx,
603 : struct sysdb_attrs **map,
604 : size_t *entries_count,
605 : struct sysdb_attrs ***entries)
606 : {
607 0 : struct sdap_get_automntmap_state *state = tevent_req_data(req,
608 : struct sdap_get_automntmap_state);
609 :
610 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
611 :
612 0 : if (map) {
613 0 : *map = talloc_steal(mem_ctx, state->map[0]);
614 : }
615 :
616 0 : if (entries_count) {
617 0 : *entries_count = state->entries_count;
618 : }
619 :
620 0 : if (entries) {
621 0 : *entries = talloc_steal(mem_ctx, state->entries);
622 : }
623 :
624 0 : return EOK;
625 : }
626 :
627 : struct sdap_autofs_setautomntent_state {
628 : char *filter;
629 : const char **attrs;
630 : struct sdap_options *opts;
631 : struct sdap_handle *sh;
632 : struct sysdb_ctx *sysdb;
633 : struct sdap_id_op *sdap_op;
634 : struct sss_domain_info *dom;
635 :
636 : const char *mapname;
637 : struct sysdb_attrs *map;
638 : struct sysdb_attrs **entries;
639 : size_t entries_count;
640 :
641 : int dp_error;
642 : };
643 :
644 : static void
645 : sdap_autofs_setautomntent_done(struct tevent_req *subreq);
646 :
647 : struct tevent_req *
648 0 : sdap_autofs_setautomntent_send(TALLOC_CTX *memctx,
649 : struct tevent_context *ev,
650 : struct sss_domain_info *dom,
651 : struct sysdb_ctx *sysdb,
652 : struct sdap_handle *sh,
653 : struct sdap_id_op *op,
654 : struct sdap_options *opts,
655 : const char *mapname)
656 : {
657 : struct tevent_req *req;
658 : struct tevent_req *subreq;
659 : struct sdap_autofs_setautomntent_state *state;
660 : char *clean_mapname;
661 : errno_t ret;
662 :
663 0 : req = tevent_req_create(memctx, &state,
664 : struct sdap_autofs_setautomntent_state);
665 0 : if (!req) return NULL;
666 :
667 0 : if (!mapname) {
668 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No map name given\n");
669 0 : ret = EINVAL;
670 0 : goto fail;
671 : }
672 :
673 0 : state->sh = sh;
674 0 : state->sysdb = sysdb;
675 0 : state->opts = opts;
676 0 : state->sdap_op = op;
677 0 : state->dom = dom;
678 0 : state->mapname = mapname;
679 :
680 0 : ret = sss_filter_sanitize(state, mapname, &clean_mapname);
681 0 : if (ret != EOK) {
682 0 : goto fail;
683 : }
684 :
685 0 : state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
686 0 : state->opts->autofs_mobject_map[SDAP_AT_AUTOFS_MAP_NAME].name,
687 : clean_mapname,
688 0 : state->opts->autofs_mobject_map[SDAP_OC_AUTOFS_MAP].name);
689 0 : if (!state->filter) {
690 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build filter\n");
691 0 : ret = ENOMEM;
692 0 : goto fail;
693 : }
694 0 : talloc_free(clean_mapname);
695 :
696 0 : ret = build_attrs_from_map(state, state->opts->autofs_mobject_map,
697 : SDAP_OPTS_AUTOFS_MAP, NULL,
698 0 : &state->attrs, NULL);
699 0 : if (ret != EOK) {
700 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build attributes from map\n");
701 0 : ret = ENOMEM;
702 0 : goto fail;
703 : }
704 :
705 0 : subreq = sdap_get_automntmap_send(state, ev, dom,
706 0 : state->opts,
707 0 : state->opts->sdom->autofs_search_bases,
708 0 : state->sh,
709 0 : state->attrs, state->filter,
710 0 : dp_opt_get_int(state->opts->basic,
711 : SDAP_SEARCH_TIMEOUT));
712 0 : if (!subreq) {
713 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
714 0 : ret = ENOMEM;
715 0 : goto fail;
716 : }
717 0 : tevent_req_set_callback(subreq, sdap_autofs_setautomntent_done, req);
718 0 : return req;
719 :
720 : fail:
721 0 : tevent_req_error(req, ret);
722 0 : tevent_req_post(req, ev);
723 0 : return req;
724 : }
725 :
726 : static errno_t
727 : sdap_autofs_setautomntent_save(struct tevent_req *req);
728 :
729 : static void
730 0 : sdap_autofs_setautomntent_done(struct tevent_req *subreq)
731 : {
732 : errno_t ret;
733 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
734 : struct tevent_req);
735 0 : struct sdap_autofs_setautomntent_state *state = tevent_req_data(req,
736 : struct sdap_autofs_setautomntent_state);
737 :
738 0 : ret = sdap_get_automntmap_recv(subreq, state, &state->map,
739 : &state->entries_count, &state->entries);
740 0 : talloc_zfree(subreq);
741 0 : if (ret != EOK) {
742 0 : if (ret == ENOENT) {
743 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not find automount map\n");
744 : } else {
745 0 : DEBUG(SSSDBG_OP_FAILURE,
746 : "sdap_get_automntmap_recv failed [%d]: %s\n",
747 : ret, strerror(ret));
748 : }
749 0 : tevent_req_error(req, ret);
750 0 : return;
751 : }
752 :
753 0 : ret = sdap_autofs_setautomntent_save(req);
754 0 : if (ret != EOK) {
755 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not save automount map\n");
756 0 : tevent_req_error(req, ret);
757 0 : return;
758 : }
759 :
760 0 : state->dp_error = DP_ERR_OK;
761 0 : tevent_req_done(req);
762 0 : return;
763 : }
764 :
765 : static errno_t
766 0 : sdap_autofs_setautomntent_save(struct tevent_req *req)
767 : {
768 0 : struct sdap_autofs_setautomntent_state *state = tevent_req_data(req,
769 : struct sdap_autofs_setautomntent_state);
770 : errno_t ret, tret;
771 0 : bool in_transaction = false;
772 : TALLOC_CTX *tmp_ctx;
773 0 : struct ldb_message **entries = NULL;
774 : size_t count;
775 : const char *key;
776 : const char *val;
777 : char **sysdb_entrylist;
778 : char **ldap_entrylist;
779 : char **add_entries;
780 : char **del_entries;
781 : size_t i, j;
782 :
783 : hash_table_t *entry_hash;
784 : hash_key_t hkey;
785 : hash_value_t value;
786 : int hret;
787 :
788 0 : tmp_ctx = talloc_new(NULL);
789 0 : if (!tmp_ctx) return ENOMEM;
790 :
791 0 : DEBUG(SSSDBG_TRACE_LIBS,
792 : "Got %zu map entries from LDAP\n", state->entries_count);
793 0 : if (state->entries_count == 0) {
794 : /* No entries for this map in LDAP.
795 : * We need to ensure that there are no entries
796 : * in the sysdb either.
797 : */
798 0 : ldap_entrylist = NULL;
799 : } else {
800 0 : ldap_entrylist = talloc_array(tmp_ctx, char *,
801 : state->entries_count+1);
802 0 : if (!ldap_entrylist) {
803 0 : ret = ENOMEM;
804 0 : goto done;
805 : }
806 :
807 0 : ret = sss_hash_create(state, 32, &entry_hash);
808 0 : if (ret) {
809 0 : goto done;
810 : }
811 :
812 : /* Get a list of the map members by DN */
813 0 : for (i=0, j=0; i < state->entries_count; i++) {
814 0 : key = get_autofs_entry_key(state->entries[i], state->opts);
815 0 : val = get_autofs_entry_value(state->entries[i], state->opts);
816 0 : if (!key || !val) {
817 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Malformed entry, skipping\n");
818 0 : continue;
819 : }
820 :
821 0 : ldap_entrylist[j] = sysdb_autofsentry_strdn(ldap_entrylist,
822 : state->dom,
823 : state->mapname,
824 : key, val);
825 0 : if (!ldap_entrylist[j]) {
826 0 : ret = ENOMEM;
827 0 : goto done;
828 : }
829 :
830 0 : hkey.type = HASH_KEY_STRING;
831 0 : hkey.str = ldap_entrylist[j];
832 0 : value.type = HASH_VALUE_PTR;
833 0 : value.ptr = state->entries[i];
834 :
835 0 : hret = hash_enter(entry_hash, &hkey, &value);
836 0 : if (hret != HASH_SUCCESS) {
837 0 : ret = EIO;
838 0 : goto done;
839 : }
840 :
841 0 : j++;
842 : }
843 : /* terminate array with NULL after the last retrieved entry */
844 0 : ldap_entrylist[j] = NULL;
845 : }
846 :
847 0 : ret = sysdb_autofs_entries_by_map(tmp_ctx, state->dom, state->mapname,
848 : &count, &entries);
849 0 : if (ret != EOK && ret != ENOENT) {
850 0 : DEBUG(SSSDBG_OP_FAILURE,
851 : "cache lookup for the map failed [%d]: %s\n",
852 : ret, strerror(ret));
853 0 : goto done;
854 : }
855 :
856 0 : DEBUG(SSSDBG_TRACE_LIBS, "Got %zu map entries from sysdb\n", count);
857 0 : if (count == 0) {
858 : /* No map members for this map in sysdb currently */
859 0 : sysdb_entrylist = NULL;
860 : } else {
861 0 : sysdb_entrylist = talloc_array(state, char *, count+1);
862 0 : if (!sysdb_entrylist) {
863 0 : ret = ENOMEM;
864 0 : goto done;
865 : }
866 :
867 : /* Get a list of the map members by DN */
868 0 : for (i=0; i < count; i++) {
869 0 : sysdb_entrylist[i] = talloc_strdup(sysdb_entrylist,
870 0 : ldb_dn_get_linearized(entries[i]->dn));
871 0 : if (!sysdb_entrylist[i]) {
872 0 : ret = ENOMEM;
873 0 : goto done;
874 : }
875 : }
876 0 : sysdb_entrylist[count] = NULL;
877 : }
878 :
879 : /* Find the differences between the sysdb and LDAP lists
880 : * Entries in the sysdb only must be removed.
881 : */
882 0 : ret = diff_string_lists(tmp_ctx, ldap_entrylist, sysdb_entrylist,
883 : &add_entries, &del_entries, NULL);
884 0 : if (ret != EOK) goto done;
885 :
886 0 : ret = sysdb_transaction_start(state->sysdb);
887 0 : if (ret != EOK) {
888 0 : DEBUG(SSSDBG_CRIT_FAILURE,
889 : "Cannot start sysdb transaction [%d]: %s\n",
890 : ret, strerror(ret));
891 0 : goto done;
892 : }
893 0 : in_transaction = true;
894 :
895 : /* Save the map itself */
896 0 : ret = save_autofs_map(state->dom, state->opts, state->map);
897 0 : if (ret != EOK) {
898 0 : DEBUG(SSSDBG_OP_FAILURE,
899 : "Cannot save autofs map entry [%d]: %s\n",
900 : ret, strerror(ret));
901 0 : goto done;
902 : }
903 :
904 : /* Create entries that don't exist yet */
905 0 : if (add_entries && add_entries[0]) {
906 0 : ret = save_autofs_entries(state->dom, state->opts,
907 : state->mapname, add_entries,
908 : entry_hash);
909 0 : if (ret != EOK) {
910 0 : DEBUG(SSSDBG_OP_FAILURE,
911 : "Cannot save autofs entries [%d]: %s\n",
912 : ret, strerror(ret));
913 0 : goto done;
914 : }
915 : }
916 :
917 : /* Delete entries that don't exist anymore */
918 0 : if (del_entries && del_entries[0]) {
919 0 : ret = del_autofs_entries(state->dom, del_entries);
920 0 : if (ret != EOK) {
921 0 : DEBUG(SSSDBG_OP_FAILURE,
922 : "Cannot delete autofs entries [%d]: %s\n",
923 : ret, strerror(ret));
924 0 : goto done;
925 : }
926 : }
927 :
928 :
929 0 : ret = sysdb_transaction_commit(state->sysdb);
930 0 : if (ret != EOK) {
931 0 : DEBUG(SSSDBG_CRIT_FAILURE,
932 : "Cannot commit sysdb transaction [%d]: %s\n",
933 : ret, strerror(ret));
934 0 : goto done;
935 : }
936 0 : in_transaction = false;
937 :
938 0 : ret = EOK;
939 : done:
940 0 : if (in_transaction) {
941 0 : tret = sysdb_transaction_cancel(state->sysdb);
942 0 : if (tret != EOK) {
943 0 : DEBUG(SSSDBG_CRIT_FAILURE,
944 : "Cannot cancel sysdb transaction [%d]: %s\n",
945 : ret, strerror(ret));
946 : }
947 : }
948 0 : talloc_zfree(tmp_ctx);
949 0 : return ret;
950 : }
951 :
952 : errno_t
953 0 : sdap_autofs_setautomntent_recv(struct tevent_req *req)
954 : {
955 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
956 0 : return EOK;
957 : }
958 :
|