r25019: Fix coverity bug #105, run #332. Use of uninitialized variable.
[mat/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 /*
508  * Map a unix group to a domain group
509  */
510
511 static NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap)
512 {
513         NTSTATUS status;
514         GROUP_MAP map;
515         const char *grpname, *dom, *name;
516         uint32 rid;
517
518         if (pdb_getgrgid(&map, grp->gr_gid)) {
519                 return NT_STATUS_GROUP_EXISTS;
520         }
521
522         map.gid = grp->gr_gid;
523         grpname = grp->gr_name;
524
525         if (lookup_name(talloc_tos(), grpname, LOOKUP_NAME_ISOLATED,
526                         &dom, &name, NULL, NULL)) {
527
528                 const char *tmp = talloc_asprintf(
529                         talloc_tos(), "Unix Group %s", grp->gr_name);
530
531                 DEBUG(5, ("%s exists as %s\\%s, retrying as \"%s\"\n",
532                           grpname, dom, name, tmp));
533                 grpname = tmp;
534         }
535
536         if (lookup_name(talloc_tos(), grpname, LOOKUP_NAME_ISOLATED,
537                         NULL, NULL, NULL, NULL)) {
538                 DEBUG(3, ("\"%s\" exists, can't map it\n", grp->gr_name));
539                 return NT_STATUS_GROUP_EXISTS;
540         }
541
542         fstrcpy(map.nt_name, grpname);
543
544         if (pdb_rid_algorithm()) {
545                 rid = algorithmic_pdb_gid_to_group_rid( grp->gr_gid );
546         } else {
547                 if (!pdb_new_rid(&rid)) {
548                         DEBUG(3, ("Could not get a new RID for %s\n",
549                                   grp->gr_name));
550                         return NT_STATUS_ACCESS_DENIED;
551                 }
552         }
553
554         sid_compose(&map.sid, get_global_sam_sid(), rid);
555         map.sid_name_use = SID_NAME_DOM_GRP;
556         fstrcpy(map.comment, talloc_asprintf(talloc_tos(), "Unix Group %s",
557                                              grp->gr_name));
558
559         status = pdb_add_group_mapping_entry(&map);
560         if (NT_STATUS_IS_OK(status)) {
561                 *pmap = map;
562         }
563         return status;
564 }
565
566 static int net_sam_mapunixgroup(int argc, const char **argv)
567 {
568         NTSTATUS status;
569         GROUP_MAP map;
570         struct group *grp;
571
572         if (argc != 1) {
573                 d_fprintf(stderr, "usage: net sam mapunixgroup <name>\n");
574                 return -1;
575         }
576
577         grp = getgrnam(argv[0]);
578         if (grp == NULL) {
579                 d_fprintf(stderr, "Could not find group %s\n", argv[0]);
580                 return -1;
581         }
582
583         status = map_unix_group(grp, &map);
584
585         if (!NT_STATUS_IS_OK(status)) {
586                 d_fprintf(stderr, "Mapping group %s failed with %s\n",
587                           argv[0], nt_errstr(status));
588                 return -1;
589         }
590
591         d_printf("Mapped unix group %s to SID %s\n", argv[0],
592                  sid_string_static(&map.sid));
593
594         return 0;
595 }
596
597 /*
598  * Remove a group mapping
599  */
600
601 static NTSTATUS unmap_unix_group(const struct group *grp, GROUP_MAP *pmap)
602 {
603         NTSTATUS status;
604         GROUP_MAP map;
605         const char *grpname;
606         DOM_SID dom_sid;
607
608         map.gid = grp->gr_gid;
609         grpname = grp->gr_name;
610
611         if (!lookup_name(talloc_tos(), grpname, LOOKUP_NAME_ISOLATED,
612                         NULL, NULL, NULL, NULL)) {
613                 DEBUG(3, ("\"%s\" does not exist, can't unmap it\n", grp->gr_name));
614                 return NT_STATUS_NO_SUCH_GROUP;
615         }
616
617         fstrcpy(map.nt_name, grpname);
618
619         if (!pdb_gid_to_sid(map.gid, &dom_sid)) {
620                 return NT_STATUS_UNSUCCESSFUL;
621         }
622
623         status = pdb_delete_group_mapping_entry(dom_sid);
624
625         return status;
626 }
627
628 static int net_sam_unmapunixgroup(int argc, const char **argv)
629 {
630         NTSTATUS status;
631         GROUP_MAP map;
632         struct group *grp;
633
634         if (argc != 1) {
635                 d_fprintf(stderr, "usage: net sam unmapunixgroup <name>\n");
636                 return -1;
637         }
638
639         grp = getgrnam(argv[0]);
640         if (grp == NULL) {
641                 d_fprintf(stderr, "Could not find mapping for group %s.\n", argv[0]);
642                 return -1;
643         }
644
645         status = unmap_unix_group(grp, &map);
646
647         if (!NT_STATUS_IS_OK(status)) {
648                 d_fprintf(stderr, "Unmapping group %s failed with %s.\n",
649                           argv[0], nt_errstr(status));
650                 return -1;
651         }
652
653         d_printf("Unmapped unix group %s.\n", argv[0]);
654
655         return 0;
656 }
657
658 /*
659  * Create a local group
660  */
661
662 static int net_sam_createlocalgroup(int argc, const char **argv)
663 {
664         NTSTATUS status;
665         uint32 rid;
666
667         if (argc != 1) {
668                 d_fprintf(stderr, "usage: net sam createlocalgroup <name>\n");
669                 return -1;
670         }
671
672         if (!winbind_ping()) {
673                 d_fprintf(stderr, "winbind seems not to run. createlocalgroup "
674                           "only works when winbind runs.\n");
675                 return -1;
676         }
677
678         status = pdb_create_alias(argv[0], &rid);
679
680         if (!NT_STATUS_IS_OK(status)) {
681                 d_fprintf(stderr, "Creating %s failed with %s\n",
682                           argv[0], nt_errstr(status));
683                 return -1;
684         }
685
686         d_printf("Created local group %s with RID %d\n", argv[0], rid);
687
688         return 0;
689 }
690
691 /*
692  * Delete a local group
693  */
694
695 static int net_sam_deletelocalgroup(int argc, const char **argv)
696 {
697         DOM_SID sid;
698         enum lsa_SidType type;
699         const char *dom, *name;
700         NTSTATUS status;
701
702         if (argc != 1) {
703                 d_fprintf(stderr, "usage: net sam deletelocalgroup <name>\n");
704                 return -1;
705         }
706
707         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
708                          &dom, &name, &sid, &type)) {
709                 d_fprintf(stderr, "Could not find %s.\n", argv[0]);
710                 return -1;
711         }
712
713         if (type != SID_NAME_ALIAS) {
714                 d_fprintf(stderr, "%s is a %s, not a local group.\n", argv[0],
715                           sid_type_lookup(type));
716                 return -1;
717         }
718
719         status = pdb_delete_alias(&sid);
720
721         if (!NT_STATUS_IS_OK(status)) {
722                 d_fprintf(stderr, "Deleting local group %s failed with %s\n",
723                           argv[0], nt_errstr(status));
724                 return -1;
725         }
726
727         d_printf("Deleted local group %s.\n", argv[0]);
728
729         return 0;
730 }
731
732 /*
733  * Create a local group
734  */
735
736 static int net_sam_createbuiltingroup(int argc, const char **argv)
737 {
738         NTSTATUS status;
739         uint32 rid;
740         enum lsa_SidType type;
741         fstring groupname;
742         DOM_SID sid;
743
744         if (argc != 1) {
745                 d_fprintf(stderr, "usage: net sam createbuiltingroup <name>\n");
746                 return -1;
747         }
748
749         if (!winbind_ping()) {
750                 d_fprintf(stderr, "winbind seems not to run. createlocalgroup "
751                           "only works when winbind runs.\n");
752                 return -1;
753         }
754
755         /* validate the name and get the group */
756         
757         fstrcpy( groupname, "BUILTIN\\" );
758         fstrcat( groupname, argv[0] );
759         
760         if ( !lookup_name(talloc_tos(), groupname, LOOKUP_NAME_ALL, NULL,
761                           NULL, &sid, &type)) {
762                 d_fprintf(stderr, "%s is not a BUILTIN group\n", argv[0]);
763                 return -1;
764         }
765         
766         if ( !sid_peek_rid( &sid, &rid ) ) {
767                 d_fprintf(stderr, "Failed to get RID for %s\n", argv[0]);
768                 return -1;
769         }
770
771         status = pdb_create_builtin_alias( rid );
772
773         if (!NT_STATUS_IS_OK(status)) {
774                 d_fprintf(stderr, "Creating %s failed with %s\n",
775                           argv[0], nt_errstr(status));
776                 return -1;
777         }
778
779         d_printf("Created BUILTIN group %s with RID %d\n", argv[0], rid);
780
781         return 0;
782 }
783
784 /*
785  * Add a group member
786  */
787
788 static int net_sam_addmem(int argc, const char **argv)
789 {
790         const char *groupdomain, *groupname, *memberdomain, *membername;
791         DOM_SID group, member;
792         enum lsa_SidType grouptype, membertype;
793         NTSTATUS status;
794
795         if (argc != 2) {
796                 d_fprintf(stderr, "usage: net sam addmem <group> <member>\n");
797                 return -1;
798         }
799
800         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
801                          &groupdomain, &groupname, &group, &grouptype)) {
802                 d_fprintf(stderr, "Could not find group %s\n", argv[0]);
803                 return -1;
804         }
805
806         /* check to see if the member to be added is a name or a SID */
807
808         if (!lookup_name(talloc_tos(), argv[1], LOOKUP_NAME_ISOLATED,
809                          &memberdomain, &membername, &member, &membertype))
810         {
811                 /* try it as a SID */
812
813                 if ( !string_to_sid( &member, argv[1] ) ) {
814                         d_fprintf(stderr, "Could not find member %s\n", argv[1]);
815                         return -1;
816                 }
817
818                 if ( !lookup_sid(talloc_tos(), &member, &memberdomain,
819                         &membername, &membertype) ) 
820                 {
821                         d_fprintf(stderr, "Could not resolve SID %s\n", argv[1]);
822                         return -1;
823                 }
824         }
825
826         if ((grouptype == SID_NAME_ALIAS) || (grouptype == SID_NAME_WKN_GRP)) {
827                 if ((membertype != SID_NAME_USER) &&
828                     (membertype != SID_NAME_DOM_GRP)) {
829                         d_fprintf(stderr, "%s is a local group, only users "
830                                   "and domain groups can be added.\n"
831                                   "%s is a %s\n", argv[0], argv[1],
832                                   sid_type_lookup(membertype));
833                         return -1;
834                 }
835                 status = pdb_add_aliasmem(&group, &member);
836
837                 if (!NT_STATUS_IS_OK(status)) {
838                         d_fprintf(stderr, "Adding local group member failed "
839                                   "with %s\n", nt_errstr(status));
840                         return -1;
841                 }
842         } else {
843                 d_fprintf(stderr, "Can only add members to local groups so "
844                           "far, %s is a %s\n", argv[0],
845                           sid_type_lookup(grouptype));
846                 return -1;
847         }
848
849         d_printf("Added %s\\%s to %s\\%s\n", memberdomain, membername, 
850                 groupdomain, groupname);
851
852         return 0;
853 }
854
855 /*
856  * Delete a group member
857  */
858
859 static int net_sam_delmem(int argc, const char **argv)
860 {
861         const char *groupdomain, *groupname;
862         const char *memberdomain = NULL;
863         const char *membername = NULL;
864         DOM_SID group, member;
865         enum lsa_SidType grouptype;
866         NTSTATUS status;
867
868         if (argc != 2) {
869                 d_fprintf(stderr, "usage: net sam delmem <group> <member>\n");
870                 return -1;
871         }
872
873         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
874                          &groupdomain, &groupname, &group, &grouptype)) {
875                 d_fprintf(stderr, "Could not find group %s\n", argv[0]);
876                 return -1;
877         }
878
879         if (!lookup_name(talloc_tos(), argv[1], LOOKUP_NAME_ISOLATED,
880                          &memberdomain, &membername, &member, NULL)) {
881                 if (!string_to_sid(&member, argv[1])) {
882                         d_fprintf(stderr, "Could not find member %s\n",
883                                   argv[1]);
884                         return -1;
885                 }
886         }
887
888         if ((grouptype == SID_NAME_ALIAS) ||
889             (grouptype == SID_NAME_WKN_GRP)) {
890                 status = pdb_del_aliasmem(&group, &member);
891
892                 if (!NT_STATUS_IS_OK(status)) {
893                         d_fprintf(stderr, "Deleting local group member failed "
894                                   "with %s\n", nt_errstr(status));
895                         return -1;
896                 }
897         } else {
898                 d_fprintf(stderr, "Can only delete members from local groups "
899                           "so far, %s is a %s\n", argv[0],
900                           sid_type_lookup(grouptype));
901                 return -1;
902         }
903
904         if (membername != NULL) {
905                 d_printf("Deleted %s\\%s from %s\\%s\n",
906                          memberdomain, membername, groupdomain, groupname);
907         } else {
908                 d_printf("Deleted %s from %s\\%s\n",
909                          sid_string_static(&member), groupdomain, groupname);
910         }
911
912         return 0;
913 }
914
915 /*
916  * List group members
917  */
918
919 static int net_sam_listmem(int argc, const char **argv)
920 {
921         const char *groupdomain, *groupname;
922         DOM_SID group;
923         enum lsa_SidType grouptype;
924         NTSTATUS status;
925
926         if (argc != 1) {
927                 d_fprintf(stderr, "usage: net sam listmem <group>\n");
928                 return -1;
929         }
930
931         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
932                          &groupdomain, &groupname, &group, &grouptype)) {
933                 d_fprintf(stderr, "Could not find group %s\n", argv[0]);
934                 return -1;
935         }
936
937         if ((grouptype == SID_NAME_ALIAS) ||
938             (grouptype == SID_NAME_WKN_GRP)) {
939                 DOM_SID *members = NULL;
940                 size_t i, num_members = 0;
941                 
942                 status = pdb_enum_aliasmem(&group, &members, &num_members);
943
944                 if (!NT_STATUS_IS_OK(status)) {
945                         d_fprintf(stderr, "Listing group members failed with "
946                                   "%s\n", nt_errstr(status));
947                         return -1;
948                 }
949
950                 d_printf("%s\\%s has %u members\n", groupdomain, groupname,
951                          (unsigned int)num_members);
952                 for (i=0; i<num_members; i++) {
953                         const char *dom, *name;
954                         if (lookup_sid(talloc_tos(), &members[i],
955                                        &dom, &name, NULL)) {
956                                 d_printf(" %s\\%s\n", dom, name);
957                         } else {
958                                 d_printf(" %s\n",
959                                          sid_string_static(&members[i]));
960                         }
961                 }
962
963                 TALLOC_FREE(members);
964         } else {
965                 d_fprintf(stderr, "Can only list local group members so far.\n"
966                           "%s is a %s\n", argv[0], sid_type_lookup(grouptype));
967                 return -1;
968         }
969
970         return 0;
971 }
972
973 /*
974  * Do the listing
975  */
976 static int net_sam_do_list(int argc, const char **argv,
977                            struct pdb_search *search, const char *what)
978 {
979         BOOL verbose = (argc == 1);
980
981         if ((argc > 1) ||
982             ((argc == 1) && !strequal(argv[0], "verbose"))) {
983                 d_fprintf(stderr, "usage: net sam list %s [verbose]\n", what);
984                 return -1;
985         }
986
987         if (search == NULL) {
988                 d_fprintf(stderr, "Could not start search\n");
989                 return -1;
990         }
991
992         while (True) {
993                 struct samr_displayentry entry;
994                 if (!search->next_entry(search, &entry)) {
995                         break;
996                 }
997                 if (verbose) {
998                         d_printf("%s:%d:%s\n",
999                                  entry.account_name,
1000                                  entry.rid,
1001                                  entry.description);
1002                 } else {
1003                         d_printf("%s\n", entry.account_name);
1004                 }
1005         }
1006
1007         search->search_end(search);
1008         return 0;
1009 }
1010
1011 static int net_sam_list_users(int argc, const char **argv)
1012 {
1013         return net_sam_do_list(argc, argv, pdb_search_users(ACB_NORMAL),
1014                                "users");
1015 }
1016
1017 static int net_sam_list_groups(int argc, const char **argv)
1018 {
1019         return net_sam_do_list(argc, argv, pdb_search_groups(), "groups");
1020 }
1021
1022 static int net_sam_list_localgroups(int argc, const char **argv)
1023 {
1024         return net_sam_do_list(argc, argv,
1025                                pdb_search_aliases(get_global_sam_sid()),
1026                                "localgroups");
1027 }
1028
1029 static int net_sam_list_builtin(int argc, const char **argv)
1030 {
1031         return net_sam_do_list(argc, argv,
1032                                pdb_search_aliases(&global_sid_Builtin),
1033                                "builtin");
1034 }
1035
1036 static int net_sam_list_workstations(int argc, const char **argv)
1037 {
1038         return net_sam_do_list(argc, argv,
1039                                pdb_search_users(ACB_WSTRUST),
1040                                "workstations");
1041 }
1042
1043 /*
1044  * List stuff
1045  */
1046
1047 static int net_sam_list(int argc, const char **argv)
1048 {
1049         struct functable2 func[] = {
1050                 { "users", net_sam_list_users,
1051                   "List SAM users" },
1052                 { "groups", net_sam_list_groups,
1053                   "List SAM groups" },
1054                 { "localgroups", net_sam_list_localgroups,
1055                   "List SAM local groups" },
1056                 { "builtin", net_sam_list_builtin,
1057                   "List builtin groups" },
1058                 { "workstations", net_sam_list_workstations,
1059                   "List domain member workstations" },
1060                 {NULL, NULL}
1061         };
1062
1063         return net_run_function2(argc, argv, "net sam list", func);
1064 }
1065
1066 /*
1067  * Show details of SAM entries
1068  */
1069
1070 static int net_sam_show(int argc, const char **argv)
1071 {
1072         DOM_SID sid;
1073         enum lsa_SidType type;
1074         const char *dom, *name;
1075
1076         if (argc != 1) {
1077                 d_fprintf(stderr, "usage: net sam show <name>\n");
1078                 return -1;
1079         }
1080
1081         if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
1082                          &dom, &name, &sid, &type)) {
1083                 d_fprintf(stderr, "Could not find name %s\n", argv[0]);
1084                 return -1;
1085         }
1086
1087         d_printf("%s\\%s is a %s with SID %s\n", dom, name,
1088                  sid_type_lookup(type), sid_string_static(&sid));
1089
1090         return 0;
1091 }
1092
1093 #ifdef HAVE_LDAP
1094
1095 /*
1096  * Init an LDAP tree with default users and Groups
1097  * if ldapsam:editposix is enabled
1098  */
1099
1100 static int net_sam_provision(int argc, const char **argv)
1101 {
1102         TALLOC_CTX *tc;
1103         char *ldap_bk;
1104         char *ldap_uri = NULL;
1105         char *p;
1106         struct smbldap_state *ls;
1107         GROUP_MAP gmap;
1108         DOM_SID gsid;
1109         gid_t domusers_gid = -1;
1110         gid_t domadmins_gid = -1;
1111         struct samu *samuser;
1112         struct passwd *pwd;
1113
1114         tc = talloc_new(NULL);
1115         if (!tc) {
1116                 d_fprintf(stderr, "Out of Memory!\n");
1117                 return -1;
1118         }
1119
1120         if ((ldap_bk = talloc_strdup(tc, lp_passdb_backend())) == NULL) {
1121                 d_fprintf(stderr, "talloc failed\n");
1122                 talloc_free(tc);
1123                 return -1;
1124         }
1125         p = strchr(ldap_bk, ':');
1126         if (p) {
1127                 *p = 0;
1128                 ldap_uri = talloc_strdup(tc, p+1);
1129                 trim_char(ldap_uri, ' ', ' ');
1130         }
1131
1132         trim_char(ldap_bk, ' ', ' ');
1133                 
1134         if (strcmp(ldap_bk, "ldapsam") != 0) {
1135                 d_fprintf(stderr, "Provisioning works only with ldapsam backend\n");
1136                 goto failed;
1137         }
1138         
1139         if (!lp_parm_bool(-1, "ldapsam", "trusted", False) ||
1140             !lp_parm_bool(-1, "ldapsam", "editposix", False)) {
1141
1142                 d_fprintf(stderr, "Provisioning works only if ldapsam:trusted"
1143                                   " and ldapsam:editposix are enabled.\n");
1144                 goto failed;
1145         }
1146
1147         if (!winbind_ping()) {
1148                 d_fprintf(stderr, "winbind seems not to run. Provisioning "
1149                           "LDAP only works when winbind runs.\n");
1150                 goto failed;
1151         }
1152
1153         if (!NT_STATUS_IS_OK(smbldap_init(tc, NULL, ldap_uri, &ls))) {
1154                 d_fprintf(stderr, "Unable to connect to the LDAP server.\n");
1155                 goto failed;
1156         }
1157
1158         d_printf("Checking for Domain Users group.\n");
1159
1160         sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS);
1161
1162         if (!pdb_getgrsid(&gmap, gsid)) {
1163                 LDAPMod **mods = NULL;
1164                 char *dn;
1165                 char *uname;
1166                 char *wname;
1167                 char *gidstr;
1168                 char *gtype;
1169                 int rc;
1170
1171                 d_printf("Adding the Domain Users group.\n");
1172
1173                 /* lets allocate a new groupid for this group */
1174                 if (!winbind_allocate_gid(&domusers_gid)) {
1175                         d_fprintf(stderr, "Unable to allocate a new gid to create Domain Users group!\n");
1176                         goto domu_done;
1177                 }
1178
1179                 uname = talloc_strdup(tc, "domusers");
1180                 wname = talloc_strdup(tc, "Domain Users");
1181                 dn = talloc_asprintf(tc, "cn=%s,%s", "domusers", lp_ldap_group_suffix());
1182                 gidstr = talloc_asprintf(tc, "%d", domusers_gid);
1183                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1184
1185                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1186                         d_fprintf(stderr, "Out of Memory!\n");
1187                         goto failed;
1188                 }
1189
1190                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
1191                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1192                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1193                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1194                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1195                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
1196                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1197
1198                 talloc_autofree_ldapmod(tc, mods);
1199
1200                 rc = smbldap_add(ls, dn, mods);
1201
1202                 if (rc != LDAP_SUCCESS) {
1203                         d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
1204                 }
1205         } else {
1206                 domusers_gid = gmap.gid;
1207                 d_printf("found!\n");
1208         }       
1209
1210 domu_done:
1211
1212         d_printf("Checking for Domain Admins group.\n");
1213
1214         sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_ADMINS);
1215
1216         if (!pdb_getgrsid(&gmap, gsid)) {
1217                 LDAPMod **mods = NULL;
1218                 char *dn;
1219                 char *uname;
1220                 char *wname;
1221                 char *gidstr;
1222                 char *gtype;
1223                 int rc;
1224
1225                 d_printf("Adding the Domain Admins group.\n");
1226
1227                 /* lets allocate a new groupid for this group */
1228                 if (!winbind_allocate_gid(&domadmins_gid)) {
1229                         d_fprintf(stderr, "Unable to allocate a new gid to create Domain Admins group!\n");
1230                         goto doma_done;
1231                 }
1232
1233                 uname = talloc_strdup(tc, "domadmins");
1234                 wname = talloc_strdup(tc, "Domain Admins");
1235                 dn = talloc_asprintf(tc, "cn=%s,%s", "domadmins", lp_ldap_group_suffix());
1236                 gidstr = talloc_asprintf(tc, "%d", domadmins_gid);
1237                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1238
1239                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1240                         d_fprintf(stderr, "Out of Memory!\n");
1241                         goto failed;
1242                 }
1243
1244                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
1245                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1246                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1247                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1248                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1249                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
1250                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1251
1252                 talloc_autofree_ldapmod(tc, mods);
1253
1254                 rc = smbldap_add(ls, dn, mods);
1255
1256                 if (rc != LDAP_SUCCESS) {
1257                         d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
1258                 }
1259         } else {
1260                 domadmins_gid = gmap.gid;
1261                 d_printf("found!\n");
1262         }
1263
1264 doma_done:
1265
1266         d_printf("Check for Administrator account.\n");
1267
1268         samuser = samu_new(tc);
1269         if (!samuser) {
1270                 d_fprintf(stderr, "Out of Memory!\n");
1271                 goto failed;
1272         }
1273
1274         if (!pdb_getsampwnam(samuser, "Administrator")) {
1275                 LDAPMod **mods = NULL;
1276                 DOM_SID sid;
1277                 char *dn;
1278                 char *name;
1279                 char *uidstr;
1280                 char *gidstr;
1281                 char *shell;
1282                 char *dir;
1283                 uid_t uid;
1284                 int rc;
1285                 
1286                 d_printf("Adding the Administrator user.\n");
1287
1288                 if (domadmins_gid == -1) {
1289                         d_fprintf(stderr, "Can't create Administrator user, Domain Admins group not available!\n");
1290                         goto done;
1291                 }
1292                 if (!winbind_allocate_uid(&uid)) {
1293                         d_fprintf(stderr, "Unable to allocate a new uid to create the Administrator user!\n");
1294                         goto done;
1295                 }
1296                 name = talloc_strdup(tc, "Administrator");
1297                 dn = talloc_asprintf(tc, "uid=Administrator,%s", lp_ldap_user_suffix());
1298                 uidstr = talloc_asprintf(tc, "%d", uid);
1299                 gidstr = talloc_asprintf(tc, "%d", domadmins_gid);
1300                 dir = talloc_sub_specified(tc, lp_template_homedir(),
1301                                                 "Administrator",
1302                                                 get_global_sam_name(),
1303                                                 uid, domadmins_gid);
1304                 shell = talloc_sub_specified(tc, lp_template_shell(),
1305                                                 "Administrator",
1306                                                 get_global_sam_name(),
1307                                                 uid, domadmins_gid);
1308
1309                 if (!name || !dn || !uidstr || !gidstr || !dir || !shell) {
1310                         d_fprintf(stderr, "Out of Memory!\n");
1311                         goto failed;
1312                 }
1313
1314                 sid_compose(&sid, get_global_sam_sid(), DOMAIN_USER_RID_ADMIN);
1315
1316                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
1317                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
1318                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
1319                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", name);
1320                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
1321                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
1322                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
1323                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1324                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", dir);
1325                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
1326                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
1327                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
1328                                 pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
1329                                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1330
1331                 talloc_autofree_ldapmod(tc, mods);
1332
1333                 rc = smbldap_add(ls, dn, mods);
1334
1335                 if (rc != LDAP_SUCCESS) {
1336                         d_fprintf(stderr, "Failed to add Administrator user to ldap directory\n");
1337                 }
1338         } else {
1339                 d_printf("found!\n");
1340         }
1341
1342         d_printf("Checking for Guest user.\n");
1343
1344         samuser = samu_new(tc);
1345         if (!samuser) {
1346                 d_fprintf(stderr, "Out of Memory!\n");
1347                 goto failed;
1348         }
1349
1350         if (!pdb_getsampwnam(samuser, lp_guestaccount())) {
1351                 LDAPMod **mods = NULL;
1352                 DOM_SID sid;
1353                 char *dn;
1354                 char *uidstr;
1355                 char *gidstr;
1356                 int rc;
1357                 
1358                 d_printf("Adding the Guest user.\n");
1359
1360                 pwd = getpwnam_alloc(tc, lp_guestaccount());
1361
1362                 if (!pwd) {
1363                         if (domusers_gid == -1) {
1364                                 d_fprintf(stderr, "Can't create Guest user, Domain Users group not available!\n");
1365                                 goto done;
1366                         }
1367                         if ((pwd = talloc(tc, struct passwd)) == NULL) {
1368                                 d_fprintf(stderr, "talloc failed\n");
1369                                 goto done;
1370                         }
1371                         pwd->pw_name = talloc_strdup(pwd, lp_guestaccount());
1372                         if (!winbind_allocate_uid(&(pwd->pw_uid))) {
1373                                 d_fprintf(stderr, "Unable to allocate a new uid to create the Guest user!\n");
1374                                 goto done;
1375                         }
1376                         pwd->pw_gid = domusers_gid;
1377                         pwd->pw_dir = talloc_strdup(tc, "/");
1378                         pwd->pw_shell = talloc_strdup(tc, "/bin/false");
1379                         if (!pwd->pw_dir || !pwd->pw_shell) {
1380                                 d_fprintf(stderr, "Out of Memory!\n");
1381                                 goto failed;
1382                         }
1383                 }
1384
1385                 sid_compose(&sid, get_global_sam_sid(), DOMAIN_USER_RID_GUEST);
1386
1387                 dn = talloc_asprintf(tc, "uid=%s,%s", pwd->pw_name, lp_ldap_user_suffix ());
1388                 uidstr = talloc_asprintf(tc, "%d", pwd->pw_uid);
1389                 gidstr = talloc_asprintf(tc, "%d", pwd->pw_gid);
1390                 if (!dn || !uidstr || !gidstr) {
1391                         d_fprintf(stderr, "Out of Memory!\n");
1392                         goto failed;
1393                 }
1394
1395                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
1396                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
1397                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
1398                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", pwd->pw_name);
1399                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", pwd->pw_name);
1400                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
1401                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
1402                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1403                 if ((pwd->pw_dir != NULL) && (pwd->pw_dir[0] != '\0')) {
1404                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
1405                 }
1406                 if ((pwd->pw_shell != NULL) && (pwd->pw_shell[0] != '\0')) {
1407                         smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
1408                 }
1409                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
1410                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
1411                                 pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
1412                                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
1413
1414                 talloc_autofree_ldapmod(tc, mods);
1415
1416                 rc = smbldap_add(ls, dn, mods);
1417
1418                 if (rc != LDAP_SUCCESS) {
1419                         d_fprintf(stderr, "Failed to add Guest user to ldap directory\n");
1420                 }
1421         } else {
1422                 d_printf("found!\n");
1423         }
1424
1425         d_printf("Checking Guest's group.\n");
1426
1427         pwd = getpwnam_alloc(NULL, lp_guestaccount());
1428         if (!pwd) {
1429                 d_fprintf(stderr, "Failed to find just created Guest account!\n"
1430                                   "   Is nss properly configured?!\n");
1431                 goto failed;
1432         }
1433
1434         if (pwd->pw_gid == domusers_gid) {
1435                 d_printf("found!\n");
1436                 goto done;
1437         }
1438
1439         if (!pdb_getgrgid(&gmap, pwd->pw_gid)) {
1440                 LDAPMod **mods = NULL;
1441                 char *dn;
1442                 char *uname;
1443                 char *wname;
1444                 char *gidstr;
1445                 char *gtype;
1446                 int rc;
1447
1448                 d_printf("Adding the Domain Guests group.\n");
1449
1450                 uname = talloc_strdup(tc, "domguests");
1451                 wname = talloc_strdup(tc, "Domain Guests");
1452                 dn = talloc_asprintf(tc, "cn=%s,%s", "domguests", lp_ldap_group_suffix());
1453                 gidstr = talloc_asprintf(tc, "%d", pwd->pw_gid);
1454                 gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
1455
1456                 if (!uname || !wname || !dn || !gidstr || !gtype) {
1457                         d_fprintf(stderr, "Out of Memory!\n");
1458                         goto failed;
1459                 }
1460
1461                 sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_GUESTS);
1462
1463                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
1464                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
1465                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
1466                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
1467                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
1468                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
1469                 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
1470
1471                 talloc_autofree_ldapmod(tc, mods);
1472
1473                 rc = smbldap_add(ls, dn, mods);
1474
1475                 if (rc != LDAP_SUCCESS) {
1476                         d_fprintf(stderr, "Failed to add Domain Guests group to ldap directory\n");
1477                 }
1478         } else {
1479                 d_printf("found!\n");
1480         }
1481
1482
1483 done:
1484         talloc_free(tc);
1485         return 0;
1486
1487 failed:
1488         talloc_free(tc);
1489         return -1;
1490 }
1491
1492 #endif
1493
1494 /***********************************************************
1495  migrated functionality from smbgroupedit
1496  **********************************************************/
1497 int net_sam(int argc, const char **argv)
1498 {
1499         struct functable2 func[] = {
1500                 { "createbuiltingroup", net_sam_createbuiltingroup,
1501                   "Create a new BUILTIN group" },
1502                 { "createlocalgroup", net_sam_createlocalgroup,
1503                   "Create a new local group" },
1504                 { "deletelocalgroup", net_sam_deletelocalgroup,
1505                   "Delete an existing local group" },
1506                 { "mapunixgroup", net_sam_mapunixgroup,
1507                   "Map a unix group to a domain group" },
1508                 { "unmapunixgroup", net_sam_unmapunixgroup,
1509                   "Remove a group mapping of an unix group to a domain group" },
1510                 { "addmem", net_sam_addmem,
1511                   "Add a member to a group" },
1512                 { "delmem", net_sam_delmem,
1513                   "Delete a member from a group" },
1514                 { "listmem", net_sam_listmem,
1515                   "List group members" },
1516                 { "list", net_sam_list,
1517                   "List users, groups and local groups" },
1518                 { "show", net_sam_show,
1519                   "Show details of a SAM entry" },
1520                 { "set", net_sam_set,
1521                   "Set details of a SAM account" },
1522                 { "policy", net_sam_policy,
1523                   "Set account policies" },
1524 #ifdef HAVE_LDAP
1525                 { "provision", net_sam_provision,
1526                   "Provision a clean User Database" },
1527 #endif
1528                 { NULL, NULL, NULL }
1529         };
1530
1531         /* we shouldn't have silly checks like this */
1532         if (getuid() != 0) {
1533                 d_fprintf(stderr, "You must be root to edit the SAM "
1534                           "directly.\n");
1535                 return -1;
1536         }
1537         
1538         return net_run_function2(argc, argv, "net sam", func);
1539 }
1540