diff options
author | Volker Lendecke <vlendec@samba.org> | 2006-02-13 17:08:25 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:10:06 -0500 |
commit | 301d51e13a1aa4e633e2da161b0dd260a8a499cd (patch) | |
tree | 7e8b9acef42b06f5ca2eac42f5b6403a035c8612 /source3/passdb | |
parent | 3b67210eec560d0c79b625ac11acb940e29fe8e0 (diff) | |
download | samba-301d51e13a1aa4e633e2da161b0dd260a8a499cd.tar.gz samba-301d51e13a1aa4e633e2da161b0dd260a8a499cd.tar.bz2 samba-301d51e13a1aa4e633e2da161b0dd260a8a499cd.zip |
r13494: Merge the stuff I've done in head the last days.
Volker
(This used to be commit bb40e544de68f01a6e774753f508e69373b39899)
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/passdb.c | 126 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 512 |
2 files changed, 536 insertions, 102 deletions
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 4d20352312..2b1da6ecce 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -6,6 +6,7 @@ Copyright (C) Gerald (Jerry) Carter 2000-2001 Copyright (C) Andrew Bartlett 2001-2002 Copyright (C) Simo Sorce 2003 + Copyright (C) Volker Lendecke 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -844,111 +845,70 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid) Convert a name into a SID. Used in the lookup name rpc. ********************************************************************/ -BOOL lookup_global_sam_name(const char *c_user, int flags, uint32_t *rid, +BOOL lookup_global_sam_name(const char *user, int flags, uint32_t *rid, enum SID_NAME_USE *type) { - fstring user; - SAM_ACCOUNT *sam_account = NULL; - struct group *grp; GROUP_MAP map; - - /* - * user may be quoted a const string, and map_username and - * friends can modify it. Make a modifiable copy. JRA. - */ - - fstrcpy(user, c_user); - - (void)map_username(user); - - if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { - return False; - } - - /* BEGIN ROOT BLOCK */ - - become_root(); + BOOL ret; /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work * correctly in the case where foo also exists as a user. If the flag * is set, don't look for users at all. */ - if (((flags & LOOKUP_NAME_GROUP) == 0) && - pdb_getsampwnam(sam_account, user)) { - const DOM_SID *user_sid; + if ((flags & LOOKUP_NAME_GROUP) == 0) { + SAM_ACCOUNT *sam_account = NULL; + DOM_SID user_sid; - unbecome_root(); - - user_sid = pdb_get_user_sid(sam_account); - - if (!sid_check_is_in_our_domain(user_sid)) { - DEBUG(0, ("User %s with invalid SID %s in passdb\n", - user, sid_string_static(user_sid))); + if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { return False; } + + become_root(); + ret = pdb_getsampwnam(sam_account, user); + unbecome_root(); - sid_peek_rid(user_sid, rid); - *type = SID_NAME_USER; + if (ret) { + sid_copy(&user_sid, pdb_get_user_sid(sam_account)); + } + pdb_free_sam(&sam_account); - return True; - } - pdb_free_sam(&sam_account); - - /* - * Maybe it was a group ? - */ - - /* check if it's a mapped group */ - if (pdb_getgrnam(&map, user)) { - - unbecome_root(); + if (ret) { + if (!sid_check_is_in_our_domain(&user_sid)) { + DEBUG(0, ("User %s with invalid SID %s in passdb\n", + user, sid_string_static(&user_sid))); + return False; + } - /* BUILTIN groups are looked up elsewhere */ - if (!sid_check_is_in_our_domain(&map.sid)) { - DEBUG(10, ("Found group %s (%s) not in our domain -- " - "ignoring.", user, - sid_string_static(&map.sid))); - return False; + sid_peek_rid(&user_sid, rid); + *type = SID_NAME_USER; + return True; } - - /* yes it's a mapped group */ - sid_peek_rid(&map.sid, rid); - *type = map.sid_name_use; - return True; } - return False; + /* + * Maybe it is a group ? + */ + + become_root(); + ret = pdb_getgrnam(&map, user); + unbecome_root(); - /* it's not a mapped group */ - grp = getgrnam(user); - if(!grp) { - unbecome_root(); /* ---> exit form block */ + if (!ret) { return False; } - - /* - *check if it's mapped, if it is reply it doesn't exist - * - * that's to prevent this case: - * - * unix group ug is mapped to nt group ng - * someone does a lookup on ug - * we must not reply as it doesn't "exist" anymore - * for NT. For NT only ng exists. - * JFM, 30/11/2001 - */ - - if (pdb_getgrgid(&map, grp->gr_gid)) { - unbecome_root(); /* ---> exit form block */ + + /* BUILTIN groups are looked up elsewhere */ + if (!sid_check_is_in_our_domain(&map.sid)) { + DEBUG(10, ("Found group %s (%s) not in our domain -- " + "ignoring.", user, + sid_string_static(&map.sid))); return False; } - unbecome_root(); - /* END ROOT BLOCK */ - - *rid = pdb_gid_to_group_rid(grp->gr_gid); - *type = SID_NAME_ALIAS; + /* yes it's a mapped group */ + sid_peek_rid(&map.sid, rid); + *type = map.sid_name_use; return True; } @@ -1086,7 +1046,7 @@ NTSTATUS local_password_change(const char *user_name, int local_flags, } if (local_flags & LOCAL_ADD_USER) { - if (pdb_add_sam_account(sam_pass)) { + if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) { slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name); pdb_free_sam(&sam_pass); return NT_STATUS_OK; @@ -1096,7 +1056,7 @@ NTSTATUS local_password_change(const char *user_name, int local_flags, return NT_STATUS_UNSUCCESSFUL; } } else if (local_flags & LOCAL_DELETE_USER) { - if (!pdb_delete_sam_account(sam_pass)) { + if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) { slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name); pdb_free_sam(&sam_pass); return NT_STATUS_UNSUCCESSFUL; diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 479ce18c05..c8917b9356 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Bartlett 2002 Copyright (C) Jelmer Vernooij 2002 Copyright (C) Simo Sorce 2003 + Copyright (C) Volker Lendecke 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -331,15 +332,141 @@ BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid) return NT_STATUS_IS_OK(pdb->getsampwsid(pdb, sam_acct, sid)); } -BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) +static NTSTATUS pdb_default_create_user(struct pdb_methods *methods, + TALLOC_CTX *tmp_ctx, const char *name, + uint32 acb_info, uint32 *rid) +{ + SAM_ACCOUNT *sam_pass = NULL; + NTSTATUS status; + + if (Get_Pwnam_alloc(tmp_ctx, name) == NULL) { + pstring add_script; + int add_ret; + + if ((acb_info & ACB_NORMAL) && name[strlen(name)-1] != '$') { + pstrcpy(add_script, lp_adduser_script()); + } else { + pstrcpy(add_script, lp_addmachine_script()); + } + + if (add_script[0] == '\0') { + DEBUG(3, ("Could not find user %s and no add script " + "defined\n", name)); + return NT_STATUS_NO_SUCH_USER; + } + + all_string_sub(add_script, "%u", name, sizeof(add_script)); + add_ret = smbrun(add_script,NULL); + DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the " + "command `%s' gave %d\n", + add_script, add_ret)); + } + + /* implicit call to getpwnam() next. we have a valid SID coming out + * of this call */ + + flush_pwnam_cache(); + status = pdb_init_sam_new(&sam_pass, name); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("pdb_init_sam_new failed: %s\n", nt_errstr(status))); + return status; + } + + if (!sid_peek_check_rid(get_global_sam_sid(), + pdb_get_user_sid(sam_pass), rid)) { + DEBUG(0, ("Could not get RID of fresh user\n")); + return NT_STATUS_INTERNAL_ERROR; + } + + /* Disable the account on creation, it does not have a reasonable + * password yet. */ + + acb_info |= ACB_DISABLED; + + pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED); + + status = pdb_add_sam_account(sam_pass); + + pdb_free_sam(&sam_pass); + + return status; +} + +NTSTATUS pdb_create_user(TALLOC_CTX *mem_ctx, const char *name, uint32 flags, + uint32 *rid) { struct pdb_methods *pdb = pdb_get_methods(False); if ( !pdb ) { - return False; + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->create_user(pdb, mem_ctx, name, flags, rid); +} + +/**************************************************************************** + Delete a UNIX user on demand. +****************************************************************************/ + +static int smb_delete_user(const char *unix_user) +{ + pstring del_script; + int ret; + + pstrcpy(del_script, lp_deluser_script()); + if (! *del_script) + return -1; + all_string_sub(del_script, "%u", unix_user, sizeof(del_script)); + ret = smbrun(del_script,NULL); + flush_pwnam_cache(); + DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); + + return ret; +} + +static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + SAM_ACCOUNT *sam_acct) +{ + NTSTATUS status; + + status = pdb_delete_sam_account(sam_acct); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + * Now delete the unix side .... + * note: we don't check if the delete really happened as the script is + * not necessary present and maybe the sysadmin doesn't want to delete + * the unix side + */ + smb_delete_user( pdb_get_username(sam_acct) ); + + return status; +} + +NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sam_acct) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->delete_user(pdb, mem_ctx, sam_acct); +} + +NTSTATUS pdb_add_sam_account(SAM_ACCOUNT *sam_acct) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb->add_sam_account(pdb, sam_acct)); + return pdb->add_sam_account(pdb, sam_acct); } NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct) @@ -358,12 +485,12 @@ NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct) return pdb->update_sam_account(pdb, sam_acct); } -BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) +NTSTATUS pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) { struct pdb_methods *pdb = pdb_get_methods(False); if ( !pdb ) { - return False; + return NT_STATUS_UNSUCCESSFUL; } if (csamuser != NULL) { @@ -371,7 +498,7 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) csamuser = NULL; } - return NT_STATUS_IS_OK(pdb->delete_sam_account(pdb, sam_acct)); + return pdb->delete_sam_account(pdb, sam_acct); } NTSTATUS pdb_rename_sam_account(SAM_ACCOUNT *oldname, const char *newname) @@ -434,6 +561,115 @@ BOOL pdb_getgrnam(GROUP_MAP *map, const char *name) return NT_STATUS_IS_OK(pdb->getgrnam(pdb, map, name)); } +static NTSTATUS pdb_default_create_dom_group(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const char *name, + uint32 *rid) +{ + DOM_SID group_sid; + struct group *grp; + + grp = getgrnam(name); + + if (grp == NULL) { + gid_t gid; + + if (smb_create_group(name, &gid) != 0) { + return NT_STATUS_ACCESS_DENIED; + } + + grp = getgrgid(gid); + } + + if (grp == NULL) { + return NT_STATUS_ACCESS_DENIED; + } + + if (pdb_rid_algorithm()) { + *rid = pdb_gid_to_group_rid( grp->gr_gid ); + } else { + if (!pdb_new_rid(rid)) { + return NT_STATUS_ACCESS_DENIED; + } + } + + sid_compose(&group_sid, get_global_sam_sid(), *rid); + + return add_initial_entry(grp->gr_gid, sid_string_static(&group_sid), + SID_NAME_DOM_GRP, name, NULL); +} + +NTSTATUS pdb_create_dom_group(TALLOC_CTX *mem_ctx, const char *name, + uint32 *rid) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->create_dom_group(pdb, mem_ctx, name, rid); +} + +static NTSTATUS pdb_default_delete_dom_group(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + uint32 rid) +{ + DOM_SID group_sid; + GROUP_MAP map; + NTSTATUS status; + struct group *grp; + const char *grp_name; + + sid_compose(&group_sid, get_global_sam_sid(), rid); + + if (!get_domain_group_from_sid(group_sid, &map)) { + DEBUG(10, ("Could not find group for rid %d\n", rid)); + return NT_STATUS_NO_SUCH_GROUP; + } + + /* We need the group name for the smb_delete_group later on */ + + if (map.gid == (gid_t)-1) { + return NT_STATUS_NO_SUCH_GROUP; + } + + grp = getgrgid(map.gid); + if (grp == NULL) { + return NT_STATUS_NO_SUCH_GROUP; + } + + /* Copy the name, no idea what pdb_delete_group_mapping_entry does.. */ + + grp_name = talloc_strdup(mem_ctx, grp->gr_name); + if (grp_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = pdb_delete_group_mapping_entry(group_sid); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Don't check the result of smb_delete_group */ + + smb_delete_group(grp_name); + + return NT_STATUS_OK; +} + +NTSTATUS pdb_delete_dom_group(TALLOC_CTX *mem_ctx, uint32 rid) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->delete_dom_group(pdb, mem_ctx, rid); +} + NTSTATUS pdb_add_group_mapping_entry(GROUP_MAP *map) { struct pdb_methods *pdb = pdb_get_methods(False); @@ -456,15 +692,15 @@ NTSTATUS pdb_update_group_mapping_entry(GROUP_MAP *map) return pdb->update_group_mapping_entry(pdb, map); } -BOOL pdb_delete_group_mapping_entry(DOM_SID sid) +NTSTATUS pdb_delete_group_mapping_entry(DOM_SID sid) { struct pdb_methods *pdb = pdb_get_methods(False); if ( !pdb ) { - return False; + return NT_STATUS_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb->delete_group_mapping_entry(pdb, sid)); + return pdb->delete_group_mapping_entry(pdb, sid); } BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap, @@ -510,6 +746,200 @@ NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user, pp_sids, pp_gids, p_num_groups); } +static NTSTATUS pdb_default_set_unix_primary_group(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + SAM_ACCOUNT *sampass) +{ + struct group *grp; + gid_t gid; + + if (!sid_to_gid(pdb_get_group_sid(sampass), &gid) || + (grp = getgrgid(gid)) == NULL) { + return NT_STATUS_INVALID_PRIMARY_GROUP; + } + + if (smb_set_primary_group(grp->gr_name, + pdb_get_username(sampass)) != 0) { + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} + +NTSTATUS pdb_set_unix_primary_group(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->set_unix_primary_group(pdb, mem_ctx, user); +} + +/* + * Helper function to see whether a user is in a group. We can't use + * user_in_group_sid here because this creates dependencies only smbd can + * fulfil. + */ + +static BOOL pdb_user_in_group(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *account, + const DOM_SID *group_sid) +{ + DOM_SID *sids; + gid_t *gids; + size_t i, num_groups; + + if (!NT_STATUS_IS_OK(pdb_enum_group_memberships(mem_ctx, account, + &sids, &gids, + &num_groups))) { + return False; + } + + for (i=0; i<num_groups; i++) { + if (sid_equal(group_sid, &sids[i])) { + return True; + } + } + return False; +} + +static NTSTATUS pdb_default_add_groupmem(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + uint32 group_rid, + uint32 member_rid) +{ + DOM_SID group_sid, member_sid; + SAM_ACCOUNT *account = NULL; + GROUP_MAP map; + struct group *grp; + struct passwd *pwd; + const char *group_name; + uid_t uid; + NTSTATUS status; + + sid_compose(&group_sid, get_global_sam_sid(), group_rid); + sid_compose(&member_sid, get_global_sam_sid(), member_rid); + + if (!get_domain_group_from_sid(group_sid, &map) || + (map.gid == (gid_t)-1) || + ((grp = getgrgid(map.gid)) == NULL)) { + return NT_STATUS_NO_SUCH_GROUP; + } + + group_name = talloc_strdup(mem_ctx, grp->gr_name); + if (group_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!NT_STATUS_IS_OK(status = pdb_init_sam(&account))) { + return status; + } + + if (!pdb_getsampwsid(account, &member_sid) || + !sid_to_uid(&member_sid, &uid) || + ((pwd = getpwuid_alloc(mem_ctx, uid)) == NULL)) { + return NT_STATUS_NO_SUCH_USER; + } + + if (pdb_user_in_group(mem_ctx, account, &group_sid)) { + return NT_STATUS_MEMBER_IN_GROUP; + } + + /* + * ok, the group exist, the user exist, the user is not in the group, + * we can (finally) add it to the group ! + */ + + smb_add_user_group(group_name, pwd->pw_name); + + if (!pdb_user_in_group(mem_ctx, account, &group_sid)) { + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} + +NTSTATUS pdb_add_groupmem(TALLOC_CTX *mem_ctx, uint32 group_rid, + uint32 member_rid) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->add_groupmem(pdb, mem_ctx, group_rid, member_rid); +} + +static NTSTATUS pdb_default_del_groupmem(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + uint32 group_rid, + uint32 member_rid) +{ + DOM_SID group_sid, member_sid; + SAM_ACCOUNT *account = NULL; + GROUP_MAP map; + struct group *grp; + struct passwd *pwd; + const char *group_name; + uid_t uid; + NTSTATUS status; + + sid_compose(&group_sid, get_global_sam_sid(), group_rid); + sid_compose(&member_sid, get_global_sam_sid(), member_rid); + + if (!get_domain_group_from_sid(group_sid, &map) || + (map.gid == (gid_t)-1) || + ((grp = getgrgid(map.gid)) == NULL)) { + return NT_STATUS_NO_SUCH_GROUP; + } + + group_name = talloc_strdup(mem_ctx, grp->gr_name); + if (group_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!NT_STATUS_IS_OK(status = pdb_init_sam(&account))) { + return status; + } + + if (!pdb_getsampwsid(account, &member_sid) || + !sid_to_uid(&member_sid, &uid) || + ((pwd = getpwuid_alloc(mem_ctx, uid)) == NULL)) { + return NT_STATUS_NO_SUCH_USER; + } + + if (!pdb_user_in_group(mem_ctx, account, &group_sid)) { + return NT_STATUS_MEMBER_NOT_IN_GROUP; + } + + /* + * ok, the group exist, the user exist, the user is in the group, + * we can (finally) delete it from the group! + */ + + smb_delete_user_group(group_name, pwd->pw_name); + + if (pdb_user_in_group(mem_ctx, account, &group_sid)) { + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} + +NTSTATUS pdb_del_groupmem(TALLOC_CTX *mem_ctx, uint32 group_rid, + uint32 member_rid) +{ + struct pdb_methods *pdb = pdb_get_methods(False); + + if ( !pdb ) { + return NT_STATUS_UNSUCCESSFUL; + } + + return pdb->del_groupmem(pdb, mem_ctx, group_rid, member_rid); +} + BOOL pdb_find_alias(const char *name, DOM_SID *sid) { struct pdb_methods *pdb = pdb_get_methods(False); @@ -977,7 +1407,7 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size { struct group *grp; char **gr; - struct sys_pwent *userlist, *user; + struct passwd *pwd; *pp_uids = NULL; *p_num = 0; @@ -993,15 +1423,14 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size /* Primary group members */ - userlist = getpwent_list(); - - for (user = userlist; user != NULL; user = user->next) { - if (user->pw_gid != gid) - continue; - add_uid_to_array_unique(mem_ctx, user->pw_uid, pp_uids, p_num); + setpwent(); + while ((pwd = getpwent()) != NULL) { + if (pwd->pw_gid == gid) { + add_uid_to_array_unique(mem_ctx, pwd->pw_uid, + pp_uids, p_num); + } } - - pwent_free(userlist); + endpwent(); /* Secondary group members */ @@ -1048,7 +1477,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, uid_to_sid(&sid, uids[i]); if (!sid_check_is_in_our_domain(&sid)) { - DEBUG(1, ("Inconsistent SAM -- group member uid not " + DEBUG(5, ("Inconsistent SAM -- group member uid not " "in our domain\n")); continue; } @@ -1060,6 +1489,44 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, return NT_STATUS_OK; } +NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + SAM_ACCOUNT *user, + DOM_SID **pp_sids, + gid_t **pp_gids, + size_t *p_num_groups) +{ + size_t i; + gid_t gid; + + if (!sid_to_gid(pdb_get_group_sid(user), &gid)) { + DEBUG(10, ("sid_to_gid failed\n")); + return NT_STATUS_NO_SUCH_USER; + } + + if (!getgroups_unix_user(mem_ctx, pdb_get_username(user), gid, + pp_gids, p_num_groups)) { + return NT_STATUS_NO_SUCH_USER; + } + + if (*p_num_groups == 0) { + smb_panic("primary group missing"); + } + + *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups); + + if (*pp_sids == NULL) { + talloc_free(*pp_gids); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<*p_num_groups; i++) { + gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]); + } + + return NT_STATUS_OK; +} + /******************************************************************* Look up a rid in the SAM we're responsible for (i.e. passdb) ********************************************************************/ @@ -1603,6 +2070,8 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods ) (*methods)->getsampwent = pdb_default_getsampwent; (*methods)->getsampwnam = pdb_default_getsampwnam; (*methods)->getsampwsid = pdb_default_getsampwsid; + (*methods)->create_user = pdb_default_create_user; + (*methods)->delete_user = pdb_default_delete_user; (*methods)->add_sam_account = pdb_default_add_sam_account; (*methods)->update_sam_account = pdb_default_update_sam_account; (*methods)->delete_sam_account = pdb_default_delete_sam_account; @@ -1612,12 +2081,17 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods ) (*methods)->getgrsid = pdb_default_getgrsid; (*methods)->getgrgid = pdb_default_getgrgid; (*methods)->getgrnam = pdb_default_getgrnam; + (*methods)->create_dom_group = pdb_default_create_dom_group; + (*methods)->delete_dom_group = pdb_default_delete_dom_group; (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry; (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry; (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry; (*methods)->enum_group_mapping = pdb_default_enum_group_mapping; (*methods)->enum_group_members = pdb_default_enum_group_members; (*methods)->enum_group_memberships = pdb_default_enum_group_memberships; + (*methods)->set_unix_primary_group = pdb_default_set_unix_primary_group; + (*methods)->add_groupmem = pdb_default_add_groupmem; + (*methods)->del_groupmem = pdb_default_del_groupmem; (*methods)->find_alias = pdb_default_find_alias; (*methods)->create_alias = pdb_default_create_alias; (*methods)->delete_alias = pdb_default_delete_alias; |