ca4c60716630762185970b381a531a9681ea8d21
[amitay/samba.git] / source3 / utils / net_groupmap.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2001.
6  *  Copyright (C) Gerald Carter                2003,
7  *  Copyright (C) Volker Lendecke              2004
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
24 #include "includes.h"
25 #include "system/passwd.h"
26 #include "utils/net.h"
27 #include "../libcli/security/security.h"
28 #include "passdb.h"
29
30 /*********************************************************
31  Figure out if the input was an NT group or a SID string.
32  Return the SID.
33 **********************************************************/
34 static bool get_sid_from_input(struct dom_sid *sid, char *input)
35 {
36         GROUP_MAP map;
37
38         if (StrnCaseCmp( input, "S-", 2)) {
39                 /* Perhaps its the NT group name? */
40                 if (!pdb_getgrnam(&map, input)) {
41                         printf(_("NT Group %s doesn't exist in mapping DB\n"),
42                                input);
43                         return false;
44                 } else {
45                         *sid = map.sid;
46                 }
47         } else {
48                 if (!string_to_sid(sid, input)) {
49                         printf(_("converting sid %s from a string failed!\n"),
50                                input);
51                         return false;
52                 }
53         }
54         return true;
55 }
56
57 /*********************************************************
58  Dump a GROUP_MAP entry to stdout (long or short listing)
59 **********************************************************/
60
61 static void print_map_entry (const GROUP_MAP *map, bool long_list)
62 {
63         if (!long_list)
64                 d_printf("%s (%s) -> %s\n", map->nt_name,
65                          sid_string_tos(&map->sid), gidtoname(map->gid));
66         else {
67                 d_printf("%s\n", map->nt_name);
68                 d_printf(_("\tSID       : %s\n"), sid_string_tos(&map->sid));
69                 d_printf(_("\tUnix gid  : %u\n"), (unsigned int)map->gid);
70                 d_printf(_("\tUnix group: %s\n"), gidtoname(map->gid));
71                 d_printf(_("\tGroup type: %s\n"),
72                          sid_type_lookup(map->sid_name_use));
73                 d_printf(_("\tComment   : %s\n"), map->comment);
74         }
75
76 }
77 /*********************************************************
78  List the groups.
79 **********************************************************/
80 static int net_groupmap_list(struct net_context *c, int argc, const char **argv)
81 {
82         size_t entries;
83         bool long_list = false;
84         size_t i;
85         fstring ntgroup = "";
86         fstring sid_string = "";
87         const char list_usage_str[] = N_("net groupmap list [verbose] "
88                                          "[ntgroup=NT group] [sid=SID]\n"
89                                          "    verbose\tPrint verbose list\n"
90                                          "    ntgroup\tNT group to list\n"
91                                          "    sid\tSID of group to list");
92
93         if (c->display_usage) {
94                 d_printf("%s\n%s\n", _("Usage: "), list_usage_str);
95                 return 0;
96         }
97
98         if (c->opt_verbose || c->opt_long_list_entries)
99                 long_list = true;
100
101         /* get the options */
102         for ( i=0; i<argc; i++ ) {
103                 if ( !strcasecmp_m(argv[i], "verbose")) {
104                         long_list = true;
105                 }
106                 else if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) {
107                         fstrcpy( ntgroup, get_string_param( argv[i] ) );
108                         if ( !ntgroup[0] ) {
109                                 d_fprintf(stderr, _("must supply a name\n"));
110                                 return -1;
111                         }
112                 }
113                 else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) {
114                         fstrcpy( sid_string, get_string_param( argv[i] ) );
115                         if ( !sid_string[0] ) {
116                                 d_fprintf(stderr, _("must supply a SID\n"));
117                                 return -1;
118                         }
119                 }
120                 else {
121                         d_fprintf(stderr, _("Bad option: %s\n"), argv[i]);
122                         d_printf("%s\n%s\n", _("Usage:"), list_usage_str);
123                         return -1;
124                 }
125         }
126
127         /* list a single group is given a name */
128         if ( ntgroup[0] || sid_string[0] ) {
129                 struct dom_sid sid;
130                 GROUP_MAP map;
131
132                 if ( sid_string[0] )
133                         strlcpy(ntgroup, sid_string, sizeof(ntgroup));
134
135                 if (!get_sid_from_input(&sid, ntgroup)) {
136                         return -1;
137                 }
138
139                 /* Get the current mapping from the database */
140                 if(!pdb_getgrsid(&map, sid)) {
141                         d_fprintf(stderr,
142                                   _("Failure to local group SID in the "
143                                     "database\n"));
144                         return -1;
145                 }
146
147                 print_map_entry(&map, long_list );
148         }
149         else {
150                 GROUP_MAP *map=NULL;
151                 /* enumerate all group mappings */
152                 if (!pdb_enum_group_mapping(NULL, SID_NAME_UNKNOWN, &map, &entries, ENUM_ALL_MAPPED))
153                         return -1;
154
155                 for (i=0; i<entries; i++) {
156                         print_map_entry(&map[i], long_list);
157                 }
158
159                 SAFE_FREE(map);
160         }
161
162         return 0;
163 }
164
165 /*********************************************************
166  Add a new group mapping entry
167 **********************************************************/
168
169 static int net_groupmap_add(struct net_context *c, int argc, const char **argv)
170 {
171         struct dom_sid sid;
172         fstring ntgroup = "";
173         fstring unixgrp = "";
174         fstring string_sid = "";
175         fstring type = "";
176         fstring ntcomment = "";
177         enum lsa_SidType sid_type = SID_NAME_DOM_GRP;
178         uint32 rid = 0;
179         gid_t gid;
180         int i;
181         GROUP_MAP map;
182
183         const char *name_type;
184         const char add_usage_str[] = N_("net groupmap add "
185                                         "{rid=<int>|sid=<string>}"
186                                         " unixgroup=<string> "
187                                         "[type=<domain|local|builtin>] "
188                                         "[ntgroup=<string>] "
189                                         "[comment=<string>]");
190
191         ZERO_STRUCT(map);
192
193         /* Default is domain group. */
194         map.sid_name_use = SID_NAME_DOM_GRP;
195         name_type = "domain group";
196
197         if (c->display_usage) {
198                 d_printf("%s\n%s\n", _("Usage:\n"), add_usage_str);
199                 return 0;
200         }
201
202         /* get the options */
203         for ( i=0; i<argc; i++ ) {
204                 if ( !StrnCaseCmp(argv[i], "rid", strlen("rid")) ) {
205                         rid = get_int_param(argv[i]);
206                         if ( rid < DOMAIN_RID_ADMINS ) {
207                                 d_fprintf(stderr,
208                                           _("RID must be greater than %d\n"),
209                                           (uint32)DOMAIN_RID_ADMINS-1);
210                                 return -1;
211                         }
212                 }
213                 else if ( !StrnCaseCmp(argv[i], "unixgroup", strlen("unixgroup")) ) {
214                         fstrcpy( unixgrp, get_string_param( argv[i] ) );
215                         if ( !unixgrp[0] ) {
216                                 d_fprintf(stderr,_( "must supply a name\n"));
217                                 return -1;
218                         }
219                 }
220                 else if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) {
221                         fstrcpy( ntgroup, get_string_param( argv[i] ) );
222                         if ( !ntgroup[0] ) {
223                                 d_fprintf(stderr, _("must supply a name\n"));
224                                 return -1;
225                         }
226                 }
227                 else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) {
228                         fstrcpy( string_sid, get_string_param( argv[i] ) );
229                         if ( !string_sid[0] ) {
230                                 d_fprintf(stderr, _("must supply a SID\n"));
231                                 return -1;
232                         }
233                 }
234                 else if ( !StrnCaseCmp(argv[i], "comment", strlen("comment")) ) {
235                         fstrcpy( ntcomment, get_string_param( argv[i] ) );
236                         if ( !ntcomment[0] ) {
237                                 d_fprintf(stderr,
238                                           _("must supply a comment string\n"));
239                                 return -1;
240                         }
241                 }
242                 else if ( !StrnCaseCmp(argv[i], "type", strlen("type")) )  {
243                         fstrcpy( type, get_string_param( argv[i] ) );
244                         switch ( type[0] ) {
245                                 case 'b':
246                                 case 'B':
247                                         sid_type = SID_NAME_WKN_GRP;
248                                         name_type = "wellknown group";
249                                         break;
250                                 case 'd':
251                                 case 'D':
252                                         sid_type = SID_NAME_DOM_GRP;
253                                         name_type = "domain group";
254                                         break;
255                                 case 'l':
256                                 case 'L':
257                                         sid_type = SID_NAME_ALIAS;
258                                         name_type = "alias (local) group";
259                                         break;
260                                 default:
261                                         d_fprintf(stderr,
262                                                   _("unknown group type %s\n"),
263                                                   type);
264                                         return -1;
265                         }
266                 }
267                 else {
268                         d_fprintf(stderr, _("Bad option: %s\n"), argv[i]);
269                         return -1;
270                 }
271         }
272
273         if ( !unixgrp[0] ) {
274                 d_printf("%s\n%s\n", _("Usage:\n"), add_usage_str);
275                 return -1;
276         }
277
278         if ( (gid = nametogid(unixgrp)) == (gid_t)-1 ) {
279                 d_fprintf(stderr, _("Can't lookup UNIX group %s\n"), unixgrp);
280                 return -1;
281         }
282
283         {
284                 if (pdb_getgrgid(&map, gid)) {
285                         d_printf(_("Unix group %s already mapped to SID %s\n"),
286                                  unixgrp, sid_string_tos(&map.sid));
287                         return -1;
288                 }
289         }
290
291         if ( (rid == 0) && (string_sid[0] == '\0') ) {
292                 d_printf(_("No rid or sid specified, choosing a RID\n"));
293                 if (pdb_capabilities() & PDB_CAP_STORE_RIDS) {
294                         if (!pdb_new_rid(&rid)) {
295                                 d_printf(_("Could not get new RID\n"));
296                         }
297                 } else {
298                         rid = algorithmic_pdb_gid_to_group_rid(gid);
299                 }
300                 d_printf(_("Got RID %d\n"), rid);
301         }
302
303         /* append the rid to our own domain/machine SID if we don't have a full SID */
304         if ( !string_sid[0] ) {
305                 sid_compose(&sid, get_global_sam_sid(), rid);
306                 sid_to_fstring(string_sid, &sid);
307         }
308
309         if (!ntcomment[0]) {
310                 switch (sid_type) {
311                 case SID_NAME_WKN_GRP:
312                         fstrcpy(ntcomment, "Wellknown Unix group");
313                         break;
314                 case SID_NAME_DOM_GRP:
315                         fstrcpy(ntcomment, "Domain Unix group");
316                         break;
317                 case SID_NAME_ALIAS:
318                         fstrcpy(ntcomment, "Local Unix group");
319                         break;
320                 default:
321                         fstrcpy(ntcomment, "Unix group");
322                         break;
323                 }
324         }
325
326         if (!ntgroup[0] )
327                 strlcpy(ntgroup, unixgrp, sizeof(ntgroup));
328
329         if (!NT_STATUS_IS_OK(add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment))) {
330                 d_fprintf(stderr, _("adding entry for group %s failed!\n"), ntgroup);
331                 return -1;
332         }
333
334         d_printf(_("Successfully added group %s to the mapping db as a %s\n"),
335                  ntgroup, name_type);
336         return 0;
337 }
338
339 static int net_groupmap_modify(struct net_context *c, int argc, const char **argv)
340 {
341         struct dom_sid sid;
342         GROUP_MAP map;
343         fstring ntcomment = "";
344         fstring type = "";
345         fstring ntgroup = "";
346         fstring unixgrp = "";
347         fstring sid_string = "";
348         enum lsa_SidType sid_type = SID_NAME_UNKNOWN;
349         int i;
350         gid_t gid;
351         const char modify_usage_str[] = N_("net groupmap modify "
352                                            "{ntgroup=<string>|sid=<SID>} "
353                                            "[comment=<string>] "
354                                            "[unixgroup=<string>] "
355                                            "[type=<domain|local>]");
356
357         if (c->display_usage) {
358                 d_printf("%s\n%s\n", _("Usage:\n"), modify_usage_str);
359                 return 0;
360         }
361
362         /* get the options */
363         for ( i=0; i<argc; i++ ) {
364                 if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) {
365                         fstrcpy( ntgroup, get_string_param( argv[i] ) );
366                         if ( !ntgroup[0] ) {
367                                 d_fprintf(stderr, _("must supply a name\n"));
368                                 return -1;
369                         }
370                 }
371                 else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) {
372                         fstrcpy( sid_string, get_string_param( argv[i] ) );
373                         if ( !sid_string[0] ) {
374                                 d_fprintf(stderr, _("must supply a name\n"));
375                                 return -1;
376                         }
377                 }
378                 else if ( !StrnCaseCmp(argv[i], "comment", strlen("comment")) ) {
379                         fstrcpy( ntcomment, get_string_param( argv[i] ) );
380                         if ( !ntcomment[0] ) {
381                                 d_fprintf(stderr,
382                                           _("must supply a comment string\n"));
383                                 return -1;
384                         }
385                 }
386                 else if ( !StrnCaseCmp(argv[i], "unixgroup", strlen("unixgroup")) ) {
387                         fstrcpy( unixgrp, get_string_param( argv[i] ) );
388                         if ( !unixgrp[0] ) {
389                                 d_fprintf(stderr,
390                                           _("must supply a group name\n"));
391                                 return -1;
392                         }
393                 }
394                 else if ( !StrnCaseCmp(argv[i], "type", strlen("type")) )  {
395                         fstrcpy( type, get_string_param( argv[i] ) );
396                         switch ( type[0] ) {
397                                 case 'd':
398                                 case 'D':
399                                         sid_type = SID_NAME_DOM_GRP;
400                                         break;
401                                 case 'l':
402                                 case 'L':
403                                         sid_type = SID_NAME_ALIAS;
404                                         break;
405                         }
406                 }
407                 else {
408                         d_fprintf(stderr, _("Bad option: %s\n"), argv[i]);
409                         return -1;
410                 }
411         }
412
413         if ( !ntgroup[0] && !sid_string[0] ) {
414                 d_printf("%s\n%s\n", _("Usage:\n"), modify_usage_str);
415                 return -1;
416         }
417
418         /* give preference to the SID; if both the ntgroup name and SID
419            are defined, use the SID and assume that the group name could be a
420            new name */
421
422         if ( sid_string[0] ) {
423                 if (!get_sid_from_input(&sid, sid_string)) {
424                         return -1;
425                 }
426         }
427         else {
428                 if (!get_sid_from_input(&sid, ntgroup)) {
429                         return -1;
430                 }
431         }
432
433         /* Get the current mapping from the database */
434         if(!pdb_getgrsid(&map, sid)) {
435                 d_fprintf(stderr,
436                          _("Failed to find local group SID in the database\n"));
437                 return -1;
438         }
439
440         /*
441          * Allow changing of group type only between domain and local
442          * We disallow changing Builtin groups !!! (SID problem)
443          */
444         if (sid_type == SID_NAME_UNKNOWN) {
445                 d_fprintf(stderr, _("Can't map to an unknown group type.\n"));
446                 return -1;
447         }
448
449         if (map.sid_name_use == SID_NAME_WKN_GRP) {
450                 d_fprintf(stderr,
451                           _("You can only change between domain and local "
452                             "groups.\n"));
453                 return -1;
454         }
455
456         map.sid_name_use=sid_type;
457
458         /* Change comment if new one */
459         if ( ntcomment[0] )
460                 strlcpy(map.comment, ntcomment, sizeof(map.comment));
461
462         if ( ntgroup[0] )
463                 strlcpy(map.nt_name, ntgroup, sizeof(map.nt_name));
464
465         if ( unixgrp[0] ) {
466                 gid = nametogid( unixgrp );
467                 if ( gid == -1 ) {
468                         d_fprintf(stderr, _("Unable to lookup UNIX group %s.  "
469                                             "Make sure the group exists.\n"),
470                                 unixgrp);
471                         return -1;
472                 }
473
474                 map.gid = gid;
475         }
476
477         if ( !NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map)) ) {
478                 d_fprintf(stderr, _("Could not update group database\n"));
479                 return -1;
480         }
481
482         d_printf(_("Updated mapping entry for %s\n"), map.nt_name);
483
484         return 0;
485 }
486
487 static int net_groupmap_delete(struct net_context *c, int argc, const char **argv)
488 {
489         struct dom_sid sid;
490         fstring ntgroup = "";
491         fstring sid_string = "";
492         int i;
493         const char delete_usage_str[] = N_("net groupmap delete "
494                                            "{ntgroup=<string>|sid=<SID>}");
495
496         if (c->display_usage) {
497                 d_printf("%s\n%s\n", _("Usage:\n"), delete_usage_str);
498                 return 0;
499         }
500
501         /* get the options */
502         for ( i=0; i<argc; i++ ) {
503                 if ( !StrnCaseCmp(argv[i], "ntgroup", strlen("ntgroup")) ) {
504                         fstrcpy( ntgroup, get_string_param( argv[i] ) );
505                         if ( !ntgroup[0] ) {
506                                 d_fprintf(stderr, _("must supply a name\n"));
507                                 return -1;
508                         }
509                 }
510                 else if ( !StrnCaseCmp(argv[i], "sid", strlen("sid")) ) {
511                         fstrcpy( sid_string, get_string_param( argv[i] ) );
512                         if ( !sid_string[0] ) {
513                                 d_fprintf(stderr, _("must supply a SID\n"));
514                                 return -1;
515                         }
516                 }
517                 else {
518                         d_fprintf(stderr, _("Bad option: %s\n"), argv[i]);
519                         return -1;
520                 }
521         }
522
523         if ( !ntgroup[0] && !sid_string[0]) {
524                 d_printf("%s\n%s\n", _("Usage:\n"), delete_usage_str);
525                 return -1;
526         }
527
528         /* give preference to the SID if we have that */
529
530         if ( sid_string[0] )
531                 strlcpy(ntgroup, sid_string, sizeof(ntgroup));
532
533         if ( !get_sid_from_input(&sid, ntgroup) ) {
534                 d_fprintf(stderr, _("Unable to resolve group %s to a SID\n"),
535                           ntgroup);
536                 return -1;
537         }
538
539         if ( !NT_STATUS_IS_OK(pdb_delete_group_mapping_entry(sid)) ) {
540                 d_fprintf(stderr,
541                           _("Failed to remove group %s from the mapping db!\n"),
542                           ntgroup);
543                 return -1;
544         }
545
546         d_printf(_("Sucessfully removed %s from the mapping db\n"), ntgroup);
547
548         return 0;
549 }
550
551 static int net_groupmap_set(struct net_context *c, int argc, const char **argv)
552 {
553         const char *ntgroup = NULL;
554         struct group *grp = NULL;
555         GROUP_MAP map;
556         bool have_map = false;
557
558         if ((argc < 1) || (argc > 2) || c->display_usage) {
559                 d_printf("%s\n%s",
560                          _("Usage:"),
561                          _(" net groupmap set \"NT Group\" "
562                            "[\"unix group\"] [-C \"comment\"] [-L] [-D]\n"));
563                 return -1;
564         }
565
566         if ( c->opt_localgroup && c->opt_domaingroup ) {
567                 d_printf(_("Can only specify -L or -D, not both\n"));
568                 return -1;
569         }
570
571         ntgroup = argv[0];
572
573         if (argc == 2) {
574                 grp = getgrnam(argv[1]);
575
576                 if (grp == NULL) {
577                         d_fprintf(stderr, _("Could not find unix group %s\n"),
578                                   argv[1]);
579                         return -1;
580                 }
581         }
582
583         have_map = pdb_getgrnam(&map, ntgroup);
584
585         if (!have_map) {
586                 struct dom_sid sid;
587                 have_map = ( (strncmp(ntgroup, "S-", 2) == 0) &&
588                              string_to_sid(&sid, ntgroup) &&
589                              pdb_getgrsid(&map, sid) );
590         }
591
592         if (!have_map) {
593
594                 /* Ok, add it */
595
596                 if (grp == NULL) {
597                         d_fprintf(stderr,
598                                   _("Could not find group mapping for %s\n"),
599                                   ntgroup);
600                         return -1;
601                 }
602
603                 map.gid = grp->gr_gid;
604
605                 if (c->opt_rid == 0) {
606                         if ( pdb_capabilities() & PDB_CAP_STORE_RIDS ) {
607                                 if ( !pdb_new_rid((uint32*)&c->opt_rid) ) {
608                                         d_fprintf( stderr,
609                                             _("Could not allocate new RID\n"));
610                                         return -1;
611                                 }
612                         } else {
613                                 c->opt_rid = algorithmic_pdb_gid_to_group_rid(map.gid);
614                         }
615                 }
616
617                 sid_compose(&map.sid, get_global_sam_sid(), c->opt_rid);
618
619                 map.sid_name_use = SID_NAME_DOM_GRP;
620                 fstrcpy(map.nt_name, ntgroup);
621                 fstrcpy(map.comment, "");
622
623                 if (!NT_STATUS_IS_OK(pdb_add_group_mapping_entry(&map))) {
624                         d_fprintf(stderr,
625                                   _("Could not add mapping entry for %s\n"),
626                                   ntgroup);
627                         return -1;
628                 }
629         }
630
631         /* Now we have a mapping entry, update that stuff */
632
633         if ( c->opt_localgroup || c->opt_domaingroup ) {
634                 if (map.sid_name_use == SID_NAME_WKN_GRP) {
635                         d_fprintf(stderr,
636                                   _("Can't change type of the BUILTIN "
637                                     "group %s\n"),
638                                   map.nt_name);
639                         return -1;
640                 }
641         }
642
643         if (c->opt_localgroup)
644                 map.sid_name_use = SID_NAME_ALIAS;
645
646         if (c->opt_domaingroup)
647                 map.sid_name_use = SID_NAME_DOM_GRP;
648
649         /* The case (opt_domaingroup && opt_localgroup) was tested for above */
650
651         if ((c->opt_comment != NULL) && (strlen(c->opt_comment) > 0)) {
652                 fstrcpy(map.comment, c->opt_comment);
653         }
654
655         if ((c->opt_newntname != NULL) && (strlen(c->opt_newntname) > 0)) {
656                 fstrcpy(map.nt_name, c->opt_newntname);
657         }
658
659         if (grp != NULL)
660                 map.gid = grp->gr_gid;
661
662         if (!NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map))) {
663                 d_fprintf(stderr, _("Could not update group mapping for %s\n"),
664                           ntgroup);
665                 return -1;
666         }
667
668         return 0;
669 }
670
671 static int net_groupmap_cleanup(struct net_context *c, int argc, const char **argv)
672 {
673         GROUP_MAP *map = NULL;
674         size_t i, entries;
675
676         if (c->display_usage) {
677                 d_printf(  "%s\n"
678                            "net groupmap cleanup\n"
679                            "    %s\n",
680                          _("Usage:"),
681                          _("Delete all group mappings"));
682                 return 0;
683         }
684
685         if (!pdb_enum_group_mapping(NULL, SID_NAME_UNKNOWN, &map, &entries,
686                                     ENUM_ALL_MAPPED)) {
687                 d_fprintf(stderr, _("Could not list group mappings\n"));
688                 return -1;
689         }
690
691         for (i=0; i<entries; i++) {
692
693                 if (map[i].gid == -1)
694                         printf(_("Group %s is not mapped\n"), map[i].nt_name);
695
696                 if (!sid_check_is_in_our_domain(&map[i].sid)) {
697                         printf(_("Deleting mapping for NT Group %s, sid %s\n"),
698                                map[i].nt_name,
699                                sid_string_tos(&map[i].sid));
700                         pdb_delete_group_mapping_entry(map[i].sid);
701                 }
702         }
703
704         SAFE_FREE(map);
705
706         return 0;
707 }
708
709 static int net_groupmap_addmem(struct net_context *c, int argc, const char **argv)
710 {
711         struct dom_sid alias, member;
712
713         if ( (argc != 2) ||
714              c->display_usage ||
715              !string_to_sid(&alias, argv[0]) ||
716              !string_to_sid(&member, argv[1]) ) {
717                 d_printf("%s\n%s",
718                          _("Usage:"),
719                          _("net groupmap addmem alias-sid member-sid\n"));
720                 return -1;
721         }
722
723         if (!NT_STATUS_IS_OK(pdb_add_aliasmem(&alias, &member))) {
724                 d_fprintf(stderr, _("Could not add sid %s to alias %s\n"),
725                          argv[1], argv[0]);
726                 return -1;
727         }
728
729         return 0;
730 }
731
732 static int net_groupmap_delmem(struct net_context *c, int argc, const char **argv)
733 {
734         struct dom_sid alias, member;
735
736         if ( (argc != 2) ||
737              c->display_usage ||
738              !string_to_sid(&alias, argv[0]) ||
739              !string_to_sid(&member, argv[1]) ) {
740                 d_printf("%s\n%s",
741                          _("Usage:"),
742                          _("net groupmap delmem alias-sid member-sid\n"));
743                 return -1;
744         }
745
746         if (!NT_STATUS_IS_OK(pdb_del_aliasmem(&alias, &member))) {
747                 d_fprintf(stderr, _("Could not delete sid %s from alias %s\n"),
748                          argv[1], argv[0]);
749                 return -1;
750         }
751
752         return 0;
753 }
754
755 static int net_groupmap_listmem(struct net_context *c, int argc, const char **argv)
756 {
757         struct dom_sid alias;
758         struct dom_sid *members;
759         size_t i, num;
760
761         if ( (argc != 1) ||
762              c->display_usage ||
763              !string_to_sid(&alias, argv[0]) ) {
764                 d_printf("%s\n%s",
765                          _("Usage:"),
766                          _("net groupmap listmem alias-sid\n"));
767                 return -1;
768         }
769
770         members = NULL;
771         num = 0;
772
773         if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(&alias, talloc_tos(),
774                                                &members, &num))) {
775                 d_fprintf(stderr, _("Could not list members for sid %s\n"),
776                           argv[0]);
777                 return -1;
778         }
779
780         for (i = 0; i < num; i++) {
781                 printf("%s\n", sid_string_tos(&(members[i])));
782         }
783
784         TALLOC_FREE(members);
785
786         return 0;
787 }
788
789 static bool print_alias_memberships(TALLOC_CTX *mem_ctx,
790                                     const struct dom_sid *domain_sid,
791                                     const struct dom_sid *member)
792 {
793         uint32 *alias_rids;
794         size_t i, num_alias_rids;
795
796         alias_rids = NULL;
797         num_alias_rids = 0;
798
799         if (!NT_STATUS_IS_OK(pdb_enum_alias_memberships(
800                                      mem_ctx, domain_sid, member, 1,
801                                      &alias_rids, &num_alias_rids))) {
802                 d_fprintf(stderr, _("Could not list memberships for sid %s\n"),
803                          sid_string_tos(member));
804                 return false;
805         }
806
807         for (i = 0; i < num_alias_rids; i++) {
808                 struct dom_sid alias;
809                 sid_compose(&alias, domain_sid, alias_rids[i]);
810                 printf("%s\n", sid_string_tos(&alias));
811         }
812
813         return true;
814 }
815
816 static int net_groupmap_memberships(struct net_context *c, int argc, const char **argv)
817 {
818         TALLOC_CTX *mem_ctx;
819         struct dom_sid *domain_sid, member;
820
821         if ( (argc != 1) ||
822              c->display_usage ||
823              !string_to_sid(&member, argv[0]) ) {
824                 d_printf("%s\n%s",
825                          _("Usage:"),
826                          _("net groupmap memberof sid\n"));
827                 return -1;
828         }
829
830         mem_ctx = talloc_init("net_groupmap_memberships");
831         if (mem_ctx == NULL) {
832                 d_fprintf(stderr, _("talloc_init failed\n"));
833                 return -1;
834         }
835
836         domain_sid = get_global_sam_sid();
837         if (domain_sid == NULL) {
838                 d_fprintf(stderr, _("Could not get domain sid\n"));
839                 return -1;
840         }
841
842         if (!print_alias_memberships(mem_ctx, domain_sid, &member) ||
843             !print_alias_memberships(mem_ctx, &global_sid_Builtin, &member))
844                 return -1;
845
846         talloc_destroy(mem_ctx);
847
848         return 0;
849 }
850
851 /***********************************************************
852  migrated functionality from smbgroupedit
853  **********************************************************/
854 int net_groupmap(struct net_context *c, int argc, const char **argv)
855 {
856         struct functable func[] = {
857                 {
858                         "add",
859                         net_groupmap_add,
860                         NET_TRANSPORT_LOCAL,
861                         N_("Create a new group mapping"),
862                         N_("net groupmap add\n"
863                            "    Create a new group mapping")
864                 },
865                 {
866                         "modify",
867                         net_groupmap_modify,
868                         NET_TRANSPORT_LOCAL,
869                         N_("Update a group mapping"),
870                         N_("net groupmap modify\n"
871                            "    Modify an existing group mapping")
872                 },
873                 {
874                         "delete",
875                         net_groupmap_delete,
876                         NET_TRANSPORT_LOCAL,
877                         N_("Remove a group mapping"),
878                         N_("net groupmap delete\n"
879                            "    Remove a group mapping")
880                 },
881                 {
882                         "set",
883                         net_groupmap_set,
884                         NET_TRANSPORT_LOCAL,
885                         N_("Set group mapping"),
886                         N_("net groupmap set\n"
887                            "    Set a group mapping")
888                 },
889                 {
890                         "cleanup",
891                         net_groupmap_cleanup,
892                         NET_TRANSPORT_LOCAL,
893                         N_("Remove foreign group mapping entries"),
894                         N_("net groupmap cleanup\n"
895                            "    Remove foreign group mapping entries")
896                 },
897                 {
898                         "addmem",
899                         net_groupmap_addmem,
900                         NET_TRANSPORT_LOCAL,
901                         N_("Add a foreign alias member"),
902                         N_("net groupmap addmem\n"
903                            "    Add a foreign alias member")
904                 },
905                 {
906                         "delmem",
907                         net_groupmap_delmem,
908                         NET_TRANSPORT_LOCAL,
909                         N_("Delete foreign alias member"),
910                         N_("net groupmap delmem\n"
911                            "    Delete foreign alias member")
912                 },
913                 {
914                         "listmem",
915                         net_groupmap_listmem,
916                         NET_TRANSPORT_LOCAL,
917                         N_("List foreign group members"),
918                         N_("net groupmap listmem\n"
919                            "    List foreign alias members")
920                 },
921                 {
922                         "memberships",
923                         net_groupmap_memberships,
924                         NET_TRANSPORT_LOCAL,
925                         N_("List foreign group memberships"),
926                         N_("net groupmap memberships\n"
927                            "    List foreign group memberships")
928                 },
929                 {
930                         "list",
931                         net_groupmap_list,
932                         NET_TRANSPORT_LOCAL,
933                         N_("List current group map"),
934                         N_("net groupmap list\n"
935                            "    List current group map")
936                 },
937                 {NULL, NULL, 0, NULL, NULL}
938         };
939
940         return net_run_function(c,argc, argv, "net groupmap", func);
941 }
942