99eac045e026dd29cb58201c87a90eb9b5fc1aeb
[samba.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 extern PRIVS privs[];
635
636 static int net_sam_rights_list(struct net_context *c, int argc,
637                                const char **argv)
638 {
639         uint64_t mask;
640
641         if (argc > 1 || c->display_usage) {
642                 d_fprintf(stderr, "%s\n%s",
643                           _("Usage:"),
644                           _("net sam rights list [privilege name]\n"));
645                 return -1;
646         }
647
648         if (argc == 0) {
649                 int i;
650                 int num = count_all_privileges();
651
652                 for (i=0; i<num; i++) {
653                         d_printf("%s\n", privs[i].name);
654                 }
655                 return 0;
656         }
657
658         if (se_priv_from_name(argv[0], &mask)) {
659                 struct dom_sid *sids;
660                 int i, num_sids;
661                 NTSTATUS status;
662
663                 status = privilege_enum_sids(&mask, talloc_tos(),
664                                              &sids, &num_sids);
665                 if (!NT_STATUS_IS_OK(status)) {
666                         d_fprintf(stderr, _("Could not list rights: %s\n"),
667                                   nt_errstr(status));
668                         return -1;
669                 }
670
671                 for (i=0; i<num_sids; i++) {
672                         const char *dom, *name;
673                         enum lsa_SidType type;
674
675                         if (lookup_sid(talloc_tos(), &sids[i], &dom, &name,
676                                        &type)) {
677                                 d_printf("%s\\%s\n", dom, name);
678                         }
679                         else {
680                                 d_printf("%s\n", sid_string_tos(&sids[i]));
681                         }
682                 }
683                 return 0;
684         }
685
686         return -1;
687 }
688
689 static int net_sam_rights_grant(struct net_context *c, int argc,
690                                 const char **argv)
691 {
692         struct dom_sid sid;
693         enum lsa_SidType type;
694         const char *dom, *name;
695         uint64_t mask;
696         int i;
697
698         if (argc < 2 || c->display_usage) {
699                 d_fprintf(stderr, "%s\n%s",
700                           _("Usage:"),
701                           _("net sam rights grant <name> <rights> ...\n"));
702                 return -1;
703         }
704
705         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
706                         &dom, &name, &sid, &type)) {
707                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
708                 return -1;
709         }
710
711         for (i=1; i < argc; i++) {
712                 if (!se_priv_from_name(argv[i], &mask)) {
713                         d_fprintf(stderr, _("%s unknown\n"), argv[i]);
714                         return -1;
715                 }
716
717                 if (!grant_privilege(&sid, &mask)) {
718                         d_fprintf(stderr, _("Could not grant privilege\n"));
719                         return -1;
720                 }
721
722                 d_printf(_("Granted %s to %s\\%s\n"), argv[i], dom, name);
723         }
724
725         return 0;
726 }
727
728 static int net_sam_rights_revoke(struct net_context *c, int argc,
729                                 const char **argv)
730 {
731         struct dom_sid sid;
732         enum lsa_SidType type;
733         const char *dom, *name;
734         uint64_t mask;
735         int i;
736
737         if (argc < 2 || c->display_usage) {
738                 d_fprintf(stderr, "%s\n%s",
739                           _("Usage:"),
740                           _("net sam rights revoke <name> <rights>\n"));
741                 return -1;
742         }
743
744         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
745                         &dom, &name, &sid, &type)) {
746                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
747                 return -1;
748         }
749
750         for (i=1; i < argc; i++) {
751
752                 if (!se_priv_from_name(argv[i], &mask)) {
753                         d_fprintf(stderr, _("%s unknown\n"), argv[i]);
754                         return -1;
755                 }
756
757                 if (!revoke_privilege(&sid, &mask)) {
758                         d_fprintf(stderr, _("Could not revoke privilege\n"));
759                         return -1;
760                 }
761
762                 d_printf(_("Revoked %s from %s\\%s\n"), argv[i], dom, name);
763         }
764
765         return 0;
766 }
767
768 static int net_sam_rights(struct net_context *c, int argc, const char **argv)
769 {
770         struct functable func[] = {
771                 {
772                         "list",
773                         net_sam_rights_list,
774                         NET_TRANSPORT_LOCAL,
775                         N_("List possible user rights"),
776                         N_("net sam rights list\n"
777                            "    List possible user rights")
778                 },
779                 {
780                         "grant",
781                         net_sam_rights_grant,
782                         NET_TRANSPORT_LOCAL,
783                         N_("Grant right(s)"),
784                         N_("net sam rights grant\n"
785                            "    Grant right(s)")
786                 },
787                 {
788                         "revoke",
789                         net_sam_rights_revoke,
790                         NET_TRANSPORT_LOCAL,
791                         N_("Revoke right(s)"),
792                         N_("net sam rights revoke\n"
793                            "    Revoke right(s)")
794                 },
795                 {NULL, NULL, 0, NULL, NULL}
796         };
797         return net_run_function(c, argc, argv, "net sam rights", func);
798 }
799
800 /*
801  * Map a unix group to a domain group
802  */
803
804 static NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap)
805 {
806         NTSTATUS status;
807         GROUP_MAP map;
808         const char *grpname, *dom, *name;
809         uint32 rid;
810
811         if (pdb_getgrgid(&map, grp->gr_gid)) {
812                 return NT_STATUS_GROUP_EXISTS;
813         }
814
815         map.gid = grp->gr_gid;
816         grpname = grp->gr_name;
817
818         if (lookup_name(talloc_tos(), grpname, LOOKUP_NAME_LOCAL,
819                         &dom, &name, NULL, NULL)) {
820
821                 const char *tmp = talloc_asprintf(
822                         talloc_tos(), "Unix Group %s", grp->gr_name);
823
824                 DEBUG(5, ("%s exists as %s\\%s, retrying as \"%s\"\n",
825                           grpname, dom, name, tmp));
826                 grpname = tmp;
827         }
828
829         if (lookup_name(talloc_tos(), grpname, LOOKUP_NAME_LOCAL,
830                         NULL, NULL, NULL, NULL)) {
831                 DEBUG(3, ("\"%s\" exists, can't map it\n", grp->gr_name));
832                 return NT_STATUS_GROUP_EXISTS;
833         }
834
835         fstrcpy(map.nt_name, grpname);
836
837         if (pdb_capabilities() & PDB_CAP_STORE_RIDS) {
838                 if (!pdb_new_rid(&rid)) {
839                         DEBUG(3, ("Could not get a new RID for %s\n",
840                                   grp->gr_name));
841                         return NT_STATUS_ACCESS_DENIED;
842                 }
843         } else {
844                 rid = algorithmic_pdb_gid_to_group_rid( grp->gr_gid );
845         }
846
847         sid_compose(&map.sid, get_global_sam_sid(), rid);
848         map.sid_name_use = SID_NAME_DOM_GRP;
849         fstrcpy(map.comment, talloc_asprintf(talloc_tos(), "Unix Group %s",
850                                              grp->gr_name));
851
852         status = pdb_add_group_mapping_entry(&map);
853         if (NT_STATUS_IS_OK(status)) {
854                 *pmap = map;
855         }
856         return status;
857 }
858
859 static int net_sam_mapunixgroup(struct net_context *c, int argc, const char **argv)
860 {
861         NTSTATUS status;
862         GROUP_MAP map;
863         struct group *grp;
864
865         if (argc != 1 || c->display_usage) {
866                 d_fprintf(stderr, "%s\n%s",
867                           _("Usage:"),
868                           _("net sam mapunixgroup <name>\n"));
869                 return -1;
870         }
871
872         grp = getgrnam(argv[0]);
873         if (grp == NULL) {
874                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
875                 return -1;
876         }
877
878         status = map_unix_group(grp, &map);
879
880         if (!NT_STATUS_IS_OK(status)) {
881                 d_fprintf(stderr, _("Mapping group %s failed with %s\n"),
882                           argv[0], nt_errstr(status));
883                 return -1;
884         }
885
886         d_printf(_("Mapped unix group %s to SID %s\n"), argv[0],
887                  sid_string_tos(&map.sid));
888
889         return 0;
890 }
891
892 /*
893  * Remove a group mapping
894  */
895
896 static NTSTATUS unmap_unix_group(const struct group *grp, GROUP_MAP *pmap)
897 {
898         GROUP_MAP map;
899         const char *grpname;
900         struct dom_sid dom_sid;
901
902         map.gid = grp->gr_gid;
903         grpname = grp->gr_name;
904
905         if (!lookup_name(talloc_tos(), grpname, LOOKUP_NAME_LOCAL,
906                         NULL, NULL, NULL, NULL)) {
907                 DEBUG(3, ("\"%s\" does not exist, can't unmap it\n", grp->gr_name));
908                 return NT_STATUS_NO_SUCH_GROUP;
909         }
910
911         fstrcpy(map.nt_name, grpname);
912
913         if (!pdb_gid_to_sid(map.gid, &dom_sid)) {
914                 return NT_STATUS_UNSUCCESSFUL;
915         }
916
917         return pdb_delete_group_mapping_entry(dom_sid);
918 }
919
920 static int net_sam_unmapunixgroup(struct net_context *c, int argc, const char **argv)
921 {
922         NTSTATUS status;
923         GROUP_MAP map;
924         struct group *grp;
925
926         if (argc != 1 || c->display_usage) {
927                 d_fprintf(stderr, "%s\n%s",
928                           _("Usage:"),
929                           _("net sam unmapunixgroup <name>\n"));
930                 return -1;
931         }
932
933         grp = getgrnam(argv[0]);
934         if (grp == NULL) {
935                 d_fprintf(stderr, _("Could not find mapping for group %s.\n"),
936                           argv[0]);
937                 return -1;
938         }
939
940         status = unmap_unix_group(grp, &map);
941
942         if (!NT_STATUS_IS_OK(status)) {
943                 d_fprintf(stderr, _("Unmapping group %s failed with %s.\n"),
944                           argv[0], nt_errstr(status));
945                 return -1;
946         }
947
948         d_printf(_("Unmapped unix group %s.\n"), argv[0]);
949
950         return 0;
951 }
952
953 /*
954  * Create a domain group
955  */
956
957 static int net_sam_createdomaingroup(struct net_context *c, int argc,
958                                      const char **argv)
959 {
960         NTSTATUS status;
961         uint32 rid;
962
963         if (argc != 1 || c->display_usage) {
964                 d_fprintf(stderr, "%s\n%s",
965                           _("Usage:"),
966                           _("net sam createdomaingroup <name>\n"));
967                 return -1;
968         }
969
970         status = pdb_create_dom_group(talloc_tos(), argv[0], &rid);
971
972         if (!NT_STATUS_IS_OK(status)) {
973                 d_fprintf(stderr, _("Creating %s failed with %s\n"),
974                           argv[0], nt_errstr(status));
975                 return -1;
976         }
977
978         d_printf(_("Created domain group %s with RID %d\n"), argv[0], rid);
979
980         return 0;
981 }
982
983 /*
984  * Delete a domain group
985  */
986
987 static int net_sam_deletedomaingroup(struct net_context *c, int argc,
988                                      const char **argv)
989 {
990         struct dom_sid sid;
991         uint32_t rid;
992         enum lsa_SidType type;
993         const char *dom, *name;
994         NTSTATUS status;
995
996         if (argc != 1 || c->display_usage) {
997                 d_fprintf(stderr, "%s\n%s",
998                           _("Usage:"),
999                           _("net sam deletelocalgroup <name>\n"));
1000                 return -1;
1001         }
1002
1003         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1004                          &dom, &name, &sid, &type)) {
1005                 d_fprintf(stderr, _("Could not find %s.\n"), argv[0]);
1006                 return -1;
1007         }
1008
1009         if (type != SID_NAME_DOM_GRP) {
1010                 d_fprintf(stderr, _("%s is a %s, not a domain group.\n"),
1011                           argv[0], sid_type_lookup(type));
1012                 return -1;
1013         }
1014
1015         sid_peek_rid(&sid, &rid);
1016
1017         status = pdb_delete_dom_group(talloc_tos(), rid);
1018
1019         if (!NT_STATUS_IS_OK(status)) {
1020                 d_fprintf(stderr,_("Deleting domain group %s failed with %s\n"),
1021                           argv[0], nt_errstr(status));
1022                 return -1;
1023         }
1024
1025         d_printf(_("Deleted domain group %s.\n"), argv[0]);
1026
1027         return 0;
1028 }
1029
1030 /*
1031  * Create a local group
1032  */
1033
1034 static int net_sam_createlocalgroup(struct net_context *c, int argc, const char **argv)
1035 {
1036         NTSTATUS status;
1037         uint32 rid;
1038
1039         if (argc != 1 || c->display_usage) {
1040                 d_fprintf(stderr, "%s\n%s",
1041                           _("Usage:"),
1042                           _("net sam createlocalgroup <name>\n"));
1043                 return -1;
1044         }
1045
1046         if (!winbind_ping()) {
1047                 d_fprintf(stderr, _("winbind seems not to run. "
1048                           "createlocalgroup only works when winbind runs.\n"));
1049                 return -1;
1050         }
1051
1052         status = pdb_create_alias(argv[0], &rid);
1053
1054         if (!NT_STATUS_IS_OK(status)) {
1055                 d_fprintf(stderr, _("Creating %s failed with %s\n"),
1056                           argv[0], nt_errstr(status));
1057                 return -1;
1058         }
1059
1060         d_printf(_("Created local group %s with RID %d\n"), argv[0], rid);
1061
1062         return 0;
1063 }
1064
1065 /*
1066  * Delete a local group
1067  */
1068
1069 static int net_sam_deletelocalgroup(struct net_context *c, int argc, const char **argv)
1070 {
1071         struct dom_sid sid;
1072         enum lsa_SidType type;
1073         const char *dom, *name;
1074         NTSTATUS status;
1075
1076         if (argc != 1 || c->display_usage) {
1077                 d_fprintf(stderr, "%s\n%s",
1078                           _("Usage:"),
1079                           _("net sam deletelocalgroup <name>\n"));
1080                 return -1;
1081         }
1082
1083         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1084                          &dom, &name, &sid, &type)) {
1085                 d_fprintf(stderr,_("Could not find %s.\n"), argv[0]);
1086                 return -1;
1087         }
1088
1089         if (type != SID_NAME_ALIAS) {
1090                 d_fprintf(stderr, _("%s is a %s, not a local group.\n"),argv[0],
1091                           sid_type_lookup(type));
1092                 return -1;
1093         }
1094
1095         status = pdb_delete_alias(&sid);
1096
1097         if (!NT_STATUS_IS_OK(status)) {
1098                 d_fprintf(stderr, _("Deleting local group %s failed with %s\n"),
1099                           argv[0], nt_errstr(status));
1100                 return -1;
1101         }
1102
1103         d_printf(_("Deleted local group %s.\n"), argv[0]);
1104
1105         return 0;
1106 }
1107
1108 /*
1109  * Create a builtin group
1110  */
1111
1112 static int net_sam_createbuiltingroup(struct net_context *c, int argc, const char **argv)
1113 {
1114         NTSTATUS status;
1115         uint32 rid;
1116         enum lsa_SidType type;
1117         fstring groupname;
1118         struct dom_sid sid;
1119
1120         if (argc != 1 || c->display_usage) {
1121                 d_fprintf(stderr, "%s\n%s",
1122                           _("Usage:"),
1123                           _("net sam createbuiltingroup <name>\n"));
1124                 return -1;
1125         }
1126
1127         if (!winbind_ping()) {
1128                 d_fprintf(stderr, _("winbind seems not to run. "
1129                           "createbuiltingroup only works when winbind "
1130                           "runs.\n"));
1131                 return -1;
1132         }
1133
1134         /* validate the name and get the group */
1135
1136         fstrcpy( groupname, "BUILTIN\\" );
1137         fstrcat( groupname, argv[0] );
1138
1139         if ( !lookup_name(talloc_tos(), groupname, LOOKUP_NAME_ALL, NULL,
1140                           NULL, &sid, &type)) {
1141                 d_fprintf(stderr, _("%s is not a BUILTIN group\n"), argv[0]);
1142                 return -1;
1143         }
1144
1145         if ( !sid_peek_rid( &sid, &rid ) ) {
1146                 d_fprintf(stderr, _("Failed to get RID for %s\n"), argv[0]);
1147                 return -1;
1148         }
1149
1150         status = pdb_create_builtin_alias( rid );
1151
1152         if (!NT_STATUS_IS_OK(status)) {
1153                 d_fprintf(stderr, _("Creating %s failed with %s\n"),
1154                           argv[0], nt_errstr(status));
1155                 return -1;
1156         }
1157
1158         d_printf(_("Created BUILTIN group %s with RID %d\n"), argv[0], rid);
1159
1160         return 0;
1161 }
1162
1163 /*
1164  * Add a group member
1165  */
1166
1167 static int net_sam_addmem(struct net_context *c, int argc, const char **argv)
1168 {
1169         const char *groupdomain, *groupname, *memberdomain, *membername;
1170         struct dom_sid group, member;
1171         enum lsa_SidType grouptype, membertype;
1172         NTSTATUS status;
1173
1174         if (argc != 2 || c->display_usage) {
1175                 d_fprintf(stderr, "%s\n%s",
1176                           _("Usage:"),
1177                           _("net sam addmem <group> <member>\n"));
1178                 return -1;
1179         }
1180
1181         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1182                          &groupdomain, &groupname, &group, &grouptype)) {
1183                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
1184                 return -1;
1185         }
1186
1187         /* check to see if the member to be added is a name or a SID */
1188
1189         if (!lookup_name(talloc_tos(), argv[1], LOOKUP_NAME_LOCAL,
1190                          &memberdomain, &membername, &member, &membertype))
1191         {
1192                 /* try it as a SID */
1193
1194                 if ( !string_to_sid( &member, argv[1] ) ) {
1195                         d_fprintf(stderr, _("Could not find member %s\n"),
1196                                   argv[1]);
1197                         return -1;
1198                 }
1199
1200                 if ( !lookup_sid(talloc_tos(), &member, &memberdomain,
1201                         &membername, &membertype) )
1202                 {
1203                         d_fprintf(stderr, _("Could not resolve SID %s\n"),
1204                                   argv[1]);
1205                         return -1;
1206                 }
1207         }
1208
1209         if ((grouptype == SID_NAME_ALIAS) || (grouptype == SID_NAME_WKN_GRP)) {
1210                 if ((membertype != SID_NAME_USER) &&
1211                     (membertype != SID_NAME_DOM_GRP)) {
1212                         d_fprintf(stderr, _("%s is a local group, only users "
1213                                   "and domain groups can be added.\n"
1214                                   "%s is a %s\n"), argv[0], argv[1],
1215                                   sid_type_lookup(membertype));
1216                         return -1;
1217                 }
1218                 status = pdb_add_aliasmem(&group, &member);
1219
1220                 if (!NT_STATUS_IS_OK(status)) {
1221                         d_fprintf(stderr, _("Adding local group member failed "
1222                                   "with %s\n"), nt_errstr(status));
1223                         return -1;
1224                 }
1225         } else if (grouptype == SID_NAME_DOM_GRP) {
1226                 uint32_t grouprid, memberrid;
1227
1228                 sid_peek_rid(&group, &grouprid);
1229                 sid_peek_rid(&member, &memberrid);
1230
1231                 status = pdb_add_groupmem(talloc_tos(), grouprid, memberrid);
1232                 if (!NT_STATUS_IS_OK(status)) {
1233                         d_fprintf(stderr, _("Adding domain group member failed "
1234                                   "with %s\n"), nt_errstr(status));
1235                         return -1;
1236                 }
1237         } else {
1238                 d_fprintf(stderr, _("Can only add members to local groups so "
1239                           "far, %s is a %s\n"), argv[0],
1240                           sid_type_lookup(grouptype));
1241                 return -1;
1242         }
1243
1244         d_printf(_("Added %s\\%s to %s\\%s\n"), memberdomain, membername,
1245                 groupdomain, groupname);
1246
1247         return 0;
1248 }
1249
1250 /*
1251  * Delete a group member
1252  */
1253
1254 static int net_sam_delmem(struct net_context *c, int argc, const char **argv)
1255 {
1256         const char *groupdomain, *groupname;
1257         const char *memberdomain = NULL;
1258         const char *membername = NULL;
1259         struct dom_sid group, member;
1260         enum lsa_SidType grouptype;
1261         NTSTATUS status;
1262
1263         if (argc != 2 || c->display_usage) {
1264                 d_fprintf(stderr,"%s\n%s",
1265                           _("Usage:"),
1266                           _("net sam delmem <group> <member>\n"));
1267                 return -1;
1268         }
1269
1270         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1271                          &groupdomain, &groupname, &group, &grouptype)) {
1272                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
1273                 return -1;
1274         }
1275
1276         if (!lookup_name(talloc_tos(), argv[1], LOOKUP_NAME_LOCAL,
1277                          &memberdomain, &membername, &member, NULL)) {
1278                 if (!string_to_sid(&member, argv[1])) {
1279                         d_fprintf(stderr, _("Could not find member %s\n"),
1280                                   argv[1]);
1281                         return -1;
1282                 }
1283         }
1284
1285         if ((grouptype == SID_NAME_ALIAS) ||
1286             (grouptype == SID_NAME_WKN_GRP)) {
1287                 status = pdb_del_aliasmem(&group, &member);
1288
1289                 if (!NT_STATUS_IS_OK(status)) {
1290                         d_fprintf(stderr,_("Deleting local group member failed "
1291                                   "with %s\n"), nt_errstr(status));
1292                         return -1;
1293                 }
1294         } else if (grouptype == SID_NAME_DOM_GRP) {
1295                 uint32_t grouprid, memberrid;
1296
1297                 sid_peek_rid(&group, &grouprid);
1298                 sid_peek_rid(&member, &memberrid);
1299
1300                 status = pdb_del_groupmem(talloc_tos(), grouprid, memberrid);
1301                 if (!NT_STATUS_IS_OK(status)) {
1302                         d_fprintf(stderr, _("Deleting domain group member "
1303                                   "failed with %s\n"), nt_errstr(status));
1304                         return -1;
1305                 }
1306         } else {
1307                 d_fprintf(stderr, _("Can only delete members from local groups "
1308                           "so far, %s is a %s\n"), argv[0],
1309                           sid_type_lookup(grouptype));
1310                 return -1;
1311         }
1312
1313         if (membername != NULL) {
1314                 d_printf(_("Deleted %s\\%s from %s\\%s\n"),
1315                          memberdomain, membername, groupdomain, groupname);
1316         } else {
1317                 d_printf(_("Deleted %s from %s\\%s\n"),
1318                          sid_string_tos(&member), groupdomain, groupname);
1319         }
1320
1321         return 0;
1322 }
1323
1324 /*
1325  * List group members
1326  */
1327
1328 static int net_sam_listmem(struct net_context *c, int argc, const char **argv)
1329 {
1330         const char *groupdomain, *groupname;
1331         struct dom_sid group;
1332         struct dom_sid *members = NULL;
1333         size_t i, num_members = 0;
1334         enum lsa_SidType grouptype;
1335         NTSTATUS status;
1336
1337         if (argc != 1 || c->display_usage) {
1338                 d_fprintf(stderr, "%s\n%s",
1339                           _("Usage:"),
1340                           _("net sam listmem <group>\n"));
1341                 return -1;
1342         }
1343
1344         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1345                          &groupdomain, &groupname, &group, &grouptype)) {
1346                 d_fprintf(stderr, _("Could not find group %s\n"), argv[0]);
1347                 return -1;
1348         }
1349
1350         if ((grouptype == SID_NAME_ALIAS) ||
1351             (grouptype == SID_NAME_WKN_GRP)) {
1352                 status = pdb_enum_aliasmem(&group, talloc_tos(), &members,
1353                                            &num_members);
1354                 if (!NT_STATUS_IS_OK(status)) {
1355                         d_fprintf(stderr, _("Listing group members failed with "
1356                                   "%s\n"), nt_errstr(status));
1357                         return -1;
1358                 }
1359         } else if (grouptype == SID_NAME_DOM_GRP) {
1360                 uint32_t *rids;
1361
1362                 status = pdb_enum_group_members(talloc_tos(), &group,
1363                                                 &rids, &num_members);
1364                 if (!NT_STATUS_IS_OK(status)) {
1365                         d_fprintf(stderr, _("Listing group members failed with "
1366                                   "%s\n"), nt_errstr(status));
1367                         return -1;
1368                 }
1369
1370                 members = talloc_array(talloc_tos(), struct dom_sid,
1371                                        num_members);
1372                 if (members == NULL) {
1373                         TALLOC_FREE(rids);
1374                         return -1;
1375                 }
1376
1377                 for (i=0; i<num_members; i++) {
1378                         sid_compose(&members[i], get_global_sam_sid(),
1379                                     rids[i]);
1380                 }
1381                 TALLOC_FREE(rids);
1382         } else {
1383                 d_fprintf(stderr,_("Can only list local group members so far.\n"
1384                           "%s is a %s\n"), argv[0], sid_type_lookup(grouptype));
1385                 return -1;
1386         }
1387
1388         d_printf(_("%s\\%s has %u members\n"), groupdomain, groupname,
1389                  (unsigned int)num_members);
1390         for (i=0; i<num_members; i++) {
1391                 const char *dom, *name;
1392                 if (lookup_sid(talloc_tos(), &members[i], &dom, &name, NULL)) {
1393                         d_printf(" %s\\%s\n", dom, name);
1394                 } else {
1395                         d_printf(" %s\n", sid_string_tos(&members[i]));
1396                 }
1397         }
1398
1399                 TALLOC_FREE(members);
1400
1401         return 0;
1402 }
1403
1404 /*
1405  * Do the listing
1406  */
1407 static int net_sam_do_list(struct net_context *c, int argc, const char **argv,
1408                            struct pdb_search *search, const char *what)
1409 {
1410         bool verbose = (argc == 1);
1411
1412         if ((argc > 1) || c->display_usage ||
1413             ((argc == 1) && !strequal(argv[0], "verbose"))) {
1414                 d_fprintf(stderr, "%s\n", _("Usage:"));
1415                 d_fprintf(stderr, _("net sam list %s [verbose]\n"), what);
1416                 return -1;
1417         }
1418
1419         if (search == NULL) {
1420                 d_fprintf(stderr, _("Could not start search\n"));
1421                 return -1;
1422         }
1423
1424         while (true) {
1425                 struct samr_displayentry entry;
1426                 if (!search->next_entry(search, &entry)) {
1427                         break;
1428                 }
1429                 if (verbose) {
1430                         d_printf("%s:%d:%s\n",
1431                                  entry.account_name,
1432                                  entry.rid,
1433                                  entry.description);
1434                 } else {
1435                         d_printf("%s\n", entry.account_name);
1436                 }
1437         }
1438
1439         TALLOC_FREE(search);
1440         return 0;
1441 }
1442
1443 static int net_sam_list_users(struct net_context *c, int argc,
1444                               const char **argv)
1445 {
1446         return net_sam_do_list(c, argc, argv,
1447                                pdb_search_users(talloc_tos(), ACB_NORMAL),
1448                                "users");
1449 }
1450
1451 static int net_sam_list_groups(struct net_context *c, int argc,
1452                                const char **argv)
1453 {
1454         return net_sam_do_list(c, argc, argv, pdb_search_groups(talloc_tos()),
1455                                "groups");
1456 }
1457
1458 static int net_sam_list_localgroups(struct net_context *c, int argc,
1459                                     const char **argv)
1460 {
1461         return net_sam_do_list(c, argc, argv,
1462                                pdb_search_aliases(talloc_tos(),
1463                                                   get_global_sam_sid()),
1464                                "localgroups");
1465 }
1466
1467 static int net_sam_list_builtin(struct net_context *c, int argc,
1468                                 const char **argv)
1469 {
1470         return net_sam_do_list(c, argc, argv,
1471                                pdb_search_aliases(talloc_tos(),
1472                                                   &global_sid_Builtin),
1473                                "builtin");
1474 }
1475
1476 static int net_sam_list_workstations(struct net_context *c, int argc,
1477                                      const char **argv)
1478 {
1479         return net_sam_do_list(c, argc, argv,
1480                                pdb_search_users(talloc_tos(), ACB_WSTRUST),
1481                                "workstations");
1482 }
1483
1484 /*
1485  * List stuff
1486  */
1487
1488 static int net_sam_list(struct net_context *c, int argc, const char **argv)
1489 {
1490         struct functable func[] = {
1491                 {
1492                         "users",
1493                         net_sam_list_users,
1494                         NET_TRANSPORT_LOCAL,
1495                         N_("List SAM users"),
1496                         N_("net sam list users\n"
1497                            "    List SAM users")
1498                 },
1499                 {
1500                         "groups",
1501                         net_sam_list_groups,
1502                         NET_TRANSPORT_LOCAL,
1503                         N_("List SAM groups"),
1504                         N_("net sam list groups\n"
1505                            "    List SAM groups")
1506                 },
1507                 {
1508                         "localgroups",
1509                         net_sam_list_localgroups,
1510                         NET_TRANSPORT_LOCAL,
1511                         N_("List SAM local groups"),
1512                         N_("net sam list localgroups\n"
1513                            "    List SAM local groups")
1514                 },
1515                 {
1516                         "builtin",
1517                         net_sam_list_builtin,
1518                         NET_TRANSPORT_LOCAL,
1519                         N_("List builtin groups"),
1520                         N_("net sam list builtin\n"
1521                            "    List builtin groups")
1522                 },
1523                 {
1524                         "workstations",
1525                         net_sam_list_workstations,
1526                         NET_TRANSPORT_LOCAL,
1527                         N_("List domain member workstations"),
1528                         N_("net sam list workstations\n"
1529                            "    List domain member workstations")
1530                 },
1531                 {NULL, NULL, 0, NULL, NULL}
1532         };
1533
1534         return net_run_function(c, argc, argv, "net sam list", func);
1535 }
1536
1537 /*
1538  * Show details of SAM entries
1539  */
1540
1541 static int net_sam_show(struct net_context *c, int argc, const char **argv)
1542 {
1543         struct dom_sid sid;
1544         enum lsa_SidType type;
1545         const char *dom, *name;
1546
1547         if (argc != 1 || c->display_usage) {
1548                 d_fprintf(stderr, "%s\n%s",
1549                           _("Usage:"),
1550                           _("net sam show <name>\n"));
1551                 return -1;
1552         }
1553
1554         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_LOCAL,
1555                          &dom, &name, &sid, &type)) {
1556                 d_fprintf(stderr, _("Could not find name %s\n"), argv[0]);
1557                 return -1;
1558         }
1559
1560         d_printf(_("%s\\%s is a %s with SID %s\n"), dom, name,
1561                  sid_type_lookup(type), sid_string_tos(&sid));
1562
1563         return 0;
1564 }
1565
1566 #ifdef HAVE_LDAP
1567
1568 /*
1569  * Init an LDAP tree with default users and Groups
1570  * if ldapsam:editposix is enabled
1571  */
1572
1573 static int net_sam_provision(struct net_context *c, int argc, const char **argv)
1574 {
1575         TALLOC_CTX *tc;
1576         char *ldap_bk;
1577         char *ldap_uri = NULL;
1578         char *p;
1579         struct smbldap_state *ls;
1580         GROUP_MAP gmap;
1581         struct dom_sid gsid;
1582         gid_t domusers_gid = -1;
1583         gid_t domadmins_gid = -1;
1584         struct samu *samuser;
1585         struct passwd *pwd;
1586
1587         if (c->display_usage) {
1588                 d_printf(  "%s\n"
1589                            "net sam provision\n"
1590                             "    %s\n",
1591                           _("Usage:"),
1592                           _("Init an LDAP tree with default users/groups"));
1593                 return 0;
1594         }
1595
1596         tc = talloc_new(NULL);
1597         if (!tc) {
1598                 d_fprintf(stderr, _("Out of Memory!\n"));
1599                 return -1;
1600         }
1601
1602         if ((ldap_bk = talloc_strdup(tc, lp_passdb_backend())) == NULL) {
1603                 d_fprintf(stderr, _("talloc failed\n"));
1604                 talloc_free(tc);
1605                 return -1;
1606         }
1607         p = strchr(ldap_bk, ':');
1608         if (p) {
1609                 *p = 0;
1610                 ldap_uri = talloc_strdup(tc, p+1);
1611                 trim_char(ldap_uri, ' ', ' ');
1612         }
1613
1614         trim_char(ldap_bk, ' ', ' ');
1615
1616         if (strcmp(ldap_bk, "ldapsam") != 0) {
1617                 d_fprintf(stderr,
1618                           _("Provisioning works only with ldapsam backend\n"));
1619                 goto failed;
1620         }
1621
1622         if (!lp_parm_bool(-1, "ldapsam", "trusted", false) ||
1623             !lp_parm_bool(-1, "ldapsam", "editposix", false)) {
1624
1625                 d_fprintf(stderr, _("Provisioning works only if ldapsam:trusted"
1626                                     " and ldapsam:editposix are enabled.\n"));
1627                 goto failed;
1628         }
1629
1630         if (!winbind_ping()) {
1631                 d_fprintf(stderr, _("winbind seems not to run. Provisioning "
1632                             "LDAP only works when winbind runs.\n"));
1633                 goto failed;
1634         }
1635
1636         if (!NT_STATUS_IS_OK(smbldap_init(tc, NULL, ldap_uri, &ls))) {
1637                 d_fprintf(stderr, _("Unable to connect to the LDAP server.\n"));
1638                 goto failed;
1639         }
1640
1641         d_printf(_("Checking for Domain Users group.\n"));
1642
1643         sid_compose(&gsid, get_global_sam_sid(), DOMAIN_RID_USERS);
1644
1645         if (!pdb_getgrsid(&gmap, gsid)) {
1646                 LDAPMod **mods = NULL;
1647                 char *dn;
1648                 char *uname;
1649                 char *wname;
1650                 char *gidstr;
1651                 char *gtype;
1652                 int rc;
1653
1654                 d_printf(_("Adding the Domain Users group.\n"));
1655
1656                 /* lets allocate a new groupid for this group */
1657                 if (!winbind_allocate_gid(&domusers_gid)) {
1658                         d_fprintf(stderr, _("Unable to allocate a new gid to "
1659                                             "create Domain Users group!\n"));
1660                         goto domu_done;
1661                 }
1662
1663                 uname = talloc_strdup(tc, "domusers");
1664                 wname = talloc_strdup(tc, "Domain Users");
1665                 dn = talloc_asprintf(tc, "cn=%s,%s", "domusers", lp_ldap_group_suffix());
1666                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)domusers_gid);
1667                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1668
1669                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1670                         d_fprintf(stderr, "Out of Memory!\n");
1671                         goto failed;
1672                 }
1673
1674                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXGROUP);
1675                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1676                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1677                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1678                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1679                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid",
1680                                 sid_string_talloc(tc, &gsid));
1681                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1682
1683                 talloc_autofree_ldapmod(tc, mods);
1684
1685                 rc = smbldap_add(ls, dn, mods);
1686
1687                 if (rc != LDAP_SUCCESS) {
1688                         d_fprintf(stderr, _("Failed to add Domain Users group "
1689                                             "to ldap directory\n"));
1690                 }
1691         } else {
1692                 domusers_gid = gmap.gid;
1693                 d_printf(_("found!\n"));
1694         }
1695
1696 domu_done:
1697
1698         d_printf(_("Checking for Domain Admins group.\n"));
1699
1700         sid_compose(&gsid, get_global_sam_sid(), DOMAIN_RID_ADMINS);
1701
1702         if (!pdb_getgrsid(&gmap, gsid)) {
1703                 LDAPMod **mods = NULL;
1704                 char *dn;
1705                 char *uname;
1706                 char *wname;
1707                 char *gidstr;
1708                 char *gtype;
1709                 int rc;
1710
1711                 d_printf(_("Adding the Domain Admins group.\n"));
1712
1713                 /* lets allocate a new groupid for this group */
1714                 if (!winbind_allocate_gid(&domadmins_gid)) {
1715                         d_fprintf(stderr, _("Unable to allocate a new gid to "
1716                                             "create Domain Admins group!\n"));
1717                         goto doma_done;
1718                 }
1719
1720                 uname = talloc_strdup(tc, "domadmins");
1721                 wname = talloc_strdup(tc, "Domain Admins");
1722                 dn = talloc_asprintf(tc, "cn=%s,%s", "domadmins", lp_ldap_group_suffix());
1723                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)domadmins_gid);
1724                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1725
1726                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1727                         d_fprintf(stderr, _("Out of Memory!\n"));
1728                         goto failed;
1729                 }
1730
1731                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXGROUP);
1732                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1733                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1734                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1735                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1736                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid",
1737                                 sid_string_talloc(tc, &gsid));
1738                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1739
1740                 talloc_autofree_ldapmod(tc, mods);
1741
1742                 rc = smbldap_add(ls, dn, mods);
1743
1744                 if (rc != LDAP_SUCCESS) {
1745                         d_fprintf(stderr, _("Failed to add Domain Admins group "
1746                                             "to ldap directory\n"));
1747                 }
1748         } else {
1749                 domadmins_gid = gmap.gid;
1750                 d_printf(_("found!\n"));
1751         }
1752
1753 doma_done:
1754
1755         d_printf(_("Check for Administrator account.\n"));
1756
1757         samuser = samu_new(tc);
1758         if (!samuser) {
1759                 d_fprintf(stderr, _("Out of Memory!\n"));
1760                 goto failed;
1761         }
1762
1763         if (!pdb_getsampwnam(samuser, "Administrator")) {
1764                 LDAPMod **mods = NULL;
1765                 struct dom_sid sid;
1766                 char *dn;
1767                 char *name;
1768                 char *uidstr;
1769                 char *gidstr;
1770                 char *shell;
1771                 char *dir;
1772                 uid_t uid;
1773                 int rc;
1774
1775                 d_printf(_("Adding the Administrator user.\n"));
1776
1777                 if (domadmins_gid == -1) {
1778                         d_fprintf(stderr,
1779                                   _("Can't create Administrator user, Domain "
1780                                     "Admins group not available!\n"));
1781                         goto done;
1782                 }
1783                 name = talloc_strdup(tc, "Administrator");
1784                 dn = talloc_asprintf(tc, "uid=Administrator,%s", lp_ldap_user_suffix());
1785                 uidstr = talloc_asprintf(tc, "%u", (unsigned int)uid);
1786                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)domadmins_gid);
1787                 dir = talloc_sub_specified(tc, lp_template_homedir(),
1788                                                 "Administrator",
1789                                                 get_global_sam_name(),
1790                                                 uid, domadmins_gid);
1791                 shell = talloc_sub_specified(tc, lp_template_shell(),
1792                                                 "Administrator",
1793                                                 get_global_sam_name(),
1794                                                 uid, domadmins_gid);
1795
1796                 if (!name || !dn || !uidstr || !gidstr || !dir || !shell) {
1797                         d_fprintf(stderr, _("Out of Memory!\n"));
1798                         goto failed;
1799                 }
1800
1801                 sid_compose(&sid, get_global_sam_sid(), DOMAIN_RID_ADMINISTRATOR);
1802
1803                 if (!winbind_allocate_uid(&uid)) {
1804                         d_fprintf(stderr,
1805                                   _("Unable to allocate a new uid to create "
1806                                     "the Administrator user!\n"));
1807                         goto done;
1808                 }
1809
1810                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
1811                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
1812                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
1813                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", name);
1814                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
1815                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
1816                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
1817                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1818                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", dir);
1819                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
1820                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID",
1821                                 sid_string_talloc(tc, &sid));
1822                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
1823                                 pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
1824                                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1825
1826                 talloc_autofree_ldapmod(tc, mods);
1827
1828                 rc = smbldap_add(ls, dn, mods);
1829
1830                 if (rc != LDAP_SUCCESS) {
1831                         d_fprintf(stderr, _("Failed to add Administrator user "
1832                                             "to ldap directory\n"));
1833                 }
1834         } else {
1835                 d_printf(_("found!\n"));
1836         }
1837
1838         d_printf(_("Checking for Guest user.\n"));
1839
1840         samuser = samu_new(tc);
1841         if (!samuser) {
1842                 d_fprintf(stderr, _("Out of Memory!\n"));
1843                 goto failed;
1844         }
1845
1846         if (!pdb_getsampwnam(samuser, lp_guestaccount())) {
1847                 LDAPMod **mods = NULL;
1848                 struct dom_sid sid;
1849                 char *dn;
1850                 char *uidstr;
1851                 char *gidstr;
1852                 int rc;
1853
1854                 d_printf(_("Adding the Guest user.\n"));
1855
1856                 sid_compose(&sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
1857
1858                 pwd = getpwnam_alloc(tc, lp_guestaccount());
1859
1860                 if (!pwd) {
1861                         if (domusers_gid == -1) {
1862                                 d_fprintf(stderr,
1863                                           _("Can't create Guest user, Domain "
1864                                             "Users group not available!\n"));
1865                                 goto done;
1866                         }
1867                         if ((pwd = talloc(tc, struct passwd)) == NULL) {
1868                                 d_fprintf(stderr, _("talloc failed\n"));
1869                                 goto done;
1870                         }
1871                         pwd->pw_name = talloc_strdup(pwd, lp_guestaccount());
1872                         if (!winbind_allocate_uid(&(pwd->pw_uid))) {
1873                                 d_fprintf(stderr,
1874                                           _("Unable to allocate a new uid to "
1875                                             "create the Guest user!\n"));
1876                                 goto done;
1877                         }
1878                         pwd->pw_gid = domusers_gid;
1879                         pwd->pw_dir = talloc_strdup(tc, "/");
1880                         pwd->pw_shell = talloc_strdup(tc, "/bin/false");
1881                         if (!pwd->pw_dir || !pwd->pw_shell) {
1882                                 d_fprintf(stderr, _("Out of Memory!\n"));
1883                                 goto failed;
1884                         }
1885                 }
1886
1887                 dn = talloc_asprintf(tc, "uid=%s,%s", pwd->pw_name, lp_ldap_user_suffix ());
1888                 uidstr = talloc_asprintf(tc, "%u", (unsigned int)pwd->pw_uid);
1889                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)pwd->pw_gid);
1890                 if (!dn || !uidstr || !gidstr) {
1891                         d_fprintf(stderr, _("Out of Memory!\n"));
1892                         goto failed;
1893                 }
1894
1895                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
1896                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
1897                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
1898                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", pwd->pw_name);
1899                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", pwd->pw_name);
1900                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
1901                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
1902                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1903                 if ((pwd->pw_dir != NULL) && (pwd->pw_dir[0] != '\0')) {
1904                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
1905                 }
1906                 if ((pwd->pw_shell != NULL) && (pwd->pw_shell[0] != '\0')) {
1907                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
1908                 }
1909                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID",
1910                                 sid_string_talloc(tc, &sid));
1911                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
1912                                 pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
1913                                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1914
1915                 talloc_autofree_ldapmod(tc, mods);
1916
1917                 rc = smbldap_add(ls, dn, mods);
1918
1919                 if (rc != LDAP_SUCCESS) {
1920                         d_fprintf(stderr, _("Failed to add Guest user to "
1921                                             "ldap directory\n"));
1922                 }
1923         } else {
1924                 d_printf(_("found!\n"));
1925         }
1926
1927         d_printf(_("Checking Guest's group.\n"));
1928
1929         pwd = getpwnam_alloc(talloc_autofree_context(), lp_guestaccount());
1930         if (!pwd) {
1931                 d_fprintf(stderr,
1932                           _("Failed to find just created Guest account!\n"
1933                             "   Is nss properly configured?!\n"));
1934                 goto failed;
1935         }
1936
1937         if (pwd->pw_gid == domusers_gid) {
1938                 d_printf(_("found!\n"));
1939                 goto done;
1940         }
1941
1942         if (!pdb_getgrgid(&gmap, pwd->pw_gid)) {
1943                 LDAPMod **mods = NULL;
1944                 char *dn;
1945                 char *uname;
1946                 char *wname;
1947                 char *gidstr;
1948                 char *gtype;
1949                 int rc;
1950
1951                 d_printf(_("Adding the Domain Guests group.\n"));
1952
1953                 uname = talloc_strdup(tc, "domguests");
1954                 wname = talloc_strdup(tc, "Domain Guests");
1955                 dn = talloc_asprintf(tc, "cn=%s,%s", "domguests", lp_ldap_group_suffix());
1956                 gidstr = talloc_asprintf(tc, "%u", (unsigned int)pwd->pw_gid);
1957                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1958
1959                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1960                         d_fprintf(stderr, _("Out of Memory!\n"));
1961                         goto failed;
1962                 }
1963
1964                 sid_compose(&gsid, get_global_sam_sid(), DOMAIN_RID_GUESTS);
1965
1966                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXGROUP);
1967                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1968                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1969                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1970                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1971                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid",
1972                                 sid_string_talloc(tc, &gsid));
1973                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1974
1975                 talloc_autofree_ldapmod(tc, mods);
1976
1977                 rc = smbldap_add(ls, dn, mods);
1978
1979                 if (rc != LDAP_SUCCESS) {
1980                         d_fprintf(stderr,
1981                                   _("Failed to add Domain Guests group to ldap "
1982                                     "directory\n"));
1983                 }
1984         } else {
1985                 d_printf(_("found!\n"));
1986         }
1987
1988
1989 done:
1990         talloc_free(tc);
1991         return 0;
1992
1993 failed:
1994         talloc_free(tc);
1995         return -1;
1996 }
1997
1998 #endif
1999
2000 /***********************************************************
2001  migrated functionality from smbgroupedit
2002  **********************************************************/
2003 int net_sam(struct net_context *c, int argc, const char **argv)
2004 {
2005         struct functable func[] = {
2006                 {
2007                         "createbuiltingroup",
2008                         net_sam_createbuiltingroup,
2009                         NET_TRANSPORT_LOCAL,
2010                         N_("Create a new BUILTIN group"),
2011                         N_("net sam createbuiltingroup\n"
2012                            "    Create a new BUILTIN group")
2013                 },
2014                 {
2015                         "createlocalgroup",
2016                         net_sam_createlocalgroup,
2017                         NET_TRANSPORT_LOCAL,
2018                         N_("Create a new local group"),
2019                         N_("net sam createlocalgroup\n"
2020                            "    Create a new local group")
2021                 },
2022                 {
2023                         "createdomaingroup",
2024                         net_sam_createdomaingroup,
2025                         NET_TRANSPORT_LOCAL,
2026                         N_("Create a new group"),
2027                         N_("net sam createdomaingroup\n"
2028                            "    Create a new group")
2029                 },
2030                 {
2031                         "deletelocalgroup",
2032                         net_sam_deletelocalgroup,
2033                         NET_TRANSPORT_LOCAL,
2034                         N_("Delete an existing local group"),
2035                         N_("net sam deletelocalgroup\n"
2036                            "    Delete an existing local group")
2037                 },
2038                 {
2039                         "deletedomaingroup",
2040                         net_sam_deletedomaingroup,
2041                         NET_TRANSPORT_LOCAL,
2042                         N_("Delete a domain group"),
2043                         N_("net sam deletedomaingroup\n"
2044                            "    Delete a group")
2045                 },
2046                 {
2047                         "mapunixgroup",
2048                         net_sam_mapunixgroup,
2049                         NET_TRANSPORT_LOCAL,
2050                         N_("Map a unix group to a domain group"),
2051                         N_("net sam mapunixgroup\n"
2052                            "    Map a unix group to a domain group")
2053                 },
2054                 {
2055                         "unmapunixgroup",
2056                         net_sam_unmapunixgroup,
2057                         NET_TRANSPORT_LOCAL,
2058                         N_("Remove a group mapping of an unix group to a "
2059                            "domain group"),
2060                         N_("net sam unmapunixgroup\n"
2061                            "    Remove a group mapping of an unix group to a "
2062                            "domain group")
2063                 },
2064                 {
2065                         "addmem",
2066                         net_sam_addmem,
2067                         NET_TRANSPORT_LOCAL,
2068                         N_("Add a member to a group"),
2069                         N_("net sam addmem\n"
2070                         "    Add a member to a group")
2071                 },
2072                 {
2073                         "delmem",
2074                         net_sam_delmem,
2075                         NET_TRANSPORT_LOCAL,
2076                         N_("Delete a member from a group"),
2077                         N_("net sam delmem\n"
2078                            "    Delete a member from a group")
2079                 },
2080                 {
2081                         "listmem",
2082                         net_sam_listmem,
2083                         NET_TRANSPORT_LOCAL,
2084                         N_("List group members"),
2085                         N_("net sam listmem\n"
2086                            "    List group members")
2087                 },
2088                 {
2089                         "list",
2090                         net_sam_list,
2091                         NET_TRANSPORT_LOCAL,
2092                         N_("List users, groups and local groups"),
2093                         N_("net sam list\n"
2094                            "    List users, groups and local groups")
2095                 },
2096                 {
2097                         "show",
2098                         net_sam_show,
2099                         NET_TRANSPORT_LOCAL,
2100                         N_("Show details of a SAM entry"),
2101                         N_("net sam show\n"
2102                            "    Show details of a SAM entry")
2103                 },
2104                 {
2105                         "set",
2106                         net_sam_set,
2107                         NET_TRANSPORT_LOCAL,
2108                         N_("Set details of a SAM account"),
2109                         N_("net sam set\n"
2110                            "    Set details of a SAM account")
2111                 },
2112                 {
2113                         "policy",
2114                         net_sam_policy,
2115                         NET_TRANSPORT_LOCAL,
2116                         N_("Set account policies"),
2117                         N_("net sam policy\n"
2118                            "    Set account policies")
2119                 },
2120                 {
2121                         "rights",
2122                         net_sam_rights,
2123                         NET_TRANSPORT_LOCAL,
2124                         N_("Manipulate user privileges"),
2125                         N_("net sam rights\n"
2126                            "    Manipulate user privileges")
2127                 },
2128 #ifdef HAVE_LDAP
2129                 {
2130                         "provision",
2131                         net_sam_provision,
2132                         NET_TRANSPORT_LOCAL,
2133                         N_("Provision a clean user database"),
2134                         N_("net sam privison\n"
2135                            "    Provision a clear user database")
2136                 },
2137 #endif
2138                 {NULL, NULL, 0, NULL, NULL}
2139         };
2140
2141         if (getuid() != 0) {
2142                 d_fprintf(stderr, _("You are not root, most things won't "
2143                           "work\n"));
2144         }
2145
2146         return net_run_function(c, argc, argv, "net sam", func);
2147 }
2148