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