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