Line data Source code
1 : /*
2 : SSSD
3 :
4 : sss_groupshow
5 :
6 : Copyright (C) Jakub Hrozek <jhrozek@redhat.com> 2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <talloc.h>
25 : #include <popt.h>
26 :
27 : #include "db/sysdb.h"
28 : #include "util/util.h"
29 : #include "tools/tools_util.h"
30 : #include "tools/sss_sync_ops.h"
31 :
32 : #define PADDING_SPACES 4
33 : #define GROUP_SHOW_ATTRS { SYSDB_MEMBEROF, SYSDB_GIDNUM, \
34 : SYSDB_MEMBER, SYSDB_GHOST, SYSDB_NAME, \
35 : NULL }
36 : #define GROUP_SHOW_MPG_ATTRS { SYSDB_MEMBEROF, SYSDB_UIDNUM, \
37 : SYSDB_NAME, NULL }
38 :
39 : struct group_info {
40 : const char *name;
41 : gid_t gid;
42 : bool mpg;
43 :
44 : const char **user_members;
45 : const char **memberofs;
46 :
47 : struct group_info **group_members;
48 : };
49 :
50 : /*==================Helper routines to process results================= */
51 0 : const char *rdn_as_string(TALLOC_CTX *mem_ctx,
52 : struct ldb_dn *dn)
53 : {
54 : const struct ldb_val *val;
55 :
56 0 : val = ldb_dn_get_rdn_val(dn);
57 0 : if (val == NULL) {
58 0 : return NULL;
59 : }
60 :
61 0 : return ldb_dn_escape_value(mem_ctx, *val);;
62 : }
63 :
64 0 : static int parse_memberofs(struct ldb_context *ldb,
65 : struct ldb_message_element *el,
66 : struct group_info *gi)
67 : {
68 : int i;
69 0 : struct ldb_dn *dn = NULL;
70 :
71 0 : gi->memberofs = talloc_array(gi, const char *, el->num_values+1);
72 0 : if (gi->memberofs == NULL) {
73 0 : return ENOMEM;
74 : }
75 :
76 0 : for (i = 0; i< el->num_values; ++i) {
77 0 : dn = ldb_dn_from_ldb_val(gi, ldb, &(el->values[i]));
78 0 : gi->memberofs[i] = talloc_strdup(gi, rdn_as_string(gi, dn));
79 0 : talloc_zfree(dn);
80 0 : if (gi->memberofs[i] == NULL) {
81 0 : return ENOMEM;
82 : }
83 0 : DEBUG(SSSDBG_TRACE_FUNC, "memberof value: %s\n", gi->memberofs[i]);
84 : }
85 0 : gi->memberofs[el->num_values] = NULL;
86 :
87 0 : return EOK;
88 : }
89 :
90 0 : static int parse_members(TALLOC_CTX *mem_ctx,
91 : struct ldb_context *ldb,
92 : struct sss_domain_info *domain,
93 : struct ldb_message_element *el,
94 : const char *parent_name,
95 : const char ***user_members,
96 : const char ***group_members,
97 : int *num_group_members)
98 : {
99 0 : struct ldb_dn *user_basedn = NULL, *group_basedn = NULL;
100 0 : struct ldb_dn *parent_dn = NULL;
101 0 : struct ldb_dn *dn = NULL;
102 0 : const char **um = NULL, **gm = NULL;
103 0 : unsigned int um_index = 0, gm_index = 0;
104 0 : TALLOC_CTX *tmp_ctx = NULL;
105 : int ret;
106 : int i;
107 :
108 0 : tmp_ctx = talloc_new(mem_ctx);
109 0 : if (!tmp_ctx) {
110 0 : ret = ENOMEM;
111 0 : goto fail;
112 : }
113 :
114 0 : user_basedn = sysdb_user_base_dn(tmp_ctx, domain);
115 0 : group_basedn = sysdb_group_base_dn(tmp_ctx, domain);
116 0 : if (!user_basedn || !group_basedn) {
117 0 : ret = ENOMEM;
118 0 : goto fail;
119 : }
120 :
121 0 : um = talloc_array(mem_ctx, const char *, el->num_values+1);
122 0 : gm = talloc_array(mem_ctx, const char *, el->num_values+1);
123 0 : if (!um || !gm) {
124 0 : ret = ENOMEM;
125 0 : goto fail;
126 : }
127 :
128 0 : for (i = 0; i< el->num_values; ++i) {
129 0 : dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &(el->values[i]));
130 :
131 : /* user member or group member? */
132 0 : parent_dn = ldb_dn_get_parent(tmp_ctx, dn);
133 0 : if (ldb_dn_compare_base(parent_dn, user_basedn) == 0) {
134 0 : um[um_index] = rdn_as_string(mem_ctx, dn);
135 0 : if (um[um_index] == NULL) {
136 0 : ret = ENOMEM;
137 0 : goto fail;
138 : }
139 0 : DEBUG(SSSDBG_TRACE_FUNC, "User member %s\n", um[um_index]);
140 0 : um_index++;
141 0 : } else if (ldb_dn_compare_base(parent_dn, group_basedn) == 0) {
142 0 : gm[gm_index] = rdn_as_string(mem_ctx, dn);
143 0 : if (gm[gm_index] == NULL) {
144 0 : ret = ENOMEM;
145 0 : goto fail;
146 : }
147 0 : if (parent_name && strcmp(gm[gm_index], parent_name) == 0) {
148 0 : DEBUG(SSSDBG_TRACE_FUNC,
149 : "Skipping circular nesting for group %s\n",
150 : gm[gm_index]);
151 0 : continue;
152 : }
153 0 : DEBUG(SSSDBG_TRACE_FUNC, "Group member %s\n", gm[gm_index]);
154 0 : gm_index++;
155 : } else {
156 0 : DEBUG(SSSDBG_OP_FAILURE, "Group member not a user nor group: %s\n",
157 : ldb_dn_get_linearized(dn));
158 0 : ret = EIO;
159 0 : goto fail;
160 : }
161 :
162 0 : talloc_zfree(dn);
163 0 : talloc_zfree(parent_dn);
164 : }
165 0 : um[um_index] = NULL;
166 0 : gm[gm_index] = NULL;
167 :
168 0 : if (um_index > 0) {
169 0 : um = talloc_realloc(mem_ctx, um, const char *, um_index+1);
170 0 : if (!um) {
171 0 : ret = ENOMEM;
172 0 : goto fail;
173 : }
174 : } else {
175 0 : talloc_zfree(um);
176 : }
177 :
178 0 : if (gm_index > 0) {
179 0 : gm = talloc_realloc(mem_ctx, gm, const char *, gm_index+1);
180 0 : if (!gm) {
181 0 : ret = ENOMEM;
182 0 : goto fail;
183 : }
184 : } else {
185 0 : talloc_zfree(gm);
186 : }
187 :
188 0 : *user_members = um;
189 0 : if (group_members) *group_members = gm;
190 0 : if (num_group_members) *num_group_members = gm_index;
191 0 : talloc_zfree(tmp_ctx);
192 0 : return EOK;
193 :
194 : fail:
195 0 : talloc_zfree(um);
196 0 : talloc_zfree(gm);
197 0 : talloc_zfree(tmp_ctx);
198 0 : return ret;
199 : }
200 :
201 0 : static int process_group(TALLOC_CTX *mem_ctx,
202 : struct ldb_context *ldb,
203 : struct ldb_message *msg,
204 : struct sss_domain_info *domain,
205 : const char *parent_name,
206 : struct group_info **info,
207 : const char ***group_members,
208 : int *num_group_members)
209 : {
210 : struct ldb_message_element *el;
211 : int ret, i, j;
212 0 : int count = 0;
213 0 : struct group_info *gi = NULL;
214 : const char **user_members;
215 :
216 0 : DEBUG(SSSDBG_TRACE_FUNC,
217 : "Found entry %s\n", ldb_dn_get_linearized(msg->dn));
218 :
219 0 : gi = talloc_zero(mem_ctx, struct group_info);
220 0 : if (!gi) {
221 0 : ret = ENOMEM;
222 0 : goto done;
223 : }
224 :
225 : /* mandatory data - name and gid */
226 0 : gi->name = talloc_strdup(gi,
227 : ldb_msg_find_attr_as_string(msg,
228 : SYSDB_NAME,
229 : NULL));
230 0 : gi->gid = ldb_msg_find_attr_as_uint64(msg,
231 : SYSDB_GIDNUM, 0);
232 0 : if (gi->gid == 0 || gi->name == NULL) {
233 0 : DEBUG(SSSDBG_MINOR_FAILURE, "No name or no GID?\n");
234 0 : ret = EIO;
235 0 : goto done;
236 : }
237 :
238 : /* list members */
239 0 : el = ldb_msg_find_element(msg, SYSDB_MEMBER);
240 0 : if (el) {
241 0 : ret = parse_members(gi, ldb, domain, el,
242 : parent_name,
243 : &gi->user_members,
244 : group_members, num_group_members);
245 0 : if (ret != EOK) {
246 0 : goto done;
247 : }
248 0 : if (gi->user_members == NULL) {
249 0 : count = 0;
250 : } else {
251 0 : for (count = 0; gi->user_members[count]; count++) ;
252 : }
253 : }
254 0 : el = ldb_msg_find_element(msg, SYSDB_GHOST);
255 0 : if (el) {
256 0 : ret = parse_members(gi, ldb, domain, el,
257 : parent_name,
258 : &user_members,
259 : NULL, NULL);
260 0 : if (ret != EOK) {
261 0 : goto done;
262 : }
263 :
264 0 : if (user_members != NULL) {
265 0 : i = count;
266 0 : for (count = 0; user_members[count]; count++) ;
267 0 : gi->user_members = talloc_realloc(gi, gi->user_members,
268 : const char *,
269 : i + count + 1);
270 0 : if (gi->user_members == NULL) {
271 0 : ret = ENOMEM;
272 0 : goto done;
273 : }
274 0 : for (j = 0; j < count; j++, i++) {
275 0 : gi->user_members[i] = talloc_steal(gi->user_members,
276 : user_members[j]);
277 : }
278 0 : gi->user_members[i] = NULL;
279 :
280 0 : talloc_zfree(user_members);
281 : }
282 : }
283 :
284 : /* list memberofs */
285 0 : el = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
286 0 : if (el) {
287 0 : ret = parse_memberofs(ldb, el, gi);
288 0 : if (ret != EOK) {
289 0 : goto done;
290 : }
291 : }
292 :
293 0 : *info = gi;
294 0 : return EOK;
295 : done:
296 0 : talloc_zfree(gi);
297 0 : return ret;
298 : }
299 :
300 : /*========Find info about a group and recursively about subgroups====== */
301 :
302 : int group_show_recurse(TALLOC_CTX *mem_ctx,
303 : struct sysdb_ctx *sysdb,
304 : struct sss_domain_info *domain,
305 : struct group_info *root,
306 : struct group_info *parent,
307 : const char **group_members,
308 : const int nmembers,
309 : struct group_info ***up_members);
310 :
311 : static int group_show_trim_memberof(TALLOC_CTX *mem_ctx,
312 : struct sss_domain_info *domain,
313 : const char *name,
314 : const char **memberofs,
315 : const char ***_direct);
316 :
317 0 : int group_show(TALLOC_CTX *mem_ctx,
318 : struct sysdb_ctx *sysdb,
319 : struct sss_domain_info *domain,
320 : bool recursive,
321 : const char *name,
322 : struct group_info **res)
323 : {
324 : struct group_info *root;
325 : static const char *attrs[] = GROUP_SHOW_ATTRS;
326 0 : struct ldb_message *msg = NULL;
327 0 : const char **group_members = NULL;
328 0 : int nmembers = 0;
329 : int ret;
330 : int i;
331 :
332 : /* First, search for the root group */
333 0 : ret = sysdb_search_group_by_name(mem_ctx, domain, name, attrs, &msg);
334 0 : if (ret) {
335 0 : DEBUG(SSSDBG_OP_FAILURE,
336 : "Search failed: %s (%d)\n", strerror(ret), ret);
337 0 : goto done;
338 : }
339 :
340 0 : ret = process_group(mem_ctx, sysdb_ctx_get_ldb(sysdb),
341 : msg, domain, NULL, &root,
342 : &group_members, &nmembers);
343 0 : if (ret != EOK) {
344 0 : DEBUG(SSSDBG_OP_FAILURE, "Group processing failed: %s (%d)\n",
345 : strerror(ret), ret);
346 0 : goto done;
347 : }
348 :
349 0 : if (!recursive) {
350 0 : if (group_members) {
351 0 : root->group_members = talloc_array(root,
352 : struct group_info *,
353 : nmembers+1);
354 0 : if (!root->group_members) {
355 0 : ret = ENOMEM;
356 0 : goto done;
357 : }
358 0 : for (i = 0; i < nmembers; i++) {
359 0 : root->group_members[i] = talloc_zero(root, struct group_info);
360 0 : if (!root->group_members[i]) {
361 0 : ret = ENOMEM;
362 0 : goto done;
363 : }
364 0 : root->group_members[i]->name = talloc_strdup(root,
365 0 : group_members[i]);
366 0 : if (!root->group_members[i]->name) {
367 0 : ret = ENOMEM;
368 0 : goto done;
369 : }
370 : }
371 0 : root->group_members[nmembers] = NULL;
372 : }
373 :
374 0 : if (root->memberofs == NULL) {
375 0 : ret = EOK;
376 0 : goto done;
377 : }
378 :
379 : /* if not recursive, only show the direct parent */
380 0 : ret = group_show_trim_memberof(mem_ctx, domain, root->name,
381 0 : root->memberofs, &root->memberofs);
382 0 : goto done;
383 : }
384 :
385 0 : if (group_members == NULL) {
386 0 : ret = EOK;
387 0 : goto done;
388 : }
389 :
390 0 : ret = group_show_recurse(root, sysdb, domain, root, root,
391 : group_members, nmembers,
392 0 : &root->group_members);
393 0 : if (ret) {
394 0 : DEBUG(SSSDBG_OP_FAILURE,
395 : "Recursive search failed: %s (%d)\n", strerror(ret), ret);
396 0 : goto done;
397 : }
398 :
399 0 : ret = EOK;
400 : done:
401 0 : if (ret == EOK) {
402 0 : *res = root;
403 : }
404 0 : return ret;
405 : }
406 :
407 : /*=========Nonrecursive search should only show direct parent========== */
408 :
409 0 : static int group_show_trim_memberof(TALLOC_CTX *mem_ctx,
410 : struct sss_domain_info *domain,
411 : const char *name,
412 : const char **memberofs,
413 : const char ***_direct)
414 : {
415 : struct ldb_dn *dn;
416 : char *filter;
417 : struct ldb_message **msgs;
418 : size_t count;
419 0 : const char **direct = NULL;
420 0 : int ndirect = 0;
421 : int ret;
422 : int i;
423 :
424 0 : dn = sysdb_group_dn(mem_ctx, domain, name);
425 0 : if (!dn) {
426 0 : return ENOMEM;
427 : }
428 :
429 0 : for (i = 0; memberofs[i]; i++) {
430 :
431 0 : filter = talloc_asprintf(mem_ctx, "(&(%s=%s)(%s=%s))",
432 0 : SYSDB_NAME, memberofs[i],
433 : SYSDB_MEMBER, ldb_dn_get_linearized(dn));
434 0 : if (!filter) {
435 0 : return ENOMEM;
436 : }
437 :
438 0 : ret = sysdb_search_groups(mem_ctx, domain,
439 : filter, NULL, &count, &msgs);
440 : /* ENOENT is OK, the group is just not a direct parent */
441 0 : if (ret != EOK && ret != ENOENT) {
442 0 : return ret;
443 : }
444 :
445 0 : if (count > 0) {
446 0 : name = ldb_msg_find_attr_as_string(msgs[0],
447 : SYSDB_NAME, NULL);
448 0 : if (!name) {
449 0 : DEBUG(SSSDBG_OP_FAILURE, "Entry %s has no Name Attribute ?!?\n",
450 : ldb_dn_get_linearized(msgs[0]->dn));
451 0 : return EFAULT;
452 : }
453 :
454 0 : direct = talloc_realloc(mem_ctx, direct,
455 : const char *, ndirect + 2);
456 0 : if (!direct) {
457 0 : return ENOMEM;
458 : }
459 :
460 0 : direct[ndirect] = talloc_strdup(direct, name);
461 0 : if (!direct[ndirect]) {
462 0 : return ENOMEM;
463 : }
464 :
465 0 : direct[ndirect + 1] = NULL;
466 0 : ndirect++;
467 : }
468 : }
469 :
470 0 : *_direct = direct;
471 0 : return EOK;
472 : }
473 :
474 : /*==================Recursive search for nested groups================= */
475 :
476 0 : int group_show_recurse(TALLOC_CTX *mem_ctx,
477 : struct sysdb_ctx *sysdb,
478 : struct sss_domain_info *domain,
479 : struct group_info *root,
480 : struct group_info *parent,
481 : const char **group_members,
482 : const int nmembers,
483 : struct group_info ***up_members)
484 : {
485 : struct group_info **groups;
486 : static const char *attrs[] = GROUP_SHOW_ATTRS;
487 : struct ldb_message *msg;
488 0 : const char **new_group_members = NULL;
489 0 : int new_nmembers = 0;
490 : int ret;
491 : int i;
492 :
493 0 : groups = talloc_zero_array(root,
494 : struct group_info *,
495 : nmembers+1); /* trailing NULL */
496 :
497 0 : if (!group_members || !group_members[0]) {
498 0 : return ENOENT;
499 : }
500 :
501 0 : for (i = 0; i < nmembers; i++) {
502 : /* Skip circular groups */
503 0 : if (strcmp(group_members[i], parent->name) == 0) {
504 0 : continue;
505 : }
506 :
507 0 : ret = sysdb_search_group_by_name(mem_ctx, domain, group_members[i],
508 : attrs, &msg);
509 0 : if (ret) {
510 0 : DEBUG(SSSDBG_OP_FAILURE,
511 : "Search failed: %s (%d)\n", strerror(ret), ret);
512 0 : return EIO;
513 : }
514 :
515 0 : ret = process_group(root, sysdb_ctx_get_ldb(sysdb),
516 : msg, domain, parent->name,
517 0 : &groups[i], &new_group_members, &new_nmembers);
518 0 : if (ret != EOK) {
519 0 : DEBUG(SSSDBG_OP_FAILURE, "Group processing failed: %s (%d)\n",
520 : strerror(ret), ret);
521 0 : return ret;
522 : }
523 :
524 : /* descend to another level */
525 0 : if (new_nmembers > 0) {
526 0 : ret = group_show_recurse(mem_ctx, sysdb, domain,
527 0 : root, groups[i],
528 : new_group_members, new_nmembers,
529 : &parent->group_members);
530 0 : if (ret != EOK) {
531 0 : DEBUG(SSSDBG_OP_FAILURE, "Recursive search failed: %s (%d)\n",
532 : strerror(ret), ret);
533 0 : return ret;
534 : }
535 0 : talloc_zfree(new_group_members);
536 : }
537 : }
538 :
539 0 : *up_members = groups;
540 0 : return EOK;
541 : }
542 :
543 : /*==================Get info about MPG================================= */
544 :
545 0 : static int group_show_mpg(TALLOC_CTX *mem_ctx,
546 : struct sss_domain_info *domain,
547 : const char *name,
548 : struct group_info **res)
549 : {
550 0 : const char *attrs[] = GROUP_SHOW_MPG_ATTRS;
551 : struct ldb_message *msg;
552 : struct group_info *info;
553 : int ret;
554 :
555 0 : info = talloc_zero(mem_ctx, struct group_info);
556 0 : if (!info) {
557 0 : ret = ENOMEM;
558 0 : goto fail;
559 : }
560 :
561 0 : ret = sysdb_search_user_by_name(info, domain, name, attrs, &msg);
562 0 : if (ret) {
563 0 : DEBUG(SSSDBG_OP_FAILURE,
564 : "Search failed: %s (%d)\n", strerror(ret), ret);
565 0 : goto fail;
566 : }
567 :
568 0 : info->name = talloc_strdup(info,
569 : ldb_msg_find_attr_as_string(msg,
570 : SYSDB_NAME, NULL));
571 0 : info->gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
572 0 : if (info->gid == 0 || info->name == NULL) {
573 0 : DEBUG(SSSDBG_MINOR_FAILURE, "No name or no GID?\n");
574 0 : ret = EIO;
575 0 : goto fail;
576 : }
577 0 : info->mpg = true;
578 :
579 0 : *res = info;
580 0 : return EOK;
581 :
582 : fail:
583 0 : talloc_zfree(info);
584 0 : return ret;
585 : }
586 :
587 : /*==================The main program=================================== */
588 :
589 0 : static void print_group_info(struct group_info *g, int level)
590 : {
591 : int i;
592 : char padding[512];
593 : char fmt[8];
594 :
595 0 : snprintf(fmt, 8, "%%%ds", level*PADDING_SPACES);
596 0 : snprintf(padding, 512, fmt, "");
597 :
598 0 : printf(_("%1$s%2$sGroup: %3$s\n"), padding,
599 0 : g->mpg ? _("Magic Private ") : "",
600 : g->name);
601 0 : printf(_("%1$sGID number: %2$d\n"), padding, g->gid);
602 :
603 0 : printf(_("%1$sMember users: "), padding);
604 0 : if (g->user_members) {
605 0 : for (i=0; g->user_members[i]; ++i) {
606 0 : printf("%s%s", i>0 ? "," : "",
607 0 : g->user_members[i]);
608 : }
609 : }
610 0 : printf(_("\n%1$sIs a member of: "), padding);
611 0 : if (g->memberofs) {
612 0 : for (i=0; g->memberofs[i]; ++i) {
613 0 : printf("%s%s", i>0 ? "," : "",
614 0 : g->memberofs[i]);
615 : }
616 : }
617 0 : printf(_("\n%1$sMember groups: "), padding);
618 0 : }
619 :
620 0 : static void print_recursive(struct group_info **group_members, int level)
621 : {
622 : int i;
623 :
624 0 : if (group_members == NULL) {
625 0 : return;
626 : }
627 :
628 0 : level++;
629 0 : for (i=0; group_members[i]; ++i) {
630 0 : printf("\n");
631 0 : print_group_info(group_members[i], level);
632 0 : printf("\n");
633 0 : print_recursive(group_members[i]->group_members, level);
634 : }
635 : }
636 :
637 0 : int main(int argc, const char **argv)
638 : {
639 0 : int ret = EXIT_SUCCESS;
640 0 : int pc_debug = SSSDBG_DEFAULT;
641 0 : bool pc_recursive = false;
642 0 : const char *pc_groupname = NULL;
643 0 : struct tools_ctx *tctx = NULL;
644 0 : struct group_info *root = NULL;
645 : int i;
646 :
647 0 : poptContext pc = NULL;
648 0 : struct poptOption long_options[] = {
649 : POPT_AUTOHELP
650 : { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug,
651 0 : 0, _("The debug level to run with"), NULL },
652 : { "recursive", 'R', POPT_ARG_NONE, NULL, 'r',
653 0 : _("Print indirect group members recursively"), NULL },
654 : POPT_TABLEEND
655 : };
656 :
657 0 : debug_prg_name = argv[0];
658 :
659 0 : ret = set_locale();
660 0 : if (ret != EOK) {
661 0 : DEBUG(SSSDBG_CRIT_FAILURE,
662 : "set_locale failed (%d): %s\n", ret, strerror(ret));
663 0 : ERROR("Error setting the locale\n");
664 0 : ret = EXIT_FAILURE;
665 0 : goto fini;
666 : }
667 :
668 : /* parse ops_ctx */
669 0 : pc = poptGetContext(NULL, argc, argv, long_options, 0);
670 0 : poptSetOtherOptionHelp(pc, "GROUPNAME");
671 0 : while ((ret = poptGetNextOpt(pc)) > 0) {
672 0 : switch (ret) {
673 : case 'r':
674 0 : pc_recursive = true;
675 0 : break;
676 : }
677 : }
678 :
679 0 : DEBUG_CLI_INIT(pc_debug);
680 :
681 0 : if (ret != -1) {
682 0 : BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
683 : }
684 :
685 0 : pc_groupname = poptGetArg(pc);
686 0 : if (pc_groupname == NULL) {
687 0 : BAD_POPT_PARAMS(pc, _("Specify group to show\n"), ret, fini);
688 : }
689 :
690 0 : CHECK_ROOT(ret, debug_prg_name);
691 :
692 0 : ret = init_sss_tools(&tctx);
693 0 : if (ret != EOK) {
694 0 : DEBUG(SSSDBG_CRIT_FAILURE,
695 : "init_sss_tools failed (%d): %s\n", ret, strerror(ret));
696 0 : if (ret == ENOENT) {
697 0 : ERROR("Error initializing the tools - no local domain\n");
698 : } else {
699 0 : ERROR("Error initializing the tools\n");
700 : }
701 0 : ret = EXIT_FAILURE;
702 0 : goto fini;
703 : }
704 :
705 : /* if the domain was not given as part of FQDN, default to local domain */
706 0 : ret = parse_name_domain(tctx, pc_groupname);
707 0 : if (ret != EOK) {
708 0 : ERROR("Invalid domain specified in FQDN\n");
709 0 : ret = EXIT_FAILURE;
710 0 : goto fini;
711 : }
712 :
713 : /* The search itself */
714 0 : ret = group_show(tctx, tctx->sysdb,
715 0 : tctx->local, pc_recursive, tctx->octx->name, &root);
716 : /* Also show MPGs */
717 0 : if (ret == ENOENT) {
718 0 : ret = group_show_mpg(tctx, tctx->local, tctx->octx->name, &root);
719 : }
720 :
721 : /* Process result */
722 0 : if (ret) {
723 0 : DEBUG(SSSDBG_CRIT_FAILURE,
724 : "sysdb operation failed (%d)[%s]\n", ret, strerror(ret));
725 0 : switch (ret) {
726 : case ENOENT:
727 0 : ERROR("No such group in local domain. "
728 : "Printing groups only allowed in local domain.\n");
729 0 : break;
730 :
731 : default:
732 0 : ERROR("Internal error. Could not print group.\n");
733 0 : break;
734 : }
735 0 : ret = EXIT_FAILURE;
736 0 : goto fini;
737 : }
738 :
739 : /* print the results */
740 0 : print_group_info(root, 0);
741 0 : if (pc_recursive) {
742 0 : printf("\n");
743 0 : print_recursive(root->group_members, 0);
744 : } else {
745 0 : if (root->group_members) {
746 0 : for (i=0; root->group_members[i]; ++i) {
747 0 : printf("%s%s", i>0 ? "," : "",
748 0 : root->group_members[i]->name);
749 : }
750 : }
751 0 : printf("\n");
752 : }
753 :
754 : fini:
755 0 : talloc_free(tctx);
756 0 : poptFreeContext(pc);
757 0 : exit(ret);
758 : }
|