#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 */
TDB_DATA kbuf, dbuf;
pstring key;
fstring string_sid;
- int ret;
+ int ret = 0;
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
&map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
SAFE_FREE(dbuf.dptr);
+
+ if ( ret == -1 ) {
+ DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
+ return False;
+ }
sid_copy(&map->sid, &sid);
SAFE_FREE(dbuf.dptr);
+ if ( ret == -1 ) {
+ DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n"));
+ return False;
+ }
+
if (gid==map->gid) {
SAFE_FREE(kbuf.dptr);
return True;
&map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
SAFE_FREE(dbuf.dptr);
+
+ if ( ret == -1 ) {
+ DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n"));
+ return False;
+ }
if (StrCaseCmp(name, map->nt_name)==0) {
SAFE_FREE(kbuf.dptr);
SAFE_FREE(dbuf.dptr);
+ if ( ret == -1 ) {
+ DEBUG(3,("enum_group_mapping: tdb_unpack failure\n"));
+ continue;
+ }
+
/* list only the type or everything if UNKNOWN */
if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) {
DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
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
BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
{
struct group *grp;
-
+ BOOL ret;
+
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
return(False);
DEBUG(10, ("get_domain_group_from_sid\n"));
/* if the group is NOT in the database, it CAN NOT be a domain group */
- if(!pdb_getgrsid(map, sid))
+
+ become_root();
+ ret = pdb_getgrsid(map, sid);
+ unbecome_root();
+
+ if ( !ret )
return False;
DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
}
DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid));
-
- if ( (grp=getgrgid(map->gid)) == NULL) {
+
+ grp = getgrgid(map->gid);
+ if ( !grp ) {
DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
return False;
}
/* get a local (alias) group from it's SID */
-BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map)
+BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
{
- struct group *grp;
-
+ BOOL ret;
+
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
return(False);
}
/* The group is in the mapping table */
- if(pdb_getgrsid(map, sid)) {
- if (map->sid_name_use!=SID_NAME_ALIAS) {
- return False;
- }
+ become_root();
+ ret = pdb_getgrsid(map, *sid);
+ unbecome_root();
+
+ if ( !ret )
+ return False;
- if (map->gid==-1) {
- return False;
- }
-
- if ( (grp=getgrgid(map->gid)) == NULL) {
- return False;
- }
- } else {
+ if ( ( (map->sid_name_use != SID_NAME_ALIAS) &&
+ (map->sid_name_use != SID_NAME_WKN_GRP) )
+ || (map->gid == -1)
+ || (getgrgid(map->gid) == NULL) )
+ {
+ return False;
+ }
+
+#if 1 /* JERRY */
+ /* local groups only exist in the group mapping DB so this
+ is not necessary */
+
+ else {
/* the group isn't in the mapping table.
* make one based on the unix information */
uint32 alias_rid;
+ struct group *grp;
- sid_peek_rid(&sid, &alias_rid);
+ sid_peek_rid(sid, &alias_rid);
map->gid=pdb_group_rid_to_gid(alias_rid);
-
- if ((grp=getgrgid(map->gid)) == NULL)
+
+ grp = getgrgid(map->gid);
+ if ( !grp ) {
+ DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid));
return False;
+ }
map->sid_name_use=SID_NAME_ALIAS;
fstrcpy(map->nt_name, grp->gr_name);
fstrcpy(map->comment, "Local Unix Group");
- sid_copy(&map->sid, &sid);
+ sid_copy(&map->sid, sid);
}
+#endif
return True;
}
/* get a builtin group from it's SID */
-BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map)
+BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
{
struct group *grp;
+ BOOL ret;
+
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
return(False);
}
- if(!pdb_getgrsid(map, sid))
+ become_root();
+ ret = pdb_getgrsid(map, *sid);
+ unbecome_root();
+
+ if ( !ret )
return False;
if (map->sid_name_use!=SID_NAME_WKN_GRP) {
BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
{
struct group *grp;
+ BOOL ret;
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
/*
* make a group map from scratch if doesn't exist.
*/
- if (!pdb_getgrgid(map, gid)) {
+
+ become_root();
+ ret = pdb_getgrgid(map, gid);
+ unbecome_root();
+
+ if ( !ret ) {
map->gid=gid;
map->sid_name_use=SID_NAME_ALIAS;
Get the member users of a group and
all the users who have that group as primary.
- give back an array of uid
+ give back an array of SIDS
return the grand number of users
****************************************************************************/
-BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
+BOOL get_sid_list_of_group(gid_t gid, DOM_SID **sids, int *num_sids)
{
struct group *grp;
- struct passwd *pwd;
int i=0;
char *gr;
- uid_t *u;
+ DOM_SID *s;
+ DOM_SID sid;
+ DOM_SID *members;
+ int num_members;
+
+ struct sys_pwent *userlist;
+ struct sys_pwent *user;
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping"));
return(False);
}
- *num_uids = 0;
- *uid=NULL;
+ *num_sids = 0;
+ *sids=NULL;
if ( (grp=getgrgid(gid)) == NULL)
return False;
DEBUG(10, ("getting members\n"));
while (gr && (*gr != (char)'\0')) {
- u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
- if (!u) {
- DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
+ SAM_ACCOUNT *group_member_acct = NULL;
+ BOOL found_user;
+ s = Realloc((*sids), sizeof(**sids)*(*num_sids+1));
+ if (!s) {
+ DEBUG(0,("get_uid_list_of_group: unable to enlarge SID list!\n"));
return False;
}
- else (*uid) = u;
+ else (*sids) = s;
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&group_member_acct))) {
+ continue;
+ }
- if( (pwd=getpwnam_alloc(gr)) !=NULL) {
- (*uid)[*num_uids]=pwd->pw_uid;
- (*num_uids)++;
- passwd_free(&pwd);
+ become_root();
+ found_user = pdb_getsampwnam(group_member_acct, gr);
+ unbecome_root();
+
+ if (found_user) {
+ sid_copy(&(*sids)[*num_sids], pdb_get_user_sid(group_member_acct));
+ (*num_sids)++;
}
+
+ pdb_free_sam(&group_member_acct);
+
gr = grp->gr_mem[++i];
}
- DEBUG(10, ("got [%d] members\n", *num_uids));
+ DEBUG(10, ("got [%d] members\n", *num_sids));
- setpwent();
- while ((pwd=getpwent()) != NULL) {
- if (pwd->pw_gid==gid) {
- u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
- if (!u) {
- DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
- return False;
- }
- else (*uid) = u;
- (*uid)[*num_uids]=pwd->pw_uid;
+ winbind_off();
+
+ user = userlist = getpwent_list();
+
+ while (user != NULL) {
- (*num_uids)++;
+ SAM_ACCOUNT *group_member_acct = NULL;
+ BOOL found_user;
+
+ if (user->pw_gid != gid) {
+ user = user->next;
+ continue;
+ }
+
+ s = Realloc((*sids), sizeof(**sids)*(*num_sids+1));
+ if (!s) {
+ DEBUG(0,("get_sid_list_of_group: unable to enlarge "
+ "SID list!\n"));
+ pwent_free(userlist);
+ winbind_on();
+ return False;
+ }
+ else (*sids) = s;
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&group_member_acct))) {
+ continue;
+ }
+
+ become_root();
+ found_user = pdb_getsampwnam(group_member_acct, user->pw_name);
+ unbecome_root();
+
+ if (found_user) {
+ sid_copy(&(*sids)[*num_sids],
+ pdb_get_user_sid(group_member_acct));
+ (*num_sids)++;
+ } else {
+ DEBUG(4,("get_sid_list_of_group: User %s [uid == %lu] "
+ "has no samba account\n",
+ user->pw_name, (unsigned long)user->pw_uid));
+ if (algorithmic_uid_to_sid(&(*sids)[*num_sids],
+ user->pw_uid))
+ (*num_sids)++;
+ }
+ pdb_free_sam(&group_member_acct);
+
+ user = user->next;
+ }
+ pwent_free(userlist);
+ 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);
}
}
- endpwent();
- DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
return True;
}
close(fd);
}
- }
- /* Try winbindd */
+ } else if ( winbind_create_group( unix_group, NULL ) ) {
- if ( winbind_create_group( unix_group, NULL ) ) {
DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
unix_group));
ret = 0;
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
*********************************************************************/