Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Stephen Gallagher <sgallagh@redhat.com>
6 :
7 : Copyright (C) 2012 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "util/util.h"
24 : #include "providers/ldap/sdap_async.h"
25 : #include "providers/ldap/sdap_async_ad.h"
26 : #include "providers/ldap/ldap_common.h"
27 : #include "providers/ldap/sdap_async_private.h"
28 : #include "providers/ldap/sdap_idmap.h"
29 : #include "providers/ad/ad_common.h"
30 : #include "lib/idmap/sss_idmap.h"
31 :
32 : struct sdap_ad_match_rule_initgr_state {
33 : struct tevent_context *ev;
34 : struct sdap_options *opts;
35 : struct sysdb_ctx *sysdb;
36 : struct sss_domain_info *domain;
37 : struct sdap_handle *sh;
38 : const char *name;
39 : const char *orig_dn;
40 : const char **attrs;
41 : int timeout;
42 : const char *base_filter;
43 : char *filter;
44 :
45 : size_t count;
46 : struct sysdb_attrs **groups;
47 :
48 : size_t base_iter;
49 : struct sdap_search_base **search_bases;
50 : };
51 :
52 : static errno_t
53 : sdap_get_ad_match_rule_initgroups_next_base(struct tevent_req *req);
54 :
55 : static void
56 : sdap_get_ad_match_rule_initgroups_step(struct tevent_req *subreq);
57 :
58 : struct tevent_req *
59 0 : sdap_get_ad_match_rule_initgroups_send(TALLOC_CTX *mem_ctx,
60 : struct tevent_context *ev,
61 : struct sdap_options *opts,
62 : struct sysdb_ctx *sysdb,
63 : struct sss_domain_info *domain,
64 : struct sdap_handle *sh,
65 : const char *name,
66 : const char *orig_dn,
67 : int timeout)
68 : {
69 : errno_t ret;
70 : struct tevent_req *req;
71 : struct sdap_ad_match_rule_initgr_state *state;
72 : const char **filter_members;
73 : char *sanitized_user_dn;
74 : char *oc_list;
75 :
76 0 : req = tevent_req_create(mem_ctx, &state,
77 : struct sdap_ad_match_rule_initgr_state);
78 0 : if (!req) return NULL;
79 :
80 0 : state->ev = ev;
81 0 : state->opts = opts;
82 0 : state->sysdb = sysdb;
83 0 : state->domain = domain;
84 0 : state->sh = sh;
85 0 : state->name = name;
86 0 : state->orig_dn = orig_dn;
87 0 : state->base_iter = 0;
88 0 : state->search_bases = opts->sdom->group_search_bases;
89 :
90 : /* Request all of the group attributes that we know
91 : * about, except for 'member' because that wastes a
92 : * lot of bandwidth here and we only really
93 : * care about a single member (the one we already
94 : * have).
95 : */
96 0 : filter_members = talloc_array(state, const char *, 2);
97 0 : if (!filter_members) {
98 0 : ret = ENOMEM;
99 0 : goto immediate;
100 : }
101 0 : filter_members[0] = opts->group_map[SDAP_AT_GROUP_MEMBER].name;
102 0 : filter_members[1] = NULL;
103 :
104 0 : ret = build_attrs_from_map(state, opts->group_map,
105 : SDAP_OPTS_GROUP,
106 : filter_members,
107 0 : &state->attrs, NULL);
108 0 : if (ret != EOK) {
109 0 : DEBUG(SSSDBG_MINOR_FAILURE,
110 : "Could not build attribute map: [%s]\n",
111 : strerror(ret));
112 0 : goto immediate;
113 : }
114 :
115 : /* Sanitize the user DN in case we have special characters in DN */
116 0 : ret = sss_filter_sanitize(state, state->orig_dn, &sanitized_user_dn);
117 0 : if (ret != EOK) {
118 0 : DEBUG(SSSDBG_MINOR_FAILURE,
119 : "Could not sanitize user DN: %s\n",
120 : strerror(ret));
121 0 : goto immediate;
122 : }
123 :
124 : /* Craft a special filter according to
125 : * http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx
126 : */
127 0 : oc_list = sdap_make_oc_list(state, state->opts->group_map);
128 0 : if (oc_list == NULL) {
129 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
130 0 : ret = ENOMEM;
131 0 : goto immediate;
132 : }
133 :
134 0 : state->base_filter =
135 0 : talloc_asprintf(state,
136 : "(&(%s:%s:=%s)(%s))",
137 0 : state->opts->group_map[SDAP_AT_GROUP_MEMBER].name,
138 : SDAP_MATCHING_RULE_IN_CHAIN,
139 : sanitized_user_dn, oc_list);
140 0 : talloc_zfree(sanitized_user_dn);
141 0 : if (!state->base_filter) {
142 0 : ret = ENOMEM;
143 0 : goto immediate;
144 : }
145 :
146 : /* Start the loop through the search bases to get all of the
147 : * groups to which this user belongs.
148 : */
149 0 : ret = sdap_get_ad_match_rule_initgroups_next_base(req);
150 0 : if (ret != EOK) {
151 0 : DEBUG(SSSDBG_MINOR_FAILURE,
152 : "sdap_get_ad_match_rule_members_next_base failed: [%s]\n",
153 : strerror(ret));
154 0 : goto immediate;
155 : }
156 :
157 0 : return req;
158 :
159 : immediate:
160 0 : tevent_req_error(req, ret);
161 0 : tevent_req_post(req, ev);
162 0 : return req;
163 : }
164 :
165 : static errno_t
166 0 : sdap_get_ad_match_rule_initgroups_next_base(struct tevent_req *req)
167 : {
168 : struct tevent_req *subreq;
169 : struct sdap_ad_match_rule_initgr_state *state;
170 :
171 0 : state = tevent_req_data(req, struct sdap_ad_match_rule_initgr_state);
172 :
173 0 : talloc_zfree(state->filter);
174 0 : state->filter = sdap_combine_filters(state, state->base_filter,
175 0 : state->search_bases[state->base_iter]->filter);
176 0 : if (!state->filter) {
177 0 : return ENOMEM;
178 : }
179 :
180 0 : DEBUG(SSSDBG_TRACE_FUNC,
181 : "Searching for groups with base [%s]\n",
182 : state->search_bases[state->base_iter]->basedn);
183 :
184 0 : subreq = sdap_get_generic_send(
185 : state, state->ev, state->opts, state->sh,
186 0 : state->search_bases[state->base_iter]->basedn,
187 0 : state->search_bases[state->base_iter]->scope,
188 0 : state->filter, state->attrs,
189 0 : state->opts->group_map, SDAP_OPTS_GROUP,
190 : state->timeout, true);
191 0 : if (!subreq) {
192 0 : return ENOMEM;
193 : }
194 :
195 0 : tevent_req_set_callback(subreq,
196 : sdap_get_ad_match_rule_initgroups_step,
197 : req);
198 :
199 0 : return EOK;
200 : }
201 :
202 : static void
203 0 : sdap_get_ad_match_rule_initgroups_step(struct tevent_req *subreq)
204 : {
205 : errno_t ret;
206 0 : struct tevent_req *req =
207 0 : tevent_req_callback_data(subreq, struct tevent_req);
208 0 : struct sdap_ad_match_rule_initgr_state *state =
209 0 : tevent_req_data(req, struct sdap_ad_match_rule_initgr_state);
210 : size_t count, i;
211 : struct sysdb_attrs **groups;
212 : char **sysdb_grouplist;
213 :
214 0 : ret = sdap_get_generic_recv(subreq, state, &count, &groups);
215 0 : talloc_zfree(subreq);
216 0 : if (ret != EOK) {
217 0 : DEBUG(SSSDBG_MINOR_FAILURE,
218 : "LDAP search failed: [%s]\n", sss_strerror(ret));
219 0 : goto error;
220 : }
221 :
222 0 : DEBUG(SSSDBG_TRACE_LIBS,
223 : "Search for users returned %zu results\n", count);
224 :
225 : /* Add this batch of groups to the list */
226 0 : if (count > 0) {
227 0 : state->groups = talloc_realloc(state, state->groups,
228 : struct sysdb_attrs *,
229 : state->count + count + 1);
230 0 : if (!state->groups) {
231 0 : tevent_req_error(req, ENOMEM);
232 0 : return;
233 : }
234 :
235 : /* Copy the new groups into the list */
236 0 : for (i = 0; i < count; i++) {
237 0 : state->groups[state->count + i] =
238 0 : talloc_steal(state->groups, groups[i]);
239 : }
240 :
241 0 : state->count += count;
242 0 : state->groups[state->count] = NULL;
243 : }
244 :
245 : /* Continue checking other search bases */
246 0 : state->base_iter++;
247 0 : if (state->search_bases[state->base_iter]) {
248 : /* There are more search bases to try */
249 0 : ret = sdap_get_ad_match_rule_initgroups_next_base(req);
250 0 : if (ret != EOK) {
251 0 : goto error;
252 : }
253 0 : return;
254 : }
255 :
256 : /* No more search bases. Save the groups. */
257 :
258 0 : if (state->count == 0) {
259 0 : DEBUG(SSSDBG_TRACE_LIBS,
260 : "User is not a member of any group in the search bases\n");
261 : }
262 :
263 : /* Get the current sysdb group list for this user
264 : * so we can update it.
265 : */
266 0 : ret = get_sysdb_grouplist(state, state->sysdb, state->domain,
267 : state->name, &sysdb_grouplist);
268 0 : if (ret != EOK) {
269 0 : DEBUG(SSSDBG_MINOR_FAILURE,
270 : "Could not get the list of groups for [%s] in the sysdb: "
271 : "[%s]\n",
272 : state->name, strerror(ret));
273 0 : goto error;
274 : }
275 :
276 : /* The extensibleMatch search rule eliminates the need for
277 : * nested group searches, so we can just update the
278 : * memberships now.
279 : */
280 0 : ret = sdap_initgr_common_store(state->sysdb,
281 : state->domain,
282 : state->opts,
283 : state->name,
284 : SYSDB_MEMBER_USER,
285 : sysdb_grouplist,
286 : state->groups,
287 0 : state->count);
288 0 : if (ret != EOK) {
289 0 : DEBUG(SSSDBG_MINOR_FAILURE,
290 : "Could not store groups for user [%s]: [%s]\n",
291 : state->name, strerror(ret));
292 0 : goto error;
293 : }
294 :
295 0 : tevent_req_done(req);
296 0 : return;
297 :
298 : error:
299 0 : tevent_req_error(req, ret);
300 : }
301 :
302 : errno_t
303 0 : sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req)
304 : {
305 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
306 0 : return EOK;
307 : }
308 :
309 : struct sdap_get_ad_tokengroups_state {
310 : struct tevent_context *ev;
311 : struct sss_idmap_ctx *idmap_ctx;
312 : const char *username;
313 :
314 : char **sids;
315 : size_t num_sids;
316 : };
317 :
318 : static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq);
319 :
320 : static struct tevent_req *
321 0 : sdap_get_ad_tokengroups_send(TALLOC_CTX *mem_ctx,
322 : struct tevent_context *ev,
323 : struct sdap_options *opts,
324 : struct sdap_handle *sh,
325 : const char *name,
326 : const char *orig_dn,
327 : int timeout)
328 : {
329 0 : struct sdap_get_ad_tokengroups_state *state = NULL;
330 0 : struct tevent_req *req = NULL;
331 0 : struct tevent_req *subreq = NULL;
332 0 : const char *attrs[] = {AD_TOKENGROUPS_ATTR, NULL};
333 : errno_t ret;
334 :
335 0 : req = tevent_req_create(mem_ctx, &state,
336 : struct sdap_get_ad_tokengroups_state);
337 0 : if (req == NULL) {
338 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
339 0 : return NULL;
340 : }
341 :
342 0 : state->idmap_ctx = opts->idmap_ctx->map;
343 0 : state->ev = ev;
344 0 : state->username = talloc_strdup(state, name);
345 0 : if (state->username == NULL) {
346 0 : ret = ENOMEM;
347 0 : goto immediately;
348 : }
349 :
350 0 : subreq = sdap_get_generic_send(state, state->ev, opts, sh, orig_dn,
351 : LDAP_SCOPE_BASE, NULL, attrs,
352 : NULL, 0, timeout, false);
353 0 : if (subreq == NULL) {
354 0 : ret = ENOMEM;
355 0 : goto immediately;
356 : }
357 :
358 0 : tevent_req_set_callback(subreq, sdap_get_ad_tokengroups_done, req);
359 :
360 0 : return req;
361 :
362 : immediately:
363 0 : if (ret == EOK) {
364 0 : tevent_req_done(req);
365 : } else {
366 0 : tevent_req_error(req, ret);
367 : }
368 0 : tevent_req_post(req, ev);
369 :
370 0 : return req;
371 : }
372 :
373 0 : static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq)
374 : {
375 0 : TALLOC_CTX *tmp_ctx = NULL;
376 0 : struct sdap_get_ad_tokengroups_state *state = NULL;
377 0 : struct tevent_req *req = NULL;
378 0 : struct sysdb_attrs **users = NULL;
379 0 : struct ldb_message_element *el = NULL;
380 : enum idmap_error_code err;
381 0 : char *sid_str = NULL;
382 : size_t num_users;
383 : size_t i;
384 : errno_t ret;
385 :
386 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
387 0 : state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state);
388 :
389 0 : ret = sdap_get_generic_recv(subreq, tmp_ctx, &num_users, &users);
390 0 : talloc_zfree(subreq);
391 0 : if (ret != EOK) {
392 0 : DEBUG(SSSDBG_MINOR_FAILURE,
393 : "LDAP search failed: [%s]\n", sss_strerror(ret));
394 0 : goto done;
395 : }
396 :
397 0 : if (num_users != 1) {
398 0 : DEBUG(SSSDBG_MINOR_FAILURE,
399 : "More than one result on a base search!\n");
400 0 : ret = EINVAL;
401 0 : goto done;
402 : }
403 :
404 : /* get the list of sids from tokengroups */
405 0 : ret = sysdb_attrs_get_el_ext(users[0], AD_TOKENGROUPS_ATTR, false, &el);
406 0 : if (ret == ENOENT) {
407 0 : DEBUG(SSSDBG_TRACE_LIBS, "No tokenGroups entries for [%s]\n",
408 : state->username);
409 :
410 0 : state->sids = NULL;
411 0 : state->num_sids = 0;
412 0 : ret = EOK;
413 0 : goto done;
414 0 : } else if (ret != EOK) {
415 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not read tokenGroups attribute: "
416 : "[%s]\n", strerror(ret));
417 0 : goto done;
418 : }
419 :
420 0 : state->num_sids = 0;
421 0 : state->sids = talloc_zero_array(state, char*, el->num_values);
422 0 : if (state->sids == NULL) {
423 0 : ret = ENOMEM;
424 0 : goto done;
425 : }
426 :
427 : /* convert binary sid to string */
428 0 : for (i = 0; i < el->num_values; i++) {
429 0 : err = sss_idmap_bin_sid_to_sid(state->idmap_ctx, el->values[i].data,
430 0 : el->values[i].length, &sid_str);
431 0 : if (err != IDMAP_SUCCESS) {
432 0 : DEBUG(SSSDBG_MINOR_FAILURE,
433 : "Could not convert binary SID to string: [%s]. Skipping\n",
434 : idmap_error_string(err));
435 0 : continue;
436 : }
437 :
438 0 : state->sids[i] = talloc_move(state->sids, &sid_str);
439 0 : state->num_sids++;
440 : }
441 :
442 : /* shrink array to final number of elements */
443 0 : state->sids = talloc_realloc(state, state->sids, char*, state->num_sids);
444 0 : if (state->sids == NULL) {
445 0 : ret = ENOMEM;
446 0 : goto done;
447 : }
448 :
449 0 : ret = EOK;
450 :
451 : done:
452 0 : talloc_free(tmp_ctx);
453 :
454 0 : if (ret != EOK) {
455 0 : tevent_req_error(req, ret);
456 0 : return;
457 : }
458 :
459 0 : tevent_req_done(req);
460 : }
461 :
462 0 : static errno_t sdap_get_ad_tokengroups_recv(TALLOC_CTX *mem_ctx,
463 : struct tevent_req *req,
464 : size_t *_num_sids,
465 : char ***_sids)
466 : {
467 0 : struct sdap_get_ad_tokengroups_state *state = NULL;
468 0 : state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state);
469 :
470 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
471 :
472 0 : if (_num_sids != NULL) {
473 0 : *_num_sids = state->num_sids;
474 : }
475 :
476 0 : if (_sids != NULL) {
477 0 : *_sids = talloc_steal(mem_ctx, state->sids);
478 : }
479 :
480 0 : return EOK;
481 : }
482 :
483 : errno_t
484 0 : sdap_ad_tokengroups_update_members(const char *username,
485 : struct sysdb_ctx *sysdb,
486 : struct sss_domain_info *domain,
487 : char **ldap_groups)
488 : {
489 0 : TALLOC_CTX *tmp_ctx = NULL;
490 0 : char **sysdb_groups = NULL;
491 0 : char **add_groups = NULL;
492 0 : char **del_groups = NULL;
493 : errno_t ret;
494 :
495 0 : tmp_ctx = talloc_new(NULL);
496 0 : if (tmp_ctx == NULL) {
497 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
498 0 : return ENOMEM;
499 : }
500 :
501 : /* Get the current sysdb group list for this user so we can update it. */
502 0 : ret = get_sysdb_grouplist_dn(tmp_ctx, sysdb, domain,
503 : username, &sysdb_groups);
504 0 : if (ret != EOK) {
505 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not get the list of groups for "
506 : "[%s] in the sysdb: [%s]\n", username, strerror(ret));
507 0 : goto done;
508 : }
509 :
510 : /* Find the differences between the sysdb and LDAP lists.
511 : * Groups in the sysdb only must be removed. */
512 0 : ret = diff_string_lists(tmp_ctx, ldap_groups, sysdb_groups,
513 : &add_groups, &del_groups, NULL);
514 0 : if (ret != EOK) {
515 0 : goto done;
516 : }
517 :
518 0 : DEBUG(SSSDBG_TRACE_LIBS, "Updating memberships for [%s]\n", username);
519 :
520 0 : ret = sysdb_update_members_dn(domain, username, SYSDB_MEMBER_USER,
521 : (const char *const *) add_groups,
522 : (const char *const *) del_groups);
523 0 : if (ret != EOK) {
524 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
525 : ret, strerror(ret));
526 0 : goto done;
527 : }
528 :
529 : done:
530 0 : talloc_free(tmp_ctx);
531 0 : return ret;
532 : }
533 :
534 : struct sdap_ad_resolve_sids_state {
535 : struct tevent_context *ev;
536 : struct sdap_id_ctx *id_ctx;
537 : struct sdap_id_conn_ctx *conn;
538 : struct sdap_options *opts;
539 : struct sss_domain_info *domain;
540 : char **sids;
541 :
542 : const char *current_sid;
543 : int index;
544 : };
545 :
546 : static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req);
547 : static void sdap_ad_resolve_sids_done(struct tevent_req *subreq);
548 :
549 : struct tevent_req *
550 0 : sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx,
551 : struct tevent_context *ev,
552 : struct sdap_id_ctx *id_ctx,
553 : struct sdap_id_conn_ctx *conn,
554 : struct sdap_options *opts,
555 : struct sss_domain_info *domain,
556 : char **sids)
557 : {
558 0 : struct sdap_ad_resolve_sids_state *state = NULL;
559 0 : struct tevent_req *req = NULL;
560 : errno_t ret;
561 :
562 0 : req = tevent_req_create(mem_ctx, &state,
563 : struct sdap_ad_resolve_sids_state);
564 0 : if (req == NULL) {
565 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
566 0 : return NULL;
567 : }
568 :
569 0 : state->ev = ev;
570 0 : state->id_ctx = id_ctx;
571 0 : state->conn = conn;
572 0 : state->opts = opts;
573 0 : state->domain = get_domains_head(domain);
574 0 : state->sids = sids;
575 0 : state->index = 0;
576 :
577 0 : if (state->sids == NULL || state->sids[0] == NULL) {
578 0 : ret = EOK;
579 0 : goto immediately;
580 : }
581 :
582 0 : ret = sdap_ad_resolve_sids_step(req);
583 0 : if (ret != EAGAIN) {
584 0 : goto immediately;
585 : }
586 :
587 0 : return req;
588 :
589 : immediately:
590 0 : if (ret == EOK) {
591 0 : tevent_req_done(req);
592 : } else {
593 0 : tevent_req_error(req, ret);
594 : }
595 0 : tevent_req_post(req, ev);
596 :
597 0 : return req;
598 : }
599 :
600 0 : static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req)
601 : {
602 0 : struct sdap_ad_resolve_sids_state *state = NULL;
603 0 : struct tevent_req *subreq = NULL;
604 0 : struct sdap_domain *sdap_domain = NULL;
605 0 : struct sss_domain_info *domain = NULL;
606 :
607 0 : state = tevent_req_data(req, struct sdap_ad_resolve_sids_state);
608 :
609 : do {
610 0 : state->current_sid = state->sids[state->index];
611 0 : if (state->current_sid == NULL) {
612 0 : return EOK;
613 : }
614 0 : state->index++;
615 :
616 0 : domain = sss_get_domain_by_sid_ldap_fallback(state->domain,
617 : state->current_sid);
618 :
619 0 : if (domain == NULL) {
620 0 : DEBUG(SSSDBG_MINOR_FAILURE, "SID %s does not belong to any known "
621 : "domain\n", state->current_sid);
622 : }
623 0 : } while (domain == NULL);
624 :
625 0 : sdap_domain = sdap_domain_get(state->opts, domain);
626 0 : if (sdap_domain == NULL) {
627 0 : DEBUG(SSSDBG_CRIT_FAILURE, "SDAP domain does not exist?\n");
628 0 : return ERR_INTERNAL;
629 : }
630 :
631 0 : subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain,
632 : state->conn, state->current_sid,
633 : BE_FILTER_SECID, BE_ATTR_CORE, false, true);
634 0 : if (subreq == NULL) {
635 0 : return ENOMEM;
636 : }
637 :
638 0 : tevent_req_set_callback(subreq, sdap_ad_resolve_sids_done, req);
639 :
640 0 : return EAGAIN;
641 : }
642 :
643 0 : static void sdap_ad_resolve_sids_done(struct tevent_req *subreq)
644 : {
645 0 : struct sdap_ad_resolve_sids_state *state = NULL;
646 0 : struct tevent_req *req = NULL;
647 : int dp_error;
648 : int sdap_error;
649 : errno_t ret;
650 :
651 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
652 0 : state = tevent_req_data(req, struct sdap_ad_resolve_sids_state);
653 :
654 0 : ret = groups_get_recv(subreq, &dp_error, &sdap_error);
655 0 : talloc_zfree(subreq);
656 :
657 0 : if (ret == EOK && sdap_error == ENOENT && dp_error == DP_ERR_OK) {
658 : /* Group was not found, we will ignore the error and continue with
659 : * next group. This may happen for example if the group is built-in,
660 : * but a custom search base is provided. */
661 0 : DEBUG(SSSDBG_CRIT_FAILURE,
662 : "Unable to resolve SID %s - will try next sid.\n",
663 : state->current_sid);
664 0 : } else if (ret != EOK || sdap_error != EOK || dp_error != DP_ERR_OK) {
665 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s [dp_error: %d, "
666 : "sdap_error: %d, ret: %d]: %s\n", state->current_sid, dp_error,
667 : sdap_error, ret, strerror(ret));
668 0 : goto done;
669 : }
670 :
671 0 : ret = sdap_ad_resolve_sids_step(req);
672 0 : if (ret == EAGAIN) {
673 : /* continue with next SID */
674 0 : return;
675 : }
676 :
677 : done:
678 0 : if (ret != EOK) {
679 0 : tevent_req_error(req, ret);
680 0 : return;
681 : }
682 :
683 0 : tevent_req_done(req);
684 : }
685 :
686 0 : errno_t sdap_ad_resolve_sids_recv(struct tevent_req *req)
687 : {
688 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
689 :
690 0 : return EOK;
691 : }
692 :
693 :
694 : struct sdap_ad_tokengroups_initgr_mapping_state {
695 : struct tevent_context *ev;
696 : struct sdap_options *opts;
697 : struct sdap_handle *sh;
698 : struct sdap_idmap_ctx *idmap_ctx;
699 : struct sysdb_ctx *sysdb;
700 : struct sss_domain_info *domain;
701 : const char *orig_dn;
702 : int timeout;
703 : const char *username;
704 :
705 : struct sdap_id_op *op;
706 : };
707 :
708 : static void
709 : sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq);
710 : static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq);
711 : static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx,
712 : struct tevent_context *ev,
713 : struct sdap_options *opts,
714 : const char *orig_dn,
715 : int timeout,
716 : const char *username,
717 : struct sdap_handle *sh,
718 : struct tevent_req *req,
719 : tevent_req_fn callback);
720 :
721 : static struct tevent_req *
722 0 : sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx,
723 : struct tevent_context *ev,
724 : struct sdap_options *opts,
725 : struct sysdb_ctx *sysdb,
726 : struct sss_domain_info *domain,
727 : struct sdap_handle *sh,
728 : const char *name,
729 : const char *orig_dn,
730 : int timeout)
731 : {
732 0 : struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
733 0 : struct tevent_req *req = NULL;
734 0 : struct tevent_req *subreq = NULL;
735 : struct sdap_domain *sdom;
736 : struct ad_id_ctx *subdom_id_ctx;
737 : errno_t ret;
738 :
739 0 : req = tevent_req_create(mem_ctx, &state,
740 : struct sdap_ad_tokengroups_initgr_mapping_state);
741 0 : if (req == NULL) {
742 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
743 0 : return NULL;
744 : }
745 :
746 0 : state->ev = ev;
747 0 : state->opts = opts;
748 0 : state->sh = sh;
749 0 : state->idmap_ctx = opts->idmap_ctx;
750 0 : state->sysdb = sysdb;
751 0 : state->domain = domain;
752 0 : state->timeout = timeout;
753 0 : state->orig_dn = orig_dn;
754 0 : state->username = talloc_strdup(state, name);
755 0 : if (state->username == NULL) {
756 0 : ret = ENOMEM;
757 0 : goto immediately;
758 : }
759 :
760 0 : sdom = sdap_domain_get(opts, domain);
761 0 : if (sdom == NULL || sdom->pvt == NULL) {
762 0 : ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout,
763 0 : state->username, sh, req,
764 : sdap_ad_tokengroups_initgr_mapping_done);
765 0 : if (ret == EOK) {
766 0 : return req;
767 : } else {
768 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
769 : domain->name);
770 0 : goto immediately;
771 : }
772 : }
773 :
774 0 : subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
775 0 : state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache);
776 0 : if (!state->op) {
777 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
778 0 : ret = ENOMEM;
779 0 : goto immediately;
780 : }
781 :
782 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
783 0 : if (subreq == NULL) {
784 0 : ret = ENOMEM;
785 0 : goto immediately;
786 : }
787 :
788 0 : tevent_req_set_callback(subreq,
789 : sdap_ad_tokengroups_initgr_mapping_connect_done,
790 : req);
791 :
792 0 : return req;
793 :
794 : immediately:
795 0 : if (ret == EOK) {
796 0 : tevent_req_done(req);
797 : } else {
798 0 : tevent_req_error(req, ret);
799 : }
800 0 : tevent_req_post(req, ev);
801 :
802 0 : return req;
803 : }
804 :
805 : static void
806 0 : sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq)
807 : {
808 0 : struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
809 0 : struct tevent_req *req = NULL;
810 : int ret;
811 0 : int dp_error = DP_ERR_FATAL;
812 :
813 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
814 0 : state = tevent_req_data(req,
815 : struct sdap_ad_tokengroups_initgr_mapping_state);
816 :
817 :
818 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
819 0 : talloc_zfree(subreq);
820 :
821 0 : if (ret != EOK) {
822 0 : tevent_req_error(req, ret);
823 0 : return;
824 : }
825 :
826 0 : subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts,
827 : sdap_id_op_handle(state->op),
828 : state->username,
829 : state->orig_dn, state->timeout);
830 0 : if (subreq == NULL) {
831 0 : tevent_req_error(req, ENOMEM);
832 0 : return;
833 : }
834 :
835 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_mapping_done,
836 : req);
837 :
838 0 : return;
839 : }
840 :
841 0 : errno_t sdap_ad_save_group_membership_with_idmapping(const char *username,
842 : struct sss_domain_info *user_dom,
843 : struct sdap_idmap_ctx *idmap_ctx,
844 : size_t num_sids,
845 : char **sids)
846 : {
847 0 : TALLOC_CTX *tmp_ctx = NULL;
848 0 : struct sss_domain_info *domain = NULL;
849 0 : struct ldb_message *msg = NULL;
850 0 : const char *attrs[] = {SYSDB_NAME, NULL};
851 0 : const char *name = NULL;
852 0 : const char *sid = NULL;
853 : size_t i;
854 : time_t now;
855 : gid_t gid;
856 0 : char **groups = NULL;
857 : size_t num_groups;
858 : errno_t ret;
859 : errno_t sret;
860 0 : bool in_transaction = false;
861 :
862 0 : tmp_ctx = talloc_new(NULL);
863 0 : if (tmp_ctx == NULL) {
864 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
865 0 : return ENOMEM;
866 : }
867 :
868 0 : num_groups = 0;
869 0 : groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
870 0 : if (groups == NULL) {
871 0 : ret = ENOMEM;
872 0 : goto done;
873 : }
874 :
875 0 : now = time(NULL);
876 0 : ret = sysdb_transaction_start(user_dom->sysdb);
877 0 : if (ret != EOK) {
878 0 : goto done;
879 : }
880 0 : in_transaction = true;
881 :
882 0 : for (i = 0; i < num_sids; i++) {
883 0 : sid = sids[i];
884 0 : DEBUG(SSSDBG_TRACE_LIBS, "Processing membership SID [%s]\n", sid);
885 :
886 0 : ret = sdap_idmap_sid_to_unix(idmap_ctx, sid, &gid);
887 0 : if (ret == ENOTSUP) {
888 0 : DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n");
889 0 : continue;
890 0 : } else if (ret != EOK) {
891 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not convert SID to GID: [%s]. "
892 : "Skipping\n", strerror(ret));
893 0 : continue;
894 : }
895 :
896 0 : domain = sss_get_domain_by_sid_ldap_fallback(user_dom, sid);
897 0 : if (domain == NULL) {
898 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found for SID %s\n", sid);
899 0 : continue;
900 : }
901 :
902 0 : DEBUG(SSSDBG_TRACE_LIBS, "SID [%s] maps to GID [%"SPRIgid"]\n",
903 : sid, gid);
904 :
905 : /* Check whether this GID already exists in the sysdb */
906 0 : ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, attrs, &msg);
907 0 : if (ret == EOK) {
908 0 : name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
909 0 : if (name == NULL) {
910 0 : DEBUG(SSSDBG_MINOR_FAILURE,
911 : "Could not retrieve group name from sysdb\n");
912 0 : ret = EINVAL;
913 0 : goto done;
914 : }
915 0 : } else if (ret == ENOENT) {
916 : /* This is a new group. For now, we will store it under the name
917 : * of its SID. When a direct lookup of the group or its GID occurs,
918 : * it will replace this temporary entry. */
919 0 : name = sid;
920 0 : ret = sysdb_add_incomplete_group(domain, name, gid,
921 : NULL, sid, NULL, false, now);
922 0 : if (ret != EOK) {
923 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not create incomplete "
924 : "group: [%s]\n", strerror(ret));
925 0 : goto done;
926 : }
927 : } else {
928 : /* Unexpected error */
929 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not look up group in sysdb: "
930 : "[%s]\n", strerror(ret));
931 0 : goto done;
932 : }
933 :
934 0 : groups[num_groups] = sysdb_group_strdn(tmp_ctx, domain->name, name);
935 0 : if (groups[num_groups] == NULL) {
936 0 : ret = ENOMEM;
937 0 : goto done;
938 : }
939 0 : num_groups++;
940 : }
941 :
942 0 : groups[num_groups] = NULL;
943 :
944 0 : ret = sdap_ad_tokengroups_update_members(username,
945 : user_dom->sysdb, user_dom,
946 : groups);
947 0 : if (ret != EOK) {
948 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
949 : ret, strerror(ret));
950 0 : goto done;
951 : }
952 :
953 0 : ret = sysdb_transaction_commit(user_dom->sysdb);
954 0 : if (ret != EOK) {
955 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not commit transaction! [%s]\n",
956 : strerror(ret));
957 0 : goto done;
958 : }
959 0 : in_transaction = false;
960 :
961 : done:
962 0 : talloc_free(tmp_ctx);
963 :
964 0 : if (in_transaction) {
965 0 : sret = sysdb_transaction_cancel(user_dom->sysdb);
966 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Could not cancel transaction! [%s]\n",
967 : strerror(sret));
968 : }
969 :
970 0 : return ret;
971 : }
972 :
973 0 : static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq)
974 : {
975 0 : struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
976 0 : struct tevent_req *req = NULL;
977 0 : char **sids = NULL;
978 0 : size_t num_sids = 0;
979 : errno_t ret;
980 :
981 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
982 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_mapping_state);
983 :
984 0 : ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
985 0 : talloc_zfree(subreq);
986 0 : if (ret != EOK) {
987 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire tokengroups [%d]: %s\n",
988 : ret, strerror(ret));
989 0 : goto done;
990 : }
991 :
992 0 : ret = sdap_ad_save_group_membership_with_idmapping(state->username,
993 : state->domain,
994 : state->idmap_ctx,
995 : num_sids,
996 : sids);
997 0 : if (ret != EOK) {
998 0 : DEBUG(SSSDBG_OP_FAILURE,
999 : "sdap_ad_save_group_membership_with_idmapping failed.\n");
1000 0 : goto done;
1001 : }
1002 :
1003 : done:
1004 0 : if (ret != EOK) {
1005 0 : tevent_req_error(req, ret);
1006 0 : return;
1007 : }
1008 :
1009 0 : tevent_req_done(req);
1010 : }
1011 :
1012 0 : static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req)
1013 : {
1014 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1015 :
1016 0 : return EOK;
1017 : }
1018 :
1019 : struct sdap_ad_tokengroups_initgr_posix_state {
1020 : struct tevent_context *ev;
1021 : struct sdap_id_ctx *id_ctx;
1022 : struct sdap_id_conn_ctx *conn;
1023 : struct sdap_options *opts;
1024 : struct sdap_handle *sh;
1025 : struct sysdb_ctx *sysdb;
1026 : struct sss_domain_info *domain;
1027 : const char *orig_dn;
1028 : int timeout;
1029 : const char *username;
1030 :
1031 : struct sdap_id_op *op;
1032 : char **missing_sids;
1033 : size_t num_missing_sids;
1034 : char **cached_groups;
1035 : size_t num_cached_groups;
1036 : };
1037 :
1038 : static void
1039 : sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq);
1040 :
1041 : static void
1042 : sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq);
1043 : static void
1044 : sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq);
1045 :
1046 : static struct tevent_req *
1047 0 : sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx,
1048 : struct tevent_context *ev,
1049 : struct sdap_id_ctx *id_ctx,
1050 : struct sdap_id_conn_ctx *conn,
1051 : struct sdap_options *opts,
1052 : struct sysdb_ctx *sysdb,
1053 : struct sss_domain_info *domain,
1054 : struct sdap_handle *sh,
1055 : const char *name,
1056 : const char *orig_dn,
1057 : int timeout)
1058 : {
1059 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1060 0 : struct tevent_req *req = NULL;
1061 0 : struct tevent_req *subreq = NULL;
1062 : struct sdap_domain *sdom;
1063 : struct ad_id_ctx *subdom_id_ctx;
1064 : errno_t ret;
1065 :
1066 0 : req = tevent_req_create(mem_ctx, &state,
1067 : struct sdap_ad_tokengroups_initgr_posix_state);
1068 0 : if (req == NULL) {
1069 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1070 0 : return NULL;
1071 : }
1072 :
1073 0 : state->ev = ev;
1074 0 : state->id_ctx = id_ctx;
1075 0 : state->conn = conn;
1076 0 : state->opts = opts;
1077 0 : state->sh = sh;
1078 0 : state->sysdb = sysdb;
1079 0 : state->domain = domain;
1080 0 : state->orig_dn = orig_dn;
1081 0 : state->timeout = timeout;
1082 0 : state->username = talloc_strdup(state, name);
1083 0 : if (state->username == NULL) {
1084 0 : ret = ENOMEM;
1085 0 : goto immediately;
1086 : }
1087 :
1088 0 : sdom = sdap_domain_get(opts, domain);
1089 0 : if (sdom == NULL || sdom->pvt == NULL) {
1090 0 : ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout,
1091 0 : state->username, sh, req,
1092 : sdap_ad_tokengroups_initgr_posix_tg_done);
1093 0 : if (ret == EOK) {
1094 0 : return req;
1095 : } else {
1096 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
1097 : domain->name);
1098 0 : goto immediately;
1099 : }
1100 : }
1101 0 : subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
1102 0 : state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache);
1103 0 : if (!state->op) {
1104 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
1105 0 : ret = ENOMEM;
1106 0 : goto immediately;
1107 : }
1108 :
1109 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
1110 0 : if (subreq == NULL) {
1111 0 : ret = ENOMEM;
1112 0 : goto immediately;
1113 : }
1114 :
1115 0 : tevent_req_set_callback(subreq,
1116 : sdap_ad_tokengroups_initgr_posix_sids_connect_done,
1117 : req);
1118 :
1119 0 : return req;
1120 :
1121 : immediately:
1122 0 : if (ret == EOK) {
1123 0 : tevent_req_done(req);
1124 : } else {
1125 0 : tevent_req_error(req, ret);
1126 : }
1127 0 : tevent_req_post(req, ev);
1128 :
1129 0 : return req;
1130 : }
1131 :
1132 : static void
1133 0 : sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq)
1134 : {
1135 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1136 0 : struct tevent_req *req = NULL;
1137 : int ret;
1138 0 : int dp_error = DP_ERR_FATAL;
1139 :
1140 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1141 0 : state = tevent_req_data(req,
1142 : struct sdap_ad_tokengroups_initgr_posix_state);
1143 :
1144 :
1145 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
1146 0 : talloc_zfree(subreq);
1147 :
1148 0 : if (ret != EOK) {
1149 0 : tevent_req_error(req, ret);
1150 0 : return;
1151 : }
1152 :
1153 0 : subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts,
1154 : sdap_id_op_handle(state->op),
1155 : state->username, state->orig_dn,
1156 : state->timeout);
1157 0 : if (subreq == NULL) {
1158 0 : tevent_req_error(req, ENOMEM);
1159 0 : return;
1160 : }
1161 :
1162 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done,
1163 : req);
1164 :
1165 0 : return;
1166 : }
1167 :
1168 : errno_t
1169 0 : sdap_ad_tokengroups_get_posix_members(TALLOC_CTX *mem_ctx,
1170 : struct sss_domain_info *user_domain,
1171 : size_t num_sids,
1172 : char **sids,
1173 : size_t *_num_missing,
1174 : char ***_missing,
1175 : size_t *_num_valid,
1176 : char ***_valid_groups)
1177 : {
1178 0 : TALLOC_CTX *tmp_ctx = NULL;
1179 0 : struct sss_domain_info *domain = NULL;
1180 0 : struct ldb_message *msg = NULL;
1181 0 : const char *attrs[] = {SYSDB_NAME, NULL};
1182 0 : const char *name = NULL;
1183 0 : char *sid = NULL;
1184 0 : char **valid_groups = NULL;
1185 : size_t num_valid_groups;
1186 0 : char **missing_sids = NULL;
1187 : size_t num_missing_sids;
1188 : size_t i;
1189 : errno_t ret;
1190 :
1191 0 : tmp_ctx = talloc_new(NULL);
1192 0 : if (tmp_ctx == NULL) {
1193 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
1194 0 : ret = ENOMEM;
1195 0 : goto done;
1196 : }
1197 :
1198 0 : num_valid_groups = 0;
1199 0 : valid_groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
1200 0 : if (valid_groups == NULL) {
1201 0 : ret = ENOMEM;
1202 0 : goto done;
1203 : }
1204 :
1205 0 : num_missing_sids = 0;
1206 0 : missing_sids = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
1207 0 : if (missing_sids == NULL) {
1208 0 : ret = ENOMEM;
1209 0 : goto done;
1210 : }
1211 :
1212 : /* For each SID check if it is already present in the cache. If yes, we
1213 : * will get name of the group and update the membership. Otherwise we need
1214 : * to remember the SID and download missing groups one by one. */
1215 0 : for (i = 0; i < num_sids; i++) {
1216 0 : sid = sids[i];
1217 0 : DEBUG(SSSDBG_TRACE_LIBS, "Processing membership SID [%s]\n", sid);
1218 :
1219 0 : domain = sss_get_domain_by_sid_ldap_fallback(user_domain, sid);
1220 0 : if (domain == NULL) {
1221 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found for SID %s\n", sid);
1222 0 : continue;
1223 : }
1224 :
1225 0 : ret = sysdb_search_group_by_sid_str(tmp_ctx, domain, sid, attrs, &msg);
1226 0 : if (ret == EOK) {
1227 : /* we will update membership of this group */
1228 0 : name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1229 0 : if (name == NULL) {
1230 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1231 : "Could not retrieve group name from sysdb\n");
1232 0 : ret = EINVAL;
1233 0 : goto done;
1234 : }
1235 :
1236 0 : valid_groups[num_valid_groups] = sysdb_group_strdn(valid_groups,
1237 0 : domain->name,
1238 : name);
1239 0 : if (valid_groups[num_valid_groups] == NULL) {
1240 0 : ret = ENOMEM;
1241 0 : goto done;
1242 : }
1243 0 : num_valid_groups++;
1244 0 : } else if (ret == ENOENT) {
1245 0 : if (_missing != NULL) {
1246 : /* we need to download this group */
1247 0 : missing_sids[num_missing_sids] = talloc_steal(missing_sids,
1248 : sid);
1249 0 : num_missing_sids++;
1250 :
1251 0 : DEBUG(SSSDBG_TRACE_FUNC, "Missing SID %s will be downloaded\n",
1252 : sid);
1253 : }
1254 :
1255 : /* else: We have downloaded missing groups but some of them may
1256 : * remained missing because they are outside of search base. We
1257 : * will just ignore them and continue with the next group. */
1258 : } else {
1259 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not look up SID %s in sysdb: "
1260 : "[%s]\n", sid, strerror(ret));
1261 0 : goto done;
1262 : }
1263 : }
1264 :
1265 0 : valid_groups[num_valid_groups] = NULL;
1266 0 : missing_sids[num_missing_sids] = NULL;
1267 :
1268 : /* return list of missing groups */
1269 0 : if (_missing != NULL) {
1270 0 : *_missing = talloc_steal(mem_ctx, missing_sids);
1271 0 : *_num_missing = num_missing_sids;
1272 : }
1273 :
1274 : /* return list of missing groups */
1275 0 : if (_valid_groups != NULL) {
1276 0 : *_valid_groups = talloc_steal(mem_ctx, valid_groups);
1277 0 : *_num_valid = num_valid_groups;
1278 : }
1279 :
1280 0 : ret = EOK;
1281 :
1282 : done:
1283 0 : talloc_free(tmp_ctx);
1284 0 : return ret;
1285 : }
1286 :
1287 : static void
1288 0 : sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq)
1289 : {
1290 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1291 0 : struct tevent_req *req = NULL;
1292 0 : char **sids = NULL;
1293 0 : size_t num_sids = 0;
1294 : errno_t ret;
1295 :
1296 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1297 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state);
1298 :
1299 0 : ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
1300 0 : talloc_zfree(subreq);
1301 0 : if (ret != EOK) {
1302 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire tokengroups [%d]: %s\n",
1303 : ret, strerror(ret));
1304 0 : goto done;
1305 : }
1306 :
1307 0 : ret = sdap_ad_tokengroups_get_posix_members(state, state->domain,
1308 : num_sids, sids,
1309 : &state->num_missing_sids,
1310 : &state->missing_sids,
1311 : &state->num_cached_groups,
1312 : &state->cached_groups);
1313 0 : if (ret != EOK) {
1314 0 : goto done;
1315 : }
1316 :
1317 : /* download missing SIDs */
1318 0 : subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx,
1319 : state->conn,
1320 : state->opts, state->domain,
1321 : state->missing_sids);
1322 0 : if (subreq == NULL) {
1323 0 : ret = ENOMEM;
1324 0 : goto done;
1325 : }
1326 :
1327 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_sids_done,
1328 : req);
1329 :
1330 0 : return;
1331 :
1332 : done:
1333 0 : if (ret != EOK) {
1334 0 : tevent_req_error(req, ret);
1335 0 : return;
1336 : }
1337 :
1338 0 : tevent_req_done(req);
1339 : }
1340 :
1341 : static void
1342 0 : sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq)
1343 : {
1344 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1345 0 : struct tevent_req *req = NULL;
1346 : errno_t ret;
1347 : char **cached_groups;
1348 : size_t num_cached_groups;
1349 :
1350 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1351 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state);
1352 :
1353 0 : ret = sdap_ad_resolve_sids_recv(subreq);
1354 0 : talloc_zfree(subreq);
1355 0 : if (ret != EOK) {
1356 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve missing SIDs "
1357 : "[%d]: %s\n", ret, strerror(ret));
1358 0 : goto done;
1359 : }
1360 :
1361 0 : ret = sdap_ad_tokengroups_get_posix_members(state, state->domain,
1362 : state->num_missing_sids,
1363 : state->missing_sids,
1364 : NULL, NULL,
1365 : &num_cached_groups,
1366 : &cached_groups);
1367 0 : if (ret != EOK){
1368 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1369 : "sdap_ad_tokengroups_get_posix_members failed [%d]: %s\n",
1370 : ret, strerror(ret));
1371 0 : goto done;
1372 : }
1373 :
1374 0 : state->cached_groups = concatenate_string_array(state,
1375 : state->cached_groups,
1376 : state->num_cached_groups,
1377 : cached_groups,
1378 : num_cached_groups);
1379 0 : if (state->cached_groups == NULL) {
1380 0 : ret = ENOMEM;
1381 0 : goto done;
1382 : }
1383 :
1384 : /* update membership of existing groups */
1385 0 : ret = sdap_ad_tokengroups_update_members(state->username,
1386 : state->sysdb, state->domain,
1387 : state->cached_groups);
1388 0 : if (ret != EOK) {
1389 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
1390 : ret, strerror(ret));
1391 0 : goto done;
1392 : }
1393 :
1394 : done:
1395 0 : if (ret != EOK) {
1396 0 : tevent_req_error(req, ret);
1397 0 : return;
1398 : }
1399 :
1400 0 : tevent_req_done(req);
1401 : }
1402 :
1403 0 : static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req)
1404 : {
1405 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1406 :
1407 0 : return EOK;
1408 : }
1409 :
1410 : struct sdap_ad_tokengroups_initgroups_state {
1411 : bool use_id_mapping;
1412 : struct sss_domain_info *domain;
1413 : };
1414 :
1415 : static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq);
1416 :
1417 : struct tevent_req *
1418 0 : sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
1419 : struct tevent_context *ev,
1420 : struct sdap_id_ctx *id_ctx,
1421 : struct sdap_id_conn_ctx *conn,
1422 : struct sdap_options *opts,
1423 : struct sysdb_ctx *sysdb,
1424 : struct sss_domain_info *domain,
1425 : struct sdap_handle *sh,
1426 : const char *name,
1427 : const char *orig_dn,
1428 : int timeout,
1429 : bool use_id_mapping)
1430 : {
1431 0 : struct sdap_ad_tokengroups_initgroups_state *state = NULL;
1432 0 : struct tevent_req *req = NULL;
1433 0 : struct tevent_req *subreq = NULL;
1434 : errno_t ret;
1435 :
1436 0 : req = tevent_req_create(mem_ctx, &state,
1437 : struct sdap_ad_tokengroups_initgroups_state);
1438 0 : if (req == NULL) {
1439 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1440 0 : return NULL;
1441 : }
1442 :
1443 0 : state->use_id_mapping = use_id_mapping;
1444 0 : state->domain = domain;
1445 :
1446 : /* We can compute the gidNumber attribute from SIDs obtained from
1447 : * the tokenGroups lookup in case ID mapping is used for a user from the
1448 : * parent domain. For trusted domains, we need to know the group type
1449 : * to be able to filter out domain-local groups. Additionally, as a
1450 : * temporary workaround until https://fedorahosted.org/sssd/ticket/2656
1451 : * is fixed, we also fetch the group object if group members are ignored
1452 : * to avoid having to transfer and retain members when the fake
1453 : * tokengroups object without name is replaced by the full group object
1454 : */
1455 0 : if (state->use_id_mapping
1456 0 : && !IS_SUBDOMAIN(state->domain)
1457 0 : && state->domain->ignore_group_members == false) {
1458 0 : subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts,
1459 : sysdb, domain, sh,
1460 : name, orig_dn,
1461 : timeout);
1462 : } else {
1463 0 : subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, conn,
1464 : opts, sysdb, domain, sh,
1465 : name, orig_dn,
1466 : timeout);
1467 : }
1468 0 : if (subreq == NULL) {
1469 0 : ret = ENOMEM;
1470 0 : goto immediately;
1471 : }
1472 :
1473 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req);
1474 :
1475 0 : return req;
1476 :
1477 : immediately:
1478 0 : if (ret == EOK) {
1479 0 : tevent_req_done(req);
1480 : } else {
1481 0 : tevent_req_error(req, ret);
1482 : }
1483 0 : tevent_req_post(req, ev);
1484 :
1485 0 : return req;
1486 : }
1487 :
1488 0 : static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq)
1489 : {
1490 0 : struct sdap_ad_tokengroups_initgroups_state *state = NULL;
1491 0 : struct tevent_req *req = NULL;
1492 : errno_t ret;
1493 :
1494 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1495 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state);
1496 :
1497 0 : if (state->use_id_mapping
1498 0 : && !IS_SUBDOMAIN(state->domain)
1499 0 : && state->domain->ignore_group_members == false) {
1500 0 : ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq);
1501 : } else {
1502 0 : ret = sdap_ad_tokengroups_initgr_posix_recv(subreq);
1503 : }
1504 0 : talloc_zfree(subreq);
1505 0 : if (ret != EOK) {
1506 0 : goto done;
1507 : }
1508 :
1509 : done:
1510 0 : if (ret != EOK) {
1511 0 : tevent_req_error(req, ret);
1512 0 : return;
1513 : }
1514 :
1515 0 : tevent_req_done(req);
1516 : }
1517 :
1518 0 : errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req)
1519 : {
1520 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1521 :
1522 0 : return EOK;
1523 : }
1524 :
1525 0 : static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx,
1526 : struct tevent_context *ev,
1527 : struct sdap_options *opts,
1528 : const char *orig_dn,
1529 : int timeout,
1530 : const char *username,
1531 : struct sdap_handle *sh,
1532 : struct tevent_req *req,
1533 : tevent_req_fn callback)
1534 : {
1535 0 : struct tevent_req *subreq = NULL;
1536 : errno_t ret;
1537 :
1538 0 : if (sh != NULL) {
1539 : /* plain LDAP provider already has a sdap_handle */
1540 0 : subreq = sdap_get_ad_tokengroups_send(mem_ctx, ev, opts, sh, username,
1541 : orig_dn, timeout);
1542 0 : if (subreq == NULL) {
1543 0 : ret = ENOMEM;
1544 0 : tevent_req_error(req, ret);
1545 0 : goto done;
1546 : }
1547 :
1548 0 : tevent_req_set_callback(subreq, callback, req);
1549 0 : ret = EOK;
1550 0 : goto done;
1551 :
1552 : } else {
1553 0 : ret = EINVAL;
1554 0 : goto done;
1555 : }
1556 :
1557 : done:
1558 0 : return ret;
1559 : }
|