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