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