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