Line data Source code
1 : /*
2 : SSSD
3 :
4 : Async LDAP Helper routines for netgroups
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2010 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 "providers/ldap/ldap_common.h"
29 :
30 0 : bool is_dn(const char *str)
31 : {
32 : int ret;
33 : LDAPDN dn;
34 :
35 0 : ret = ldap_str2dn(str, &dn, LDAP_DN_FORMAT_LDAPV3);
36 0 : ldap_dnfree(dn);
37 :
38 0 : return (ret == LDAP_SUCCESS ? true : false);
39 : }
40 :
41 0 : static errno_t sdap_save_netgroup(TALLOC_CTX *memctx,
42 : struct sss_domain_info *dom,
43 : struct sdap_options *opts,
44 : struct sysdb_attrs *attrs,
45 : char **_timestamp,
46 : time_t now)
47 : {
48 : struct ldb_message_element *el;
49 : struct sysdb_attrs *netgroup_attrs;
50 0 : const char *name = NULL;
51 : int ret;
52 0 : char *timestamp = NULL;
53 0 : char **missing = NULL;
54 :
55 0 : ret = sdap_get_netgroup_primary_name(memctx, opts, attrs, dom, &name);
56 0 : if (ret != EOK) {
57 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to get netgroup name\n");
58 0 : goto fail;
59 : }
60 :
61 0 : DEBUG(SSSDBG_TRACE_FUNC, "Processing netgroup %s\n", name);
62 :
63 0 : netgroup_attrs = sysdb_new_attrs(memctx);
64 0 : if (!netgroup_attrs) {
65 0 : ret = ENOMEM;
66 0 : goto fail;
67 : }
68 :
69 0 : ret = sdap_attrs_add_string(attrs, SYSDB_ORIG_DN,
70 : "original DN",
71 : name, netgroup_attrs);
72 0 : if (ret != EOK) {
73 0 : goto fail;
74 : }
75 :
76 0 : ret = sysdb_attrs_get_el(attrs,
77 0 : opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name,
78 : &el);
79 0 : if (ret) {
80 0 : goto fail;
81 : }
82 0 : if (el->num_values == 0) {
83 0 : DEBUG(SSSDBG_TRACE_LIBS,
84 : "Original mod-Timestamp is not available for [%s].\n",
85 : name);
86 : } else {
87 0 : ret = sysdb_attrs_add_string(netgroup_attrs,
88 0 : opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name,
89 0 : (const char*)el->values[0].data);
90 0 : if (ret) {
91 0 : goto fail;
92 : }
93 0 : timestamp = talloc_strdup(memctx, (const char*)el->values[0].data);
94 0 : if (!timestamp) {
95 0 : ret = ENOMEM;
96 0 : goto fail;
97 : }
98 : }
99 :
100 0 : ret = sdap_attrs_add_list(attrs,
101 : opts->netgroup_map[SDAP_AT_NETGROUP_TRIPLE].sys_name,
102 : "netgroup triple",
103 : name, netgroup_attrs);
104 0 : if (ret != EOK) {
105 0 : goto fail;
106 : }
107 :
108 0 : ret = sdap_attrs_add_list(attrs,
109 : opts->netgroup_map[SDAP_AT_NETGROUP_MEMBER].sys_name,
110 : "original members",
111 : name, netgroup_attrs);
112 0 : if (ret != EOK) {
113 0 : goto fail;
114 : }
115 :
116 0 : ret = sdap_attrs_add_list(attrs, SYSDB_NETGROUP_MEMBER,
117 : "members", name, netgroup_attrs);
118 0 : if (ret != EOK) {
119 0 : goto fail;
120 : }
121 :
122 0 : DEBUG(SSSDBG_TRACE_FUNC, "Storing info for netgroup %s\n", name);
123 :
124 0 : ret = sdap_save_all_names(name, attrs, dom,
125 : netgroup_attrs);
126 0 : if (ret != EOK) {
127 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save netgroup names\n");
128 0 : goto fail;
129 : }
130 :
131 : /* Make sure that any attributes we requested from LDAP that we
132 : * did not receive are also removed from the sysdb
133 : */
134 0 : ret = list_missing_attrs(attrs, opts->netgroup_map, SDAP_OPTS_NETGROUP,
135 : attrs, &missing);
136 0 : if (ret != EOK) {
137 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to list missing attributes\n");
138 0 : goto fail;
139 : }
140 :
141 0 : ret = sysdb_add_netgroup(dom, name, NULL, netgroup_attrs, missing,
142 0 : dom->netgroup_timeout, now);
143 0 : if (ret) goto fail;
144 :
145 0 : if (_timestamp) {
146 0 : *_timestamp = timestamp;
147 : }
148 :
149 0 : return EOK;
150 :
151 : fail:
152 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to save netgroup %s\n", name);
153 0 : return ret;
154 : }
155 :
156 0 : errno_t update_dn_list(struct dn_item *dn_list, const size_t count,
157 : struct ldb_message **res, bool *all_resolved)
158 : {
159 : struct dn_item *dn_item;
160 : size_t c;
161 : const char *dn;
162 : const char *cn;
163 0 : bool not_resolved = false;
164 :
165 0 : *all_resolved = false;
166 :
167 0 : DLIST_FOR_EACH(dn_item, dn_list) {
168 0 : if (dn_item->cn != NULL) {
169 0 : continue;
170 : }
171 :
172 0 : for(c = 0; c < count; c++) {
173 0 : dn = ldb_msg_find_attr_as_string(res[c], SYSDB_ORIG_DN, NULL);
174 0 : if (dn == NULL) {
175 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Missing original DN.\n");
176 0 : return EINVAL;
177 : }
178 0 : if (strcmp(dn, dn_item->dn) == 0) {
179 0 : DEBUG(SSSDBG_TRACE_ALL,
180 : "Found matching entry for [%s].\n", dn_item->dn);
181 0 : cn = ldb_msg_find_attr_as_string(res[c], SYSDB_NAME, NULL);
182 0 : if (cn == NULL) {
183 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Missing name.\n");
184 0 : return EINVAL;
185 : }
186 0 : dn_item->cn = talloc_strdup(dn_item, cn);
187 0 : break;
188 : }
189 : }
190 :
191 0 : if (dn_item->cn == NULL) {
192 0 : not_resolved = true;
193 : }
194 : }
195 :
196 0 : *all_resolved = !not_resolved;
197 :
198 0 : return EOK;
199 : }
200 :
201 : struct netgr_translate_members_state {
202 : struct tevent_context *ev;
203 : struct sdap_options *opts;
204 : struct sdap_handle *sh;
205 :
206 : struct sysdb_attrs **netgroups;
207 : size_t count;
208 : struct dn_item *dn_list;
209 : struct dn_item *dn_item;
210 : struct dn_item *dn_idx;
211 : };
212 :
213 : static errno_t netgr_translate_members_ldap_step(struct tevent_req *req);
214 : static void netgr_translate_members_ldap_done(struct tevent_req *subreq);
215 :
216 0 : struct tevent_req *netgr_translate_members_send(TALLOC_CTX *memctx,
217 : struct tevent_context *ev,
218 : struct sdap_options *opts,
219 : struct sdap_handle *sh,
220 : struct sss_domain_info *dom,
221 : struct sysdb_ctx *sysdb,
222 : const size_t count,
223 : struct sysdb_attrs **netgroups)
224 : {
225 : struct tevent_req *req;
226 : struct netgr_translate_members_state *state;
227 : size_t c;
228 : size_t mc;
229 : const char **member_list;
230 : size_t sysdb_count;
231 : int ret;
232 : struct ldb_message **sysdb_res;
233 : struct dn_item *dn_item;
234 : char *dn_filter;
235 : char *sysdb_filter;
236 : struct ldb_dn *netgr_basedn;
237 : bool all_resolved;
238 0 : const char *cn_attr[] = { SYSDB_NAME, SYSDB_ORIG_DN, NULL };
239 :
240 0 : req = tevent_req_create(memctx, &state,
241 : struct netgr_translate_members_state);
242 0 : if (req == NULL) {
243 0 : return NULL;
244 : }
245 :
246 0 : state->ev = ev;
247 0 : state->opts = opts;
248 0 : state->sh = sh;
249 0 : state->netgroups = netgroups;
250 0 : state->count = count;
251 0 : state->dn_list = NULL;
252 0 : state->dn_item = NULL;
253 0 : state->dn_idx = NULL;
254 :
255 0 : for (c = 0; c < count; c++) {
256 0 : ret = sysdb_attrs_get_string_array(netgroups[c],
257 : SYSDB_ORIG_NETGROUP_MEMBER, state,
258 : &member_list);
259 0 : if (ret != EOK) {
260 0 : DEBUG(SSSDBG_TRACE_LIBS, "Missing netgroup members.\n");
261 0 : continue;
262 : }
263 :
264 0 : for (mc = 0; member_list[mc] != NULL; mc++) {
265 0 : if (is_dn(member_list[mc])) {
266 0 : dn_item = talloc_zero(state, struct dn_item);
267 0 : if (dn_item == NULL) {
268 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
269 0 : ret = ENOMEM;
270 0 : goto fail;
271 : }
272 :
273 0 : DEBUG(SSSDBG_TRACE_ALL,
274 : "Adding [%s] to DN list.\n", member_list[mc]);
275 0 : dn_item->netgroup = netgroups[c];
276 0 : dn_item->dn = member_list[mc];
277 0 : DLIST_ADD(state->dn_list, dn_item);
278 : } else {
279 0 : ret = sysdb_attrs_add_string(netgroups[c], SYSDB_NETGROUP_MEMBER,
280 0 : member_list[mc]);
281 0 : if (ret != EOK) {
282 0 : DEBUG(SSSDBG_CRIT_FAILURE,
283 : "sysdb_attrs_add_string failed.\n");
284 0 : goto fail;
285 : }
286 : }
287 : }
288 : }
289 :
290 0 : if (state->dn_list == NULL) {
291 0 : DEBUG(SSSDBG_TRACE_ALL, "No DNs found among netgroup members.\n");
292 0 : tevent_req_done(req);
293 0 : tevent_req_post(req, ev);
294 0 : return req;
295 : }
296 :
297 0 : dn_filter = talloc_strdup(state, "(|");
298 0 : if (dn_filter == NULL) {
299 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
300 0 : ret = ENOMEM;;
301 0 : goto fail;
302 : }
303 :
304 0 : DLIST_FOR_EACH(dn_item, state->dn_list) {
305 0 : dn_filter = talloc_asprintf_append(dn_filter, "(%s=%s)",
306 : SYSDB_ORIG_DN, dn_item->dn);
307 0 : if (dn_filter == NULL) {
308 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf_append failed.\n");
309 0 : ret = ENOMEM;
310 0 : goto fail;
311 : }
312 : }
313 :
314 0 : dn_filter = talloc_asprintf_append(dn_filter, ")");
315 0 : if (dn_filter == NULL) {
316 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf_append failed.\n");
317 0 : ret = ENOMEM;
318 0 : goto fail;
319 : }
320 :
321 0 : sysdb_filter = talloc_asprintf(state, "(&(%s)%s)", SYSDB_NC, dn_filter);
322 0 : if (sysdb_filter == NULL) {
323 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
324 0 : ret = ENOMEM;
325 0 : goto fail;
326 : }
327 :
328 0 : netgr_basedn = sysdb_netgroup_base_dn(state, dom);
329 0 : if (netgr_basedn == NULL) {
330 0 : ret = ENOMEM;
331 0 : goto fail;
332 : }
333 :
334 0 : ret = sysdb_search_entry(state, sysdb, netgr_basedn, LDB_SCOPE_BASE,
335 : sysdb_filter, cn_attr, &sysdb_count, &sysdb_res);
336 0 : talloc_zfree(netgr_basedn);
337 0 : talloc_zfree(sysdb_filter);
338 0 : if (ret != EOK && ret != ENOENT) {
339 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry failed.\n");
340 0 : goto fail;
341 : }
342 :
343 0 : if (ret == EOK) {
344 0 : ret = update_dn_list(state->dn_list, sysdb_count, sysdb_res,
345 : &all_resolved);
346 0 : if (ret != EOK) {
347 0 : DEBUG(SSSDBG_CRIT_FAILURE, "update_dn_list failed.\n");
348 0 : goto fail;
349 : }
350 :
351 0 : if (all_resolved) {
352 0 : DLIST_FOR_EACH(dn_item, state->dn_list) {
353 0 : ret = sysdb_attrs_add_string(dn_item->netgroup,
354 : SYSDB_NETGROUP_MEMBER,
355 0 : dn_item->cn);
356 0 : if (ret != EOK) {
357 0 : DEBUG(SSSDBG_CRIT_FAILURE,
358 : "sysdb_attrs_add_string failed.\n");
359 0 : goto fail;
360 : }
361 : }
362 :
363 0 : tevent_req_done(req);
364 0 : tevent_req_post(req, ev);
365 0 : return req;
366 : }
367 : }
368 :
369 0 : state->dn_idx = state->dn_list;
370 0 : ret = netgr_translate_members_ldap_step(req);
371 0 : if (ret != EOK && ret != EAGAIN) {
372 0 : DEBUG(SSSDBG_CRIT_FAILURE,
373 : "netgr_translate_members_ldap_step failed.\n");
374 0 : goto fail;
375 : }
376 :
377 0 : if (ret == EOK) {
378 0 : tevent_req_done(req);
379 0 : tevent_req_post(req, ev);
380 : }
381 0 : return req;
382 :
383 : fail:
384 0 : tevent_req_error(req, ret);
385 0 : tevent_req_post(req, ev);
386 0 : return req;
387 : }
388 :
389 : /* netgr_translate_members_ldap_step() returns
390 : * EOK: if everthing is translated, the caller can call tevent_req_done
391 : * EAGAIN: if there are still members waiting to be translated, the caller
392 : * should return to the mainloop
393 : * Exyz: every other return code indicates an error and tevent_req_error
394 : * should be called
395 : */
396 0 : static errno_t netgr_translate_members_ldap_step(struct tevent_req *req)
397 : {
398 0 : struct netgr_translate_members_state *state = tevent_req_data(req,
399 : struct netgr_translate_members_state);
400 : const char **cn_attr;
401 0 : char *filter = NULL;
402 : struct tevent_req *subreq;
403 : int ret;
404 :
405 0 : DLIST_FOR_EACH(state->dn_item, state->dn_idx) {
406 0 : if (state->dn_item->cn == NULL) {
407 0 : break;
408 : }
409 : }
410 0 : if (state->dn_item == NULL) {
411 0 : DLIST_FOR_EACH(state->dn_item, state->dn_list) {
412 0 : ret = sysdb_attrs_add_string(state->dn_item->netgroup,
413 : SYSDB_NETGROUP_MEMBER,
414 0 : state->dn_item->cn);
415 0 : if (ret != EOK) {
416 0 : DEBUG(SSSDBG_CRIT_FAILURE,
417 : "sysdb_attrs_add_string failed.\n");
418 0 : tevent_req_error(req, ret);
419 0 : return ret;
420 : }
421 : }
422 :
423 0 : return EOK;
424 : }
425 :
426 0 : if (!sss_ldap_dn_in_search_bases(state, state->dn_item->dn,
427 0 : state->opts->sdom->netgroup_search_bases,
428 : &filter)) {
429 : /* not in search base, skip it */
430 0 : state->dn_idx = state->dn_item->next;
431 0 : DLIST_REMOVE(state->dn_list, state->dn_item);
432 0 : return netgr_translate_members_ldap_step(req);
433 : }
434 :
435 0 : cn_attr = talloc_array(state, const char *, 3);
436 0 : if (cn_attr == NULL) {
437 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n");
438 0 : return ENOMEM;
439 : }
440 0 : cn_attr[0] = state->opts->netgroup_map[SDAP_AT_NETGROUP_NAME].name;
441 0 : cn_attr[1] = "objectclass";
442 0 : cn_attr[2] = NULL;
443 :
444 0 : DEBUG(SSSDBG_TRACE_ALL, "LDAP base search for [%s].\n", state->dn_item->dn);
445 0 : subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
446 0 : state->dn_item->dn, LDAP_SCOPE_BASE, filter,
447 0 : cn_attr, state->opts->netgroup_map,
448 : SDAP_OPTS_NETGROUP,
449 0 : dp_opt_get_int(state->opts->basic,
450 : SDAP_SEARCH_TIMEOUT),
451 : false);
452 0 : if (!subreq) {
453 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_send failed.\n");
454 0 : return ENOMEM;
455 : }
456 0 : talloc_steal(subreq, cn_attr);
457 :
458 0 : tevent_req_set_callback(subreq, netgr_translate_members_ldap_done, req);
459 0 : return EAGAIN;
460 : }
461 :
462 0 : static void netgr_translate_members_ldap_done(struct tevent_req *subreq)
463 : {
464 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
465 : struct tevent_req);
466 0 : struct netgr_translate_members_state *state = tevent_req_data(req,
467 : struct netgr_translate_members_state);
468 : int ret;
469 : size_t count;
470 : struct sysdb_attrs **netgroups;
471 : const char *str;
472 :
473 0 : ret = sdap_get_generic_recv(subreq, state, &count, &netgroups);
474 0 : talloc_zfree(subreq);
475 0 : if (ret != EOK) {
476 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic request failed.\n");
477 0 : goto fail;
478 : }
479 :
480 0 : switch (count) {
481 : case 0:
482 0 : DEBUG(SSSDBG_FATAL_FAILURE,
483 : "sdap_get_generic_recv found no entry for [%s].\n",
484 : state->dn_item->dn);
485 0 : break;
486 : case 1:
487 0 : ret = sysdb_attrs_get_string(netgroups[0], SYSDB_NAME, &str);
488 0 : if (ret != EOK) {
489 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_add_string failed.\n");
490 0 : break;
491 : }
492 0 : state->dn_item->cn = talloc_strdup(state->dn_item, str);
493 0 : if (state->dn_item->cn == NULL) {
494 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
495 : }
496 0 : break;
497 : default:
498 0 : DEBUG(SSSDBG_CRIT_FAILURE,
499 : "Unexpected number of results [%zu] for base search.\n",
500 : count);
501 : }
502 :
503 0 : if (state->dn_item->cn == NULL) {
504 0 : DEBUG(SSSDBG_CRIT_FAILURE,
505 : "Failed to resolve netgroup name for DN [%s], using DN.\n",
506 : state->dn_item->dn);
507 0 : state->dn_item->cn = talloc_strdup(state->dn_item, state->dn_item->dn);
508 : }
509 :
510 0 : state->dn_idx = state->dn_item->next;
511 0 : ret = netgr_translate_members_ldap_step(req);
512 0 : if (ret != EOK && ret != EAGAIN) {
513 0 : DEBUG(SSSDBG_CRIT_FAILURE,
514 : "netgr_translate_members_ldap_step failed.\n");
515 0 : goto fail;
516 : }
517 :
518 0 : if (ret == EOK) {
519 0 : tevent_req_done(req);
520 : }
521 0 : return;
522 :
523 : fail:
524 0 : tevent_req_error(req, ret);
525 0 : return;
526 : }
527 :
528 0 : static errno_t netgroup_translate_ldap_members_recv(struct tevent_req *req,
529 : TALLOC_CTX *mem_ctx,
530 : size_t *count,
531 : struct sysdb_attrs ***netgroups)
532 : {
533 0 : struct netgr_translate_members_state *state = tevent_req_data(req,
534 : struct netgr_translate_members_state);
535 :
536 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
537 :
538 0 : *count = state->count;
539 0 : *netgroups = talloc_steal(mem_ctx, state->netgroups);
540 :
541 0 : return EOK;
542 : }
543 :
544 : /* ==Search-Netgroups-with-filter============================================ */
545 :
546 : struct sdap_get_netgroups_state {
547 : struct tevent_context *ev;
548 : struct sdap_options *opts;
549 : struct sdap_handle *sh;
550 : struct sss_domain_info *dom;
551 : struct sysdb_ctx *sysdb;
552 : const char **attrs;
553 : const char *base_filter;
554 : char *filter;
555 : int timeout;
556 :
557 : char *higher_timestamp;
558 : struct sysdb_attrs **netgroups;
559 : size_t count;
560 :
561 : size_t base_iter;
562 : struct sdap_search_base **search_bases;
563 : };
564 :
565 : static errno_t sdap_get_netgroups_next_base(struct tevent_req *req);
566 : static void sdap_get_netgroups_process(struct tevent_req *subreq);
567 : static void netgr_translate_members_done(struct tevent_req *subreq);
568 :
569 0 : struct tevent_req *sdap_get_netgroups_send(TALLOC_CTX *memctx,
570 : struct tevent_context *ev,
571 : struct sss_domain_info *dom,
572 : struct sysdb_ctx *sysdb,
573 : struct sdap_options *opts,
574 : struct sdap_search_base **search_bases,
575 : struct sdap_handle *sh,
576 : const char **attrs,
577 : const char *filter,
578 : int timeout)
579 : {
580 : errno_t ret;
581 : struct tevent_req *req;
582 : struct sdap_get_netgroups_state *state;
583 :
584 0 : req = tevent_req_create(memctx, &state, struct sdap_get_netgroups_state);
585 0 : if (!req) return NULL;
586 :
587 0 : state->ev = ev;
588 0 : state->opts = opts;
589 0 : state->dom = dom;
590 0 : state->sh = sh;
591 0 : state->sysdb = sysdb;
592 0 : state->attrs = attrs;
593 0 : state->higher_timestamp = NULL;
594 0 : state->netgroups = NULL;
595 0 : state->count = 0;
596 0 : state->timeout = timeout;
597 0 : state->base_filter = filter;
598 0 : state->base_iter = 0;
599 0 : state->search_bases = search_bases;
600 :
601 0 : if (!state->search_bases) {
602 0 : DEBUG(SSSDBG_CRIT_FAILURE,
603 : "Netgroup lookup request without a netgroup search base\n");
604 0 : ret = EINVAL;
605 0 : goto done;
606 : }
607 :
608 :
609 0 : ret = sdap_get_netgroups_next_base(req);
610 :
611 : done:
612 0 : if (ret != EOK) {
613 0 : tevent_req_error(req, ret);
614 0 : tevent_req_post(req, state->ev);
615 : }
616 0 : return req;
617 : }
618 :
619 0 : static errno_t sdap_get_netgroups_next_base(struct tevent_req *req)
620 : {
621 : struct tevent_req *subreq;
622 : struct sdap_get_netgroups_state *state;
623 :
624 0 : state = tevent_req_data(req, struct sdap_get_netgroups_state);
625 :
626 0 : talloc_zfree(state->filter);
627 0 : state->filter = sdap_combine_filters(state, state->base_filter,
628 0 : state->search_bases[state->base_iter]->filter);
629 0 : if (!state->filter) {
630 0 : return ENOMEM;
631 : }
632 :
633 0 : DEBUG(SSSDBG_TRACE_FUNC,
634 : "Searching for netgroups with base [%s]\n",
635 : state->search_bases[state->base_iter]->basedn);
636 :
637 0 : subreq = sdap_get_generic_send(
638 : state, state->ev, state->opts, state->sh,
639 0 : state->search_bases[state->base_iter]->basedn,
640 0 : state->search_bases[state->base_iter]->scope,
641 0 : state->filter, state->attrs,
642 0 : state->opts->netgroup_map, SDAP_OPTS_NETGROUP,
643 : state->timeout,
644 : false);
645 0 : if (!subreq) {
646 0 : return ENOMEM;
647 : }
648 0 : tevent_req_set_callback(subreq, sdap_get_netgroups_process, req);
649 :
650 0 : return EOK;
651 : }
652 :
653 0 : static void sdap_get_netgroups_process(struct tevent_req *subreq)
654 : {
655 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
656 : struct tevent_req);
657 0 : struct sdap_get_netgroups_state *state = tevent_req_data(req,
658 : struct sdap_get_netgroups_state);
659 : int ret;
660 :
661 0 : ret = sdap_get_generic_recv(subreq, state,
662 : &state->count, &state->netgroups);
663 0 : talloc_zfree(subreq);
664 0 : if (ret) {
665 0 : tevent_req_error(req, ret);
666 0 : return;
667 : }
668 :
669 0 : DEBUG(SSSDBG_TRACE_FUNC,
670 : "Search for netgroups, returned %zu results.\n", state->count);
671 :
672 0 : if (state->count == 0) {
673 : /* No netgroups found in this search */
674 0 : state->base_iter++;
675 0 : if (state->search_bases[state->base_iter]) {
676 : /* There are more search bases to try */
677 0 : ret = sdap_get_netgroups_next_base(req);
678 0 : if (ret != EOK) {
679 0 : tevent_req_error(req, ENOENT);
680 : }
681 0 : return;
682 : }
683 :
684 0 : tevent_req_error(req, ENOENT);
685 0 : return;
686 : }
687 :
688 0 : subreq = netgr_translate_members_send(state, state->ev, state->opts,
689 : state->sh, state->dom, state->sysdb,
690 : state->count, state->netgroups);
691 0 : if (!subreq) {
692 0 : tevent_req_error(req, ENOMEM);
693 0 : return;
694 : }
695 0 : tevent_req_set_callback(subreq, netgr_translate_members_done, req);
696 :
697 0 : return;
698 :
699 : }
700 :
701 0 : static void netgr_translate_members_done(struct tevent_req *subreq)
702 : {
703 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
704 : struct tevent_req);
705 0 : struct sdap_get_netgroups_state *state = tevent_req_data(req,
706 : struct sdap_get_netgroups_state);
707 : int ret;
708 : size_t c;
709 : time_t now;
710 :
711 0 : ret = netgroup_translate_ldap_members_recv(subreq, state, &state->count,
712 : &state->netgroups);
713 0 : talloc_zfree(subreq);
714 0 : if (ret) {
715 0 : tevent_req_error(req, ret);
716 0 : return;
717 : }
718 :
719 0 : now = time(NULL);
720 0 : for (c = 0; c < state->count; c++) {
721 0 : ret = sdap_save_netgroup(state,
722 : state->dom,
723 : state->opts,
724 0 : state->netgroups[c],
725 : &state->higher_timestamp,
726 : now);
727 0 : if (ret) {
728 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to store netgroups.\n");
729 0 : tevent_req_error(req, ret);
730 0 : return;
731 : }
732 : }
733 :
734 0 : DEBUG(SSSDBG_TRACE_ALL, "Saving %zu Netgroups - Done\n", state->count);
735 :
736 0 : tevent_req_done(req);
737 : }
738 :
739 0 : int sdap_get_netgroups_recv(struct tevent_req *req,
740 : TALLOC_CTX *mem_ctx, char **timestamp,
741 : size_t *reply_count,
742 : struct sysdb_attrs ***reply)
743 : {
744 0 : struct sdap_get_netgroups_state *state = tevent_req_data(req,
745 : struct sdap_get_netgroups_state);
746 :
747 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
748 :
749 0 : if (timestamp) {
750 0 : *timestamp = talloc_steal(mem_ctx, state->higher_timestamp);
751 : }
752 :
753 0 : if (reply_count) {
754 0 : *reply_count = state->count;
755 : }
756 :
757 0 : if (reply) {
758 0 : *reply = talloc_steal(mem_ctx, state->netgroups);
759 : }
760 :
761 0 : return EOK;
762 : }
|