summaryrefslogtreecommitdiff
path: root/source3/groupdb/mapping.c
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2004-02-29 16:48:19 +0000
committerVolker Lendecke <vlendec@samba.org>2004-02-29 16:48:19 +0000
commit0d45ad1b0d55546c6a4afcb002acefefc2e2feb0 (patch)
tree34fa0e74191cef6a5070a0e1499c919a43b4f64d /source3/groupdb/mapping.c
parent4628a2da1e32f397696640452c950e4b55ada9e7 (diff)
downloadsamba-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.c282
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
*********************************************************************/