diff options
author | Volker Lendecke <vlendec@samba.org> | 2004-02-29 16:48:19 +0000 |
---|---|---|
committer | Volker Lendecke <vlendec@samba.org> | 2004-02-29 16:48:19 +0000 |
commit | 0d45ad1b0d55546c6a4afcb002acefefc2e2feb0 (patch) | |
tree | 34fa0e74191cef6a5070a0e1499c919a43b4f64d /source3/groupdb/mapping.c | |
parent | 4628a2da1e32f397696640452c950e4b55ada9e7 (diff) | |
download | samba-0d45ad1b0d55546c6a4afcb002acefefc2e2feb0.tar.gz samba-0d45ad1b0d55546c6a4afcb002acefefc2e2feb0.tar.bz2 samba-0d45ad1b0d55546c6a4afcb002acefefc2e2feb0.zip |
Apply my experimental aliases support to HEAD. This will be a bit difficult to
merge to 3_0, as the pdb interfaces has changed a bit between the two.
This has not been tested too severly (which means it's completely broken ;-),
but I want it in for review. Feel free to revert it :-)
TODO:
make 'net groupmap' a bit more friendly for alias members.
Put that stuff into pdb_ldap.
Getting the information over to winbind. One plan without linking pdb into
winbind would be to fill group_mapping.tdb with the membership information and
have that as a cache (or use gencache.tdb?). smbd on a PDC or stand-alone
could trigger that itself, the problem is a BDC using LDAP. This needs to do
it on a regular basis. The BDC smbd needs to be informed about SAM changes
somehow...
Volker
(This used to be commit 30ef8fe1e85c0ca229b54f3f1595c4330f7191d1)
Diffstat (limited to 'source3/groupdb/mapping.c')
-rw-r--r-- | source3/groupdb/mapping.c | 282 |
1 files changed, 281 insertions, 1 deletions
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 71ef38e6c8..5eaa4e1386 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -27,6 +27,7 @@ static TDB_CONTEXT *tdb; /* used for driver files */ #define DATABASE_VERSION_V2 2 /* le format. */ #define GROUP_PREFIX "UNIXGROUP/" +#define ALIASMEM_PREFIX "ALIASMEMBERS/" PRIVS privs[] = { {SE_PRIV_NONE, "no_privs", "No privilege" }, /* this one MUST be first */ @@ -489,6 +490,246 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, return True; } +static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member) +{ + GROUP_MAP map; + TDB_DATA kbuf, dbuf; + pstring key; + fstring string_sid; + char *new_memberstring; + int result; + + if(!init_group_mapping()) { + DEBUG(0,("failed to initialize group mapping")); + return NT_STATUS_ACCESS_DENIED; + } + + if (!get_group_map_from_sid(*alias, &map)) + return NT_STATUS_NO_SUCH_ALIAS; + + if ( (map.sid_name_use != SID_NAME_ALIAS) && + (map.sid_name_use != SID_NAME_WKN_GRP) ) + return NT_STATUS_NO_SUCH_ALIAS; + + sid_to_string(string_sid, alias); + slprintf(key, sizeof(key), "%s%s", ALIASMEM_PREFIX, string_sid); + + kbuf.dsize = strlen(key)+1; + kbuf.dptr = key; + + dbuf = tdb_fetch(tdb, kbuf); + + sid_to_string(string_sid, member); + + if (dbuf.dptr != NULL) { + asprintf(&new_memberstring, "%s %s", (char *)(dbuf.dptr), + string_sid); + } else { + new_memberstring = strdup(string_sid); + } + + if (new_memberstring == NULL) + return NT_STATUS_NO_MEMORY; + + SAFE_FREE(dbuf.dptr); + dbuf.dsize = strlen(new_memberstring)+1; + dbuf.dptr = new_memberstring; + + result = tdb_store(tdb, kbuf, dbuf, 0); + + SAFE_FREE(new_memberstring); + + return (result == 0 ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED); +} + +static BOOL add_sid_to_array(DOM_SID sid, DOM_SID **sids, int *num) +{ + *sids = Realloc(*sids, ((*num)+1) * sizeof(DOM_SID)); + + if (*sids == NULL) + return False; + + sid_copy(&((*sids)[*num]), &sid); + *num += 1; + + return True; +} + +static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, int *num) +{ + GROUP_MAP map; + TDB_DATA kbuf, dbuf; + pstring key; + fstring string_sid; + const char *p; + + if(!init_group_mapping()) { + DEBUG(0,("failed to initialize group mapping")); + return NT_STATUS_ACCESS_DENIED; + } + + if (!get_group_map_from_sid(*alias, &map)) + return NT_STATUS_NO_SUCH_ALIAS; + + if ( (map.sid_name_use != SID_NAME_ALIAS) && + (map.sid_name_use != SID_NAME_WKN_GRP) ) + return NT_STATUS_NO_SUCH_ALIAS; + + *sids = NULL; + *num = 0; + + sid_to_string(string_sid, alias); + slprintf(key, sizeof(key), "%s%s", ALIASMEM_PREFIX, string_sid); + + kbuf.dsize = strlen(key)+1; + kbuf.dptr = key; + + dbuf = tdb_fetch(tdb, kbuf); + + if (dbuf.dptr == NULL) { + return NT_STATUS_OK; + } + + p = dbuf.dptr; + + while (next_token(&p, string_sid, " ", sizeof(string_sid))) { + + DOM_SID sid; + + if (!string_to_sid(&sid, string_sid)) + continue; + + if (!add_sid_to_array(sid, sids, num)) + return NT_STATUS_NO_MEMORY; + } + + SAFE_FREE(dbuf.dptr); + + return NT_STATUS_OK; +} + +/* This is racy as hell, but hey, it's only a prototype :-) */ + +static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member) +{ + NTSTATUS result; + DOM_SID *sids; + int i, num; + BOOL found = False; + char *member_string; + TDB_DATA kbuf, dbuf; + pstring key; + fstring sid_string; + + result = enum_aliasmem(alias, &sids, &num); + + if (!NT_STATUS_IS_OK(result)) + return result; + + for (i=0; i<num; i++) { + if (sid_compare(&sids[i], member) == 0) { + found = True; + break; + } + } + + if (!found) { + SAFE_FREE(sids); + return NT_STATUS_MEMBER_NOT_IN_ALIAS; + } + + if (i < num) + sids[i] = sids[num-1]; + + num -= 1; + + member_string = strdup(""); + + if (member_string == NULL) { + SAFE_FREE(sids); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<num; i++) { + char *s = member_string; + + sid_to_string(sid_string, &sids[i]); + asprintf(&member_string, "%s %s", s, sid_string); + + SAFE_FREE(s); + if (member_string == NULL) { + SAFE_FREE(sids); + return NT_STATUS_NO_MEMORY; + } + } + + sid_to_string(sid_string, alias); + slprintf(key, sizeof(key), "%s%s", ALIASMEM_PREFIX, sid_string); + + kbuf.dsize = strlen(key)+1; + kbuf.dptr = key; + dbuf.dsize = strlen(member_string)+1; + dbuf.dptr = member_string; + + result = tdb_store(tdb, kbuf, dbuf, 0) == 0 ? + NT_STATUS_OK : NT_STATUS_ACCESS_DENIED; + + SAFE_FREE(sids); + SAFE_FREE(member_string); + + return result; +} + +static BOOL is_foreign_alias_member(const DOM_SID *sid, const DOM_SID *alias) +{ + DOM_SID *members; + int i, num; + BOOL result = False; + + if (!NT_STATUS_IS_OK(enum_aliasmem(alias, &members, &num))) + return False; + + for (i=0; i<num; i++) { + + if (sid_compare(&members[i], sid) == 0) { + result = True; + break; + } + } + + SAFE_FREE(members); + return result; +} + +static NTSTATUS alias_memberships(const DOM_SID *sid, DOM_SID **sids, int *num) +{ + GROUP_MAP *maps; + int i, num_maps; + + *num = 0; + *sids = NULL; + + if (!enum_group_mapping(SID_NAME_WKN_GRP, &maps, &num_maps, False)) + return NT_STATUS_NO_MEMORY; + + for (i=0; i<num_maps; i++) { + if (is_foreign_alias_member(sid, &maps[i].sid)) + add_sid_to_array(maps[i].sid, sids, num); + } + SAFE_FREE(maps); + + if (!enum_group_mapping(SID_NAME_ALIAS, &maps, &num_maps, False)) + return NT_STATUS_NO_MEMORY; + + for (i=0; i<num_maps; i++) { + if (is_foreign_alias_member(sid, &maps[i].sid)) + add_sid_to_array(maps[i].sid, sids, num); + } + SAFE_FREE(maps); + + return NT_STATUS_OK; +} + /* * * High level functions @@ -568,7 +809,8 @@ BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map) if ( !ret ) return False; - if ( (map->sid_name_use != SID_NAME_ALIAS) + if ( ( (map->sid_name_use != SID_NAME_ALIAS) && + (map->sid_name_use != SID_NAME_WKN_GRP) ) || (map->gid == -1) || (getgrgid(map->gid) == NULL) ) { @@ -704,6 +946,9 @@ BOOL get_sid_list_of_group(gid_t gid, DOM_SID **sids, int *num_sids) int i=0; char *gr; DOM_SID *s; + DOM_SID sid; + DOM_SID *members; + int num_members; struct sys_pwent *userlist; struct sys_pwent *user; @@ -803,6 +1048,15 @@ BOOL get_sid_list_of_group(gid_t gid, DOM_SID **sids, int *num_sids) DEBUG(10, ("got primary groups, members: [%d]\n", *num_sids)); winbind_on(); + + if ( NT_STATUS_IS_OK(gid_to_sid(&sid, gid)) && + NT_STATUS_IS_OK(enum_aliasmem(&sid, &members, &num_members)) ) { + + for (i=0; i<num_members; i++) { + add_sid_to_array(members[i], sids, num_sids); + } + } + return True; } @@ -1029,6 +1283,32 @@ NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods, NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } +NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, const DOM_SID *member) +{ + return add_aliasmem(alias, member); +} + +NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, const DOM_SID *member) +{ + return del_aliasmem(alias, member); +} + +NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, DOM_SID **members, + int *num_members) +{ + return enum_aliasmem(alias, members, num_members); +} + +NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods, + const DOM_SID *sid, + DOM_SID **aliases, int *num) +{ + return alias_memberships(sid, aliases, num); +} + /********************************************************************** no ops for passdb backends that don't implement group mapping *********************************************************************/ |