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_get_id_specific_filter(state,
315 0 : state->base_filter,
316 0 : state->search_bases[state->base_iter]->filter);
317 0 : if (!state->filter) {
318 0 : return ENOMEM;
319 : }
320 :
321 0 : DEBUG(SSSDBG_TRACE_FUNC,
322 : "Searching for automount map entries with base [%s]\n",
323 : state->search_bases[state->base_iter]->basedn);
324 :
325 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
326 : state->orig_dn,
327 0 : state->search_bases[state->base_iter]->scope,
328 0 : state->filter, state->attrs,
329 0 : state->opts->autofs_entry_map,
330 : SDAP_OPTS_AUTOFS_ENTRY,
331 : state->timeout, true);
332 0 : if (!subreq) {
333 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot start search for entries\n");
334 0 : return EIO;
335 : }
336 0 : tevent_req_set_callback(subreq, automntmaps_process_members_done, req);
337 :
338 0 : return EOK;
339 : }
340 :
341 : static void
342 0 : automntmaps_process_members_done(struct tevent_req *subreq)
343 : {
344 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
345 : struct tevent_req);
346 0 : struct automntmaps_process_members_state *state =
347 0 : tevent_req_data(req, struct automntmaps_process_members_state);
348 : errno_t ret;
349 : struct sysdb_attrs **entries;
350 : size_t entries_count, i;
351 :
352 0 : ret = sdap_get_generic_recv(subreq, state,
353 : &entries_count, &entries);
354 0 : talloc_zfree(subreq);
355 0 : if (ret) {
356 0 : tevent_req_error(req, ret);
357 0 : return;
358 : }
359 :
360 0 : if (entries_count > 0) {
361 0 : state->entries = talloc_realloc(state, state->entries,
362 : struct sysdb_attrs *,
363 : state->entries_count + entries_count + 1);
364 0 : if (state->entries == NULL) {
365 0 : tevent_req_error(req, ENOMEM);
366 0 : return;
367 : }
368 :
369 0 : for (i=0; i < entries_count; i++) {
370 0 : state->entries[state->entries_count + i] =
371 0 : talloc_steal(state->entries, entries[i]);
372 : }
373 :
374 0 : state->entries_count += entries_count;
375 0 : state->entries[state->entries_count] = NULL;
376 : }
377 :
378 0 : state->base_iter++;
379 0 : if (state->search_bases[state->base_iter]) {
380 0 : ret = automntmaps_process_members_next_base(req);
381 0 : if (ret != EOK) {
382 0 : tevent_req_error(req, ret);
383 0 : return;
384 : }
385 : }
386 :
387 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "No more search bases to try\n");
388 :
389 0 : DEBUG(SSSDBG_TRACE_FUNC,
390 : "Search for autofs entries, returned %zu results.\n",
391 : state->entries_count);
392 :
393 0 : tevent_req_done(req);
394 0 : return;
395 : }
396 :
397 : static errno_t
398 0 : automntmaps_process_members_recv(struct tevent_req *req,
399 : TALLOC_CTX *mem_ctx,
400 : size_t *entries_count,
401 : struct sysdb_attrs ***entries)
402 : {
403 : struct automntmaps_process_members_state *state;
404 0 : state = tevent_req_data(req, struct automntmaps_process_members_state);
405 :
406 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
407 :
408 0 : if (entries_count) {
409 0 : *entries_count = state->entries_count;
410 : }
411 :
412 0 : if (entries) {
413 0 : *entries = talloc_steal(mem_ctx, state->entries);
414 : }
415 :
416 0 : return EOK;
417 : }
418 :
419 : struct sdap_get_automntmap_state {
420 : struct tevent_context *ev;
421 : struct sdap_options *opts;
422 : struct sdap_handle *sh;
423 : struct sss_domain_info *dom;
424 : const char **attrs;
425 : const char *base_filter;
426 : char *filter;
427 : int timeout;
428 :
429 : char *higher_timestamp;
430 :
431 : struct sysdb_attrs **map;
432 : size_t count;
433 :
434 : struct sysdb_attrs **entries;
435 : size_t entries_count;
436 :
437 : size_t base_iter;
438 : struct sdap_search_base **search_bases;
439 : };
440 :
441 : static errno_t
442 : sdap_get_automntmap_next_base(struct tevent_req *req);
443 : static void
444 : sdap_get_automntmap_process(struct tevent_req *subreq);
445 :
446 : static struct tevent_req *
447 0 : sdap_get_automntmap_send(TALLOC_CTX *memctx,
448 : struct tevent_context *ev,
449 : struct sss_domain_info *dom,
450 : struct sdap_options *opts,
451 : struct sdap_search_base **search_bases,
452 : struct sdap_handle *sh,
453 : const char **attrs,
454 : const char *filter,
455 : int timeout)
456 : {
457 : errno_t ret;
458 : struct tevent_req *req;
459 : struct sdap_get_automntmap_state *state;
460 :
461 0 : req = tevent_req_create(memctx, &state, struct sdap_get_automntmap_state);
462 0 : if (!req) return NULL;
463 :
464 0 : state->ev = ev;
465 0 : state->opts = opts;
466 0 : state->dom = dom;
467 0 : state->sh = sh;
468 0 : state->attrs = attrs;
469 0 : state->higher_timestamp = NULL;
470 0 : state->map = NULL;
471 0 : state->count = 0;
472 0 : state->timeout = timeout;
473 0 : state->base_filter = filter;
474 0 : state->base_iter = 0;
475 0 : state->search_bases = search_bases;
476 :
477 0 : ret = sdap_get_automntmap_next_base(req);
478 0 : if (ret != EOK) {
479 0 : tevent_req_error(req, ret);
480 0 : tevent_req_post(req, state->ev);
481 : }
482 0 : return req;
483 : }
484 :
485 : static errno_t
486 0 : sdap_get_automntmap_next_base(struct tevent_req *req)
487 : {
488 : struct tevent_req *subreq;
489 : struct sdap_get_automntmap_state *state;
490 :
491 0 : state = tevent_req_data(req, struct sdap_get_automntmap_state);
492 :
493 0 : talloc_zfree(state->filter);
494 0 : state->filter = sdap_get_id_specific_filter(state,
495 : state->base_filter,
496 0 : state->search_bases[state->base_iter]->filter);
497 0 : if (!state->filter) {
498 0 : return ENOMEM;
499 : }
500 :
501 0 : DEBUG(SSSDBG_TRACE_FUNC,
502 : "Searching for automount maps with base [%s]\n",
503 : state->search_bases[state->base_iter]->basedn);
504 :
505 0 : subreq = sdap_get_generic_send(
506 : state, state->ev, state->opts, state->sh,
507 0 : state->search_bases[state->base_iter]->basedn,
508 0 : state->search_bases[state->base_iter]->scope,
509 0 : state->filter, state->attrs,
510 0 : state->opts->autofs_mobject_map, SDAP_OPTS_AUTOFS_MAP,
511 : state->timeout,
512 : false);
513 0 : if (!subreq) {
514 0 : return EIO;
515 : }
516 0 : tevent_req_set_callback(subreq, sdap_get_automntmap_process, req);
517 :
518 0 : return EOK;
519 : }
520 :
521 : static void
522 : sdap_get_automntmap_done(struct tevent_req *subreq);
523 :
524 : static void
525 0 : sdap_get_automntmap_process(struct tevent_req *subreq)
526 : {
527 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
528 : struct tevent_req);
529 0 : struct sdap_get_automntmap_state *state = tevent_req_data(req,
530 : struct sdap_get_automntmap_state);
531 : errno_t ret;
532 :
533 0 : ret = sdap_get_generic_recv(subreq, state,
534 : &state->count, &state->map);
535 0 : talloc_zfree(subreq);
536 0 : if (ret) {
537 0 : tevent_req_error(req, ret);
538 0 : return;
539 : }
540 :
541 0 : DEBUG(SSSDBG_TRACE_FUNC,
542 : "Search for autofs maps, returned %zu results.\n", state->count);
543 :
544 0 : if (state->count == 0) {
545 : /* No maps found in this search */
546 0 : state->base_iter++;
547 0 : if (state->search_bases[state->base_iter]) {
548 : /* There are more search bases to try */
549 0 : ret = sdap_get_automntmap_next_base(req);
550 0 : if (ret != EOK) {
551 0 : tevent_req_error(req, ENOENT);
552 : }
553 0 : return;
554 : }
555 :
556 0 : tevent_req_error(req, ENOENT);
557 0 : return;
558 0 : } else if (state->count > 1) {
559 0 : DEBUG(SSSDBG_OP_FAILURE,
560 : "The search yielded more than one autofs map\n");
561 0 : tevent_req_error(req, EIO);
562 0 : return;
563 : }
564 :
565 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Processing autofs maps\n");
566 0 : subreq = automntmaps_process_members_send(state, state->ev, state->opts,
567 : state->sh, state->dom,
568 : state->search_bases,
569 : state->timeout,
570 0 : state->map[0]);
571 0 : if (!subreq) {
572 0 : tevent_req_error(req, ENOMEM);
573 0 : return;
574 : }
575 0 : tevent_req_set_callback(subreq, sdap_get_automntmap_done, req);
576 :
577 0 : return;
578 : }
579 :
580 : static void
581 0 : sdap_get_automntmap_done(struct tevent_req *subreq)
582 : {
583 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
584 : struct tevent_req);
585 0 : struct sdap_get_automntmap_state *state = tevent_req_data(req,
586 : struct sdap_get_automntmap_state);
587 : errno_t ret;
588 :
589 0 : ret = automntmaps_process_members_recv(subreq, state, &state->entries_count,
590 : &state->entries);
591 0 : talloc_zfree(subreq);
592 0 : if (ret != EOK) {
593 0 : tevent_req_error(req, ret);
594 0 : return;
595 : }
596 :
597 0 : DEBUG(SSSDBG_TRACE_FUNC, "automount map members received\n");
598 0 : tevent_req_done(req);
599 0 : return;
600 : }
601 :
602 : static errno_t
603 0 : sdap_get_automntmap_recv(struct tevent_req *req,
604 : TALLOC_CTX *mem_ctx,
605 : struct sysdb_attrs **map,
606 : size_t *entries_count,
607 : struct sysdb_attrs ***entries)
608 : {
609 0 : struct sdap_get_automntmap_state *state = tevent_req_data(req,
610 : struct sdap_get_automntmap_state);
611 :
612 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
613 :
614 0 : if (map) {
615 0 : *map = talloc_steal(mem_ctx, state->map[0]);
616 : }
617 :
618 0 : if (entries_count) {
619 0 : *entries_count = state->entries_count;
620 : }
621 :
622 0 : if (entries) {
623 0 : *entries = talloc_steal(mem_ctx, state->entries);
624 : }
625 :
626 0 : return EOK;
627 : }
628 :
629 : struct sdap_autofs_setautomntent_state {
630 : char *filter;
631 : const char **attrs;
632 : struct sdap_options *opts;
633 : struct sdap_handle *sh;
634 : struct sysdb_ctx *sysdb;
635 : struct sdap_id_op *sdap_op;
636 : struct sss_domain_info *dom;
637 :
638 : const char *mapname;
639 : struct sysdb_attrs *map;
640 : struct sysdb_attrs **entries;
641 : size_t entries_count;
642 :
643 : int dp_error;
644 : };
645 :
646 : static void
647 : sdap_autofs_setautomntent_done(struct tevent_req *subreq);
648 :
649 : struct tevent_req *
650 0 : sdap_autofs_setautomntent_send(TALLOC_CTX *memctx,
651 : struct tevent_context *ev,
652 : struct sss_domain_info *dom,
653 : struct sysdb_ctx *sysdb,
654 : struct sdap_handle *sh,
655 : struct sdap_id_op *op,
656 : struct sdap_options *opts,
657 : const char *mapname)
658 : {
659 : struct tevent_req *req;
660 : struct tevent_req *subreq;
661 : struct sdap_autofs_setautomntent_state *state;
662 : char *clean_mapname;
663 : errno_t ret;
664 :
665 0 : req = tevent_req_create(memctx, &state,
666 : struct sdap_autofs_setautomntent_state);
667 0 : if (!req) return NULL;
668 :
669 0 : if (!mapname) {
670 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No map name given\n");
671 0 : ret = EINVAL;
672 0 : goto fail;
673 : }
674 :
675 0 : state->sh = sh;
676 0 : state->sysdb = sysdb;
677 0 : state->opts = opts;
678 0 : state->sdap_op = op;
679 0 : state->dom = dom;
680 0 : state->mapname = mapname;
681 :
682 0 : ret = sss_filter_sanitize(state, mapname, &clean_mapname);
683 0 : if (ret != EOK) {
684 0 : goto fail;
685 : }
686 :
687 0 : state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
688 0 : state->opts->autofs_mobject_map[SDAP_AT_AUTOFS_MAP_NAME].name,
689 : clean_mapname,
690 0 : state->opts->autofs_mobject_map[SDAP_OC_AUTOFS_MAP].name);
691 0 : if (!state->filter) {
692 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build filter\n");
693 0 : ret = ENOMEM;
694 0 : goto fail;
695 : }
696 0 : talloc_free(clean_mapname);
697 :
698 0 : ret = build_attrs_from_map(state, state->opts->autofs_mobject_map,
699 : SDAP_OPTS_AUTOFS_MAP, NULL,
700 0 : &state->attrs, NULL);
701 0 : if (ret != EOK) {
702 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build attributes from map\n");
703 0 : ret = ENOMEM;
704 0 : goto fail;
705 : }
706 :
707 0 : subreq = sdap_get_automntmap_send(state, ev, dom,
708 0 : state->opts,
709 0 : state->opts->sdom->autofs_search_bases,
710 0 : state->sh,
711 0 : state->attrs, state->filter,
712 0 : dp_opt_get_int(state->opts->basic,
713 : SDAP_SEARCH_TIMEOUT));
714 0 : if (!subreq) {
715 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
716 0 : ret = ENOMEM;
717 0 : goto fail;
718 : }
719 0 : tevent_req_set_callback(subreq, sdap_autofs_setautomntent_done, req);
720 0 : return req;
721 :
722 : fail:
723 0 : tevent_req_error(req, ret);
724 0 : tevent_req_post(req, ev);
725 0 : return req;
726 : }
727 :
728 : static errno_t
729 : sdap_autofs_setautomntent_save(struct tevent_req *req);
730 :
731 : static void
732 0 : sdap_autofs_setautomntent_done(struct tevent_req *subreq)
733 : {
734 : errno_t ret;
735 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
736 : struct tevent_req);
737 0 : struct sdap_autofs_setautomntent_state *state = tevent_req_data(req,
738 : struct sdap_autofs_setautomntent_state);
739 :
740 0 : ret = sdap_get_automntmap_recv(subreq, state, &state->map,
741 : &state->entries_count, &state->entries);
742 0 : talloc_zfree(subreq);
743 0 : if (ret != EOK) {
744 0 : if (ret == ENOENT) {
745 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not find automount map\n");
746 : } else {
747 0 : DEBUG(SSSDBG_OP_FAILURE,
748 : "sdap_get_automntmap_recv failed [%d]: %s\n",
749 : ret, strerror(ret));
750 : }
751 0 : tevent_req_error(req, ret);
752 0 : return;
753 : }
754 :
755 0 : ret = sdap_autofs_setautomntent_save(req);
756 0 : if (ret != EOK) {
757 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not save automount map\n");
758 0 : tevent_req_error(req, ret);
759 0 : return;
760 : }
761 :
762 0 : state->dp_error = DP_ERR_OK;
763 0 : tevent_req_done(req);
764 0 : return;
765 : }
766 :
767 : static errno_t
768 0 : sdap_autofs_setautomntent_save(struct tevent_req *req)
769 : {
770 0 : struct sdap_autofs_setautomntent_state *state = tevent_req_data(req,
771 : struct sdap_autofs_setautomntent_state);
772 : errno_t ret, tret;
773 0 : bool in_transaction = false;
774 : TALLOC_CTX *tmp_ctx;
775 0 : struct ldb_message **entries = NULL;
776 : size_t count;
777 : const char *key;
778 : const char *val;
779 : char **sysdb_entrylist;
780 : char **ldap_entrylist;
781 : char **add_entries;
782 : char **del_entries;
783 : size_t i, j;
784 :
785 : hash_table_t *entry_hash;
786 : hash_key_t hkey;
787 : hash_value_t value;
788 : int hret;
789 :
790 0 : tmp_ctx = talloc_new(NULL);
791 0 : if (!tmp_ctx) return ENOMEM;
792 :
793 0 : DEBUG(SSSDBG_TRACE_LIBS,
794 : "Got %zu map entries from LDAP\n", state->entries_count);
795 0 : if (state->entries_count == 0) {
796 : /* No entries for this map in LDAP.
797 : * We need to ensure that there are no entries
798 : * in the sysdb either.
799 : */
800 0 : ldap_entrylist = NULL;
801 : } else {
802 0 : ldap_entrylist = talloc_array(tmp_ctx, char *,
803 : state->entries_count+1);
804 0 : if (!ldap_entrylist) {
805 0 : ret = ENOMEM;
806 0 : goto done;
807 : }
808 :
809 0 : ret = sss_hash_create(state, 32, &entry_hash);
810 0 : if (ret) {
811 0 : goto done;
812 : }
813 :
814 : /* Get a list of the map members by DN */
815 0 : for (i=0, j=0; i < state->entries_count; i++) {
816 0 : key = get_autofs_entry_key(state->entries[i], state->opts);
817 0 : val = get_autofs_entry_value(state->entries[i], state->opts);
818 0 : if (!key || !val) {
819 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Malformed entry, skipping\n");
820 0 : continue;
821 : }
822 :
823 0 : ldap_entrylist[j] = sysdb_autofsentry_strdn(ldap_entrylist,
824 : state->dom,
825 : state->mapname,
826 : key, val);
827 0 : if (!ldap_entrylist[j]) {
828 0 : ret = ENOMEM;
829 0 : goto done;
830 : }
831 :
832 0 : hkey.type = HASH_KEY_STRING;
833 0 : hkey.str = ldap_entrylist[j];
834 0 : value.type = HASH_VALUE_PTR;
835 0 : value.ptr = state->entries[i];
836 :
837 0 : hret = hash_enter(entry_hash, &hkey, &value);
838 0 : if (hret != HASH_SUCCESS) {
839 0 : ret = EIO;
840 0 : goto done;
841 : }
842 :
843 0 : j++;
844 : }
845 : /* terminate array with NULL after the last retrieved entry */
846 0 : ldap_entrylist[j] = NULL;
847 : }
848 :
849 0 : ret = sysdb_autofs_entries_by_map(tmp_ctx, state->dom, state->mapname,
850 : &count, &entries);
851 0 : if (ret != EOK && ret != ENOENT) {
852 0 : DEBUG(SSSDBG_OP_FAILURE,
853 : "cache lookup for the map failed [%d]: %s\n",
854 : ret, strerror(ret));
855 0 : goto done;
856 : }
857 :
858 0 : DEBUG(SSSDBG_TRACE_LIBS, "Got %zu map entries from sysdb\n", count);
859 0 : if (count == 0) {
860 : /* No map members for this map in sysdb currently */
861 0 : sysdb_entrylist = NULL;
862 : } else {
863 0 : sysdb_entrylist = talloc_array(state, char *, count+1);
864 0 : if (!sysdb_entrylist) {
865 0 : ret = ENOMEM;
866 0 : goto done;
867 : }
868 :
869 : /* Get a list of the map members by DN */
870 0 : for (i=0; i < count; i++) {
871 0 : sysdb_entrylist[i] = talloc_strdup(sysdb_entrylist,
872 0 : ldb_dn_get_linearized(entries[i]->dn));
873 0 : if (!sysdb_entrylist[i]) {
874 0 : ret = ENOMEM;
875 0 : goto done;
876 : }
877 : }
878 0 : sysdb_entrylist[count] = NULL;
879 : }
880 :
881 : /* Find the differences between the sysdb and LDAP lists
882 : * Entries in the sysdb only must be removed.
883 : */
884 0 : ret = diff_string_lists(tmp_ctx, ldap_entrylist, sysdb_entrylist,
885 : &add_entries, &del_entries, NULL);
886 0 : if (ret != EOK) goto done;
887 :
888 0 : ret = sysdb_transaction_start(state->sysdb);
889 0 : if (ret != EOK) {
890 0 : DEBUG(SSSDBG_CRIT_FAILURE,
891 : "Cannot start sysdb transaction [%d]: %s\n",
892 : ret, strerror(ret));
893 0 : goto done;
894 : }
895 0 : in_transaction = true;
896 :
897 : /* Save the map itself */
898 0 : ret = save_autofs_map(state->dom, state->opts, state->map);
899 0 : if (ret != EOK) {
900 0 : DEBUG(SSSDBG_OP_FAILURE,
901 : "Cannot save autofs map entry [%d]: %s\n",
902 : ret, strerror(ret));
903 0 : goto done;
904 : }
905 :
906 : /* Create entries that don't exist yet */
907 0 : if (add_entries && add_entries[0]) {
908 0 : ret = save_autofs_entries(state->dom, state->opts,
909 : state->mapname, add_entries,
910 : entry_hash);
911 0 : if (ret != EOK) {
912 0 : DEBUG(SSSDBG_OP_FAILURE,
913 : "Cannot save autofs entries [%d]: %s\n",
914 : ret, strerror(ret));
915 0 : goto done;
916 : }
917 : }
918 :
919 : /* Delete entries that don't exist anymore */
920 0 : if (del_entries && del_entries[0]) {
921 0 : ret = del_autofs_entries(state->dom, del_entries);
922 0 : if (ret != EOK) {
923 0 : DEBUG(SSSDBG_OP_FAILURE,
924 : "Cannot delete autofs entries [%d]: %s\n",
925 : ret, strerror(ret));
926 0 : goto done;
927 : }
928 : }
929 :
930 :
931 0 : ret = sysdb_transaction_commit(state->sysdb);
932 0 : if (ret != EOK) {
933 0 : DEBUG(SSSDBG_CRIT_FAILURE,
934 : "Cannot commit sysdb transaction [%d]: %s\n",
935 : ret, strerror(ret));
936 0 : goto done;
937 : }
938 0 : in_transaction = false;
939 :
940 0 : ret = EOK;
941 : done:
942 0 : if (in_transaction) {
943 0 : tret = sysdb_transaction_cancel(state->sysdb);
944 0 : if (tret != EOK) {
945 0 : DEBUG(SSSDBG_CRIT_FAILURE,
946 : "Cannot cancel sysdb transaction [%d]: %s\n",
947 : ret, strerror(ret));
948 : }
949 : }
950 0 : talloc_zfree(tmp_ctx);
951 0 : return ret;
952 : }
953 :
954 : errno_t
955 0 : sdap_autofs_setautomntent_recv(struct tevent_req *req)
956 : {
957 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
958 0 : return EOK;
959 : }
960 :
|