s3-privs Remove a pointer indirection from revoke_privilege()
[nivanova/samba-autobuild/.git] / source3 / utils / net_sam.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Local SAM access routines
4  *  Copyright (C) Volker Lendecke 2006
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "includes.h"
22 #include "utils/net.h"
23 #include "../librpc/gen_ndr/samr.h"
24
25 /*
26  * Set a user's data
27  */
28
29 static int net_sam_userset(struct net_context *c, int argc, const char **argv,
30                            const char *field,
31                            bool (*fn)(struct samu *, const char *,
32                                       enum pdb_value_state))
33 {
34         struct samu *sam_acct = NULL;
35         struct dom_sid sid;
36         enum lsa_SidType type;
37         const char *dom, *name;
38         NTSTATUS status;
39
40         if (argc != 2 || c->display_usage) {
41                 d_fprintf(stderr, "%s\n", _("Usage:"));
42                 d_fprintf(stderr, _("net sam set %s <user> <value>\n"),
43                           field);
44                 return -1;
45         }
46
47         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
48                          &dom, &name, &sid, &type)) {
49                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
50                 return -1;
51         }
52
53         if (type != SID_NAME_USER) {
54                 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
55                           sid_type_lookup(type));
56                 return -1;
57         }
58
59         if ( !(sam_acct = samu_new( NULL )) ) {
60                 d_fprintf(stderr, _("Internal error\n"));
61                 return -1;
62         }
63
64         if (!pdb_getsampwsid(sam_acct, &sid)) {
65                 d_fprintf(stderr, _("Loading user %s failed\n"), argv[0]);
66                 return -1;
67         }
68
69         if (!fn(sam_acct, argv[1], PDB_CHANGED)) {
70                 d_fprintf(stderr, _("Internal error\n"));
71                 return -1;
72         }
73
74         status = pdb_update_sam_account(sam_acct);
75         if (!NT_STATUS_IS_OK(status)) {
76                 d_fprintf(stderr, _("Updating sam account %s failed with %s\n"),
77                           argv[0], nt_errstr(status));
78                 return -1;
79         }
80
81         TALLOC_FREE(sam_acct);
82
83         d_printf(_("Updated %s for %s\\%s to %s\n"), field, dom, name, argv[1]);
84         return 0;
85 }
86
87 static int net_sam_set_fullname(struct net_context *c, int argc,
88                                 const char **argv)
89 {
90         return net_sam_userset(c, argc, argv, "fullname",
91                                pdb_set_fullname);
92 }
93
94 static int net_sam_set_logonscript(struct net_context *c, int argc,
95                                    const char **argv)
96 {
97         return net_sam_userset(c, argc, argv, "logonscript",
98                                pdb_set_logon_script);
99 }
100
101 static int net_sam_set_profilepath(struct net_context *c, int argc,
102                                    const char **argv)
103 {
104         return net_sam_userset(c, argc, argv, "profilepath",
105                                pdb_set_profile_path);
106 }
107
108 static int net_sam_set_homedrive(struct net_context *c, int argc,
109                                  const char **argv)
110 {
111         return net_sam_userset(c, argc, argv, "homedrive",
112                                pdb_set_dir_drive);
113 }
114
115 static int net_sam_set_homedir(struct net_context *c, int argc,
116                                const char **argv)
117 {
118         return net_sam_userset(c, argc, argv, "homedir",
119                                pdb_set_homedir);
120 }
121
122 static int net_sam_set_workstations(struct net_context *c, int argc,
123                                     const char **argv)
124 {
125         return net_sam_userset(c, argc, argv, "workstations",
126                                pdb_set_workstations);
127 }
128
129 /*
130  * Set account flags
131  */
132
133 static int net_sam_set_userflag(struct net_context *c, int argc,
134                                 const char **argv, const char *field,
135                                 uint16 flag)
136 {
137         struct samu *sam_acct = NULL;
138         struct dom_sid sid;
139         enum lsa_SidType type;
140         const char *dom, *name;
141         NTSTATUS status;
142         uint32_t acct_flags;
143
144         if ((argc != 2) || c->display_usage ||
145             (!strequal(argv[1], "yes") &&
146              !strequal(argv[1], "no"))) {
147                 d_fprintf(stderr, "%s\n", _("Usage:"));
148                 d_fprintf(stderr, _("net sam set %s <user> [yes|no]\n"),
149                           field);
150                 return -1;
151         }
152
153         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
154                          &dom, &name, &sid, &type)) {
155                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
156                 return -1;
157         }
158
159         if (type != SID_NAME_USER) {
160                 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
161                           sid_type_lookup(type));
162                 return -1;
163         }
164
165         if ( !(sam_acct = samu_new( NULL )) ) {
166                 d_fprintf(stderr, _("Internal error\n"));
167                 return -1;
168         }
169
170         if (!pdb_getsampwsid(sam_acct, &sid)) {
171                 d_fprintf(stderr, _("Loading user %s failed\n"), argv[0]);
172                 return -1;
173         }
174
175         acct_flags = pdb_get_acct_ctrl(sam_acct);
176
177         if (strequal(argv[1], "yes")) {
178                 acct_flags |= flag;
179         } else {
180                 acct_flags &= ~flag;
181         }
182
183         pdb_set_acct_ctrl(sam_acct, acct_flags, PDB_CHANGED);
184
185         status = pdb_update_sam_account(sam_acct);
186         if (!NT_STATUS_IS_OK(status)) {
187                 d_fprintf(stderr, _("Updating sam account %s failed with %s\n"),
188                           argv[0], nt_errstr(status));
189                 return -1;
190         }
191
192         TALLOC_FREE(sam_acct);
193
194         d_fprintf(stderr, _("Updated flag %s for %s\\%s to %s\n"), field, dom,
195                   name, argv[1]);
196         return 0;
197 }
198
199 static int net_sam_set_disabled(struct net_context *c, int argc,
200                                 const char **argv)
201 {
202         return net_sam_set_userflag(c, argc, argv, "disabled", ACB_DISABLED);
203 }
204
205 static int net_sam_set_pwnotreq(struct net_context *c, int argc,
206                                 const char **argv)
207 {
208         return net_sam_set_userflag(c, argc, argv, "pwnotreq", ACB_PWNOTREQ);
209 }
210
211 static int net_sam_set_autolock(struct net_context *c, int argc,
212                                 const char **argv)
213 {
214         return net_sam_set_userflag(c, argc, argv, "autolock", ACB_AUTOLOCK);
215 }
216
217 static int net_sam_set_pwnoexp(struct net_context *c, int argc,
218                                const char **argv)
219 {
220         return net_sam_set_userflag(c, argc, argv, "pwnoexp", ACB_PWNOEXP);
221 }
222
223 /*
224  * Set pass last change time, based on force pass change now
225  */
226
227 static int net_sam_set_pwdmustchangenow(struct net_context *c, int argc,
228                                         const char **argv)
229 {
230         struct samu *sam_acct = NULL;
231         struct dom_sid sid;
232         enum lsa_SidType type;
233         const char *dom, *name;
234         NTSTATUS status;
235
236         if ((argc != 2) || c->display_usage ||
237             (!strequal(argv[1], "yes") &&
238              !strequal(argv[1], "no"))) {
239                 d_fprintf(stderr, "%s\n%s",
240                           _("Usage:"),
241                           _("net sam set pwdmustchangenow <user> [yes|no]\n"));
242                 return -1;
243         }
244
245         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
246                          &dom, &name, &sid, &type)) {
247                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
248                 return -1;
249         }
250
251         if (type != SID_NAME_USER) {
252                 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
253                           sid_type_lookup(type));
254                 return -1;
255         }
256
257         if ( !(sam_acct = samu_new( NULL )) ) {
258                 d_fprintf(stderr, _("Internal error\n"));
259                 return -1;
260         }
261
262         if (!pdb_getsampwsid(sam_acct, &sid)) {
263                 d_fprintf(stderr, _("Loading user %s failed\n"), argv[0]);
264                 return -1;
265         }
266
267         if (strequal(argv[1], "yes")) {
268                 pdb_set_pass_last_set_time(sam_acct, 0, PDB_CHANGED);
269         } else {
270                 pdb_set_pass_last_set_time(sam_acct, time(NULL), PDB_CHANGED);
271         }
272
273         status = pdb_update_sam_account(sam_acct);
274         if (!NT_STATUS_IS_OK(status)) {
275                 d_fprintf(stderr, _("Updating sam account %s failed with %s\n"),
276                           argv[0], nt_errstr(status));
277                 return -1;
278         }
279
280         TALLOC_FREE(sam_acct);
281
282         d_fprintf(stderr, _("Updated 'user must change password at next logon' "
283                             "for %s\\%s to %s\n"), dom,
284                   name, argv[1]);
285         return 0;
286 }
287
288
289 /*
290  * Set a user's or a group's comment
291  */
292
293 static int net_sam_set_comment(struct net_context *c, int argc,
294                                const char **argv)
295 {
296         GROUP_MAP map;
297         struct dom_sid sid;
298         enum lsa_SidType type;
299         const char *dom, *name;
300         NTSTATUS status;
301
302         if (argc != 2 || c->display_usage) {
303                 d_fprintf(stderr, "%s\n%s",
304                           _("Usage:"),
305                           _("net sam set comment <name> <comment>\n"));
306                 return -1;
307         }
308
309         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
310                          &dom, &name, &sid, &type)) {
311                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
312                 return -1;
313         }
314
315         if (type == SID_NAME_USER) {
316                 return net_sam_userset(c, argc, argv, "comment",
317                                        pdb_set_acct_desc);
318         }
319
320         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
321             (type != SID_NAME_WKN_GRP)) {
322                 d_fprintf(stderr, _("%s is a %s, not a group\n"), argv[0],
323                           sid_type_lookup(type));
324                 return -1;
325         }
326
327         if (!pdb_getgrsid(&map, sid)) {
328                 d_fprintf(stderr, _("Could not load group %s\n"), argv[0]);
329                 return -1;
330         }
331
332         fstrcpy(map.comment, argv[1]);
333
334         status = pdb_update_group_mapping_entry(&map);
335
336         if (!NT_STATUS_IS_OK(status)) {
337                 d_fprintf(stderr, _("Updating group mapping entry failed with "
338                           "%s\n"), nt_errstr(status));
339                 return -1;
340         }
341
342         d_printf("Updated comment of group %s\\%s to %s\n", dom, name,
343                  argv[1]);
344
345         return 0;
346 }
347
348 static int net_sam_set(struct net_context *c, int argc, const char **argv)
349 {
350         struct functable func[] = {
351                 {
352                         "homedir",
353                         net_sam_set_homedir,
354                         NET_TRANSPORT_LOCAL,
355                         N_("Change a user's home directory"),
356                         N_("net sam set homedir\n"
357                            "    Change a user's home directory")
358                 },
359                 {
360                         "profilepath",
361                         net_sam_set_profilepath,
362                         NET_TRANSPORT_LOCAL,
363                         N_("Change a user's profile path"),
364                         N_("net sam set profilepath\n"
365                            "    Change a user's profile path")
366                 },
367                 {
368                         "comment",
369                         net_sam_set_comment,
370                         NET_TRANSPORT_LOCAL,
371                         N_("Change a users or groups description"),
372                         N_("net sam set comment\n"
373                            "    Change a users or groups description")
374                 },
375                 {
376                         "fullname",
377                         net_sam_set_fullname,
378                         NET_TRANSPORT_LOCAL,
379                         N_("Change a user's full name"),
380                         N_("net sam set fullname\n"
381                            "    Change a user's full name")
382                 },
383                 {
384                         "logonscript",
385                         net_sam_set_logonscript,
386                         NET_TRANSPORT_LOCAL,
387                         N_("Change a user's logon script"),
388                         N_("net sam set logonscript\n"
389                            "    Change a user's logon script")
390                 },
391                 {
392                         "homedrive",
393                         net_sam_set_homedrive,
394                         NET_TRANSPORT_LOCAL,
395                         N_("Change a user's home drive"),
396                         N_("net sam set homedrive\n"
397                            "    Change a user's home drive")
398                 },
399                 {
400                         "workstations",
401                         net_sam_set_workstations,
402                         NET_TRANSPORT_LOCAL,
403                         N_("Change a user's allowed workstations"),
404                         N_("net sam set workstations\n"
405                            "    Change a user's allowed workstations")
406                 },
407                 {
408                         "disabled",
409                         net_sam_set_disabled,
410                         NET_TRANSPORT_LOCAL,
411                         N_("Disable/Enable a user"),
412                         N_("net sam set disable\n"
413                            "    Disable/Enable a user")
414                 },
415                 {
416                         "pwnotreq",
417                         net_sam_set_pwnotreq,
418                         NET_TRANSPORT_LOCAL,
419                         N_("Disable/Enable the password not required flag"),
420                         N_("net sam set pwnotreq\n"
421                            "    Disable/Enable the password not required flag")
422                 },
423                 {
424                         "autolock",
425                         net_sam_set_autolock,
426                         NET_TRANSPORT_LOCAL,
427                         N_("Disable/Enable a user's lockout flag"),
428                         N_("net sam set autolock\n"
429                            "    Disable/Enable a user's lockout flag")
430                 },
431                 {
432                         "pwnoexp",
433                         net_sam_set_pwnoexp,
434                         NET_TRANSPORT_LOCAL,
435                         N_("Disable/Enable whether a user's pw does not "
436                            "expire"),
437                         N_("net sam set pwnoexp\n"
438                            "    Disable/Enable whether a user's pw does not "
439                            "expire")
440                 },
441                 {
442                         "pwdmustchangenow",
443                         net_sam_set_pwdmustchangenow,
444                         NET_TRANSPORT_LOCAL,
445                         N_("Force users password must change at next logon"),
446                         N_("net sam set pwdmustchangenow\n"
447                            "    Force users password must change at next logon")
448                 },
449                 {NULL, NULL, 0, NULL, NULL}
450         };
451
452         return net_run_function(c, argc, argv, "net sam set", func);
453 }
454
455 /*
456  * Manage account policies
457  */
458
459 static int net_sam_policy_set(struct net_context *c, int argc, const char **argv)
460 {
461         const char *account_policy = NULL;
462         uint32 value = 0;
463         uint32 old_value = 0;
464         enum pdb_policy_type field;
465         char *endptr;
466
467         if (argc != 2 || c->display_usage) {
468                 d_fprintf(stderr, "%s\n%s",
469                           _("Usage:"),
470                           _("net sam policy set \"<account policy>\" <value>\n"));
471                 return -1;
472         }
473
474         account_policy = argv[0];
475         field = account_policy_name_to_typenum(account_policy);
476
477         if (strequal(argv[1], "forever") || strequal(argv[1], "never")
478             || strequal(argv[1], "off")) {
479                 value = -1;
480         }
481         else {
482                 value = strtoul(argv[1], &endptr, 10);
483
484                 if ((endptr == argv[1]) || (endptr[0] != '\0')) {
485                         d_printf(_("Unable to set policy \"%s\"! Invalid value "
486                                  "\"%s\".\n"),
487                                  account_policy, argv[1]);
488                         return -1;
489                 }
490         }
491
492         if (field == 0) {
493                 const char **names;
494                 int i, count;
495
496                 account_policy_names_list(&names, &count);
497                 d_fprintf(stderr, _("No account policy \"%s\"!\n\n"), argv[0]);
498                 d_fprintf(stderr, _("Valid account policies are:\n"));
499
500                 for (i=0; i<count; i++) {
501                         d_fprintf(stderr, "%s\n", names[i]);
502                 }
503
504                 SAFE_FREE(names);
505                 return -1;
506         }
507
508         if (!pdb_get_account_policy(field, &old_value)) {
509                 d_fprintf(stderr, _("Valid account policy, but unable to fetch "
510                           "value!\n"));
511         } else {
512                 d_printf(_("Account policy \"%s\" value was: %d\n"),
513                         account_policy, old_value);
514         }
515
516         if (!pdb_set_account_policy(field, value)) {
517                 d_fprintf(stderr, _("Valid account policy, but unable to "
518                           "set value!\n"));
519                 return -1;
520         } else {
521                 d_printf(_("Account policy \"%s\" value is now: %d\n"),
522                         account_policy, value);
523         }
524
525         return 0;
526 }
527
528 static int net_sam_policy_show(struct net_context *c, int argc, const char **argv)
529 {
530         const char *account_policy = NULL;
531         uint32 old_value;
532         enum pdb_policy_type field;
533
534         if (argc != 1 || c->display_usage) {
535                 d_fprintf(stderr, "%s\n%s",
536                           _("Usage:"),
537                           _("net sam policy show \"<account policy>\"\n"));
538                 return -1;
539         }
540
541         account_policy = argv[0];
542         field = account_policy_name_to_typenum(account_policy);
543
544         if (field == 0) {
545                 const char **names;
546                 int count;
547                 int i;
548                 account_policy_names_list(&names, &count);
549                 d_fprintf(stderr, _("No account policy by that name!\n"));
550                 if (count != 0) {
551                         d_fprintf(stderr, _("Valid account policies "
552                                   "are:\n"));
553                         for (i=0; i<count; i++) {
554                                 d_fprintf(stderr, "%s\n", names[i]);
555                         }
556                 }
557                 SAFE_FREE(names);
558                 return -1;
559         }
560
561         if (!pdb_get_account_policy(field, &old_value)) {
562                 fprintf(stderr, _("Valid account policy, but unable to "
563                         "fetch value!\n"));
564                 return -1;
565         }
566
567         printf(_("Account policy \"%s\" description: %s\n"),
568                account_policy, account_policy_get_desc(field));
569         printf(_("Account policy \"%s\" value is: %d\n"), account_policy,
570                old_value);
571         return 0;
572 }
573
574 static int net_sam_policy_list(struct net_context *c, int argc, const char **argv)
575 {
576         const char **names;
577         int count;
578         int i;
579
580         if (c->display_usage) {
581                 d_printf(  "%s\n"
582                            "net sam policy list\n"
583                            "    %s\n",
584                          _("Usage:"),
585                          _("List account policies"));
586                 return 0;
587         }
588
589         account_policy_names_list(&names, &count);
590         if (count != 0) {
591                 d_fprintf(stderr, _("Valid account policies "
592                           "are:\n"));
593                 for (i = 0; i < count ; i++) {
594                         d_fprintf(stderr, "%s\n", names[i]);
595                 }
596         }
597         SAFE_FREE(names);
598         return -1;
599 }
600
601 static int net_sam_policy(struct net_context *c, int argc, const char **argv)
602 {
603         struct functable func[] = {
604                 {
605                         "list",
606                         net_sam_policy_list,
607                         NET_TRANSPORT_LOCAL,
608                         N_("List account policies"),
609                         N_("net sam policy list\n"
610                            "    List account policies")
611                 },
612                 {
613                         "show",
614                         net_sam_policy_show,
615                         NET_TRANSPORT_LOCAL,
616                         N_("Show account policies"),
617                         N_("net sam policy show\n"
618                            "    Show account policies")
619                 },
620                 {
621                         "set",
622                         net_sam_policy_set,
623                         NET_TRANSPORT_LOCAL,
624                         N_("Change account policies"),
625                         N_("net sam policy set\n"
626                            "    Change account policies")
627                 },
628                 {NULL, NULL, 0, NULL, NULL}
629         };
630
631         return net_run_function(c, argc, argv, "net sam policy", func);
632 }
633
634 static int net_sam_rights_list(struct net_context *c, int argc,
635                                const char **argv)
636 {
637         uint64_t mask;
638
639         if (argc > 1 || c->display_usage) {
640                 d_fprintf(stderr, "%s\n%s",
641                           _("Usage:"),
642                           _("net sam rights list [privilege name]\n"));
643                 return -1;
644         }
645
646         if (argc == 0) {
647                 int i;
648                 int num = num_privileges_in_short_list();
649
650                 for (i=0; i<num; i++) {
651                         d_printf("%s\n", sec_privilege_name_from_index(i));
652                 }
653                 return 0;
654         }
655
656         if (se_priv_from_name(argv[0], &mask)) {
657                 struct dom_sid *sids;
658                 int i, num_sids;
659                 NTSTATUS status;
660
661                 status = privilege_enum_sids(&mask, talloc_tos(),
662                                              &sids, &num_sids);
663                 if (!NT_STATUS_IS_OK(status)) {
664                         d_fprintf(stderr, _("Could not list rights: %s\n"),
665                                   nt_errstr(status));
666                         return -1;
667                 }
668
669                 for (i=0; i<num_sids; i++) {
670                         const char *dom, *name;
671                         enum lsa_SidType type;
672
673                         if (lookup_sid(talloc_tos(), &sids[i], &dom, &name,
674                                        &type)) {
675                                 d_printf("%s\\%s\n", dom, name);
676                         }
677                         else {
678                                 d_printf("%s\n", sid_string_tos(&sids[i]));
679                         }
680                 }
681                 return 0;
682         }
683
684         return -1;
685 }
686
687 static int net_sam_rights_grant(struct net_context *c, int argc,
688                                 const char **argv)
689 {
690         struct dom_sid sid;
691         enum lsa_SidType type;
692         const char *dom, *name;
693         uint64_t mask;
694         int i;
695
696         if (argc < 2 || c->display_usage) {
697                 d_fprintf(stderr, "%s\n%s",
698                           _("Usage:"),
699                           _("net sam rights grant <name> <rights> ...\n"));
700                 return -1;
701         }
702
703         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
704                         &dom, &name, &sid, &type)) {
705                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
706                 return -1;
707         }
708
709         for (i=1; i < argc; i++) {
710                 if (!se_priv_from_name(argv[i], &mask)) {
711                         d_fprintf(stderr, _("%s unknown\n"), argv[i]);
712                         return -1;
713                 }
714
715                 if (!grant_privilege(&sid, &mask)) {
716                         d_fprintf(stderr, _("Could not grant privilege\n"));
717                         return -1;
718                 }
719
720                 d_printf(_("Granted %s to %s\\%s\n"), argv[i], dom, name);
721         }
722
723         return 0;
724 }
725
726 static int net_sam_rights_revoke(struct net_context *c, int argc,
727                                 const char **argv)
728 {
729         struct dom_sid sid;
730         enum lsa_SidType type;
731         const char *dom, *name;
732         uint64_t mask;
733         int i;
734
735         if (argc < 2 || c->display_usage) {
736                 d_fprintf(stderr, "%s\n%s",
737                           _("Usage:"),
738                           _("net sam rights revoke <name> <rights>\n"));
739                 return -1;
740         }
741
742         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
743                         &dom, &name, &sid, &type)) {
744                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
745                 return -1;
746         }
747
748         for (i=1; i < argc; i++) {
749
750                 if (!se_priv_from_name(argv[i], &mask)) {
751                         d_fprintf(stderr, _("%s unknown\n"), argv[i]);
752                         return -1;
753                 }
754
755                 if (!revoke_privilege(&sid, mask)) {
756                         d_fprintf(stderr, _("Could not revoke privilege\n"));
757                         return -1;
758                 }
759
760                 d_printf(_("Revoked %s from %s\\%s\n"), argv[i], dom, name);
761         }
762
763         return 0;
764 }
765
766 static int net_sam_rights(struct net_context *c, int argc, const char **argv)
767 {
768         struct functable func[] = {
769                 {
770                         "list",
771                         net_sam_rights_list,
772                         NET_TRANSPORT_LOCAL,
773                         N_("List possible user rights"),
774                         N_("net sam rights list\n"
775                            "    List possible user rights")
776                 },
777                 {
778                         "grant",
779                         net_sam_rights_grant,
780                         NET_TRANSPORT_LOCAL,
781                         N_("Grant right(s)"),
782                         N_("net sam rights grant\n"
783                            "    Grant right(s)")
784                 },
785                 {
786                         "revoke",
787                         net_sam_rights_revoke,
788                         NET_TRANSPORT_LOCAL,
789                         N_("Revoke right(s)"),
790                         N_("net sam rights revoke\n"
791                            "    Revoke right(s)")
792                 },
793                 {NULL, NULL, 0, NULL, NULL}
794         };
795         return net_run_function(c, argc, argv, "net sam rights", func);
796 }
797
798 /*
799  * Map a unix group to a domain group
800  */
801
802 static NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap)
803 {
804         NTSTATUS status;
805         GROUP_MAP map;
806         const char *grpname, *dom, *name;
807         uint32 rid;
808
809         if (pdb_getgrgid(&map, grp->gr_gid)) {
810                 return NT_STATUS_GROUP_EXISTS;
811         }
812
813         map.gid = grp->gr_gid;
814         grpname = grp->gr_name;
815
816         if (lookup_name(talloc_tos(), grpname, LOOKUP_NAME_LOCAL,
817                         &dom, &name, NULL, NULL)) {
818
819                 const char *tmp = talloc_asprintf(
820                         talloc_tos(), "Unix Group %s", grp->gr_name);
821
822                 DEBUG(5, ("%s exists as %s\\%s, retrying as \"%s\"\n",
823                           grpname, dom, name, tmp));
824                 grpname = tmp;
825         }
826
827         if (lookup_name(talloc_tos(), grpname, LOOKUP_NAME_LOCAL,
828                         NULL, NULL, NULL, NULL)) {
829                 DEBUG(3, ("\"%s\" exists, can't map it\n", grp->gr_name));
830                 return NT_STATUS_GROUP_EXISTS;
831         }
832
833         fstrcpy(map.nt_name, grpname);
834
835         if (pdb_capabilities() & PDB_CAP_STORE_RIDS) {
836                 if (!pdb_new_rid(&rid)) {
837                         DEBUG(3, ("Could not get a new RID for %s\n",
838                                   grp->gr_name));
839                         return NT_STATUS_ACCESS_DENIED;
840                 }
841         } else {
842                 rid = algorithmic_pdb_gid_to_group_rid( grp->gr_gid );
843         }
844
845         sid_compose(&map.sid, get_global_sam_sid(), rid);
846         map.sid_name_use = SID_NAME_DOM_GRP;
847         fstrcpy(map.comment, talloc_asprintf(talloc_tos(), "Unix Group %s",
848                                              grp->gr_name));
849
850         status = pdb_add_group_mapping_entry(&map);
851         if (NT_STATUS_IS_OK(status)) {
852                 *pmap = map;
853         }
854         return status;
855 }
856
857 static int net_sam_mapunixgroup(struct net_context *c, int argc, const char **argv)
858 {
859         NTSTATUS status;
860         GROUP_MAP map;
861         struct group *grp;
862
863         if (argc != 1 || c->display_usage) {
864                 d_fprintf(stderr, "%s\n%s",
865                           _("Usage:"),
866                           _("net sam mapunixgroup <name>\n"));
867                 return -1;
868         }
869
870         grp = getgrnam(argv[0]);
871         if (grp == NULL) {
872                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
873                 return -1;
874         }
875
876         status = map_unix_group(grp, &map);
877
878         if (!NT_STATUS_IS_OK(status)) {
879                 d_fprintf(stderr, _("Mapping group %s failed with %s\n"),
880                           argv[0], nt_errstr(status));
881                 return -1;
882         }
883
884         d_printf(_("Mapped unix group %s to SID %s\n"), argv[0],
885                  sid_string_tos(&map.sid));
886
887         return 0;
888 }
889
890 /*
891  * Remove a group mapping
892  */
893
894 static NTSTATUS unmap_unix_group(const struct group *grp, GROUP_MAP *pmap)
895 {
896         GROUP_MAP map;
897         const char *grpname;
898         struct dom_sid dom_sid;
899
900         map.gid = grp->gr_gid;
901         grpname = grp->gr_name;
902
903         if (!lookup_name(talloc_tos(), grpname, LOOKUP_NAME_LOCAL,
904                         NULL, NULL, NULL, NULL)) {
905                 DEBUG(3, ("\"%s\" does not exist, can't unmap it\n", grp->gr_name));
906                 return NT_STATUS_NO_SUCH_GROUP;
907         }
908
909         fstrcpy(map.nt_name, grpname);
910
911         if (!pdb_gid_to_sid(map.gid, &dom_sid)) {
912                 return NT_STATUS_UNSUCCESSFUL;
913         }
914
915         return pdb_delete_group_mapping_entry(dom_sid);
916 }
917
918 static int net_sam_unmapunixgroup(struct net_context *c, int argc, const char **argv)
919 {
920         NTSTATUS status;
921         GROUP_MAP map;
922         struct group *grp;
923
924         if (argc != 1 || c->display_usage) {
925                 d_fprintf(stderr, "%s\n%s",
926                           _("Usage:"),
927                           _("net sam unmapunixgroup <name>\n"));
928                 return -1;
929         }
930
931         grp = getgrnam(argv[0]);
932         if (grp == NULL) {
933                 d_fprintf(stderr, _("Could not find mapping for group %s.\n"),
934                           argv[0]);
935                 return -1;
936         }
937
938         status = unmap_unix_group(grp, &map);
939
940         if (!NT_STATUS_IS_OK(status)) {
941                 d_fprintf(stderr, _("Unmapping group %s failed with %s.\n"),
942                           argv[0], nt_errstr(status));
943                 return -1;
944         }
945
946         d_printf(_("Unmapped unix group %s.\n"), argv[0]);
947
948         return 0;
949 }
950
951 /*
952  * Create a domain group
953  */
954
955 static int net_sam_createdomaingroup(struct net_context *c, int argc,
956                                      const char **argv)
957 {
958         NTSTATUS status;
959         uint32 rid;
960
961         if (argc != 1 || c->display_usage) {
962                 d_fprintf(stderr, "%s\n%s",
963                           _("Usage:"),
964                           _("net sam createdomaingroup <name>\n"));
965                 return -1;
966         }
967
968         status = pdb_create_dom_group(talloc_tos(), argv[0], &rid);
969
970         if (!NT_STATUS_IS_OK(status)) {
971                 d_fprintf(stderr, _("Creating %s failed with %s\n"),
972                           argv[0], nt_errstr(status));
973                 return -1;
974         }
975
976         d_printf(_("Created domain group %s with RID %d\n"), argv[0], rid);
977
978         return 0;
979 }
980
981 /*
982  * Delete a domain group
983  */
984
985 static int net_sam_deletedomaingroup(struct net_context *c, int argc,
986                                      const char **argv)
987 {
988         struct dom_sid sid;
989         uint32_t rid;
990         enum lsa_SidType type;
991         const char *dom, *name;
992         NTSTATUS status;
993
994         if (argc != 1 || c->display_usage) {
995                 d_fprintf(stderr, "%s\n%s",
996                           _("Usage:"),
997                           _("net sam deletelocalgroup <name>\n"));
998                 return -1;
999         }
1000
1001         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1002                          &dom, &name, &sid, &type)) {
1003                 d_fprintf(stderr, _("Could not find %s.\n"), argv[0]);
1004                 return -1;
1005         }
1006
1007         if (type != SID_NAME_DOM_GRP) {
1008                 d_fprintf(stderr, _("%s is a %s, not a domain group.\n"),
1009                           argv[0], sid_type_lookup(type));
1010                 return -1;
1011         }
1012
1013         sid_peek_rid(&sid, &rid);
1014
1015         status = pdb_delete_dom_group(talloc_tos(), rid);
1016
1017         if (!NT_STATUS_IS_OK(status)) {
1018                 d_fprintf(stderr,_("Deleting domain group %s failed with %s\n"),
1019                           argv[0], nt_errstr(status));
1020                 return -1;
1021         }
1022
1023         d_printf(_("Deleted domain group %s.\n"), argv[0]);
1024
1025         return 0;
1026 }
1027
1028 /*
1029  * Create a local group
1030  */
1031
1032 static int net_sam_createlocalgroup(struct net_context *c, int argc, const char **argv)
1033 {
1034         NTSTATUS status;
1035         uint32 rid;
1036
1037         if (argc != 1 || c->display_usage) {
1038                 d_fprintf(stderr, "%s\n%s",
1039                           _("Usage:"),
1040                           _("net sam createlocalgroup <name>\n"));
1041                 return -1;
1042         }
1043
1044         if (!winbind_ping()) {
1045                 d_fprintf(stderr, _("winbind seems not to run. "
1046                           "createlocalgroup only works when winbind runs.\n"));
1047                 return -1;
1048         }
1049
1050         status = pdb_create_alias(argv[0], &rid);
1051
1052         if (!NT_STATUS_IS_OK(status)) {
1053                 d_fprintf(stderr, _("Creating %s failed with %s\n"),
1054                           argv[0], nt_errstr(status));
1055                 return -1;
1056         }
1057
1058         d_printf(_("Created local group %s with RID %d\n"), argv[0], rid);
1059
1060         return 0;
1061 }
1062
1063 /*
1064  * Delete a local group
1065  */
1066
1067 static int net_sam_deletelocalgroup(struct net_context *c, int argc, const char **argv)
1068 {
1069         struct dom_sid sid;
1070         enum lsa_SidType type;
1071         const char *dom, *name;
1072         NTSTATUS status;
1073
1074         if (argc != 1 || c->display_usage) {
1075                 d_fprintf(stderr, "%s\n%s",
1076                           _("Usage:"),
1077                           _("net sam deletelocalgroup <name>\n"));
1078                 return -1;
1079         }
1080
1081         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1082                          &dom, &name, &sid, &type)) {
1083                 d_fprintf(stderr,_("Could not find %s.\n"), argv[0]);
1084                 return -1;
1085         }
1086
1087         if (type != SID_NAME_ALIAS) {
1088                 d_fprintf(stderr, _("%s is a %s, not a local group.\n"),argv[0],
1089                           sid_type_lookup(type));
1090                 return -1;
1091         }
1092
1093         status = pdb_delete_alias(&sid);
1094
1095         if (!NT_STATUS_IS_OK(status)) {
1096                 d_fprintf(stderr, _("Deleting local group %s failed with %s\n"),
1097                           argv[0], nt_errstr(status));
1098                 return -1;
1099         }
1100
1101         d_printf(_("Deleted local group %s.\n"), argv[0]);
1102
1103         return 0;
1104 }
1105
1106 /*
1107  * Create a builtin group
1108  */
1109
1110 static int net_sam_createbuiltingroup(struct net_context *c, int argc, const char **argv)
1111 {
1112         NTSTATUS status;
1113         uint32 rid;
1114         enum lsa_SidType type;
1115         fstring groupname;
1116         struct dom_sid sid;
1117
1118         if (argc != 1 || c->display_usage) {
1119                 d_fprintf(stderr, "%s\n%s",
1120                           _("Usage:"),
1121                           _("net sam createbuiltingroup <name>\n"));
1122                 return -1;
1123         }
1124
1125         if (!winbind_ping()) {
1126                 d_fprintf(stderr, _("winbind seems not to run. "
1127                           "createbuiltingroup only works when winbind "
1128                           "runs.\n"));
1129                 return -1;
1130         }
1131
1132         /* validate the name and get the group */
1133
1134         fstrcpy( groupname, "BUILTIN\\" );
1135         fstrcat( groupname, argv[0] );
1136
1137         if ( !lookup_name(talloc_tos(), groupname, LOOKUP_NAME_ALL, NULL,
1138                           NULL, &sid, &type)) {
1139                 d_fprintf(stderr, _("%s is not a BUILTIN group\n"), argv[0]);
1140                 return -1;
1141         }
1142
1143         if ( !sid_peek_rid( &sid, &rid ) ) {
1144                 d_fprintf(stderr, _("Failed to get RID for %s\n"), argv[0]);
1145                 return -1;
1146         }
1147
1148         status = pdb_create_builtin_alias( rid );
1149
1150         if (!NT_STATUS_IS_OK(status)) {
1151                 d_fprintf(stderr, _("Creating %s failed with %s\n"),
1152                           argv[0], nt_errstr(status));
1153                 return -1;
1154         }
1155
1156         d_printf(_("Created BUILTIN group %s with RID %d\n"), argv[0], rid);
1157
1158         return 0;
1159 }
1160
1161 /*
1162  * Add a group member
1163  */
1164
1165 static int net_sam_addmem(struct net_context *c, int argc, const char **argv)
1166 {
1167         const char *groupdomain, *groupname, *memberdomain, *membername;
1168         struct dom_sid group, member;
1169         enum lsa_SidType grouptype, membertype;
1170         NTSTATUS status;
1171
1172         if (argc != 2 || c->display_usage) {
1173                 d_fprintf(stderr, "%s\n%s",
1174                           _("Usage:"),
1175                           _("net sam addmem <group> <member>\n"));
1176                 return -1;
1177         }
1178
1179         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1180                          &groupdomain, &groupname, &group, &grouptype)) {
1181                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
1182                 return -1;
1183         }
1184
1185         /* check to see if the member to be added is a name or a SID */
1186
1187         if (!lookup_name(talloc_tos(), argv[1], LOOKUP_NAME_LOCAL,
1188                          &memberdomain, &membername, &member, &membertype))
1189         {
1190                 /* try it as a SID */
1191
1192                 if ( !string_to_sid( &member, argv[1] ) ) {
1193                         d_fprintf(stderr, _("Could not find member %s\n"),
1194                                   argv[1]);
1195                         return -1;
1196                 }
1197
1198                 if ( !lookup_sid(talloc_tos(), &member, &memberdomain,
1199                         &membername, &membertype) )
1200                 {
1201                         d_fprintf(stderr, _("Could not resolve SID %s\n"),
1202                                   argv[1]);
1203                         return -1;
1204                 }
1205         }
1206
1207         if ((grouptype == SID_NAME_ALIAS) || (grouptype == SID_NAME_WKN_GRP)) {
1208                 if ((membertype != SID_NAME_USER) &&
1209                     (membertype != SID_NAME_DOM_GRP)) {
1210                         d_fprintf(stderr, _("%s is a local group, only users "
1211                                   "and domain groups can be added.\n"
1212                                   "%s is a %s\n"), argv[0], argv[1],
1213                                   sid_type_lookup(membertype));
1214                         return -1;
1215                 }
1216                 status = pdb_add_aliasmem(&group, &member);
1217
1218                 if (!NT_STATUS_IS_OK(status)) {
1219                         d_fprintf(stderr, _("Adding local group member failed "
1220                                   "with %s\n"), nt_errstr(status));
1221                         return -1;
1222                 }
1223         } else if (grouptype == SID_NAME_DOM_GRP) {
1224                 uint32_t grouprid, memberrid;
1225
1226                 sid_peek_rid(&group, &grouprid);
1227                 sid_peek_rid(&member, &memberrid);
1228
1229                 status = pdb_add_groupmem(talloc_tos(), grouprid, memberrid);
1230                 if (!NT_STATUS_IS_OK(status)) {
1231                         d_fprintf(stderr, _("Adding domain group member failed "
1232                                   "with %s\n"), nt_errstr(status));
1233                         return -1;
1234                 }
1235         } else {
1236                 d_fprintf(stderr, _("Can only add members to local groups so "
1237                           "far, %s is a %s\n"), argv[0],
1238                           sid_type_lookup(grouptype));
1239                 return -1;
1240         }
1241
1242         d_printf(_("Added %s\\%s to %s\\%s\n"), memberdomain, membername,
1243                 groupdomain, groupname);
1244
1245         return 0;
1246 }
1247
1248 /*
1249  * Delete a group member
1250  */
1251
1252 static int net_sam_delmem(struct net_context *c, int argc, const char **argv)
1253 {
1254         const char *groupdomain, *groupname;
1255         const char *memberdomain = NULL;
1256         const char *membername = NULL;
1257         struct dom_sid group, member;
1258         enum lsa_SidType grouptype;
1259         NTSTATUS status;
1260
1261         if (argc != 2 || c->display_usage) {
1262                 d_fprintf(stderr,"%s\n%s",
1263                           _("Usage:"),
1264                           _("net sam delmem <group> <member>\n"));
1265                 return -1;
1266         }
1267
1268         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1269                          &groupdomain, &groupname, &group, &grouptype)) {
1270                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
1271                 return -1;
1272         }
1273
1274         if (!lookup_name(talloc_tos(), argv[1], LOOKUP_NAME_LOCAL,
1275                          &memberdomain, &membername, &member, NULL)) {
1276                 if (!string_to_sid(&member, argv[1])) {
1277                         d_fprintf(stderr, _("Could not find member %s\n"),
1278                                   argv[1]);
1279                         return -1;
1280                 }
1281         }
1282
1283         if ((grouptype == SID_NAME_ALIAS) ||
1284             (grouptype == SID_NAME_WKN_GRP)) {
1285                 status = pdb_del_aliasmem(&group, &member);
1286
1287                 if (!NT_STATUS_IS_OK(status)) {
1288                         d_fprintf(stderr,_("Deleting local group member failed "
1289                                   "with %s\n"), nt_errstr(status));
1290                         return -1;
1291                 }
1292         } else if (grouptype == SID_NAME_DOM_GRP) {
1293                 uint32_t grouprid, memberrid;
1294
1295                 sid_peek_rid(&group, &grouprid);
1296                 sid_peek_rid(&member, &memberrid);
1297
1298                 status = pdb_del_groupmem(talloc_tos(), grouprid, memberrid);
1299                 if (!NT_STATUS_IS_OK(status)) {
1300                         d_fprintf(stderr, _("Deleting domain group member "
1301                                   "failed with %s\n"), nt_errstr(status));
1302                         return -1;
1303                 }
1304         } else {
1305                 d_fprintf(stderr, _("Can only delete members from local groups "
1306                           "so far, %s is a %s\n"), argv[0],
1307                           sid_type_lookup(grouptype));
1308                 return -1;
1309         }
1310
1311         if (membername != NULL) {
1312                 d_printf(_("Deleted %s\\%s from %s\\%s\n"),
1313                          memberdomain, membername, groupdomain, groupname);
1314         } else {
1315                 d_printf(_("Deleted %s from %s\\%s\n"),
1316                          sid_string_tos(&member), groupdomain, groupname);
1317         }
1318
1319         return 0;
1320 }
1321
1322 /*
1323  * List group members
1324  */
1325
1326 static int net_sam_listmem(struct net_context *c, int argc, const char **argv)
1327 {
1328         const char *groupdomain, *groupname;
1329         struct dom_sid group;
1330         struct dom_sid *members = NULL;
1331         size_t i, num_members = 0;
1332         enum lsa_SidType grouptype;
1333         NTSTATUS status;
1334
1335         if (argc != 1 || c->display_usage) {
1336                 d_fprintf(stderr, "%s\n%s",
1337                           _("Usage:"),
1338                           _("net sam listmem <group>\n"));
1339                 return -1;
1340         }
1341
1342         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1343                          &groupdomain, &groupname, &group, &grouptype)) {
1344                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
1345                 return -1;
1346         }
1347
1348         if ((grouptype == SID_NAME_ALIAS) ||
1349             (grouptype == SID_NAME_WKN_GRP)) {
1350                 status = pdb_enum_aliasmem(&group, talloc_tos(), &members,
1351                                            &num_members);
1352                 if (!NT_STATUS_IS_OK(status)) {
1353                         d_fprintf(stderr, _("Listing group members failed with "
1354                                   "%s\n"), nt_errstr(status));
1355                         return -1;
1356                 }
1357         } else if (grouptype == SID_NAME_DOM_GRP) {
1358                 uint32_t *rids;
1359
1360                 status = pdb_enum_group_members(talloc_tos(), &group,
1361                                                 &rids, &num_members);
1362                 if (!NT_STATUS_IS_OK(status)) {
1363                         d_fprintf(stderr, _("Listing group members failed with "
1364                                   "%s\n"), nt_errstr(status));
1365                         return -1;
1366                 }
1367
1368                 members = talloc_array(talloc_tos(), struct dom_sid,
1369                                        num_members);
1370                 if (members == NULL) {
1371                         TALLOC_FREE(rids);
1372                         return -1;
1373                 }
1374
1375                 for (i=0; i<num_members; i++) {
1376                         sid_compose(&members[i], get_global_sam_sid(),
1377                                     rids[i]);
1378                 }
1379                 TALLOC_FREE(rids);
1380         } else {
1381                 d_fprintf(stderr,_("Can only list local group members so far.\n"
1382                           "%s is a %s\n"), argv[0], sid_type_lookup(grouptype));
1383                 return -1;
1384         }
1385
1386         d_printf(_("%s\\%s has %u members\n"), groupdomain, groupname,
1387                  (unsigned int)num_members);
1388         for (i=0; i<num_members; i++) {
1389                 const char *dom, *name;
1390                 if (lookup_sid(talloc_tos(), &members[i], &dom, &name, NULL)) {
1391                         d_printf(" %s\\%s\n", dom, name);
1392                 } else {
1393                         d_printf(" %s\n", sid_string_tos(&members[i]));
1394                 }
1395         }
1396
1397                 TALLOC_FREE(members);
1398
1399         return 0;
1400 }
1401
1402 /*
1403  * Do the listing
1404  */
1405 static int net_sam_do_list(struct net_context *c, int argc, const char **argv,
1406                            struct pdb_search *search, const char *what)
1407 {
1408         bool verbose = (argc == 1);
1409
1410         if ((argc > 1) || c->display_usage ||
1411             ((argc == 1) && !strequal(argv[0], "verbose"))) {
1412                 d_fprintf(stderr, "%s\n", _("Usage:"));
1413                 d_fprintf(stderr, _("net sam list %s [verbose]\n"), what);
1414                 return -1;
1415         }
1416
1417         if (search == NULL) {
1418                 d_fprintf(stderr, _("Could not start search\n"));
1419                 return -1;
1420         }
1421
1422         while (true) {
1423                 struct samr_displayentry entry;
1424                 if (!search->next_entry(search, &entry)) {
1425                         break;
1426                 }
1427                 if (verbose) {
1428                         d_printf("%s:%d:%s\n",
1429                                  entry.account_name,
1430                                  entry.rid,
1431                                  entry.description);
1432                 } else {
1433                         d_printf("%s\n", entry.account_name);
1434                 }
1435         }
1436
1437         TALLOC_FREE(search);
1438         return 0;
1439 }
1440
1441 static int net_sam_list_users(struct net_context *c, int argc,
1442                               const char **argv)
1443 {
1444         return net_sam_do_list(c, argc, argv,
1445                                pdb_search_users(talloc_tos(), ACB_NORMAL),
1446                                "users");
1447 }
1448
1449 static int net_sam_list_groups(struct net_context *c, int argc,
1450                                const char **argv)
1451 {
1452         return net_sam_do_list(c, argc, argv, pdb_search_groups(talloc_tos()),
1453                                "groups");
1454 }
1455
1456 static int net_sam_list_localgroups(struct net_context *c, int argc,
1457                                     const char **argv)
1458 {
1459         return net_sam_do_list(c, argc, argv,
1460                                pdb_search_aliases(talloc_tos(),
1461                                                   get_global_sam_sid()),
1462                                "localgroups");
1463 }
1464
1465 static int net_sam_list_builtin(struct net_context *c, int argc,
1466                                 const char **argv)
1467 {
1468         return net_sam_do_list(c, argc, argv,
1469                                pdb_search_aliases(talloc_tos(),
1470                                                   &global_sid_Builtin),
1471                                "builtin");
1472 }
1473
1474 static int net_sam_list_workstations(struct net_context *c, int argc,
1475                                      const char **argv)
1476 {
1477         return net_sam_do_list(c, argc, argv,
1478                                pdb_search_users(talloc_tos(), ACB_WSTRUST),
1479                                "workstations");
1480 }
1481
1482 /*
1483  * List stuff
1484  */
1485
1486 static int net_sam_list(struct net_context *c, int argc, const char **argv)
1487 {
1488         struct functable func[] = {
1489                 {
1490                         "users",
1491                         net_sam_list_users,
1492                         NET_TRANSPORT_LOCAL,
1493                         N_("List SAM users"),
1494                         N_("net sam list users\n"
1495                            "    List SAM users")
1496                 },
1497                 {
1498                         "groups",
1499                         net_sam_list_groups,
1500                         NET_TRANSPORT_LOCAL,
1501                         N_("List SAM groups"),
1502                         N_("net sam list groups\n"
1503                            "    List SAM groups")
1504                 },
1505                 {
1506                         "localgroups",
1507                         net_sam_list_localgroups,
1508                         NET_TRANSPORT_LOCAL,
1509                         N_("List SAM local groups"),
1510                         N_("net sam list localgroups\n"
1511                            "    List SAM local groups")
1512                 },
1513                 {
1514                         "builtin",
1515                         net_sam_list_builtin,
1516                         NET_TRANSPORT_LOCAL,
1517                         N_("List builtin groups"),
1518                         N_("net sam list builtin\n"
1519                            "    List builtin groups")
1520                 },
1521                 {
1522                         "workstations",
1523                         net_sam_list_workstations,
1524                         NET_TRANSPORT_LOCAL,
1525                         N_("List domain member workstations"),
1526                         N_("net sam list workstations\n"
1527                            "    List domain member workstations")
1528                 },
1529                 {NULL, NULL, 0, NULL, NULL}
1530         };
1531
1532         return net_run_function(c, argc, argv, "net sam list", func);
1533 }
1534
1535 /*
1536  * Show details of SAM entries
1537  */
1538
1539 static int net_sam_show(struct net_context *c, int argc, const char **argv)
1540 {
1541         struct dom_sid sid;
1542         enum lsa_SidType type;
1543         const char *dom, *name;
1544
1545         if (argc != 1 || c->display_usage) {
1546                 d_fprintf(stderr, "%s\n%s",
1547                           _("Usage:"),
1548                           _("net sam show <name>\n"));
1549                 return -1;
1550         }
1551
1552         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1553                          &dom, &name, &sid, &type)) {
1554                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
1555                 return -1;
1556         }
1557
1558         d_printf(_("%s\\%s is a %s with SID %s\n"), dom, name,
1559                  sid_type_lookup(type), sid_string_tos(&sid));
1560
1561         return 0;
1562 }
1563
1564 #ifdef HAVE_LDAP
1565
1566 /*
1567  * Init an LDAP tree with default users and Groups
1568  * if ldapsam:editposix is enabled
1569  */
1570
1571 static int net_sam_provision(struct net_context *c, int argc, const char **argv)
1572 {
1573         TALLOC_CTX *tc;
1574         char *ldap_bk;
1575         char *ldap_uri = NULL;
1576         char *p;
1577         struct smbldap_state *ls;
1578         GROUP_MAP gmap;
1579         struct dom_sid gsid;
1580         gid_t domusers_gid = -1;
1581         gid_t domadmins_gid = -1;
1582         struct samu *samuser;
1583         struct passwd *pwd;
1584
1585         if (c->display_usage) {
1586                 d_printf(  "%s\n"
1587                            "net sam provision\n"
1588                             "    %s\n",
1589                           _("Usage:"),
1590                           _("Init an LDAP tree with default users/groups"));
1591                 return 0;
1592         }
1593
1594         tc = talloc_new(NULL);
1595         if (!tc) {
1596                 d_fprintf(stderr, _("Out of Memory!\n"));
1597                 return -1;
1598         }
1599
1600         if ((ldap_bk = talloc_strdup(tc, lp_passdb_backend())) == NULL) {
1601                 d_fprintf(stderr, _("talloc failed\n"));
1602                 talloc_free(tc);
1603                 return -1;
1604         }
1605         p = strchr(ldap_bk, ':');
1606         if (p) {
1607                 *p = 0;
1608                 ldap_uri = talloc_strdup(tc, p+1);
1609                 trim_char(ldap_uri, ' ', ' ');
1610         }
1611
1612         trim_char(ldap_bk, ' ', ' ');
1613
1614         if (strcmp(ldap_bk, "ldapsam") != 0) {
1615                 d_fprintf(stderr,
1616                           _("Provisioning works only with ldapsam backend\n"));
1617                 goto failed;
1618         }
1619
1620         if (!lp_parm_bool(-1, "ldapsam", "trusted", false) ||
1621             !lp_parm_bool(-1, "ldapsam", "editposix", false)) {
1622
1623                 d_fprintf(stderr, _("Provisioning works only if ldapsam:trusted"
1624                                     " and ldapsam:editposix are enabled.\n"));
1625                 goto failed;
1626         }
1627
1628         if (!winbind_ping()) {
1629                 d_fprintf(stderr, _("winbind seems not to run. Provisioning "
1630                             "LDAP only works when winbind runs.\n"));
1631                 goto failed;
1632         }
1633
1634         if (!NT_STATUS_IS_OK(smbldap_init(tc, NULL, ldap_uri, &ls))) {
1635                 d_fprintf(stderr, _("Unable to connect to the LDAP server.\n"));
1636                 goto failed;
1637         }
1638
1639         d_printf(_("Checking for Domain Users group.\n"));
1640
1641         sid_compose(&gsid, get_global_sam_sid(), DOMAIN_RID_USERS);
1642
1643         if (!pdb_getgrsid(&gmap, gsid)) {
1644                 LDAPMod **mods = NULL;
1645                 char *dn;
1646                 char *uname;
1647                 char *wname;
1648                 char *gidstr;
1649                 char *gtype;
1650                 int rc;
1651
1652                 d_printf(_("Adding the Domain Users group.\n"));
1653
1654                 /* lets allocate a new groupid for this group */
1655                 if (!winbind_allocate_gid(&domusers_gid)) {
1656                         d_fprintf(stderr, _("Unable to allocate a new gid to "
1657                                             "create Domain Users group!\n"));
1658                         goto domu_done;
1659                 }
1660
1661                 uname = talloc_strdup(tc, "domusers");
1662                 wname = talloc_strdup(tc, "Domain Users");
1663                 dn = talloc_asprintf(tc, "cn=%s,%s", "domusers", lp_ldap_group_suffix());
1664                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)domusers_gid);
1665                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1666
1667                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1668                         d_fprintf(stderr, "Out of Memory!\n");
1669                         goto failed;
1670                 }
1671
1672                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXGROUP);
1673                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1674                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1675                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1676                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1677                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid",
1678                                 sid_string_talloc(tc, &gsid));
1679                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1680
1681                 talloc_autofree_ldapmod(tc, mods);
1682
1683                 rc = smbldap_add(ls, dn, mods);
1684
1685                 if (rc != LDAP_SUCCESS) {
1686                         d_fprintf(stderr, _("Failed to add Domain Users group "
1687                                             "to ldap directory\n"));
1688                 }
1689         } else {
1690                 domusers_gid = gmap.gid;
1691                 d_printf(_("found!\n"));
1692         }
1693
1694 domu_done:
1695
1696         d_printf(_("Checking for Domain Admins group.\n"));
1697
1698         sid_compose(&gsid, get_global_sam_sid(), DOMAIN_RID_ADMINS);
1699
1700         if (!pdb_getgrsid(&gmap, gsid)) {
1701                 LDAPMod **mods = NULL;
1702                 char *dn;
1703                 char *uname;
1704                 char *wname;
1705                 char *gidstr;
1706                 char *gtype;
1707                 int rc;
1708
1709                 d_printf(_("Adding the Domain Admins group.\n"));
1710
1711                 /* lets allocate a new groupid for this group */
1712                 if (!winbind_allocate_gid(&domadmins_gid)) {
1713                         d_fprintf(stderr, _("Unable to allocate a new gid to "
1714                                             "create Domain Admins group!\n"));
1715                         goto doma_done;
1716                 }
1717
1718                 uname = talloc_strdup(tc, "domadmins");
1719                 wname = talloc_strdup(tc, "Domain Admins");
1720                 dn = talloc_asprintf(tc, "cn=%s,%s", "domadmins", lp_ldap_group_suffix());
1721                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)domadmins_gid);
1722                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1723
1724                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1725                         d_fprintf(stderr, _("Out of Memory!\n"));
1726                         goto failed;
1727                 }
1728
1729                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXGROUP);
1730                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1731                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1732                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1733                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1734                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid",
1735                                 sid_string_talloc(tc, &gsid));
1736                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1737
1738                 talloc_autofree_ldapmod(tc, mods);
1739
1740                 rc = smbldap_add(ls, dn, mods);
1741
1742                 if (rc != LDAP_SUCCESS) {
1743                         d_fprintf(stderr, _("Failed to add Domain Admins group "
1744                                             "to ldap directory\n"));
1745                 }
1746         } else {
1747                 domadmins_gid = gmap.gid;
1748                 d_printf(_("found!\n"));
1749         }
1750
1751 doma_done:
1752
1753         d_printf(_("Check for Administrator account.\n"));
1754
1755         samuser = samu_new(tc);
1756         if (!samuser) {
1757                 d_fprintf(stderr, _("Out of Memory!\n"));
1758                 goto failed;
1759         }
1760
1761         if (!pdb_getsampwnam(samuser, "Administrator")) {
1762                 LDAPMod **mods = NULL;
1763                 struct dom_sid sid;
1764                 char *dn;
1765                 char *name;
1766                 char *uidstr;
1767                 char *gidstr;
1768                 char *shell;
1769                 char *dir;
1770                 uid_t uid;
1771                 int rc;
1772
1773                 d_printf(_("Adding the Administrator user.\n"));
1774
1775                 if (domadmins_gid == -1) {
1776                         d_fprintf(stderr,
1777                                   _("Can't create Administrator user, Domain "
1778                                     "Admins group not available!\n"));
1779                         goto done;
1780                 }
1781                 name = talloc_strdup(tc, "Administrator");
1782                 dn = talloc_asprintf(tc, "uid=Administrator,%s", lp_ldap_user_suffix());
1783                 uidstr = talloc_asprintf(tc, "%u", (unsigned int)uid);
1784                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)domadmins_gid);
1785                 dir = talloc_sub_specified(tc, lp_template_homedir(),
1786                                                 "Administrator",
1787                                                 get_global_sam_name(),
1788                                                 uid, domadmins_gid);
1789                 shell = talloc_sub_specified(tc, lp_template_shell(),
1790                                                 "Administrator",
1791                                                 get_global_sam_name(),
1792                                                 uid, domadmins_gid);
1793
1794                 if (!name || !dn || !uidstr || !gidstr || !dir || !shell) {
1795                         d_fprintf(stderr, _("Out of Memory!\n"));
1796                         goto failed;
1797                 }
1798
1799                 sid_compose(&sid, get_global_sam_sid(), DOMAIN_RID_ADMINISTRATOR);
1800
1801                 if (!winbind_allocate_uid(&uid)) {
1802                         d_fprintf(stderr,
1803                                   _("Unable to allocate a new uid to create "
1804                                     "the Administrator user!\n"));
1805                         goto done;
1806                 }
1807
1808                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
1809                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
1810                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
1811                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", name);
1812                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
1813                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
1814                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
1815                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1816                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", dir);
1817                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
1818                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID",
1819                                 sid_string_talloc(tc, &sid));
1820                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
1821                                 pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
1822                                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1823
1824                 talloc_autofree_ldapmod(tc, mods);
1825
1826                 rc = smbldap_add(ls, dn, mods);
1827
1828                 if (rc != LDAP_SUCCESS) {
1829                         d_fprintf(stderr, _("Failed to add Administrator user "
1830                                             "to ldap directory\n"));
1831                 }
1832         } else {
1833                 d_printf(_("found!\n"));
1834         }
1835
1836         d_printf(_("Checking for Guest user.\n"));
1837
1838         samuser = samu_new(tc);
1839         if (!samuser) {
1840                 d_fprintf(stderr, _("Out of Memory!\n"));
1841                 goto failed;
1842         }
1843
1844         if (!pdb_getsampwnam(samuser, lp_guestaccount())) {
1845                 LDAPMod **mods = NULL;
1846                 struct dom_sid sid;
1847                 char *dn;
1848                 char *uidstr;
1849                 char *gidstr;
1850                 int rc;
1851
1852                 d_printf(_("Adding the Guest user.\n"));
1853
1854                 sid_compose(&sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
1855
1856                 pwd = getpwnam_alloc(tc, lp_guestaccount());
1857
1858                 if (!pwd) {
1859                         if (domusers_gid == -1) {
1860                                 d_fprintf(stderr,
1861                                           _("Can't create Guest user, Domain "
1862                                             "Users group not available!\n"));
1863                                 goto done;
1864                         }
1865                         if ((pwd = talloc(tc, struct passwd)) == NULL) {
1866                                 d_fprintf(stderr, _("talloc failed\n"));
1867                                 goto done;
1868                         }
1869                         pwd->pw_name = talloc_strdup(pwd, lp_guestaccount());
1870                         if (!winbind_allocate_uid(&(pwd->pw_uid))) {
1871                                 d_fprintf(stderr,
1872                                           _("Unable to allocate a new uid to "
1873                                             "create the Guest user!\n"));
1874                                 goto done;
1875                         }
1876                         pwd->pw_gid = domusers_gid;
1877                         pwd->pw_dir = talloc_strdup(tc, "/");
1878                         pwd->pw_shell = talloc_strdup(tc, "/bin/false");
1879                         if (!pwd->pw_dir || !pwd->pw_shell) {
1880                                 d_fprintf(stderr, _("Out of Memory!\n"));
1881                                 goto failed;
1882                         }
1883                 }
1884
1885                 dn = talloc_asprintf(tc, "uid=%s,%s", pwd->pw_name, lp_ldap_user_suffix ());
1886                 uidstr = talloc_asprintf(tc, "%u", (unsigned int)pwd->pw_uid);
1887                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)pwd->pw_gid);
1888                 if (!dn || !uidstr || !gidstr) {
1889                         d_fprintf(stderr, _("Out of Memory!\n"));
1890                         goto failed;
1891                 }
1892
1893                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
1894                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
1895                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
1896                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", pwd->pw_name);
1897                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", pwd->pw_name);
1898                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
1899                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
1900                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1901                 if ((pwd->pw_dir != NULL) && (pwd->pw_dir[0] != '\0')) {
1902                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
1903                 }
1904                 if ((pwd->pw_shell != NULL) && (pwd->pw_shell[0] != '\0')) {
1905                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
1906                 }
1907                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID",
1908                                 sid_string_talloc(tc, &sid));
1909                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
1910                                 pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
1911                                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1912
1913                 talloc_autofree_ldapmod(tc, mods);
1914
1915                 rc = smbldap_add(ls, dn, mods);
1916
1917                 if (rc != LDAP_SUCCESS) {
1918                         d_fprintf(stderr, _("Failed to add Guest user to "
1919                                             "ldap directory\n"));
1920                 }
1921         } else {
1922                 d_printf(_("found!\n"));
1923         }
1924
1925         d_printf(_("Checking Guest's group.\n"));
1926
1927         pwd = getpwnam_alloc(talloc_autofree_context(), lp_guestaccount());
1928         if (!pwd) {
1929                 d_fprintf(stderr,
1930                           _("Failed to find just created Guest account!\n"
1931                             "   Is nss properly configured?!\n"));
1932                 goto failed;
1933         }
1934
1935         if (pwd->pw_gid == domusers_gid) {
1936                 d_printf(_("found!\n"));
1937                 goto done;
1938         }
1939
1940         if (!pdb_getgrgid(&gmap, pwd->pw_gid)) {
1941                 LDAPMod **mods = NULL;
1942                 char *dn;
1943                 char *uname;
1944                 char *wname;
1945                 char *gidstr;
1946                 char *gtype;
1947                 int rc;
1948
1949                 d_printf(_("Adding the Domain Guests group.\n"));
1950
1951                 uname = talloc_strdup(tc, "domguests");
1952                 wname = talloc_strdup(tc, "Domain Guests");
1953                 dn = talloc_asprintf(tc, "cn=%s,%s", "domguests", lp_ldap_group_suffix());
1954                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)pwd->pw_gid);
1955                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1956
1957                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1958                         d_fprintf(stderr, _("Out of Memory!\n"));
1959                         goto failed;
1960                 }
1961
1962                 sid_compose(&gsid, get_global_sam_sid(), DOMAIN_RID_GUESTS);
1963
1964                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXGROUP);
1965                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1966                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1967                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1968                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1969                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid",
1970                                 sid_string_talloc(tc, &gsid));
1971                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1972
1973                 talloc_autofree_ldapmod(tc, mods);
1974
1975                 rc = smbldap_add(ls, dn, mods);
1976
1977                 if (rc != LDAP_SUCCESS) {
1978                         d_fprintf(stderr,
1979                                   _("Failed to add Domain Guests group to ldap "
1980                                     "directory\n"));
1981                 }
1982         } else {
1983                 d_printf(_("found!\n"));
1984         }
1985
1986
1987 done:
1988         talloc_free(tc);
1989         return 0;
1990
1991 failed:
1992         talloc_free(tc);
1993         return -1;
1994 }
1995
1996 #endif
1997
1998 /***********************************************************
1999  migrated functionality from smbgroupedit
2000  **********************************************************/
2001 int net_sam(struct net_context *c, int argc, const char **argv)
2002 {
2003         struct functable func[] = {
2004                 {
2005                         "createbuiltingroup",
2006                         net_sam_createbuiltingroup,
2007                         NET_TRANSPORT_LOCAL,
2008                         N_("Create a new BUILTIN group"),
2009                         N_("net sam createbuiltingroup\n"
2010                            "    Create a new BUILTIN group")
2011                 },
2012                 {
2013                         "createlocalgroup",
2014                         net_sam_createlocalgroup,
2015                         NET_TRANSPORT_LOCAL,
2016                         N_("Create a new local group"),
2017                         N_("net sam createlocalgroup\n"
2018                            "    Create a new local group")
2019                 },
2020                 {
2021                         "createdomaingroup",
2022                         net_sam_createdomaingroup,
2023                         NET_TRANSPORT_LOCAL,
2024                         N_("Create a new group"),
2025                         N_("net sam createdomaingroup\n"
2026                            "    Create a new group")
2027                 },
2028                 {
2029                         "deletelocalgroup",
2030                         net_sam_deletelocalgroup,
2031                         NET_TRANSPORT_LOCAL,
2032                         N_("Delete an existing local group"),
2033                         N_("net sam deletelocalgroup\n"
2034                            "    Delete an existing local group")
2035                 },
2036                 {
2037                         "deletedomaingroup",
2038                         net_sam_deletedomaingroup,
2039                         NET_TRANSPORT_LOCAL,
2040                         N_("Delete a domain group"),
2041                         N_("net sam deletedomaingroup\n"
2042                            "    Delete a group")
2043                 },
2044                 {
2045                         "mapunixgroup",
2046                         net_sam_mapunixgroup,
2047                         NET_TRANSPORT_LOCAL,
2048                         N_("Map a unix group to a domain group"),
2049                         N_("net sam mapunixgroup\n"
2050                            "    Map a unix group to a domain group")
2051                 },
2052                 {
2053                         "unmapunixgroup",
2054                         net_sam_unmapunixgroup,
2055                         NET_TRANSPORT_LOCAL,
2056                         N_("Remove a group mapping of an unix group to a "
2057                            "domain group"),
2058                         N_("net sam unmapunixgroup\n"
2059                            "    Remove a group mapping of an unix group to a "
2060                            "domain group")
2061                 },
2062                 {
2063                         "addmem",
2064                         net_sam_addmem,
2065                         NET_TRANSPORT_LOCAL,
2066                         N_("Add a member to a group"),
2067                         N_("net sam addmem\n"
2068                         "    Add a member to a group")
2069                 },
2070                 {
2071                         "delmem",
2072                         net_sam_delmem,
2073                         NET_TRANSPORT_LOCAL,
2074                         N_("Delete a member from a group"),
2075                         N_("net sam delmem\n"
2076                            "    Delete a member from a group")
2077                 },
2078                 {
2079                         "listmem",
2080                         net_sam_listmem,
2081                         NET_TRANSPORT_LOCAL,
2082                         N_("List group members"),
2083                         N_("net sam listmem\n"
2084                            "    List group members")
2085                 },
2086                 {
2087                         "list",
2088                         net_sam_list,
2089                         NET_TRANSPORT_LOCAL,
2090                         N_("List users, groups and local groups"),
2091                         N_("net sam list\n"
2092                            "    List users, groups and local groups")
2093                 },
2094                 {
2095                         "show",
2096                         net_sam_show,
2097                         NET_TRANSPORT_LOCAL,
2098                         N_("Show details of a SAM entry"),
2099                         N_("net sam show\n"
2100                            "    Show details of a SAM entry")
2101                 },
2102                 {
2103                         "set",
2104                         net_sam_set,
2105                         NET_TRANSPORT_LOCAL,
2106                         N_("Set details of a SAM account"),
2107                         N_("net sam set\n"
2108                            "    Set details of a SAM account")
2109                 },
2110                 {
2111                         "policy",
2112                         net_sam_policy,
2113                         NET_TRANSPORT_LOCAL,
2114                         N_("Set account policies"),
2115                         N_("net sam policy\n"
2116                            "    Set account policies")
2117                 },
2118                 {
2119                         "rights",
2120                         net_sam_rights,
2121                         NET_TRANSPORT_LOCAL,
2122                         N_("Manipulate user privileges"),
2123                         N_("net sam rights\n"
2124                            "    Manipulate user privileges")
2125                 },
2126 #ifdef HAVE_LDAP
2127                 {
2128                         "provision",
2129                         net_sam_provision,
2130                         NET_TRANSPORT_LOCAL,
2131                         N_("Provision a clean user database"),
2132                         N_("net sam privison\n"
2133                            "    Provision a clear user database")
2134                 },
2135 #endif
2136                 {NULL, NULL, 0, NULL, NULL}
2137         };
2138
2139         if (getuid() != 0) {
2140                 d_fprintf(stderr, _("You are not root, most things won't "
2141                           "work\n"));
2142         }
2143
2144         return net_run_function(c, argc, argv, "net sam", func);
2145 }
2146