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