r13843: Merge in net sam provision and some pdb_ldap fixes
authorSimo Sorce <idra@samba.org>
Sun, 5 Mar 2006 17:49:30 +0000 (17:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:10:56 +0000 (11:10 -0500)
(This used to be commit 705d8118081784e9907648fd1daaaa5ec0285972)

source3/passdb/pdb_ldap.c
source3/utils/net_sam.c

index 0c7efd3fb97deea7b4f71d9777a90f3a4f111831..1fe5212d57ad28ea6e5f7de8daeac7749fd8a3f7 100644 (file)
@@ -1970,7 +1970,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
                num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
                
                if (num_result > 1) {
-                       DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
+                       DEBUG (0, ("ldapsam_add_sam_account: More than one user with specified Sid exists: bailing out!\n"));
                        TALLOC_FREE( attr_list );
                        ldap_msgfree(result);
                        return NT_STATUS_UNSUCCESSFUL;
@@ -2326,9 +2326,11 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
        *p_num_members = 0;
 
        filter = talloc_asprintf(mem_ctx,
-                                "(&(objectClass=sambaGroupMapping)"
-                                "(objectClass=posixGroup)"
+                                "(&(objectClass=%s)"
+                                "(objectClass=%s)"
                                 "(sambaSID=%s))",
+                                LDAP_OBJ_POSIXGROUP,
+                                LDAP_OBJ_GROUPMAP,
                                 sid_string_static(group));
 
        rc = smbldap_search(conn, lp_ldap_group_suffix(),
@@ -2369,7 +2371,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 
        if (values) {
 
-               filter = talloc_strdup(mem_ctx, "(&(objectClass=sambaSamAccount)(|");
+               filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBAACCOUNT);
                if (filter == NULL) {
                        ret = NT_STATUS_NO_MEMORY;
                        goto done;
@@ -2437,8 +2439,10 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
        }
 
        filter = talloc_asprintf(mem_ctx,
-                                "(&(objectClass=sambaSamAccount)"
-                                "(gidNumber=%s))", gidstr);
+                                "(&(objectClass=%s)"
+                                "(gidNumber=%s))",
+                                LDAP_OBJ_SAMBASAMACCOUNT,
+                                gidstr);
 
        rc = smbldap_search(conn, lp_ldap_user_suffix(),
                            LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
@@ -2489,39 +2493,74 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
        struct smbldap_state *conn = ldap_state->smbldap_state;
-       pstring filter;
+       char *filter;
        const char *attrs[] = { "gidNumber", "sambaSID", NULL };
        char *escape_name;
-       int rc;
-       LDAPMessage *msg = NULL;
+       int rc, count;
+       LDAPMessage *result = NULL;
        LDAPMessage *entry;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        size_t num_sids, num_gids;
-       gid_t primary_gid;
+       char *gidstr;
+       gid_t primary_gid = -1;
 
        *pp_sids = NULL;
        num_sids = 0;
 
-       if (!sid_to_gid(pdb_get_group_sid(user), &primary_gid)) {
-               DEBUG(1, ("sid_to_gid failed for user's primary group\n"));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
        escape_name = escape_ldap_string_alloc(pdb_get_username(user));
-
        if (escape_name == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       pstr_sprintf(filter, "(&(objectClass=posixGroup)"
-                    "(|(memberUid=%s)(gidNumber=%d)))",
-                    escape_name, primary_gid);
+       /* retrieve the users primary gid */
+       filter = talloc_asprintf(mem_ctx,
+                                "(&(objectClass=%s)(uid=%s))",
+                                LDAP_OBJ_SAMBASAMACCOUNT,
+                                escape_name);
+
+       rc = smbldap_search(conn, lp_ldap_user_suffix(),
+                           LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
+
+       if (rc != LDAP_SUCCESS)
+               goto done;
+
+       talloc_autofree_ldapmsg(mem_ctx, result);
+
+       count = ldap_count_entries(priv2ld(ldap_state), result);
+
+       switch (count) {
+       case 0: 
+               DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
+               ret = NT_STATUS_NO_SUCH_USER;
+               goto done;
+       case 1:
+               entry = ldap_first_entry(priv2ld(ldap_state), result);
+
+               gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
+               if (!gidstr) {
+                       DEBUG (1, ("Unable to find the member's gid!\n"));
+                       ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+                       goto done;
+               }
+               primary_gid = strtoul(gidstr, NULL, 10);
+               break;
+       default:
+               DEBUG(1, ("found more than one accoutn with the same user name ?!\n"));
+               ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto done;
+       }
+
+       filter = talloc_asprintf(mem_ctx,
+                                "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%d)))",
+                                LDAP_OBJ_POSIXGROUP, escape_name, primary_gid);
 
        rc = smbldap_search(conn, lp_ldap_group_suffix(),
-                           LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
+                           LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
 
        if (rc != LDAP_SUCCESS)
                goto done;
 
+       talloc_autofree_ldapmsg(mem_ctx, result);
+
        num_gids = 0;
        *pp_gids = NULL;
 
@@ -2536,7 +2575,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
        add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
 
-       for (entry = ldap_first_entry(conn->ldap_struct, msg);
+       for (entry = ldap_first_entry(conn->ldap_struct, result);
             entry != NULL;
             entry = ldap_next_entry(conn->ldap_struct, entry))
        {
@@ -2581,15 +2620,12 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
        *p_num_groups = num_sids;
 
-       result = NT_STATUS_OK;
+       ret = NT_STATUS_OK;
 
  done:
 
        SAFE_FREE(escape_name);
-       if (msg != NULL)
-               ldap_msgfree(msg);
-
-       return result;
+       return ret;
 }
 
 /**********************************************************************
@@ -2814,9 +2850,10 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
        /* Make 100% sure that sid, gid and type are not changed by looking up
         * exactly the values we're given in LDAP. */
 
-       filter = talloc_asprintf(mem_ctx, "(&(objectClass=sambaGroupMapping)"
+       filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)"
                                 "(sambaSid=%s)(gidNumber=%u)"
                                 "(sambaGroupType=%d))",
+                                LDAP_OBJ_GROUPMAP,
                                 sid_string_static(&map->sid), map->gid,
                                 map->sid_name_use);
        if (filter == NULL) {
@@ -3613,8 +3650,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
 
        for (i=0; i<num_rids; i++) {
                DOM_SID sid;
-               sid_copy(&sid, domain_sid);
-               sid_append_rid(&sid, rids[i]);
+               sid_compose(&sid, domain_sid, rids[i]);
                allsids = talloc_asprintf_append(allsids, "(sambaSid=%s)",
                                                 sid_string_static(&sid));
                if (allsids == NULL) {
@@ -3629,8 +3665,8 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
 
                filter = talloc_asprintf(
-                       mem_ctx, ("(&(objectClass=sambaSamAccount)(|%s))"),
-                       allsids);
+                       mem_ctx, ("(&(objectClass=%s)(|%s))"),
+                       LDAP_OBJ_SAMBASAMACCOUNT, allsids);
 
                if (filter == NULL) {
                        goto done;
@@ -3698,8 +3734,8 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                                             "sambaGroupType", NULL };
 
                filter = talloc_asprintf(
-                       mem_ctx, "(&(objectClass=sambaGroupMapping)(|%s))",
-                       allsids);
+                       mem_ctx, "(&(objectClass=%s)(|%s))",
+                       LDAP_OBJ_GROUPMAP, allsids);
                if (filter == NULL) {
                        goto done;
                }
@@ -4464,9 +4500,9 @@ static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
 
        filter = talloc_asprintf(mem_ctx,
                                 "(&(sambaSid=%s)"
-                                "(|(objectClass=sambaGroupMapping)"
-                                "(objectClass=sambaSamAccount)))",
-                                sid_string_static(sid));
+                                "(|(objectClass=%s)(objectClass=%s)))",
+                                sid_string_static(sid),
+                                LDAP_OBJ_GROUPMAP, LDAP_OBJ_SAMBASAMACCOUNT);
        if (filter == NULL) {
                DEBUG(5, ("talloc_asprintf failed\n"));
                goto done;
@@ -4568,12 +4604,16 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
        NTSTATUS ret;
        int rc;
        
-       if ((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') {
+       if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
+             acb_info & ACB_WSTRUST ||
+             acb_info & ACB_SVRTRUST ||
+             acb_info & ACB_DOMTRUST) {
                is_machine = True;
        }
 
        username = escape_ldap_string_alloc(name);
-       filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=posixAccount))", username);
+       filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))",
+                                username, LDAP_OBJ_POSIXACCOUNT);
        SAFE_FREE(username);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
@@ -4625,8 +4665,7 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                return ret;
        }
 
-       sid_copy(&user_sid, get_global_sam_sid());
-       sid_append_rid(&user_sid, *rid);
+       sid_compose(&user_sid, get_global_sam_sid(), *rid);
 
        user = samu_new(tmp_ctx);
        if (!user) {
@@ -4643,9 +4682,16 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
        if (is_machine) {
-               if (!pdb_set_acct_ctrl(user, ACB_WSTRUST | ACB_DISABLED, PDB_SET)) {
-                       DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
-                       return NT_STATUS_UNSUCCESSFUL;
+               if (acb_info & ACB_NORMAL) {
+                       if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_SET)) {
+                               DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+               } else {
+                       if (!pdb_set_acct_ctrl(user, acb_info, PDB_SET)) {
+                               DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
                }
        } else {
                if (!pdb_set_acct_ctrl(user, ACB_NORMAL | ACB_DISABLED, PDB_SET)) {
@@ -4664,17 +4710,10 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       switch ( ldap_state->schema_ver ) {
-               case SCHEMAVER_SAMBAACCOUNT:
-                       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBAACCOUNT);
-                       break;
-               case SCHEMAVER_SAMBASAMACCOUNT:
-                       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
-                       break;
-               default:
-                       DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
-                       break;
+       if (ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT) {
+               DEBUG(1,("ldapsam_create_user: Unsupported schema version\n"));
        }
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
 
        if (add_posix) {
                DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
@@ -4757,9 +4796,11 @@ static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *
        
        filter = talloc_asprintf(tmp_ctx,
                                 "(&(uid=%s)"
-                                "(objectClass=posixAccount)"
-                                "(objectClass=sambaSamAccount))",
-                                pdb_get_username(sam_acct));
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                pdb_get_username(sam_acct),
+                                LDAP_OBJ_POSIXACCOUNT,
+                                LDAP_OBJ_SAMBASAMACCOUNT);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
        if (rc != LDAP_SUCCESS) {
@@ -4833,7 +4874,8 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        int rc;
        
        groupname = escape_ldap_string_alloc(name);
-       filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=posixGroup))", groupname);
+       filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
+                                groupname, LDAP_OBJ_POSIXGROUP);
        SAFE_FREE(groupname);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
@@ -4912,8 +4954,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                return ret;
        }
 
-       sid_copy(&group_sid, get_global_sam_sid());
-       sid_append_rid(&group_sid, *rid);
+       sid_compose(&group_sid, get_global_sam_sid(), *rid);
 
        groupsidstr = talloc_strdup(tmp_ctx, sid_string_static(&group_sid));
        grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
@@ -4923,7 +4964,7 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                return NT_STATUS_NO_MEMORY;
        }
 
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", "sambaGroupMapping");
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
@@ -4966,14 +5007,15 @@ static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_
        int rc;
 
        /* get the group sid */
-       sid_copy(&group_sid, get_global_sam_sid());
-       sid_append_rid(&group_sid, rid);
+       sid_compose(&group_sid, get_global_sam_sid(), rid);
 
        filter = talloc_asprintf(tmp_ctx,
                                 "(&(sambaSID=%s)"
-                                "(objectClass=posixGroup)"
-                                "(objectClass=sambaGroupMapping))",
-                                sid_string_static(&group_sid));
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                sid_string_static(&group_sid),
+                                LDAP_OBJ_POSIXGROUP,
+                                LDAP_OBJ_GROUPMAP);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
        if (rc != LDAP_SUCCESS) {
@@ -5015,9 +5057,11 @@ static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_
        /* check no user have this group marked as primary group */
        filter = talloc_asprintf(tmp_ctx,
                                 "(&(gidNumber=%s)"
-                                "(objectClass=posixAccount)"
-                                "(objectClass=sambaSamAccount))",
-                                gidstr);
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                gidstr,
+                                LDAP_OBJ_POSIXACCOUNT,
+                                LDAP_OBJ_SAMBASAMACCOUNT);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
        if (rc != LDAP_SUCCESS) {
@@ -5071,18 +5115,18 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
        }
        
        /* get member sid  */
-       sid_copy(&member_sid, get_global_sam_sid());
-       sid_append_rid(&member_sid, member_rid);
+       sid_compose(&member_sid, get_global_sam_sid(), member_rid);
 
        /* get the group sid */
-       sid_copy(&group_sid, get_global_sam_sid());
-       sid_append_rid(&group_sid, group_rid);
+       sid_compose(&group_sid, get_global_sam_sid(), group_rid);
 
        filter = talloc_asprintf(tmp_ctx,
                                 "(&(sambaSID=%s)"
-                                "(objectClass=posixAccount)"
-                                "(objectClass=sambaSamAccount))",
-                                sid_string_static(&member_sid));
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                sid_string_static(&member_sid),
+                                LDAP_OBJ_POSIXACCOUNT,
+                                LDAP_OBJ_SAMBASAMACCOUNT);
 
        /* get the member uid */
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
@@ -5142,9 +5186,11 @@ static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
 
        filter = talloc_asprintf(tmp_ctx,
                                 "(&(sambaSID=%s)"
-                                "(objectClass=posixGroup)"
-                                "(objectClass=sambaGroupMapping))",
-                                sid_string_static(&group_sid));
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                sid_string_static(&group_sid),
+                                LDAP_OBJ_POSIXGROUP,
+                                LDAP_OBJ_GROUPMAP);
 
        /* get the group */
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
@@ -5242,9 +5288,11 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
        
        filter = talloc_asprintf(mem_ctx,
                                 "(&(uid=%s)"
-                                "(objectClass=posixAccount)"
-                                "(objectClass=sambaSamAccount))",
-                                pdb_get_username(sampass));
+                                "(objectClass=%s)"
+                                "(objectClass=%s))",
+                                pdb_get_username(sampass),
+                                LDAP_OBJ_POSIXACCOUNT,
+                                LDAP_OBJ_SAMBASAMACCOUNT);
 
        rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
        if (rc != LDAP_SUCCESS) {
index ea0544abf3ae17188a5c4ea9976c2bbd3c8071a4..9c8d72b42f0792221dd94f9455ed1114414625fe 100644 (file)
@@ -747,6 +747,390 @@ static int net_sam_show(int argc, const char **argv)
        return 0;
 }
 
