Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2015 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <talloc.h>
22 : #include <tevent.h>
23 :
24 : #include "util/util.h"
25 : #include "db/sysdb.h"
26 : #include "util/strtonum.h"
27 : #include "sbus/sssd_dbus_errors.h"
28 : #include "responder/common/responder.h"
29 : #include "responder/common/responder_cache_req.h"
30 : #include "responder/ifp/ifp_groups.h"
31 : #include "responder/ifp/ifp_users.h"
32 : #include "responder/ifp/ifp_cache.h"
33 :
34 0 : char * ifp_groups_build_path_from_msg(TALLOC_CTX *mem_ctx,
35 : struct sss_domain_info *domain,
36 : struct ldb_message *msg)
37 : {
38 : const char *gid;
39 :
40 0 : gid = ldb_msg_find_attr_as_string(msg, SYSDB_GIDNUM, NULL);
41 :
42 0 : if (gid == NULL) {
43 0 : return NULL;
44 : }
45 :
46 0 : return sbus_opath_compose(mem_ctx, IFP_PATH_GROUPS, domain->name, gid);
47 : }
48 :
49 0 : static errno_t ifp_groups_decompose_path(struct sss_domain_info *domains,
50 : const char *path,
51 : struct sss_domain_info **_domain,
52 : gid_t *_gid)
53 : {
54 0 : char **parts = NULL;
55 : struct sss_domain_info *domain;
56 : gid_t gid;
57 : errno_t ret;
58 :
59 0 : ret = sbus_opath_decompose_exact(NULL, path, IFP_PATH_GROUPS, 2, &parts);
60 0 : if (ret != EOK) {
61 0 : return ret;
62 : }
63 :
64 0 : domain = find_domain_by_name(domains, parts[0], false);
65 0 : if (domain == NULL) {
66 0 : ret = ERR_DOMAIN_NOT_FOUND;
67 0 : goto done;
68 : }
69 :
70 0 : gid = strtouint32(parts[1], NULL, 10);
71 0 : ret = errno;
72 0 : if (ret != EOK) {
73 0 : goto done;
74 : }
75 :
76 0 : *_domain = domain;
77 0 : *_gid = gid;
78 :
79 : done:
80 0 : talloc_free(parts);
81 0 : return ret;
82 : }
83 :
84 0 : static int ifp_groups_list_copy(struct ifp_list_ctx *list_ctx,
85 : struct ldb_result *result)
86 : {
87 : size_t copy_count, i;
88 :
89 0 : copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count);
90 :
91 0 : for (i = 0; i < copy_count; i++) {
92 0 : list_ctx->paths[list_ctx->path_count + i] = \
93 0 : ifp_groups_build_path_from_msg(list_ctx->paths,
94 : list_ctx->dom,
95 0 : result->msgs[i]);
96 0 : if (list_ctx->paths[list_ctx->path_count + i] == NULL) {
97 0 : return ENOMEM;
98 : }
99 : }
100 :
101 0 : list_ctx->path_count += copy_count;
102 0 : return EOK;
103 : }
104 :
105 : static void ifp_groups_find_by_name_done(struct tevent_req *req);
106 :
107 0 : int ifp_groups_find_by_name(struct sbus_request *sbus_req,
108 : void *data,
109 : const char *name)
110 : {
111 : struct ifp_ctx *ctx;
112 : struct tevent_req *req;
113 :
114 0 : ctx = talloc_get_type(data, struct ifp_ctx);
115 0 : if (ctx == NULL) {
116 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
117 0 : return ERR_INTERNAL;
118 : }
119 :
120 0 : req = cache_req_group_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx,
121 : ctx->ncache, ctx->neg_timeout, 0,
122 : NULL, name);
123 0 : if (req == NULL) {
124 0 : return ENOMEM;
125 : }
126 :
127 0 : tevent_req_set_callback(req, ifp_groups_find_by_name_done, sbus_req);
128 :
129 0 : return EOK;
130 : }
131 :
132 : static void
133 0 : ifp_groups_find_by_name_done(struct tevent_req *req)
134 : {
135 : DBusError *error;
136 : struct sbus_request *sbus_req;
137 : struct sss_domain_info *domain;
138 : struct ldb_result *result;
139 : char *object_path;
140 : errno_t ret;
141 :
142 0 : sbus_req = tevent_req_callback_data(req, struct sbus_request);
143 :
144 0 : ret = cache_req_group_by_name_recv(sbus_req, req, &result, &domain, NULL);
145 0 : talloc_zfree(req);
146 0 : if (ret == ENOENT) {
147 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
148 : "Group not found");
149 0 : goto done;
150 0 : } else if (ret != EOK) {
151 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
152 : "group [%d]: %s\n", ret, sss_strerror(ret));
153 0 : goto done;
154 : }
155 :
156 0 : object_path = ifp_groups_build_path_from_msg(sbus_req, domain,
157 0 : result->msgs[0]);
158 0 : if (object_path == NULL) {
159 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
160 : "Failed to compose object path");
161 0 : goto done;
162 : }
163 :
164 0 : ret = EOK;
165 :
166 : done:
167 0 : if (ret != EOK) {
168 0 : sbus_request_fail_and_finish(sbus_req, error);
169 0 : return;
170 : }
171 :
172 0 : iface_ifp_groups_FindByName_finish(sbus_req, object_path);
173 0 : return;
174 : }
175 :
176 : static void ifp_groups_find_by_id_done(struct tevent_req *req);
177 :
178 0 : int ifp_groups_find_by_id(struct sbus_request *sbus_req,
179 : void *data,
180 : uint32_t id)
181 : {
182 : struct ifp_ctx *ctx;
183 : struct tevent_req *req;
184 :
185 0 : ctx = talloc_get_type(data, struct ifp_ctx);
186 0 : if (ctx == NULL) {
187 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
188 0 : return ERR_INTERNAL;
189 : }
190 :
191 0 : req = cache_req_group_by_id_send(sbus_req, ctx->rctx->ev, ctx->rctx,
192 : ctx->ncache, ctx->neg_timeout, 0,
193 : NULL, id);
194 0 : if (req == NULL) {
195 0 : return ENOMEM;
196 : }
197 :
198 0 : tevent_req_set_callback(req, ifp_groups_find_by_id_done, sbus_req);
199 :
200 0 : return EOK;
201 : }
202 :
203 : static void
204 0 : ifp_groups_find_by_id_done(struct tevent_req *req)
205 : {
206 : DBusError *error;
207 : struct sbus_request *sbus_req;
208 : struct sss_domain_info *domain;
209 : struct ldb_result *result;
210 : char *object_path;
211 : errno_t ret;
212 :
213 0 : sbus_req = tevent_req_callback_data(req, struct sbus_request);
214 :
215 0 : ret = cache_req_group_by_id_recv(sbus_req, req, &result, &domain);
216 0 : talloc_zfree(req);
217 0 : if (ret == ENOENT) {
218 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
219 : "Group not found");
220 0 : goto done;
221 0 : } else if (ret != EOK) {
222 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
223 : "group [%d]: %s\n", ret, sss_strerror(ret));
224 0 : goto done;
225 : }
226 :
227 0 : object_path = ifp_groups_build_path_from_msg(sbus_req, domain,
228 0 : result->msgs[0]);
229 0 : if (object_path == NULL) {
230 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
231 : "Failed to compose object path");
232 0 : goto done;
233 : }
234 :
235 : done:
236 0 : if (ret != EOK) {
237 0 : sbus_request_fail_and_finish(sbus_req, error);
238 0 : return;
239 : }
240 :
241 0 : iface_ifp_groups_FindByID_finish(sbus_req, object_path);
242 0 : return;
243 : }
244 :
245 : static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx);
246 : static void ifp_groups_list_by_name_done(struct tevent_req *req);
247 : static void ifp_groups_list_by_name_reply(struct ifp_list_ctx *list_ctx);
248 :
249 0 : int ifp_groups_list_by_name(struct sbus_request *sbus_req,
250 : void *data,
251 : const char *filter,
252 : uint32_t limit)
253 : {
254 : struct ifp_ctx *ctx;
255 : struct ifp_list_ctx *list_ctx;
256 :
257 0 : ctx = talloc_get_type(data, struct ifp_ctx);
258 0 : if (ctx == NULL) {
259 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
260 0 : return ERR_INTERNAL;
261 : }
262 :
263 0 : list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit);
264 0 : if (list_ctx == NULL) {
265 0 : return ENOMEM;
266 : }
267 :
268 0 : return ifp_groups_list_by_name_step(list_ctx);
269 : }
270 :
271 0 : static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx)
272 : {
273 : struct tevent_req *req;
274 :
275 0 : req = cache_req_group_by_filter_send(list_ctx,
276 0 : list_ctx->ctx->rctx->ev,
277 0 : list_ctx->ctx->rctx,
278 0 : list_ctx->dom->name,
279 : list_ctx->filter);
280 0 : if (req == NULL) {
281 0 : return ENOMEM;
282 : }
283 0 : tevent_req_set_callback(req,
284 : ifp_groups_list_by_name_done, list_ctx);
285 :
286 0 : return EOK;
287 : }
288 :
289 0 : static void ifp_groups_list_by_name_done(struct tevent_req *req)
290 : {
291 : DBusError *error;
292 : struct ifp_list_ctx *list_ctx;
293 : struct sbus_request *sbus_req;
294 : struct ldb_result *result;
295 : struct sss_domain_info *domain;
296 : errno_t ret;
297 :
298 0 : list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx);
299 0 : sbus_req = list_ctx->sbus_req;
300 :
301 0 : ret = cache_req_group_by_name_recv(sbus_req, req, &result, &domain, NULL);
302 0 : talloc_zfree(req);
303 0 : if (ret != EOK && ret != ENOENT) {
304 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
305 : "groups by filter [%d]: %s\n", ret, sss_strerror(ret));
306 0 : sbus_request_fail_and_finish(sbus_req, error);
307 0 : return;
308 : }
309 :
310 0 : ret = ifp_groups_list_copy(list_ctx, result);
311 0 : if (ret != EOK) {
312 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
313 : "Failed to copy domain result");
314 0 : sbus_request_fail_and_finish(sbus_req, error);
315 0 : return;
316 : }
317 :
318 0 : list_ctx->dom = get_next_domain(list_ctx->dom, true);
319 0 : if (list_ctx->dom == NULL) {
320 0 : return ifp_groups_list_by_name_reply(list_ctx);
321 : }
322 :
323 0 : ret = ifp_groups_list_by_name_step(list_ctx);
324 0 : if (ret != EOK) {
325 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
326 : "Failed to start next-domain search");
327 0 : sbus_request_fail_and_finish(sbus_req, error);
328 0 : return;
329 : }
330 : }
331 :
332 0 : static void ifp_groups_list_by_name_reply(struct ifp_list_ctx *list_ctx)
333 : {
334 0 : iface_ifp_groups_ListByDomainAndName_finish(list_ctx->sbus_req,
335 : list_ctx->paths,
336 0 : list_ctx->path_count);
337 0 : }
338 :
339 : static void ifp_groups_list_by_domain_and_name_done(struct tevent_req *req);
340 :
341 0 : int ifp_groups_list_by_domain_and_name(struct sbus_request *sbus_req,
342 : void *data,
343 : const char *domain,
344 : const char *filter,
345 : uint32_t limit)
346 : {
347 : struct tevent_req *req;
348 : struct ifp_ctx *ctx;
349 : struct ifp_list_ctx *list_ctx;
350 :
351 0 : ctx = talloc_get_type(data, struct ifp_ctx);
352 0 : if (ctx == NULL) {
353 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
354 0 : return ERR_INTERNAL;
355 : }
356 :
357 0 : list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit);
358 0 : if (list_ctx == NULL) {
359 0 : return ENOMEM;
360 : }
361 :
362 0 : req = cache_req_group_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx,
363 : domain, filter);
364 0 : if (req == NULL) {
365 0 : return ENOMEM;
366 : }
367 0 : tevent_req_set_callback(req,
368 : ifp_groups_list_by_domain_and_name_done, list_ctx);
369 :
370 0 : return EOK;
371 : }
372 :
373 0 : static void ifp_groups_list_by_domain_and_name_done(struct tevent_req *req)
374 : {
375 : DBusError *error;
376 : struct ifp_list_ctx *list_ctx;
377 : struct sbus_request *sbus_req;
378 : struct ldb_result *result;
379 : struct sss_domain_info *domain;
380 : errno_t ret;
381 :
382 0 : list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx);
383 0 : sbus_req = list_ctx->sbus_req;
384 :
385 0 : ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL);
386 0 : talloc_zfree(req);
387 0 : if (ret == ENOENT) {
388 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
389 : "User not found by filter");
390 0 : goto done;
391 0 : } else if (ret != EOK) {
392 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
393 : "groups by filter [%d]: %s\n", ret, sss_strerror(ret));
394 0 : goto done;
395 : }
396 :
397 0 : ret = ifp_groups_list_copy(list_ctx, result);
398 0 : if (ret != EOK) {
399 0 : error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
400 : "Failed to copy domain result");
401 0 : goto done;
402 : }
403 :
404 : done:
405 0 : if (ret != EOK) {
406 0 : sbus_request_fail_and_finish(sbus_req, error);
407 0 : return;
408 : }
409 :
410 0 : iface_ifp_groups_ListByDomainAndName_finish(sbus_req,
411 : list_ctx->paths,
412 0 : list_ctx->path_count);
413 0 : return;
414 : }
415 :
416 : static errno_t
417 0 : ifp_groups_group_get(struct sbus_request *sbus_req,
418 : void *data,
419 : gid_t *_gid,
420 : struct sss_domain_info **_domain,
421 : struct ldb_message **_group)
422 : {
423 : struct ifp_ctx *ctx;
424 : struct sss_domain_info *domain;
425 : struct ldb_result *res;
426 : uid_t gid;
427 : errno_t ret;
428 :
429 0 : ctx = talloc_get_type(data, struct ifp_ctx);
430 0 : if (ctx == NULL) {
431 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
432 0 : return ERR_INTERNAL;
433 : }
434 :
435 0 : ret = ifp_groups_decompose_path(ctx->rctx->domains, sbus_req->path,
436 : &domain, &gid);
437 0 : if (ret != EOK) {
438 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to decompose object path"
439 : "[%s] [%d]: %s\n", sbus_req->path, ret, sss_strerror(ret));
440 0 : return ret;
441 : }
442 :
443 0 : if (_group != NULL) {
444 0 : ret = sysdb_getgrgid_with_views(sbus_req, domain, gid, &res);
445 0 : if (ret == EOK && res->count == 0) {
446 0 : *_group = NULL;
447 0 : ret = ENOENT;
448 : }
449 :
450 0 : if (ret != EOK) {
451 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup group %u@%s [%d]: %s\n",
452 : gid, domain->name, ret, sss_strerror(ret));
453 : } else {
454 0 : *_group = res->msgs[0];
455 : }
456 : }
457 :
458 0 : if (ret == EOK || ret == ENOENT) {
459 0 : if (_gid != NULL) {
460 0 : *_gid = gid;
461 : }
462 :
463 0 : if (_domain != NULL) {
464 0 : *_domain = domain;
465 : }
466 : }
467 :
468 0 : return ret;
469 : }
470 :
471 : struct resolv_ghosts_state {
472 : struct tevent_context *ev;
473 : struct sbus_request *sbus_req;
474 : struct ifp_ctx *ctx;
475 : void *data;
476 :
477 : struct sss_domain_info *domain;
478 : const char **ghosts;
479 : int index;
480 : };
481 :
482 : static void resolv_ghosts_group_done(struct tevent_req *subreq);
483 : static errno_t resolv_ghosts_step(struct tevent_req *req);
484 : static void resolv_ghosts_done(struct tevent_req *subreq);
485 :
486 0 : static struct tevent_req *resolv_ghosts_send(TALLOC_CTX *mem_ctx,
487 : struct tevent_context *ev,
488 : struct sbus_request *sbus_req,
489 : void *data)
490 : {
491 : struct resolv_ghosts_state *state;
492 : struct sss_domain_info *domain;
493 : struct tevent_req *req;
494 : struct tevent_req *subreq;
495 : struct ldb_message *group;
496 : struct ifp_ctx *ctx;
497 : const char *name;
498 : errno_t ret;
499 :
500 0 : req = tevent_req_create(mem_ctx, &state, struct resolv_ghosts_state);
501 0 : if (req == NULL) {
502 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
503 0 : return NULL;
504 : }
505 :
506 0 : ctx = talloc_get_type(data, struct ifp_ctx);
507 0 : if (ctx == NULL) {
508 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
509 0 : ret = ERR_INTERNAL;
510 0 : goto immediately;
511 : }
512 :
513 0 : state->ev = ev;
514 0 : state->sbus_req = sbus_req;
515 0 : state->ctx = ctx;
516 0 : state->data = data;
517 :
518 0 : ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group);
519 0 : if (ret != EOK) {
520 0 : goto immediately;
521 : }
522 :
523 0 : name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL);
524 0 : if (name == NULL) {
525 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Group name is empty!\n");
526 0 : ret = ERR_INTERNAL;
527 0 : goto immediately;
528 : }
529 :
530 0 : subreq = cache_req_group_by_name_send(state, ev, ctx->rctx,
531 : ctx->ncache, ctx->neg_timeout, 0,
532 0 : domain->name, name);
533 0 : if (subreq == NULL) {
534 0 : ret = ENOMEM;
535 0 : goto immediately;
536 : }
537 :
538 0 : tevent_req_set_callback(subreq, resolv_ghosts_group_done, req);
539 :
540 0 : return req;
541 :
542 : immediately:
543 0 : if (ret == EOK) {
544 0 : tevent_req_done(req);
545 : } else {
546 0 : tevent_req_error(req, ret);
547 : }
548 0 : tevent_req_post(req, ev);
549 :
550 0 : return req;
551 : }
552 :
553 0 : static void resolv_ghosts_group_done(struct tevent_req *subreq)
554 : {
555 : struct resolv_ghosts_state *state;
556 : struct ldb_message_element *el;
557 : struct ldb_message *group;
558 : struct tevent_req *req;
559 : errno_t ret;
560 :
561 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
562 0 : state = tevent_req_data(req, struct resolv_ghosts_state);
563 :
564 0 : ret = ifp_groups_group_get(state->sbus_req, state->data, NULL,
565 : &state->domain, &group);
566 0 : if (ret != EOK) {
567 0 : goto done;
568 : }
569 :
570 0 : el = ldb_msg_find_element(group, SYSDB_GHOST);
571 0 : if (el == NULL) {
572 0 : ret = ENOMEM;
573 0 : goto done;
574 : }
575 :
576 0 : if (el->num_values == 0) {
577 0 : ret = EOK;
578 0 : goto done;
579 : }
580 :
581 0 : state->ghosts = sss_ldb_el_to_string_list(state, el);
582 0 : if (state->ghosts == NULL) {
583 0 : ret = ENOMEM;
584 0 : goto done;
585 : }
586 :
587 0 : state->index = 0;
588 0 : ret = resolv_ghosts_step(req);
589 :
590 : done:
591 0 : if (ret == EOK) {
592 0 : tevent_req_done(req);
593 0 : } else if (ret != EAGAIN) {
594 0 : tevent_req_error(req, ret);
595 : }
596 0 : }
597 :
598 0 : errno_t resolv_ghosts_step(struct tevent_req *req)
599 : {
600 : struct resolv_ghosts_state *state;
601 : struct tevent_req *subreq;
602 :
603 0 : state = tevent_req_data(req, struct resolv_ghosts_state);
604 :
605 0 : if (state->ghosts[state->index] == NULL) {
606 0 : return EOK;
607 : }
608 :
609 0 : subreq = cache_req_user_by_name_send(state, state->ev, state->ctx->rctx,
610 0 : state->ctx->ncache, state->ctx->neg_timeout,
611 0 : 0, state->domain->name,
612 0 : state->ghosts[state->index]);
613 0 : if (subreq == NULL) {
614 0 : return ENOMEM;
615 : }
616 :
617 0 : tevent_req_set_callback(subreq, resolv_ghosts_done, req);
618 :
619 0 : state->index++;
620 :
621 0 : return EAGAIN;
622 : }
623 :
624 0 : static void resolv_ghosts_done(struct tevent_req *subreq)
625 : {
626 0 : struct resolv_ghosts_state *state = NULL;
627 0 : struct tevent_req *req = NULL;
628 : errno_t ret;
629 :
630 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
631 0 : state = tevent_req_data(req, struct resolv_ghosts_state);
632 :
633 0 : ret = cache_req_user_by_name_recv(state, subreq, NULL, NULL, NULL);
634 0 : talloc_zfree(subreq);
635 0 : if (ret != EOK) {
636 0 : goto done;
637 : }
638 :
639 0 : ret = resolv_ghosts_step(req);
640 :
641 : done:
642 0 : if (ret == EOK) {
643 0 : tevent_req_done(req);
644 0 : } else if (ret != EAGAIN) {
645 0 : tevent_req_error(req, ret);
646 : }
647 0 : }
648 :
649 0 : static errno_t resolv_ghosts_recv(struct tevent_req *req)
650 : {
651 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
652 :
653 0 : return EOK;
654 : }
655 :
656 : static void ifp_groups_group_update_member_list_done(struct tevent_req *req);
657 :
658 0 : int ifp_groups_group_update_member_list(struct sbus_request *sbus_req,
659 : void *data)
660 : {
661 : struct tevent_req *subreq;
662 : struct ifp_ctx *ctx;
663 :
664 0 : ctx = talloc_get_type(data, struct ifp_ctx);
665 0 : if (ctx == NULL) {
666 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
667 0 : return ERR_INTERNAL;
668 : }
669 :
670 0 : subreq = resolv_ghosts_send(sbus_req, ctx->rctx->ev, sbus_req, data);
671 0 : if (subreq == NULL) {
672 0 : return ENOMEM;
673 : }
674 :
675 0 : tevent_req_set_callback(subreq, ifp_groups_group_update_member_list_done,
676 : sbus_req);
677 :
678 0 : return EOK;
679 : }
680 :
681 0 : static void ifp_groups_group_update_member_list_done(struct tevent_req *subreq)
682 : {
683 : DBusError *error;
684 : struct sbus_request *sbus_req;
685 : errno_t ret;
686 :
687 0 : sbus_req = tevent_req_callback_data(subreq, struct sbus_request);
688 :
689 0 : ret = resolv_ghosts_recv(subreq);
690 0 : talloc_zfree(subreq);
691 0 : if (ret != EOK) {
692 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
693 : "Unable to resolve ghost members [%d]: %s\n",
694 : ret, sss_strerror(ret));
695 0 : sbus_request_fail_and_finish(sbus_req, error);
696 0 : return;
697 : }
698 :
699 0 : iface_ifp_groups_group_UpdateMemberList_finish(sbus_req);
700 0 : return;
701 : }
702 :
703 0 : void ifp_groups_group_get_name(struct sbus_request *sbus_req,
704 : void *data,
705 : const char **_out)
706 : {
707 : struct ldb_message *msg;
708 : struct sss_domain_info *domain;
709 : errno_t ret;
710 :
711 0 : ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &msg);
712 0 : if (ret != EOK) {
713 0 : *_out = NULL;
714 0 : return;
715 : }
716 :
717 0 : *_out = sss_view_ldb_msg_find_attr_as_string(domain, msg, SYSDB_NAME, NULL);
718 :
719 0 : return;
720 : }
721 :
722 0 : void ifp_groups_group_get_gid_number(struct sbus_request *sbus_req,
723 : void *data,
724 : uint32_t *_out)
725 : {
726 : struct ldb_message *msg;
727 : struct sss_domain_info *domain;
728 : errno_t ret;
729 :
730 0 : ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &msg);
731 0 : if (ret != EOK) {
732 0 : *_out = 0;
733 0 : return;
734 : }
735 :
736 0 : *_out = sss_view_ldb_msg_find_attr_as_uint64(domain, msg, SYSDB_GIDNUM, 0);
737 :
738 0 : return;
739 : }
740 :
741 : static errno_t
742 0 : ifp_groups_group_get_members(TALLOC_CTX *mem_ctx,
743 : struct sbus_request *sbus_req,
744 : void *data,
745 : const char ***_users,
746 : int *_num_users,
747 : const char ***_groups,
748 : int *_num_groups)
749 : {
750 : TALLOC_CTX *tmp_ctx;
751 : struct sss_domain_info *domain;
752 : struct ldb_message *group;
753 : struct ldb_message **members;
754 : size_t num_members;
755 : const char *class;
756 : const char **users;
757 : const char **groups;
758 : int num_users;
759 : int num_groups;
760 : int i;
761 : errno_t ret;
762 0 : const char *attrs[] = {SYSDB_OBJECTCLASS, SYSDB_UIDNUM,
763 : SYSDB_GIDNUM, NULL};
764 :
765 0 : tmp_ctx = talloc_new(NULL);
766 0 : if (tmp_ctx == NULL) {
767 0 : return ENOMEM;
768 : }
769 :
770 0 : ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group);
771 0 : if (ret != EOK) {
772 0 : goto done;
773 : }
774 :
775 0 : ret = sysdb_asq_search(tmp_ctx, domain, group->dn, NULL, SYSDB_MEMBER,
776 : attrs, &num_members, &members);
777 0 : if (ret != EOK) {
778 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform ASQ search [%d]: %s\n",
779 : ret, sss_strerror(ret));
780 0 : goto done;
781 : }
782 :
783 0 : if (num_members == 0) {
784 0 : users = NULL;
785 0 : groups = NULL;
786 0 : num_users = 0;
787 0 : num_groups = 0;
788 0 : ret = EOK;
789 0 : goto done;
790 : }
791 :
792 0 : users = talloc_zero_array(tmp_ctx, const char *, num_members + 1);
793 0 : if (users == NULL) {
794 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
795 0 : ret = ENOMEM;
796 0 : goto done;
797 : }
798 :
799 0 : groups = talloc_zero_array(tmp_ctx, const char *, num_members + 1);
800 0 : if (groups == NULL) {
801 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
802 0 : ret = ENOMEM;
803 0 : goto done;
804 : }
805 :
806 0 : num_users = 0;
807 0 : num_groups = 0;
808 0 : for (i = 0; i < num_members; i++) {
809 0 : class = ldb_msg_find_attr_as_string(members[i], SYSDB_OBJECTCLASS,
810 : NULL);
811 0 : if (class == NULL) {
812 0 : ret = ERR_INTERNAL;
813 0 : goto done;
814 : }
815 :
816 0 : if (strcmp(class, SYSDB_USER_CLASS) == 0) {
817 0 : users[num_users] = ifp_users_build_path_from_msg(users, domain,
818 0 : members[i]);
819 0 : if (users[num_users] == NULL) {
820 0 : ret = ENOMEM;
821 0 : goto done;
822 : }
823 :
824 0 : num_users++;
825 0 : } else if (strcmp(class, SYSDB_GROUP_CLASS) == 0) {
826 0 : groups[num_groups] = ifp_groups_build_path_from_msg(groups,
827 0 : domain, members[i]);
828 0 : if (groups[num_groups] == NULL) {
829 0 : ret = ENOMEM;
830 0 : goto done;
831 : }
832 :
833 0 : num_groups++;
834 : } else {
835 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected object class %s\n", class);
836 0 : ret = ERR_INTERNAL;
837 0 : goto done;
838 : }
839 : }
840 :
841 0 : ret = EOK;
842 :
843 : done:
844 0 : if (ret == EOK) {
845 0 : if (_users != NULL) {
846 0 : *_users = talloc_steal(mem_ctx, users);
847 : }
848 :
849 0 : if (_num_users != NULL) {
850 0 : *_num_users = num_users;
851 : }
852 :
853 0 : if (_groups != NULL) {
854 0 : *_groups = talloc_steal(mem_ctx, groups);
855 : }
856 :
857 0 : if (_num_groups != NULL) {
858 0 : *_num_groups = num_groups;
859 : }
860 : }
861 :
862 0 : talloc_free(tmp_ctx);
863 0 : return ret;
864 : }
865 :
866 0 : void ifp_groups_group_get_users(struct sbus_request *sbus_req,
867 : void *data,
868 : const char ***_out,
869 : int *_size)
870 : {
871 : errno_t ret;
872 :
873 0 : *_out = NULL;
874 0 : *_size = 0;
875 :
876 0 : ret = ifp_groups_group_get_members(sbus_req, sbus_req, data, _out, _size,
877 : NULL, NULL);
878 0 : if (ret != EOK) {
879 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire groups members\n");
880 : }
881 0 : }
882 :
883 0 : void ifp_groups_group_get_groups(struct sbus_request *sbus_req,
884 : void *data,
885 : const char ***_out,
886 : int *_size)
887 : {
888 : errno_t ret;
889 :
890 0 : *_out = NULL;
891 0 : *_size = 0;
892 :
893 0 : ret = ifp_groups_group_get_members(sbus_req, sbus_req, data, NULL, NULL,
894 : _out, _size);
895 0 : if (ret != EOK) {
896 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire groups members\n");
897 : }
898 0 : }
899 :
900 0 : int ifp_cache_list_group(struct sbus_request *sbus_req,
901 : void *data)
902 : {
903 0 : return ifp_cache_list(sbus_req, data, IFP_CACHE_GROUP);
904 : }
905 :
906 0 : int ifp_cache_list_by_domain_group(struct sbus_request *sbus_req,
907 : void *data,
908 : const char *domain)
909 : {
910 0 : return ifp_cache_list_by_domain(sbus_req, data, domain, IFP_CACHE_GROUP);
911 : }
912 :
913 0 : int ifp_cache_object_store_group(struct sbus_request *sbus_req,
914 : void *data)
915 : {
916 : DBusError *error;
917 : struct sss_domain_info *domain;
918 : struct ldb_message *group;
919 : errno_t ret;
920 :
921 0 : ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group);
922 0 : if (ret != EOK) {
923 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
924 : "group [%d]: %s\n", ret, sss_strerror(ret));
925 0 : return sbus_request_fail_and_finish(sbus_req, error);
926 : }
927 :
928 : /* The request is finished inside. */
929 0 : return ifp_cache_object_store(sbus_req, domain, group->dn);
930 : }
931 :
932 0 : int ifp_cache_object_remove_group(struct sbus_request *sbus_req,
933 : void *data)
934 : {
935 : DBusError *error;
936 : struct sss_domain_info *domain;
937 : struct ldb_message *group;
938 : errno_t ret;
939 :
940 0 : ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group);
941 0 : if (ret != EOK) {
942 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
943 : "group [%d]: %s\n", ret, sss_strerror(ret));
944 0 : return sbus_request_fail_and_finish(sbus_req, error);
945 : }
946 :
947 : /* The request is finished inside. */
948 0 : return ifp_cache_object_remove(sbus_req, domain, group->dn);
949 : }
|