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