+/*
+ * Init an LDAP tree with default users and Groups
+ * if ldapsam:editposix is enabled
+ */
+
+static int net_sam_provision(int argc, const char **argv)
+{
+       TALLOC_CTX *tc;
+       char *ldap_bk;
+       char *ldap_uri = NULL;
+       char *p;
+       struct smbldap_state *ls;
+       GROUP_MAP gmap;
+       DOM_SID gsid;
+       gid_t domusers_gid = -1;
+       gid_t domadmins_gid = -1;
+       struct samu *samuser;
+       struct passwd *pwd;
+
+       tc = talloc_new(NULL);
+       if (!tc) {
+               d_fprintf(stderr, "Out of Memory!\n");
+               return -1;
+       }
+
+       ldap_bk = talloc_strdup(tc, lp_passdb_backend());
+       p = strchr(ldap_bk, ':');
+       if (p) {
+               *p = 0;
+               ldap_uri = talloc_strdup(tc, p+1);
+               trim_char(ldap_uri, ' ', ' ');
+       }
+
+       trim_char(ldap_bk, ' ', ' ');
+               
+       if (strcmp(ldap_bk, "ldapsam") != 0) {
+               d_fprintf(stderr, "Provisioning works only with ldapsam backend\n");
+               goto failed;
+       }
+       
+       if (!lp_parm_bool(-1, "ldapsam", "trusted", False) ||
+           !lp_parm_bool(-1, "ldapsam", "editposix", False)) {
+
+               d_fprintf(stderr, "Provisioning works only if ldapsam:trusted"
+                                 " and ldapsam:editposix are enabled.\n");
+               goto failed;
+       }
+
+       if (!winbind_ping()) {
+               d_fprintf(stderr, "winbind seems not to run. Provisioning "
+                         "LDAP only works when winbind runs.\n");
+               goto failed;
+       }
+
+       if (!NT_STATUS_IS_OK(smbldap_init(tc, ldap_uri, &ls))) {
+               d_fprintf(stderr, "Unable to connect to the LDAP server.\n");
+               goto failed;
+       }
+
+       d_printf("Checking for Domain Users group.\n");
+
+       sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS);
+
+       if (!pdb_getgrsid(&gmap, gsid)) {
+               LDAPMod **mods = NULL;
+               char *dn;
+               char *uname;
+               char *wname;
+               char *gidstr;
+               char *gtype;
+               int rc;
+
+               d_printf("Adding the Domain Users group.\n");
+
+               /* lets allocate a new groupid for this group */
+               if (!winbind_allocate_gid(&domusers_gid)) {
+                       d_fprintf(stderr, "Unable to allocate a new gid to create Domain Users group!\n");
+                       goto domu_done;
+               }
+
+               uname = talloc_strdup(tc, "domusers");
+               wname = talloc_strdup(tc, "Domain Users");
+               dn = talloc_asprintf(tc, "cn=%s,%s", "domusers", lp_ldap_group_suffix());
+               gidstr = talloc_asprintf(tc, "%d", domusers_gid);
+               gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
+
+               if (!uname || !wname || !dn || !gidstr || !gtype) {
+                       d_fprintf(stderr, "Out of Memory!\n");
+                       goto failed;
+               }
+
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
+
+               talloc_autofree_ldapmod(tc, mods);
+
+               rc = smbldap_add(ls, dn, mods);
+
+               if (rc != LDAP_SUCCESS) {
+                       d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
+               }
+       } else {
+               d_printf("found!\n");
+       }       
+
+domu_done:
+
+       d_printf("Checking for Domain Admins group.\n");
+
+       sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_ADMINS);
+
+       if (!pdb_getgrsid(&gmap, gsid)) {
+               LDAPMod **mods = NULL;
+               char *dn;
+               char *uname;
+               char *wname;
+               char *gidstr;
+               char *gtype;
+               int rc;
+
+               d_printf("Adding the Domain Admins group.\n");
+
+               /* lets allocate a new groupid for this group */
+               if (!winbind_allocate_gid(&domadmins_gid)) {
+                       d_fprintf(stderr, "Unable to allocate a new gid to create Domain Admins group!\n");
+                       goto doma_done;
+               }
+
+               uname = talloc_strdup(tc, "domadmins");
+               wname = talloc_strdup(tc, "Domain Admins");
+               dn = talloc_asprintf(tc, "cn=%s,%s", "domadmins", lp_ldap_group_suffix());
+               gidstr = talloc_asprintf(tc, "%d", domadmins_gid);
+               gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
+
+               if (!uname || !wname || !dn || !gidstr || !gtype) {
+                       d_fprintf(stderr, "Out of Memory!\n");
+                       goto failed;
+               }
+
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
+
+               talloc_autofree_ldapmod(tc, mods);
+
+               rc = smbldap_add(ls, dn, mods);
+
+               if (rc != LDAP_SUCCESS) {
+                       d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
+               }
+       } else {
+               d_printf("found!\n");
+       }
+
+doma_done:
+
+       d_printf("Check for Administrator account.\n");
+
+       samuser = samu_new(tc);
+       if (!samuser) {
+               d_fprintf(stderr, "Out of Memory!\n");
+               goto failed;
+       }
+
+       if (!pdb_getsampwnam(samuser, "Administrator")) {
+               LDAPMod **mods = NULL;
+               DOM_SID sid;
+               char *dn;
+               char *name;
+               char *uidstr;
+               char *gidstr;
+               char *shell;
+               char *dir;
+               uid_t uid;
+               int rc;
+               
+               d_printf("Adding the Administrator user.\n");
+
+               if (domadmins_gid == -1) {
+                       d_fprintf(stderr, "Can't create Administrtor user, Domain Admins group not available!\n");
+                       goto done;
+               }
+               if (!winbind_allocate_uid(&uid)) {
+                       d_fprintf(stderr, "Unable to allocate a new uid to create the Administrator user!\n");
+                       goto done;
+               }
+               name = talloc_strdup(tc, "Administrator");
+               dn = talloc_asprintf(tc, "uid=Administrator,%s", lp_ldap_user_suffix());
+               uidstr = talloc_asprintf(tc, "%d", uid);
+               gidstr = talloc_asprintf(tc, "%d", domadmins_gid);
+               dir = talloc_sub_specified(tc, lp_template_homedir(),
+                                               "Administrator",
+                                               get_global_sam_name(),
+                                               uid, domadmins_gid);
+               shell = talloc_sub_specified(tc, lp_template_shell(),
+                                               "Administrator",
+                                               get_global_sam_name(),
+                                               uid, domadmins_gid);
+
+               if (!name || !dn || !uidstr || !gidstr || !dir || !shell) {
+                       d_fprintf(stderr, "Out of Memory!\n");
+                       goto failed;
+               }
+
+               sid_compose(&sid, get_global_sam_sid(), DOMAIN_USER_RID_ADMIN);
+
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", name);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", dir);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
+                               pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
+                               NEW_PW_FORMAT_SPACE_PADDED_LEN));
+
+               talloc_autofree_ldapmod(tc, mods);
+
+               rc = smbldap_add(ls, dn, mods);
+
+               if (rc != LDAP_SUCCESS) {
+                       d_fprintf(stderr, "Failed to add Administrator user to ldap directory\n");
+               }
+       } else {
+               d_printf("found!\n");
+       }
+
+       d_printf("Checking for Guest user.\n");
+
+       samuser = samu_new(tc);
+       if (!samuser) {
+               d_fprintf(stderr, "Out of Memory!\n");
+               goto failed;
+       }
+
+       if (!pdb_getsampwnam(samuser, lp_guestaccount())) {
+               LDAPMod **mods = NULL;
+               DOM_SID sid;
+               char *dn;
+               char *uidstr;
+               char *gidstr;
+               int rc;
+               
+               d_printf("Adding the Guest user.\n");
+
+               pwd = getpwnam_alloc(tc, lp_guestaccount());
+
+               if (!pwd) {
+                       if (domusers_gid == -1) {
+                               d_fprintf(stderr, "Can't create Guest user, Domain Users group not available!\n");
+                               goto done;
+                       }
+                       pwd = talloc(tc, struct passwd);
+                       pwd->pw_name = talloc_strdup(pwd, lp_guestaccount());
+                       if (!winbind_allocate_uid(&(pwd->pw_uid))) {
+                               d_fprintf(stderr, "Unable to allocate a new uid to create the Guest user!\n");
+                               goto done;
+                       }
+                       pwd->pw_gid = domusers_gid;
+                       pwd->pw_dir = talloc_strdup(tc, "/");
+                       pwd->pw_shell = talloc_strdup(tc, "/bin/false");
+                       if (!pwd->pw_dir || !pwd->pw_shell) {
+                               d_fprintf(stderr, "Out of Memory!\n");
+                               goto failed;
+                       }
+               }
+
+               sid_compose(&sid, get_global_sam_sid(), DOMAIN_USER_RID_GUEST);
+
+               dn = talloc_asprintf(tc, "uid=%s,%s", pwd->pw_name, lp_ldap_user_suffix ());
+               uidstr = talloc_asprintf(tc, "%d", pwd->pw_uid);
+               gidstr = talloc_asprintf(tc, "%d", pwd->pw_gid);
+               if (!dn || !uidstr || !gidstr) {
+                       d_fprintf(stderr, "Out of Memory!\n");
+                       goto failed;
+               }
+
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", pwd->pw_name);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", pwd->pw_name);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
+                               pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
+                               NEW_PW_FORMAT_SPACE_PADDED_LEN));
+
+               talloc_autofree_ldapmod(tc, mods);
+
+               rc = smbldap_add(ls, dn, mods);
+
+               if (rc != LDAP_SUCCESS) {
+                       d_fprintf(stderr, "Failed to add Guest user to ldap directory\n");
+               }
+       } else {
+               d_printf("found!\n");
+       }
+
+       d_printf("Checking Guest's group.\n");
+
+       pwd = getpwnam_alloc(NULL, lp_guestaccount());
+       if (!pwd) {
+               d_fprintf(stderr, "Failed to find just created Guest account!\n"
+                                 "   Is nssswitch properly configured?!\n");
+               goto failed;
+       }
+
+       if (pwd->pw_gid == domusers_gid) {
+               d_printf("found!\n");
+               goto done;
+       }
+
+       if (!pdb_getgrgid(&gmap, pwd->pw_gid)) {
+               LDAPMod **mods = NULL;
+               char *dn;
+               char *uname;
+               char *wname;
+               char *gidstr;
+               char *gtype;
+               int rc;
+
+               d_printf("Adding the Domain Guests group.\n");
+
+               uname = talloc_strdup(tc, "domguests");
+               wname = talloc_strdup(tc, "Domain Guests");
+               dn = talloc_asprintf(tc, "cn=%s,%s", "domguests", lp_ldap_group_suffix());
+               gidstr = talloc_asprintf(tc, "%d", pwd->pw_gid);
+               gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
+
+               if (!uname || !wname || !dn || !gidstr || !gtype) {
+                       d_fprintf(stderr, "Out of Memory!\n");
+                       goto failed;
+               }
+
+               sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_GUESTS);
+
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
+
+               talloc_autofree_ldapmod(tc, mods);
+
+               rc = smbldap_add(ls, dn, mods);
+
+               if (rc != LDAP_SUCCESS) {
+                       d_fprintf(stderr, "Failed to add Domain Guests group to ldap directory\n");
+               }
+       } else {
+               d_printf("found!\n");
+       }
+
+
+done:
+       talloc_free(tc);
+       return 0;
+
+failed:
+       talloc_free(tc);
+       return -1;
+}
+
 /***********************************************************
  migrated functionality from smbgroupedit
  **********************************************************/
@@ -769,6 +1153,8 @@ int net_sam(int argc, const char **argv)
                  "Show details of a SAM entry" },
                { "set", net_sam_set,
                  "Set details of a SAM account" },
+               { "provision", net_sam_provision,
+                 "Provision a clean User Database" },
                { NULL, NULL, NULL }
        };