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/ldap_common.h"
26 : #include "providers/ldap/sdap_async_private.h"
27 : #include "providers/ldap/sdap_idmap.h"
28 : #include "providers/ad/ad_common.h"
29 : #include "lib/idmap/sss_idmap.h"
30 :
31 : struct sdap_ad_match_rule_initgr_state {
32 : struct tevent_context *ev;
33 : struct sdap_options *opts;
34 : struct sysdb_ctx *sysdb;
35 : struct sss_domain_info *domain;
36 : struct sdap_handle *sh;
37 : const char *name;
38 : const char *orig_dn;
39 : const char **attrs;
40 : int timeout;
41 : const char *base_filter;
42 : char *filter;
43 :
44 : size_t count;
45 : struct sysdb_attrs **groups;
46 :
47 : size_t base_iter;
48 : struct sdap_search_base **search_bases;
49 : };
50 :
51 : static errno_t
52 : sdap_get_ad_match_rule_initgroups_next_base(struct tevent_req *req);
53 :
54 : static void
55 : sdap_get_ad_match_rule_initgroups_step(struct tevent_req *subreq);
56 :
57 : struct tevent_req *
58 0 : sdap_get_ad_match_rule_initgroups_send(TALLOC_CTX *mem_ctx,
59 : struct tevent_context *ev,
60 : struct sdap_options *opts,
61 : struct sysdb_ctx *sysdb,
62 : struct sss_domain_info *domain,
63 : struct sdap_handle *sh,
64 : const char *name,
65 : const char *orig_dn,
66 : int timeout)
67 : {
68 : errno_t ret;
69 : struct tevent_req *req;
70 : struct sdap_ad_match_rule_initgr_state *state;
71 : const char **filter_members;
72 : char *sanitized_user_dn;
73 : char *oc_list;
74 :
75 0 : req = tevent_req_create(mem_ctx, &state,
76 : struct sdap_ad_match_rule_initgr_state);
77 0 : if (!req) return NULL;
78 :
79 0 : state->ev = ev;
80 0 : state->opts = opts;
81 0 : state->sysdb = sysdb;
82 0 : state->domain = domain;
83 0 : state->sh = sh;
84 0 : state->name = name;
85 0 : state->orig_dn = orig_dn;
86 0 : state->base_iter = 0;
87 0 : state->search_bases = opts->sdom->group_search_bases;
88 :
89 : /* Request all of the group attributes that we know
90 : * about, except for 'member' because that wastes a
91 : * lot of bandwidth here and we only really
92 : * care about a single member (the one we already
93 : * have).
94 : */
95 0 : filter_members = talloc_array(state, const char *, 2);
96 0 : if (!filter_members) {
97 0 : ret = ENOMEM;
98 0 : goto immediate;
99 : }
100 0 : filter_members[0] = opts->group_map[SDAP_AT_GROUP_MEMBER].name;
101 0 : filter_members[1] = NULL;
102 :
103 0 : ret = build_attrs_from_map(state, opts->group_map,
104 : SDAP_OPTS_GROUP,
105 : filter_members,
106 0 : &state->attrs, NULL);
107 0 : if (ret != EOK) {
108 0 : DEBUG(SSSDBG_MINOR_FAILURE,
109 : "Could not build attribute map: [%s]\n",
110 : strerror(ret));
111 0 : goto immediate;
112 : }
113 :
114 : /* Sanitize the user DN in case we have special characters in DN */
115 0 : ret = sss_filter_sanitize(state, state->orig_dn, &sanitized_user_dn);
116 0 : if (ret != EOK) {
117 0 : DEBUG(SSSDBG_MINOR_FAILURE,
118 : "Could not sanitize user DN: %s\n",
119 : strerror(ret));
120 0 : goto immediate;
121 : }
122 :
123 : /* Craft a special filter according to
124 : * http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx
125 : */
126 0 : oc_list = sdap_make_oc_list(state, state->opts->group_map);
127 0 : if (oc_list == NULL) {
128 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
129 0 : ret = ENOMEM;
130 0 : goto immediate;
131 : }
132 :
133 0 : state->base_filter =
134 0 : talloc_asprintf(state,
135 : "(&(%s:%s:=%s)(%s))",
136 0 : state->opts->group_map[SDAP_AT_GROUP_MEMBER].name,
137 : SDAP_MATCHING_RULE_IN_CHAIN,
138 : sanitized_user_dn, oc_list);
139 0 : talloc_zfree(sanitized_user_dn);
140 0 : if (!state->base_filter) {
141 0 : ret = ENOMEM;
142 0 : goto immediate;
143 : }
144 :
145 : /* Start the loop through the search bases to get all of the
146 : * groups to which this user belongs.
147 : */
148 0 : ret = sdap_get_ad_match_rule_initgroups_next_base(req);
149 0 : if (ret != EOK) {
150 0 : DEBUG(SSSDBG_MINOR_FAILURE,
151 : "sdap_get_ad_match_rule_members_next_base failed: [%s]\n",
152 : strerror(ret));
153 0 : goto immediate;
154 : }
155 :
156 0 : return req;
157 :
158 : immediate:
159 0 : tevent_req_error(req, ret);
160 0 : tevent_req_post(req, ev);
161 0 : return req;
162 : }
163 :
164 : static errno_t
165 0 : sdap_get_ad_match_rule_initgroups_next_base(struct tevent_req *req)
166 : {
167 : struct tevent_req *subreq;
168 : struct sdap_ad_match_rule_initgr_state *state;
169 :
170 0 : state = tevent_req_data(req, struct sdap_ad_match_rule_initgr_state);
171 :
172 0 : talloc_zfree(state->filter);
173 0 : state->filter = sdap_get_id_specific_filter(state,
174 : 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 : static 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 : static 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 : static 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 : static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq)
842 : {
843 0 : TALLOC_CTX *tmp_ctx = NULL;
844 0 : struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
845 0 : struct tevent_req *req = NULL;
846 0 : struct sss_domain_info *domain = NULL;
847 0 : struct ldb_message *msg = NULL;
848 0 : const char *attrs[] = {SYSDB_NAME, NULL};
849 0 : const char *name = NULL;
850 0 : const char *sid = NULL;
851 0 : char **sids = NULL;
852 0 : size_t num_sids = 0;
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, sret;
859 0 : bool in_transaction = false;
860 :
861 0 : tmp_ctx = talloc_new(NULL);
862 0 : if (tmp_ctx == NULL) {
863 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
864 0 : ret = ENOMEM;
865 0 : goto done;
866 : }
867 :
868 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
869 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_mapping_state);
870 :
871 0 : ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
872 0 : talloc_zfree(subreq);
873 0 : if (ret != EOK) {
874 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire tokengroups [%d]: %s\n",
875 : ret, strerror(ret));
876 0 : goto done;
877 : }
878 :
879 0 : num_groups = 0;
880 0 : groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
881 0 : if (groups == NULL) {
882 0 : ret = ENOMEM;
883 0 : goto done;
884 : }
885 :
886 0 : now = time(NULL);
887 0 : ret = sysdb_transaction_start(state->sysdb);
888 0 : if (ret != EOK) {
889 0 : goto done;
890 : }
891 0 : in_transaction = true;
892 :
893 0 : for (i = 0; i < num_sids; i++) {
894 0 : sid = sids[i];
895 0 : DEBUG(SSSDBG_TRACE_LIBS, "Processing membership SID [%s]\n", sid);
896 :
897 0 : ret = sdap_idmap_sid_to_unix(state->idmap_ctx, sid, &gid);
898 0 : if (ret == ENOTSUP) {
899 0 : DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n");
900 0 : continue;
901 0 : } else if (ret != EOK) {
902 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not convert SID to GID: [%s]. "
903 : "Skipping\n", strerror(ret));
904 0 : continue;
905 : }
906 :
907 0 : domain = sss_get_domain_by_sid_ldap_fallback(state->domain, sid);
908 0 : if (domain == NULL) {
909 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found for SID %s\n", sid);
910 0 : continue;
911 : }
912 :
913 0 : DEBUG(SSSDBG_TRACE_LIBS, "SID [%s] maps to GID [%"SPRIgid"]\n",
914 : sid, gid);
915 :
916 : /* Check whether this GID already exists in the sysdb */
917 0 : ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, attrs, &msg);
918 0 : if (ret == EOK) {
919 0 : name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
920 0 : if (name == NULL) {
921 0 : DEBUG(SSSDBG_MINOR_FAILURE,
922 : "Could not retrieve group name from sysdb\n");
923 0 : ret = EINVAL;
924 0 : goto done;
925 : }
926 0 : } else if (ret == ENOENT) {
927 : /* This is a new group. For now, we will store it under the name
928 : * of its SID. When a direct lookup of the group or its GID occurs,
929 : * it will replace this temporary entry. */
930 0 : name = sid;
931 0 : ret = sysdb_add_incomplete_group(domain, name, gid,
932 : NULL, sid, NULL, false, now);
933 0 : if (ret != EOK) {
934 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not create incomplete "
935 : "group: [%s]\n", strerror(ret));
936 0 : goto done;
937 : }
938 : } else {
939 : /* Unexpected error */
940 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not look up group in sysdb: "
941 : "[%s]\n", strerror(ret));
942 0 : goto done;
943 : }
944 :
945 0 : groups[num_groups] = sysdb_group_strdn(tmp_ctx, domain->name, name);
946 0 : if (groups[num_groups] == NULL) {
947 0 : ret = ENOMEM;
948 0 : goto done;
949 : }
950 0 : num_groups++;
951 : }
952 :
953 0 : groups[num_groups] = NULL;
954 :
955 0 : ret = sdap_ad_tokengroups_update_members(state->username,
956 : state->sysdb, state->domain,
957 : groups);
958 0 : if (ret != EOK) {
959 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
960 : ret, strerror(ret));
961 0 : goto done;
962 : }
963 :
964 0 : ret = sysdb_transaction_commit(state->sysdb);
965 0 : if (ret != EOK) {
966 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not commit transaction! [%s]\n",
967 : strerror(ret));
968 0 : goto done;
969 : }
970 0 : in_transaction = false;
971 :
972 : done:
973 0 : talloc_free(tmp_ctx);
974 :
975 0 : if (in_transaction) {
976 0 : sret = sysdb_transaction_cancel(state->sysdb);
977 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Could not cancel transaction! [%s]\n",
978 : strerror(sret));
979 : }
980 :
981 0 : if (ret != EOK) {
982 0 : tevent_req_error(req, ret);
983 0 : return;
984 : }
985 :
986 0 : tevent_req_done(req);
987 : }
988 :
989 0 : static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req)
990 : {
991 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
992 :
993 0 : return EOK;
994 : }
995 :
996 : struct sdap_ad_tokengroups_initgr_posix_state {
997 : struct tevent_context *ev;
998 : struct sdap_id_ctx *id_ctx;
999 : struct sdap_id_conn_ctx *conn;
1000 : struct sdap_options *opts;
1001 : struct sdap_handle *sh;
1002 : struct sysdb_ctx *sysdb;
1003 : struct sss_domain_info *domain;
1004 : const char *orig_dn;
1005 : int timeout;
1006 : const char *username;
1007 :
1008 : struct sdap_id_op *op;
1009 : char **missing_sids;
1010 : size_t num_missing_sids;
1011 : char **cached_groups;
1012 : size_t num_cached_groups;
1013 : };
1014 :
1015 : static void
1016 : sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq);
1017 :
1018 : static void
1019 : sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq);
1020 : static void
1021 : sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq);
1022 :
1023 : static struct tevent_req *
1024 0 : sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx,
1025 : struct tevent_context *ev,
1026 : struct sdap_id_ctx *id_ctx,
1027 : struct sdap_id_conn_ctx *conn,
1028 : struct sdap_options *opts,
1029 : struct sysdb_ctx *sysdb,
1030 : struct sss_domain_info *domain,
1031 : struct sdap_handle *sh,
1032 : const char *name,
1033 : const char *orig_dn,
1034 : int timeout)
1035 : {
1036 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1037 0 : struct tevent_req *req = NULL;
1038 0 : struct tevent_req *subreq = NULL;
1039 : struct sdap_domain *sdom;
1040 : struct ad_id_ctx *subdom_id_ctx;
1041 : errno_t ret;
1042 :
1043 0 : req = tevent_req_create(mem_ctx, &state,
1044 : struct sdap_ad_tokengroups_initgr_posix_state);
1045 0 : if (req == NULL) {
1046 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1047 0 : return NULL;
1048 : }
1049 :
1050 0 : state->ev = ev;
1051 0 : state->id_ctx = id_ctx;
1052 0 : state->conn = conn;
1053 0 : state->opts = opts;
1054 0 : state->sh = sh;
1055 0 : state->sysdb = sysdb;
1056 0 : state->domain = domain;
1057 0 : state->orig_dn = orig_dn;
1058 0 : state->timeout = timeout;
1059 0 : state->username = talloc_strdup(state, name);
1060 0 : if (state->username == NULL) {
1061 0 : ret = ENOMEM;
1062 0 : goto immediately;
1063 : }
1064 :
1065 0 : sdom = sdap_domain_get(opts, domain);
1066 0 : if (sdom == NULL || sdom->pvt == NULL) {
1067 0 : ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout,
1068 0 : state->username, sh, req,
1069 : sdap_ad_tokengroups_initgr_posix_tg_done);
1070 0 : if (ret == EOK) {
1071 0 : return req;
1072 : } else {
1073 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
1074 : domain->name);
1075 0 : goto immediately;
1076 : }
1077 : }
1078 0 : subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
1079 0 : state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache);
1080 0 : if (!state->op) {
1081 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
1082 0 : ret = ENOMEM;
1083 0 : goto immediately;
1084 : }
1085 :
1086 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
1087 0 : if (subreq == NULL) {
1088 0 : ret = ENOMEM;
1089 0 : goto immediately;
1090 : }
1091 :
1092 0 : tevent_req_set_callback(subreq,
1093 : sdap_ad_tokengroups_initgr_posix_sids_connect_done,
1094 : req);
1095 :
1096 0 : return req;
1097 :
1098 : immediately:
1099 0 : if (ret == EOK) {
1100 0 : tevent_req_done(req);
1101 : } else {
1102 0 : tevent_req_error(req, ret);
1103 : }
1104 0 : tevent_req_post(req, ev);
1105 :
1106 0 : return req;
1107 : }
1108 :
1109 : static void
1110 0 : sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq)
1111 : {
1112 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1113 0 : struct tevent_req *req = NULL;
1114 : int ret;
1115 0 : int dp_error = DP_ERR_FATAL;
1116 :
1117 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1118 0 : state = tevent_req_data(req,
1119 : struct sdap_ad_tokengroups_initgr_posix_state);
1120 :
1121 :
1122 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
1123 0 : talloc_zfree(subreq);
1124 :
1125 0 : if (ret != EOK) {
1126 0 : tevent_req_error(req, ret);
1127 0 : return;
1128 : }
1129 :
1130 0 : subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts,
1131 : sdap_id_op_handle(state->op),
1132 : state->username, state->orig_dn,
1133 : state->timeout);
1134 0 : if (subreq == NULL) {
1135 0 : tevent_req_error(req, ENOMEM);
1136 0 : return;
1137 : }
1138 :
1139 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done,
1140 : req);
1141 :
1142 0 : return;
1143 : }
1144 :
1145 : static errno_t
1146 0 : sdap_ad_tokengroups_get_posix_members(TALLOC_CTX *mem_ctx,
1147 : struct sdap_ad_tokengroups_initgr_posix_state *state,
1148 : size_t num_sids,
1149 : char **sids,
1150 : size_t *_num_missing,
1151 : char ***_missing,
1152 : size_t *_num_valid,
1153 : char ***_valid_groups)
1154 : {
1155 0 : TALLOC_CTX *tmp_ctx = NULL;
1156 0 : struct sss_domain_info *domain = NULL;
1157 0 : struct ldb_message *msg = NULL;
1158 0 : const char *attrs[] = {SYSDB_NAME, NULL};
1159 0 : const char *name = NULL;
1160 0 : char *sid = NULL;
1161 0 : char **valid_groups = NULL;
1162 : size_t num_valid_groups;
1163 0 : char **missing_sids = NULL;
1164 : size_t num_missing_sids;
1165 : size_t i;
1166 : errno_t ret;
1167 :
1168 0 : tmp_ctx = talloc_new(NULL);
1169 0 : if (tmp_ctx == NULL) {
1170 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
1171 0 : ret = ENOMEM;
1172 0 : goto done;
1173 : }
1174 :
1175 0 : num_valid_groups = 0;
1176 0 : valid_groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
1177 0 : if (valid_groups == NULL) {
1178 0 : ret = ENOMEM;
1179 0 : goto done;
1180 : }
1181 :
1182 0 : num_missing_sids = 0;
1183 0 : missing_sids = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
1184 0 : if (missing_sids == NULL) {
1185 0 : ret = ENOMEM;
1186 0 : goto done;
1187 : }
1188 :
1189 : /* For each SID check if it is already present in the cache. If yes, we
1190 : * will get name of the group and update the membership. Otherwise we need
1191 : * to remember the SID and download missing groups one by one. */
1192 0 : for (i = 0; i < num_sids; i++) {
1193 0 : sid = sids[i];
1194 0 : DEBUG(SSSDBG_TRACE_LIBS, "Processing membership SID [%s]\n", sid);
1195 :
1196 0 : domain = sss_get_domain_by_sid_ldap_fallback(state->domain, sid);
1197 0 : if (domain == NULL) {
1198 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found for SID %s\n", sid);
1199 0 : continue;
1200 : }
1201 :
1202 0 : ret = sysdb_search_group_by_sid_str(tmp_ctx, domain, sid, attrs, &msg);
1203 0 : if (ret == EOK) {
1204 : /* we will update membership of this group */
1205 0 : name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1206 0 : if (name == NULL) {
1207 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1208 : "Could not retrieve group name from sysdb\n");
1209 0 : ret = EINVAL;
1210 0 : goto done;
1211 : }
1212 :
1213 0 : valid_groups[num_valid_groups] = sysdb_group_strdn(valid_groups,
1214 0 : domain->name,
1215 : name);
1216 0 : if (valid_groups[num_valid_groups] == NULL) {
1217 0 : ret = ENOMEM;
1218 0 : goto done;
1219 : }
1220 0 : num_valid_groups++;
1221 0 : } else if (ret == ENOENT) {
1222 0 : if (_missing != NULL) {
1223 : /* we need to download this group */
1224 0 : missing_sids[num_missing_sids] = talloc_steal(missing_sids,
1225 : sid);
1226 0 : num_missing_sids++;
1227 :
1228 0 : DEBUG(SSSDBG_TRACE_FUNC, "Missing SID %s will be downloaded\n",
1229 : sid);
1230 : }
1231 :
1232 : /* else: We have downloaded missing groups but some of them may
1233 : * remained missing because they are outside of search base. We
1234 : * will just ignore them and continue with the next group. */
1235 : } else {
1236 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not look up SID %s in sysdb: "
1237 : "[%s]\n", sid, strerror(ret));
1238 0 : goto done;
1239 : }
1240 : }
1241 :
1242 0 : valid_groups[num_valid_groups] = NULL;
1243 0 : missing_sids[num_missing_sids] = NULL;
1244 :
1245 : /* return list of missing groups */
1246 0 : if (_missing != NULL) {
1247 0 : *_missing = talloc_steal(mem_ctx, missing_sids);
1248 0 : *_num_missing = num_missing_sids;
1249 : }
1250 :
1251 : /* return list of missing groups */
1252 0 : if (_valid_groups != NULL) {
1253 0 : *_valid_groups = talloc_steal(mem_ctx, valid_groups);
1254 0 : *_num_valid = num_valid_groups;
1255 : }
1256 :
1257 0 : ret = EOK;
1258 :
1259 : done:
1260 0 : talloc_free(tmp_ctx);
1261 0 : return ret;
1262 : }
1263 :
1264 : static void
1265 0 : sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq)
1266 : {
1267 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1268 0 : struct tevent_req *req = NULL;
1269 0 : char **sids = NULL;
1270 0 : size_t num_sids = 0;
1271 : errno_t ret;
1272 :
1273 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1274 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state);
1275 :
1276 0 : ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
1277 0 : talloc_zfree(subreq);
1278 0 : if (ret != EOK) {
1279 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire tokengroups [%d]: %s\n",
1280 : ret, strerror(ret));
1281 0 : goto done;
1282 : }
1283 :
1284 0 : ret = sdap_ad_tokengroups_get_posix_members(state, state,
1285 : num_sids, sids,
1286 : &state->num_missing_sids,
1287 : &state->missing_sids,
1288 : &state->num_cached_groups,
1289 : &state->cached_groups);
1290 0 : if (ret != EOK) {
1291 0 : goto done;
1292 : }
1293 :
1294 : /* download missing SIDs */
1295 0 : subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx,
1296 : state->conn,
1297 : state->opts, state->domain,
1298 : state->missing_sids);
1299 0 : if (subreq == NULL) {
1300 0 : ret = ENOMEM;
1301 0 : goto done;
1302 : }
1303 :
1304 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_sids_done,
1305 : req);
1306 :
1307 0 : return;
1308 :
1309 : done:
1310 0 : if (ret != EOK) {
1311 0 : tevent_req_error(req, ret);
1312 0 : return;
1313 : }
1314 :
1315 0 : tevent_req_done(req);
1316 : }
1317 :
1318 : static char **concatenate_string_array(TALLOC_CTX *mem_ctx,
1319 : char **arr1, size_t len1,
1320 : char **arr2, size_t len2);
1321 :
1322 : static void
1323 0 : sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq)
1324 : {
1325 0 : struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
1326 0 : struct tevent_req *req = NULL;
1327 : errno_t ret;
1328 : char **cached_groups;
1329 : size_t num_cached_groups;
1330 :
1331 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1332 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state);
1333 :
1334 0 : ret = sdap_ad_resolve_sids_recv(subreq);
1335 0 : talloc_zfree(subreq);
1336 0 : if (ret != EOK) {
1337 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve missing SIDs "
1338 : "[%d]: %s\n", ret, strerror(ret));
1339 0 : goto done;
1340 : }
1341 :
1342 0 : ret = sdap_ad_tokengroups_get_posix_members(state, state,
1343 : state->num_missing_sids,
1344 : state->missing_sids,
1345 : NULL, NULL,
1346 : &num_cached_groups,
1347 : &cached_groups);
1348 0 : if (ret != EOK){
1349 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1350 : "sdap_ad_tokengroups_get_posix_members failed [%d]: %s\n",
1351 : ret, strerror(ret));
1352 0 : goto done;
1353 : }
1354 :
1355 0 : state->cached_groups = concatenate_string_array(state,
1356 : state->cached_groups,
1357 : state->num_cached_groups,
1358 : cached_groups,
1359 : num_cached_groups);
1360 0 : if (state->cached_groups == NULL) {
1361 0 : ret = ENOMEM;
1362 0 : goto done;
1363 : }
1364 :
1365 : /* update membership of existing groups */
1366 0 : ret = sdap_ad_tokengroups_update_members(state->username,
1367 : state->sysdb, state->domain,
1368 : state->cached_groups);
1369 0 : if (ret != EOK) {
1370 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
1371 : ret, strerror(ret));
1372 0 : goto done;
1373 : }
1374 :
1375 : done:
1376 0 : if (ret != EOK) {
1377 0 : tevent_req_error(req, ret);
1378 0 : return;
1379 : }
1380 :
1381 0 : tevent_req_done(req);
1382 : }
1383 :
1384 0 : static char **concatenate_string_array(TALLOC_CTX *mem_ctx,
1385 : char **arr1, size_t len1,
1386 : char **arr2, size_t len2)
1387 : {
1388 : size_t i, j;
1389 0 : size_t new_size = len1 + len2;
1390 0 : char ** string_array = talloc_realloc(mem_ctx, arr1, char *, new_size + 1);
1391 0 : if (string_array == NULL) {
1392 0 : return NULL;
1393 : }
1394 :
1395 0 : for (i=len1, j=0; i < new_size; ++i,++j) {
1396 0 : string_array[i] = talloc_steal(string_array,
1397 : arr2[j]);
1398 : }
1399 :
1400 0 : string_array[i] = NULL;
1401 :
1402 0 : return string_array;
1403 : }
1404 :
1405 0 : static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req)
1406 : {
1407 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1408 :
1409 0 : return EOK;
1410 : }
1411 :
1412 : struct sdap_ad_tokengroups_initgroups_state {
1413 : bool use_id_mapping;
1414 : struct sss_domain_info *domain;
1415 : };
1416 :
1417 : static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq);
1418 :
1419 : struct tevent_req *
1420 0 : sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
1421 : struct tevent_context *ev,
1422 : struct sdap_id_ctx *id_ctx,
1423 : struct sdap_id_conn_ctx *conn,
1424 : struct sdap_options *opts,
1425 : struct sysdb_ctx *sysdb,
1426 : struct sss_domain_info *domain,
1427 : struct sdap_handle *sh,
1428 : const char *name,
1429 : const char *orig_dn,
1430 : int timeout,
1431 : bool use_id_mapping)
1432 : {
1433 0 : struct sdap_ad_tokengroups_initgroups_state *state = NULL;
1434 0 : struct tevent_req *req = NULL;
1435 0 : struct tevent_req *subreq = NULL;
1436 : errno_t ret;
1437 :
1438 0 : req = tevent_req_create(mem_ctx, &state,
1439 : struct sdap_ad_tokengroups_initgroups_state);
1440 0 : if (req == NULL) {
1441 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1442 0 : return NULL;
1443 : }
1444 :
1445 0 : state->use_id_mapping = use_id_mapping;
1446 0 : state->domain = domain;
1447 :
1448 : /* We can compute the gidNumber attribute from SIDs obtained from
1449 : * the tokenGroups lookup in case ID mapping is used for a user from the
1450 : * parent domain. For trusted domains, we need to know the group type
1451 : * to be able to filter out domain-local groups. Additionally, as a
1452 : * temporary workaround until https://fedorahosted.org/sssd/ticket/2656
1453 : * is fixed, we also fetch the group object if group members are ignored
1454 : * to avoid having to transfer and retain members when the fake
1455 : * tokengroups object without name is replaced by the full group object
1456 : */
1457 0 : if (state->use_id_mapping
1458 0 : && !IS_SUBDOMAIN(state->domain)
1459 0 : && state->domain->ignore_group_members == false) {
1460 0 : subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts,
1461 : sysdb, domain, sh,
1462 : name, orig_dn,
1463 : timeout);
1464 : } else {
1465 0 : subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, conn,
1466 : opts, sysdb, domain, sh,
1467 : name, orig_dn,
1468 : timeout);
1469 : }
1470 0 : if (subreq == NULL) {
1471 0 : ret = ENOMEM;
1472 0 : goto immediately;
1473 : }
1474 :
1475 0 : tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req);
1476 :
1477 0 : return req;
1478 :
1479 : immediately:
1480 0 : if (ret == EOK) {
1481 0 : tevent_req_done(req);
1482 : } else {
1483 0 : tevent_req_error(req, ret);
1484 : }
1485 0 : tevent_req_post(req, ev);
1486 :
1487 0 : return req;
1488 : }
1489 :
1490 0 : static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq)
1491 : {
1492 0 : struct sdap_ad_tokengroups_initgroups_state *state = NULL;
1493 0 : struct tevent_req *req = NULL;
1494 : errno_t ret;
1495 :
1496 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1497 0 : state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state);
1498 :
1499 0 : if (state->use_id_mapping
1500 0 : && !IS_SUBDOMAIN(state->domain)
1501 0 : && state->domain->ignore_group_members == false) {
1502 0 : ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq);
1503 : } else {
1504 0 : ret = sdap_ad_tokengroups_initgr_posix_recv(subreq);
1505 : }
1506 0 : talloc_zfree(subreq);
1507 0 : if (ret != EOK) {
1508 0 : goto done;
1509 : }
1510 :
1511 : done:
1512 0 : if (ret != EOK) {
1513 0 : tevent_req_error(req, ret);
1514 0 : return;
1515 : }
1516 :
1517 0 : tevent_req_done(req);
1518 : }
1519 :
1520 0 : errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req)
1521 : {
1522 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1523 :
1524 0 : return EOK;
1525 : }
1526 :
1527 0 : static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx,
1528 : struct tevent_context *ev,
1529 : struct sdap_options *opts,
1530 : const char *orig_dn,
1531 : int timeout,
1532 : const char *username,
1533 : struct sdap_handle *sh,
1534 : struct tevent_req *req,
1535 : tevent_req_fn callback)
1536 : {
1537 0 : struct tevent_req *subreq = NULL;
1538 : errno_t ret;
1539 :
1540 0 : if (sh != NULL) {
1541 : /* plain LDAP provider already has a sdap_handle */
1542 0 : subreq = sdap_get_ad_tokengroups_send(mem_ctx, ev, opts, sh, username,
1543 : orig_dn, timeout);
1544 0 : if (subreq == NULL) {
1545 0 : ret = ENOMEM;
1546 0 : tevent_req_error(req, ret);
1547 0 : goto done;
1548 : }
1549 :
1550 0 : tevent_req_set_callback(subreq, callback, req);
1551 0 : ret = EOK;
1552 0 : goto done;
1553 :
1554 : } else {
1555 0 : ret = EINVAL;
1556 0 : goto done;
1557 : }
1558 :
1559 : done:
1560 0 : return ret;
1561 : }
|