mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r116: volker's patch for local group and group nesting
(This used to be commit b393469d95
)
This commit is contained in:
parent
f79e40072a
commit
7af3777ab3
@ -627,6 +627,7 @@ WINBINDD_OBJ1 = \
|
||||
nsswitch/winbindd_wins.o \
|
||||
nsswitch/winbindd_rpc.o \
|
||||
nsswitch/winbindd_ads.o \
|
||||
nsswitch/winbindd_passdb.o \
|
||||
nsswitch/winbindd_dual.o \
|
||||
nsswitch/winbindd_acct.o
|
||||
|
||||
|
@ -28,6 +28,13 @@ static TDB_CONTEXT *tdb; /* used for driver files */
|
||||
|
||||
#define GROUP_PREFIX "UNIXGROUP/"
|
||||
|
||||
/* Alias memberships are stored reverse, as memberships. The performance
|
||||
* critical operation is to determine the aliases a SID is member of, not
|
||||
* listing alias members. So we store a list of alias SIDs a SID is member of
|
||||
* hanging of the member as key.
|
||||
*/
|
||||
#define MEMBEROF_PREFIX "MEMBEROF/"
|
||||
|
||||
PRIVS privs[] = {
|
||||
{SE_PRIV_NONE, "no_privs", "No privilege" }, /* this one MUST be first */
|
||||
{SE_PRIV_ADD_MACHINES, "SeMachineAccountPrivilege", "Add workstations to the domain" },
|
||||
@ -489,6 +496,284 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
|
||||
return True;
|
||||
}
|
||||
|
||||
/* This operation happens on session setup, so it should better be fast. We
|
||||
* store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
|
||||
|
||||
static NTSTATUS alias_memberships(const DOM_SID *sid, DOM_SID **sids, int *num)
|
||||
{
|
||||
fstring key, string_sid;
|
||||
TDB_DATA kbuf, dbuf;
|
||||
const char *p;
|
||||
|
||||
*num = 0;
|
||||
*sids = NULL;
|
||||
|
||||
if (!init_group_mapping()) {
|
||||
DEBUG(0,("failed to initialize group mapping\n"));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
sid_to_string(string_sid, sid);
|
||||
slprintf(key, sizeof(key), "%s%s", MEMBEROF_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 alias;
|
||||
|
||||
if (!string_to_sid(&alias, string_sid))
|
||||
continue;
|
||||
|
||||
add_sid_to_array(&alias, sids, num);
|
||||
|
||||
if (sids == NULL)
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
SAFE_FREE(dbuf.dptr);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static BOOL is_aliasmem(const DOM_SID *alias, const DOM_SID *member)
|
||||
{
|
||||
DOM_SID *sids;
|
||||
int i, num;
|
||||
|
||||
/* This feels the wrong way round, but the on-disk data structure
|
||||
* dictates it this way. */
|
||||
if (!NT_STATUS_IS_OK(alias_memberships(member, &sids, &num)))
|
||||
return False;
|
||||
|
||||
for (i=0; i<num; i++) {
|
||||
if (sid_compare(alias, &sids[i]) == 0) {
|
||||
SAFE_FREE(sids);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
SAFE_FREE(sids);
|
||||
return False;
|
||||
}
|
||||
|
||||
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\n"));
|
||||
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;
|
||||
|
||||
if (is_aliasmem(alias, member))
|
||||
return NT_STATUS_MEMBER_IN_ALIAS;
|
||||
|
||||
sid_to_string(string_sid, member);
|
||||
slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
|
||||
|
||||
kbuf.dsize = strlen(key)+1;
|
||||
kbuf.dptr = key;
|
||||
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
sid_to_string(string_sid, alias);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
struct aliasmem_closure {
|
||||
const DOM_SID *alias;
|
||||
DOM_SID **sids;
|
||||
int *num;
|
||||
};
|
||||
|
||||
static int collect_aliasmem(TDB_CONTEXT *tdb_ctx, TDB_DATA key, TDB_DATA data,
|
||||
void *state)
|
||||
{
|
||||
struct aliasmem_closure *closure = (struct aliasmem_closure *)state;
|
||||
const char *p;
|
||||
fstring alias_string;
|
||||
|
||||
if (strncmp(key.dptr, MEMBEROF_PREFIX,
|
||||
strlen(MEMBEROF_PREFIX)) != 0)
|
||||
return 0;
|
||||
|
||||
p = data.dptr;
|
||||
|
||||
while (next_token(&p, alias_string, " ", sizeof(alias_string))) {
|
||||
|
||||
DOM_SID alias, member;
|
||||
const char *member_string;
|
||||
|
||||
|
||||
if (!string_to_sid(&alias, alias_string))
|
||||
continue;
|
||||
|
||||
if (sid_compare(closure->alias, &alias) != 0)
|
||||
continue;
|
||||
|
||||
/* Ok, we found the alias we're looking for in the membership
|
||||
* list currently scanned. The key represents the alias
|
||||
* member. Add that. */
|
||||
|
||||
member_string = strchr(key.dptr, '/');
|
||||
|
||||
/* Above we tested for MEMBEROF_PREFIX which includes the
|
||||
* slash. */
|
||||
|
||||
SMB_ASSERT(member_string != NULL);
|
||||
member_string += 1;
|
||||
|
||||
if (!string_to_sid(&member, member_string))
|
||||
continue;
|
||||
|
||||
add_sid_to_array(&member, closure->sids, closure->num);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, int *num)
|
||||
{
|
||||
GROUP_MAP map;
|
||||
struct aliasmem_closure closure;
|
||||
|
||||
if(!init_group_mapping()) {
|
||||
DEBUG(0,("failed to initialize group mapping\n"));
|
||||
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;
|
||||
|
||||
closure.alias = alias;
|
||||
closure.sids = sids;
|
||||
closure.num = num;
|
||||
|
||||
tdb_traverse(tdb, collect_aliasmem, &closure);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
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 = alias_memberships(member, &sids, &num);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result))
|
||||
return result;
|
||||
|
||||
for (i=0; i<num; i++) {
|
||||
if (sid_compare(&sids[i], alias) == 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;
|
||||
|
||||
sid_to_string(sid_string, member);
|
||||
slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, sid_string);
|
||||
|
||||
kbuf.dsize = strlen(key)+1;
|
||||
kbuf.dptr = key;
|
||||
|
||||
if (num == 0)
|
||||
return tdb_delete(tdb, kbuf) == 0 ?
|
||||
NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* High level functions
|
||||
@ -568,7 +853,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) )
|
||||
{
|
||||
@ -1029,6 +1315,178 @@ NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
|
||||
NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
NTSTATUS pdb_default_find_alias(struct pdb_methods *methods,
|
||||
const char *name, DOM_SID *sid)
|
||||
{
|
||||
GROUP_MAP map;
|
||||
|
||||
if (!pdb_getgrnam(&map, name))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
if ((map.sid_name_use != SID_NAME_WKN_GRP) &&
|
||||
(map.sid_name_use != SID_NAME_ALIAS))
|
||||
return NT_STATUS_OBJECT_TYPE_MISMATCH;
|
||||
|
||||
sid_copy(sid, &map.sid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
|
||||
const char *name, uint32 *rid)
|
||||
{
|
||||
DOM_SID sid;
|
||||
enum SID_NAME_USE type;
|
||||
uint32 new_rid;
|
||||
gid_t gid;
|
||||
|
||||
GROUP_MAP map;
|
||||
|
||||
if (lookup_name(get_global_sam_name(), name, &sid, &type))
|
||||
return NT_STATUS_ALIAS_EXISTS;
|
||||
|
||||
if (!winbind_allocate_rid(&new_rid))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
sid_copy(&sid, get_global_sam_sid());
|
||||
sid_append_rid(&sid, new_rid);
|
||||
|
||||
/* Here we allocate the gid */
|
||||
if (!winbind_sid_to_gid(&gid, &sid)) {
|
||||
DEBUG(0, ("Could not get gid for new RID\n"));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
map.gid = gid;
|
||||
sid_copy(&map.sid, &sid);
|
||||
map.sid_name_use = SID_NAME_ALIAS;
|
||||
fstrcpy(map.nt_name, name);
|
||||
fstrcpy(map.comment, "");
|
||||
|
||||
if (!pdb_add_group_mapping_entry(&map)) {
|
||||
DEBUG(0, ("Could not add group mapping entry for alias %s\n",
|
||||
name));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
*rid = new_rid;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
|
||||
const DOM_SID *sid)
|
||||
{
|
||||
return pdb_delete_group_mapping_entry(*sid) ?
|
||||
NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
NTSTATUS pdb_default_enum_aliases(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
uint32 start_idx, uint32 max_entries,
|
||||
uint32 *num_aliases,
|
||||
struct acct_info **info)
|
||||
{
|
||||
extern DOM_SID global_sid_Builtin;
|
||||
|
||||
GROUP_MAP *map;
|
||||
int i, num_maps;
|
||||
enum SID_NAME_USE type = SID_NAME_UNKNOWN;
|
||||
|
||||
if (sid_compare(sid, get_global_sam_sid()) == 0)
|
||||
type = SID_NAME_ALIAS;
|
||||
|
||||
if (sid_compare(sid, &global_sid_Builtin) == 0)
|
||||
type = SID_NAME_WKN_GRP;
|
||||
|
||||
if (!pdb_enum_group_mapping(type, &map, &num_maps, False) ||
|
||||
(num_maps == 0)) {
|
||||
*num_aliases = 0;
|
||||
*info = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (start_idx > num_maps) {
|
||||
*num_aliases = 0;
|
||||
*info = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*num_aliases = num_maps - start_idx;
|
||||
|
||||
if (*num_aliases > max_entries)
|
||||
*num_aliases = max_entries;
|
||||
|
||||
*info = malloc(sizeof(struct acct_info) * (*num_aliases));
|
||||
|
||||
for (i=0; i<*num_aliases; i++) {
|
||||
fstrcpy((*info)[i].acct_name, map[i+start_idx].nt_name);
|
||||
fstrcpy((*info)[i].acct_desc, map[i+start_idx].comment);
|
||||
sid_peek_rid(&map[i].sid, &(*info)[i+start_idx].rid);
|
||||
}
|
||||
|
||||
done:
|
||||
SAFE_FREE(map);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info)
|
||||
{
|
||||
GROUP_MAP map;
|
||||
|
||||
if (!pdb_getgrsid(&map, *sid))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
fstrcpy(info->acct_name, map.nt_name);
|
||||
fstrcpy(info->acct_desc, map.comment);
|
||||
sid_peek_rid(&map.sid, &info->rid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info)
|
||||
{
|
||||
GROUP_MAP map;
|
||||
|
||||
if (!pdb_getgrsid(&map, *sid))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
fstrcpy(map.comment, info->acct_desc);
|
||||
|
||||
if (!pdb_update_group_mapping_entry(&map))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
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
|
||||
*********************************************************************/
|
||||
|
@ -366,13 +366,6 @@ typedef struct
|
||||
|
||||
} rid_name;
|
||||
|
||||
struct acct_info
|
||||
{
|
||||
fstring acct_name; /* account name */
|
||||
fstring acct_desc; /* account name */
|
||||
uint32 rid; /* domain-relative RID */
|
||||
};
|
||||
|
||||
/*
|
||||
* higher order functions for use with msrpc client code
|
||||
*/
|
||||
|
@ -223,6 +223,12 @@ typedef struct sam_group {
|
||||
|
||||
} SAM_GROUP;
|
||||
|
||||
struct acct_info
|
||||
{
|
||||
fstring acct_name; /* account name */
|
||||
fstring acct_desc; /* account name */
|
||||
uint32 rid; /* domain-relative RID */
|
||||
};
|
||||
|
||||
/*****************************************************************
|
||||
Functions to be implemented by the new (v2) passdb API
|
||||
@ -233,7 +239,7 @@ typedef struct sam_group {
|
||||
* this SAMBA will load. Increment this if *ANY* changes are made to the interface.
|
||||
*/
|
||||
|
||||
#define PASSDB_INTERFACE_VERSION 4
|
||||
#define PASSDB_INTERFACE_VERSION 5
|
||||
|
||||
typedef struct pdb_context
|
||||
{
|
||||
@ -279,6 +285,46 @@ typedef struct pdb_context
|
||||
GROUP_MAP **rmap, int *num_entries,
|
||||
BOOL unix_only);
|
||||
|
||||
NTSTATUS (*pdb_find_alias)(struct pdb_context *context,
|
||||
const char *name, DOM_SID *sid);
|
||||
|
||||
NTSTATUS (*pdb_create_alias)(struct pdb_context *context,
|
||||
const char *name, uint32 *rid);
|
||||
|
||||
NTSTATUS (*pdb_delete_alias)(struct pdb_context *context,
|
||||
const DOM_SID *sid);
|
||||
|
||||
NTSTATUS (*pdb_enum_aliases)(struct pdb_context *context,
|
||||
const DOM_SID *domain_sid,
|
||||
uint32 start_idx, uint32 num_entries,
|
||||
uint32 *num_aliases,
|
||||
struct acct_info **aliases);
|
||||
|
||||
NTSTATUS (*pdb_get_aliasinfo)(struct pdb_context *context,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info);
|
||||
|
||||
NTSTATUS (*pdb_set_aliasinfo)(struct pdb_context *context,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info);
|
||||
|
||||
NTSTATUS (*pdb_add_aliasmem)(struct pdb_context *context,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member);
|
||||
|
||||
NTSTATUS (*pdb_del_aliasmem)(struct pdb_context *context,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member);
|
||||
|
||||
NTSTATUS (*pdb_enum_aliasmem)(struct pdb_context *context,
|
||||
const DOM_SID *alias,
|
||||
DOM_SID **members, int *num_members);
|
||||
|
||||
NTSTATUS (*pdb_enum_alias_memberships)(struct pdb_context *context,
|
||||
const DOM_SID *alias,
|
||||
DOM_SID **aliases,
|
||||
int *num);
|
||||
|
||||
void (*free_fn)(struct pdb_context **);
|
||||
|
||||
TALLOC_CTX *mem_ctx;
|
||||
@ -330,6 +376,39 @@ typedef struct pdb_methods
|
||||
GROUP_MAP **rmap, int *num_entries,
|
||||
BOOL unix_only);
|
||||
|
||||
NTSTATUS (*find_alias)(struct pdb_methods *methods,
|
||||
const char *name, DOM_SID *sid);
|
||||
|
||||
NTSTATUS (*create_alias)(struct pdb_methods *methods,
|
||||
const char *name, uint32 *rid);
|
||||
|
||||
NTSTATUS (*delete_alias)(struct pdb_methods *methods,
|
||||
const DOM_SID *sid);
|
||||
|
||||
NTSTATUS (*enum_aliases)(struct pdb_methods *methods,
|
||||
const DOM_SID *domain_sid,
|
||||
uint32 start_idx, uint32 max_entries,
|
||||
uint32 *num_aliases, struct acct_info **info);
|
||||
|
||||
NTSTATUS (*get_aliasinfo)(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info);
|
||||
|
||||
NTSTATUS (*set_aliasinfo)(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info);
|
||||
|
||||
NTSTATUS (*add_aliasmem)(struct pdb_methods *methods,
|
||||
const DOM_SID *alias, const DOM_SID *member);
|
||||
NTSTATUS (*del_aliasmem)(struct pdb_methods *methods,
|
||||
const DOM_SID *alias, const DOM_SID *member);
|
||||
NTSTATUS (*enum_aliasmem)(struct pdb_methods *methods,
|
||||
const DOM_SID *alias, DOM_SID **members,
|
||||
int *num_members);
|
||||
NTSTATUS (*enum_alias_memberships)(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
DOM_SID **aliases, int *num);
|
||||
|
||||
void *private_data; /* Private data of some kind */
|
||||
|
||||
void (*free_private_data)(void **);
|
||||
|
@ -49,6 +49,7 @@
|
||||
#define LDAP_ATTRIBUTE_SID "sambaSID"
|
||||
#define LDAP_ATTRIBUTE_UIDNUMBER "uidNumber"
|
||||
#define LDAP_ATTRIBUTE_GIDNUMBER "gidNumber"
|
||||
#define LDAP_ATTRIBUTE_SID_LIST "sambaSIDList"
|
||||
|
||||
/* attribute map table indexes */
|
||||
|
||||
@ -93,6 +94,8 @@
|
||||
#define LDAP_ATTR_MUNGED_DIAL 37
|
||||
#define LDAP_ATTR_BAD_PASSWORD_TIME 38
|
||||
|
||||
#define LDAP_ATTR_SID_LIST 40
|
||||
|
||||
typedef struct _attrib_map_entry {
|
||||
int attrib;
|
||||
const char *name;
|
||||
|
@ -122,6 +122,7 @@ ATTRIB_MAP_ENTRY groupmap_attr_list[] = {
|
||||
{ LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER},
|
||||
{ LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID },
|
||||
{ LDAP_ATTR_GROUP_TYPE, "sambaGroupType" },
|
||||
{ LDAP_ATTR_SID_LIST, "sambaSIDList" },
|
||||
{ LDAP_ATTR_DESC, "description" },
|
||||
{ LDAP_ATTR_DISPLAY_NAME, "displayName" },
|
||||
{ LDAP_ATTR_CN, "cn" },
|
||||
@ -134,6 +135,7 @@ ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = {
|
||||
{ LDAP_ATTR_GROUP_TYPE, "sambaGroupType" },
|
||||
{ LDAP_ATTR_DESC, "description" },
|
||||
{ LDAP_ATTR_DISPLAY_NAME, "displayName" },
|
||||
{ LDAP_ATTR_SID_LIST, "sambaSIDList" },
|
||||
{ LDAP_ATTR_LIST_END, NULL }
|
||||
};
|
||||
|
||||
|
@ -2038,3 +2038,21 @@ SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void string_append(char **left, const char *right)
|
||||
{
|
||||
int new_len = strlen(right) + 1;
|
||||
|
||||
if (*left == NULL) {
|
||||
*left = malloc(new_len);
|
||||
*left[0] = '\0';
|
||||
} else {
|
||||
new_len += strlen(*left);
|
||||
*left = Realloc(*left, new_len);
|
||||
}
|
||||
|
||||
if (*left == NULL)
|
||||
return;
|
||||
|
||||
safe_strcat(*left, right, new_len-1);
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ smbc_parse_path(SMBCCTX *context,
|
||||
p += 2; /* Skip the double slash */
|
||||
|
||||
/* See if any options were specified */
|
||||
if (q = strrchr(p, '?')) {
|
||||
if ( (q = strrchr(p, '?')) != NULL ) {
|
||||
/* There are options. Null terminate here and point to them */
|
||||
*q++ = '\0';
|
||||
|
||||
@ -537,9 +537,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
|
||||
SMBCSRV *srv=NULL;
|
||||
struct cli_state c;
|
||||
struct nmb_name called, calling;
|
||||
char *p;
|
||||
const char *server_n = server;
|
||||
fstring group;
|
||||
pstring ipenv;
|
||||
struct in_addr ip;
|
||||
int tried_reverse = 0;
|
||||
|
@ -235,6 +235,30 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
|
||||
return (result == NSS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
BOOL winbind_allocate_rid(uint32 *rid)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
int result;
|
||||
|
||||
/* Initialise request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
/* Make request */
|
||||
|
||||
result = winbindd_request(WINBINDD_ALLOCATE_RID, &request, &response);
|
||||
|
||||
if (result != NSS_STATUS_SUCCESS)
|
||||
return False;
|
||||
|
||||
/* Copy out result */
|
||||
*rid = response.data.rid;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Fetch the list of groups a user is a member of from winbindd. This is
|
||||
used by winbind_getgroups. */
|
||||
|
||||
|
@ -436,6 +436,18 @@ static BOOL wbinfo_sid_to_gid(char *sid)
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL wbinfo_allocate_rid(void)
|
||||
{
|
||||
uint32 rid;
|
||||
|
||||
if (!winbind_allocate_rid(&rid))
|
||||
return False;
|
||||
|
||||
d_printf("New rid: %d\n", rid);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Convert sid to string */
|
||||
|
||||
static BOOL wbinfo_lookupsid(char *sid)
|
||||
@ -1042,6 +1054,7 @@ int main(int argc, char **argv)
|
||||
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
|
||||
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
|
||||
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
|
||||
{ "allocate-rid", 'A', POPT_ARG_NONE, 0, 'A', "Get a new RID out of idmap" },
|
||||
{ "create-user", 'c', POPT_ARG_STRING, &string_arg, 'c', "Create a local user account", "name" },
|
||||
{ "delete-user", 'x', POPT_ARG_STRING, &string_arg, 'x', "Delete a local user account", "name" },
|
||||
{ "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" },
|
||||
@ -1164,6 +1177,12 @@ int main(int argc, char **argv)
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
if (!wbinfo_allocate_rid()) {
|
||||
d_printf("Could not allocate a RID\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (!wbinfo_check_secret()) {
|
||||
d_printf("Could not check secret\n");
|
||||
|
@ -255,6 +255,7 @@ static struct dispatch_table dispatch_table[] = {
|
||||
{ WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
|
||||
{ WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
|
||||
{ WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
|
||||
{ WINBINDD_ALLOCATE_RID, winbindd_allocate_rid, "ALLOCATE_RID" },
|
||||
|
||||
/* Miscellaneous */
|
||||
|
||||
|
@ -97,6 +97,7 @@ struct winbindd_domain {
|
||||
BOOL native_mode; /* is this a win2k domain in native mode ? */
|
||||
BOOL active_directory; /* is this a win2k active directory ? */
|
||||
BOOL primary; /* is this our primary domain ? */
|
||||
BOOL internal; /* BUILTIN and member SAM */
|
||||
|
||||
/* Lookup methods for this domain (LDAP or RPC) */
|
||||
struct winbindd_methods *methods;
|
||||
|
@ -106,6 +106,15 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
|
||||
DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid)));
|
||||
|
||||
*num_gr_mem = 0;
|
||||
|
||||
/* HACK ALERT!! This whole routine does not cope with group members
|
||||
* from more than one domain, ie aliases. Thus we have to work it out
|
||||
* ourselves in a special routine. */
|
||||
|
||||
if (domain->internal)
|
||||
return fill_passdb_alias_grmem(domain, group_sid,
|
||||
num_gr_mem,
|
||||
gr_mem, gr_mem_len);
|
||||
|
||||
if ( !((group_name_type==SID_NAME_DOM_GRP) ||
|
||||
((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
|
||||
@ -243,14 +252,11 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
|
||||
/* if no domain or our local domain, then do a local tdb search */
|
||||
|
||||
if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
|
||||
if ( (!*name_domain || strequal(name_domain, get_global_sam_name())) &&
|
||||
((grp = wb_getgrnam(name_group)) != NULL) ) {
|
||||
|
||||
char *buffer = NULL;
|
||||
|
||||
if ( !(grp=wb_getgrnam(name_group)) ) {
|
||||
DEBUG(5,("winbindd_getgrnam: lookup for %s\\%s failed\n",
|
||||
name_domain, name_group));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) );
|
||||
|
||||
gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem );
|
||||
@ -262,6 +268,13 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
/* if no domain or our local domain and no local tdb group, default to
|
||||
* our local domain for aliases */
|
||||
|
||||
if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
|
||||
fstrcpy(name_domain, get_global_sam_name());
|
||||
}
|
||||
|
||||
/* Get info for the domain */
|
||||
|
||||
if ((domain = find_domain_from_name(name_domain)) == NULL) {
|
||||
@ -287,7 +300,8 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
}
|
||||
|
||||
if ( !((name_type==SID_NAME_DOM_GRP) ||
|
||||
((name_type==SID_NAME_ALIAS) && domain->primary)) )
|
||||
((name_type==SID_NAME_ALIAS) && domain->primary) ||
|
||||
((name_type==SID_NAME_ALIAS) && domain->internal)) )
|
||||
{
|
||||
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
|
||||
name_group, name_type));
|
||||
@ -378,7 +392,8 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
|
||||
}
|
||||
|
||||
if ( !((name_type==SID_NAME_DOM_GRP) ||
|
||||
((name_type==SID_NAME_ALIAS) && domain->primary) ))
|
||||
((name_type==SID_NAME_ALIAS) && domain->primary) ||
|
||||
((name_type==SID_NAME_ALIAS) && domain->internal)) )
|
||||
{
|
||||
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
|
||||
group_name, name_type));
|
||||
@ -541,8 +556,8 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
|
||||
/* get the domain local groups if we are a member of a native win2k domain
|
||||
and are not using LDAP to get the groups */
|
||||
|
||||
if ( lp_security() != SEC_ADS && domain->native_mode
|
||||
&& domain->primary )
|
||||
if ( ( lp_security() != SEC_ADS && domain->native_mode
|
||||
&& domain->primary) || domain->internal )
|
||||
{
|
||||
DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
|
||||
|
||||
@ -898,6 +913,61 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((*num) >= groups_max())
|
||||
return;
|
||||
|
||||
for (i=0; i<*num; i++) {
|
||||
if ((*gids)[i] == gid)
|
||||
return;
|
||||
}
|
||||
|
||||
*gids = Realloc(*gids, (*num+1) * sizeof(gid_t));
|
||||
|
||||
if (*gids == NULL)
|
||||
return;
|
||||
|
||||
(*gids)[*num] = gid;
|
||||
*num += 1;
|
||||
}
|
||||
|
||||
static void add_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num)
|
||||
{
|
||||
gid_t gid;
|
||||
DOM_SID *aliases;
|
||||
int j, num_aliases;
|
||||
|
||||
DEBUG(10, ("Adding gids from SID: %s\n", sid_string_static(sid)));
|
||||
|
||||
if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &gid, 0)))
|
||||
add_gid_to_array_unique(gid, gids, num);
|
||||
|
||||
/* Don't expand aliases if not explicitly activated -- for now */
|
||||
/* we don't support windows local nested groups if we are a DC.
|
||||
refer to to sid_to_gid() in the smbd server code to see why
|
||||
-- jerry */
|
||||
|
||||
if (!lp_winbind_nested_groups() || IS_DC)
|
||||
return;
|
||||
|
||||
/* Add nested group memberships */
|
||||
|
||||
if (!pdb_enum_alias_memberships(sid, &aliases, &num_aliases))
|
||||
return;
|
||||
|
||||
for (j=0; j<num_aliases; j++) {
|
||||
|
||||
if (!NT_STATUS_IS_OK(sid_to_gid(&aliases[j], &gid)))
|
||||
continue;
|
||||
|
||||
add_gid_to_array_unique(gid, gids, num);
|
||||
}
|
||||
SAFE_FREE(aliases);
|
||||
}
|
||||
|
||||
/* Get user supplementary groups. This is much quicker than trying to
|
||||
invert the groups database. We merge the groups from the gids and
|
||||
other_sids info3 fields as trusted domain, universal group
|
||||
@ -915,7 +985,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
DOM_SID **user_grpsids;
|
||||
struct winbindd_domain *domain;
|
||||
enum winbindd_result result = WINBINDD_ERROR;
|
||||
gid_t *gid_list;
|
||||
gid_t *gid_list = NULL;
|
||||
unsigned int i;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
NET_USER_INFO_3 *info3 = NULL;
|
||||
@ -963,6 +1033,8 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
goto done;
|
||||
}
|
||||
|
||||
add_gids_from_sid(&user_sid, &gid_list, &num_gids);
|
||||
|
||||
/* Treat the info3 cache as authoritative as the
|
||||
lookup_usergroups() function may return cached data. */
|
||||
|
||||
@ -972,7 +1044,6 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
info3->num_groups2, info3->num_other_sids));
|
||||
|
||||
num_groups = info3->num_other_sids + info3->num_groups2;
|
||||
gid_list = calloc(sizeof(gid_t), num_groups);
|
||||
|
||||
/* Go through each other sid and convert it to a gid */
|
||||
|
||||
@ -1006,23 +1077,11 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Map to a gid */
|
||||
add_gids_from_sid(&info3->other_sids[i].sid,
|
||||
&gid_list, &num_gids);
|
||||
|
||||
if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&info3->other_sids[i].sid, &gid_list[num_gids], 0)) )
|
||||
{
|
||||
DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
|
||||
sid_string_static(&info3->other_sids[i].sid)));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We've jumped through a lot of hoops to get here */
|
||||
|
||||
DEBUG(10, ("winbindd_getgroups: mapped other sid %s to "
|
||||
"gid %lu\n", sid_string_static(
|
||||
&info3->other_sids[i].sid),
|
||||
(unsigned long)gid_list[num_gids]));
|
||||
|
||||
num_gids++;
|
||||
if (gid_list == NULL)
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < info3->num_groups2; i++) {
|
||||
@ -1032,12 +1091,10 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
sid_copy( &group_sid, &domain->sid );
|
||||
sid_append_rid( &group_sid, info3->gids[i].g_rid );
|
||||
|
||||
if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid_list[num_gids], 0)) ) {
|
||||
DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
|
||||
sid_string_static(&group_sid)));
|
||||
}
|
||||
add_gids_from_sid(&group_sid, &gid_list, &num_gids);
|
||||
|
||||
num_gids++;
|
||||
if (gid_list == NULL)
|
||||
goto done;
|
||||
}
|
||||
|
||||
SAFE_FREE(info3);
|
||||
@ -1049,18 +1106,15 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
goto done;
|
||||
|
||||
gid_list = malloc(sizeof(gid_t) * num_groups);
|
||||
|
||||
if (state->response.extra_data)
|
||||
goto done;
|
||||
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
if (!NT_STATUS_IS_OK(idmap_sid_to_gid(user_grpsids[i], &gid_list[num_gids], 0))) {
|
||||
DEBUG(1, ("unable to convert group sid %s to gid\n",
|
||||
sid_string_static(user_grpsids[i])));
|
||||
continue;
|
||||
}
|
||||
num_gids++;
|
||||
add_gids_from_sid(user_grpsids[i],
|
||||
&gid_list, &num_gids);
|
||||
|
||||
if (gid_list == NULL)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ enum winbindd_cmd {
|
||||
WINBINDD_SID_TO_GID,
|
||||
WINBINDD_UID_TO_SID,
|
||||
WINBINDD_GID_TO_SID,
|
||||
WINBINDD_ALLOCATE_RID,
|
||||
|
||||
/* Miscellaneous other stuff */
|
||||
|
||||
@ -270,7 +271,7 @@ struct winbindd_response {
|
||||
char user_session_key[16];
|
||||
char first_8_lm_hash[8];
|
||||
} auth;
|
||||
uint32 rid; /* create user or group */
|
||||
uint32 rid; /* create user or group or allocate rid */
|
||||
struct {
|
||||
fstring name;
|
||||
fstring alt_name;
|
||||
|
339
source3/nsswitch/winbindd_passdb.c
Normal file
339
source3/nsswitch/winbindd_passdb.c
Normal file
@ -0,0 +1,339 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Winbind rpc backend functions
|
||||
|
||||
Copyright (C) Tim Potter 2000-2001,2003
|
||||
Copyright (C) Simo Sorce 2003
|
||||
Copyright (C) Volker Lendecke 2004
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
|
||||
static void
|
||||
add_member(const char *domain, const char *user,
|
||||
char **members, int *num_members)
|
||||
{
|
||||
fstring name;
|
||||
|
||||
fill_domain_username(name, domain, user);
|
||||
safe_strcat(name, ",", sizeof(name)-1);
|
||||
string_append(members, name);
|
||||
*num_members += 1;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Add member users resulting from sid. Expand if it is a domain group.
|
||||
**********************************************************************/
|
||||
|
||||
static void
|
||||
add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
|
||||
{
|
||||
DOM_SID dom_sid;
|
||||
uint32 rid;
|
||||
struct winbindd_domain *domain;
|
||||
int i;
|
||||
|
||||
char *name = NULL;
|
||||
enum SID_NAME_USE type;
|
||||
|
||||
uint32 num_names;
|
||||
DOM_SID **sid_mem;
|
||||
char **names;
|
||||
uint32 *types;
|
||||
|
||||
NTSTATUS result;
|
||||
|
||||
TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
|
||||
|
||||
if (mem_ctx == NULL) {
|
||||
DEBUG(1, ("talloc_init failed\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
sid_copy(&dom_sid, sid);
|
||||
sid_split_rid(&dom_sid, &rid);
|
||||
|
||||
domain = find_domain_from_sid(&dom_sid);
|
||||
|
||||
if (domain == NULL) {
|
||||
DEBUG(3, ("Could not find domain for sid %s\n",
|
||||
sid_string_static(sid)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = domain->methods->sid_to_name(domain, mem_ctx, sid,
|
||||
&name, &type);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
DEBUG(3, ("sid_to_name failed for sid %s\n",
|
||||
sid_string_static(sid)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(10, ("Found name %s, type %d\n", name, type));
|
||||
|
||||
if (type == SID_NAME_USER) {
|
||||
add_member(domain->name, name, members, num_members);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (type != SID_NAME_DOM_GRP) {
|
||||
DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
|
||||
name));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Expand the domain group */
|
||||
|
||||
result = domain->methods->lookup_groupmem(domain, mem_ctx,
|
||||
sid, &num_names,
|
||||
&sid_mem, &names,
|
||||
&types);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
DEBUG(10, ("Could not lookup group members for %s: %s\n",
|
||||
name, nt_errstr(result)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i=0; i<num_names; i++) {
|
||||
DEBUG(10, ("Adding group member SID %s\n",
|
||||
sid_string_static(sid_mem[i])));
|
||||
|
||||
if (types[i] != SID_NAME_USER) {
|
||||
DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
|
||||
"Ignoring.\n", names[i], name));
|
||||
continue;
|
||||
}
|
||||
|
||||
add_member(domain->name, names[i], members, num_members);
|
||||
}
|
||||
|
||||
done:
|
||||
talloc_destroy(mem_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
|
||||
DOM_SID *group_sid,
|
||||
int *num_gr_mem, char **gr_mem, int *gr_mem_len)
|
||||
{
|
||||
DOM_SID *members;
|
||||
int i, num_members;
|
||||
|
||||
*num_gr_mem = 0;
|
||||
*gr_mem = NULL;
|
||||
*gr_mem_len = 0;
|
||||
|
||||
if (!pdb_enum_aliasmem(group_sid, &members, &num_members))
|
||||
return True;
|
||||
|
||||
for (i=0; i<num_members; i++) {
|
||||
add_expanded_sid(&members[i], gr_mem, num_gr_mem);
|
||||
}
|
||||
|
||||
SAFE_FREE(members);
|
||||
|
||||
if (*gr_mem != NULL) {
|
||||
int len;
|
||||
|
||||
/* We have at least one member, strip off the last "," */
|
||||
len = strlen(*gr_mem);
|
||||
(*gr_mem)[len-1] = '\0';
|
||||
*gr_mem_len = len;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Query display info for a domain. This returns enough information plus a
|
||||
bit extra to give an overview of domain users for the User Manager
|
||||
application. */
|
||||
static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_entries,
|
||||
WINBIND_USERINFO **info)
|
||||
{
|
||||
/* We don't have users */
|
||||
*num_entries = 0;
|
||||
*info = NULL;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* list all domain groups */
|
||||
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_entries,
|
||||
struct acct_info **info)
|
||||
{
|
||||
/* We don't have domain groups */
|
||||
*num_entries = 0;
|
||||
*info = NULL;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* List all domain groups */
|
||||
|
||||
static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_entries,
|
||||
struct acct_info **info)
|
||||
{
|
||||
struct acct_info *talloced_info;
|
||||
|
||||
/* Hmm. One billion aliases should be enough for a start */
|
||||
|
||||
if (!pdb_enum_aliases(&domain->sid, 0, 1000000000,
|
||||
num_entries, info)) {
|
||||
/* Nothing to report, just exit. */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
talloced_info = (struct acct_info *)
|
||||
talloc_memdup(mem_ctx, *info,
|
||||
*num_entries * sizeof(struct acct_info));
|
||||
|
||||
SAFE_FREE(*info);
|
||||
*info = talloced_info;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* convert a single name to a sid in a domain */
|
||||
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *name,
|
||||
DOM_SID *sid,
|
||||
enum SID_NAME_USE *type)
|
||||
{
|
||||
DEBUG(10, ("Finding name %s\n", name));
|
||||
|
||||
if (!pdb_find_alias(name, sid))
|
||||
return NT_STATUS_NONE_MAPPED;
|
||||
|
||||
*type = SID_NAME_ALIAS;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
convert a domain SID to a user or group name
|
||||
*/
|
||||
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *sid,
|
||||
char **name,
|
||||
enum SID_NAME_USE *type)
|
||||
{
|
||||
struct acct_info info;
|
||||
|
||||
DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
|
||||
|
||||
if (!pdb_get_aliasinfo(sid, &info))
|
||||
return NT_STATUS_NONE_MAPPED;
|
||||
|
||||
*name = talloc_strdup(mem_ctx, info.acct_name);
|
||||
*type = SID_NAME_ALIAS;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Lookup user information from a rid or username. */
|
||||
static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *user_sid,
|
||||
WINBIND_USERINFO *user_info)
|
||||
{
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
|
||||
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *user_sid,
|
||||
uint32 *num_groups, DOM_SID ***user_gids)
|
||||
{
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
|
||||
/* Lookup group membership given a rid. */
|
||||
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *group_sid, uint32 *num_names,
|
||||
DOM_SID ***sid_mem, char ***names,
|
||||
uint32 **name_types)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* find the sequence number for a domain */
|
||||
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
{
|
||||
*seq = 1;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* get a list of trusted domains */
|
||||
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_domains,
|
||||
char ***names,
|
||||
char ***alt_names,
|
||||
DOM_SID **dom_sids)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* find the domain sid for a domain */
|
||||
static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
|
||||
{
|
||||
sid_copy(sid, &domain->sid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* find alternate names list for the domain
|
||||
* should we look for netbios aliases??
|
||||
SSS */
|
||||
static NTSTATUS alternate_name(struct winbindd_domain *domain)
|
||||
{
|
||||
DEBUG(3,("pdb: alternate_name\n"));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* the rpc backend methods are exposed via this structure */
|
||||
struct winbindd_methods passdb_methods = {
|
||||
False,
|
||||
query_user_list,
|
||||
enum_dom_groups,
|
||||
enum_local_groups,
|
||||
name_to_sid,
|
||||
sid_to_name,
|
||||
query_user,
|
||||
lookup_usergroups,
|
||||
lookup_groupmem,
|
||||
sequence_number,
|
||||
trusted_domains,
|
||||
domain_sid,
|
||||
alternate_name
|
||||
};
|
@ -30,10 +30,8 @@
|
||||
|
||||
enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
|
||||
{
|
||||
extern DOM_SID global_sid_Builtin;
|
||||
enum SID_NAME_USE type;
|
||||
DOM_SID sid, tmp_sid;
|
||||
uint32 rid;
|
||||
DOM_SID sid;
|
||||
fstring name;
|
||||
fstring dom_name;
|
||||
|
||||
@ -50,15 +48,6 @@ enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Don't look up BUILTIN sids */
|
||||
|
||||
sid_copy(&tmp_sid, &sid);
|
||||
sid_split_rid(&tmp_sid, &rid);
|
||||
|
||||
if (sid_equal(&tmp_sid, &global_sid_Builtin)) {
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Lookup the sid */
|
||||
|
||||
if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) {
|
||||
@ -445,3 +434,23 @@ done:
|
||||
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
enum winbindd_result winbindd_allocate_rid(struct winbindd_cli_state *state)
|
||||
{
|
||||
if ( !state->privileged ) {
|
||||
DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
|
||||
"denied!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* We tell idmap to always allocate a user RID. There might be a good
|
||||
* reason to keep RID allocation for users to even and groups to
|
||||
* odd. This needs discussion I think. For now only allocate user
|
||||
* rids. */
|
||||
|
||||
if (!NT_STATUS_IS_OK(idmap_allocate_rid(&state->response.data.rid,
|
||||
USER_RID_TYPE)))
|
||||
return WINBINDD_ERROR;
|
||||
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
@ -83,6 +83,20 @@ void free_domain_list(void)
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL is_internal_domain(const DOM_SID *sid)
|
||||
{
|
||||
DOM_SID tmp_sid;
|
||||
|
||||
if (sid_equal(sid, get_global_sam_sid()))
|
||||
return True;
|
||||
|
||||
string_to_sid(&tmp_sid, "S-1-5-32");
|
||||
if (sid_equal(sid, &tmp_sid))
|
||||
return True;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
/* Add a trusted domain to our list of domains */
|
||||
static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
|
||||
@ -143,6 +157,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
|
||||
|
||||
domain->methods = methods;
|
||||
domain->backend = NULL;
|
||||
domain->internal = is_internal_domain(sid);
|
||||
domain->sequence_number = DOM_SEQUENCE_NONE;
|
||||
domain->last_seq_check = 0;
|
||||
if (sid) {
|
||||
@ -150,8 +165,9 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
|
||||
}
|
||||
|
||||
/* set flags about native_mode, active_directory */
|
||||
|
||||
set_dc_type_and_flags( domain );
|
||||
|
||||
if (!domain->internal)
|
||||
set_dc_type_and_flags( domain );
|
||||
|
||||
DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
|
||||
domain->active_directory ? "ADS" : "NT4",
|
||||
@ -303,6 +319,29 @@ BOOL init_domain_list(void)
|
||||
|
||||
/* do an initial scan for trusted domains */
|
||||
add_trusted_domains(domain);
|
||||
|
||||
/* Don't expand aliases if not explicitly activated -- for now */
|
||||
/* we don't support windows local nested groups if we are a DC.
|
||||
refer to to sid_to_gid() in the smbd server code to see why
|
||||
-- jerry */
|
||||
|
||||
|
||||
if (lp_winbind_nested_groups() || IS_DC) {
|
||||
|
||||
/* Add our local SAM domains */
|
||||
DOM_SID sid;
|
||||
extern struct winbindd_methods passdb_methods;
|
||||
struct winbindd_domain *dom;
|
||||
|
||||
string_to_sid(&sid, "S-1-5-32");
|
||||
|
||||
dom = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
|
||||
&sid);
|
||||
|
||||
dom = add_trusted_domain(get_global_sam_name(), NULL,
|
||||
&passdb_methods,
|
||||
get_global_sam_sid());
|
||||
}
|
||||
|
||||
/* avoid rescanning this right away */
|
||||
last_trustdom_scan = time(NULL);
|
||||
|
@ -174,6 +174,7 @@ typedef struct
|
||||
BOOL bWinbindEnumGroups;
|
||||
BOOL bWinbindUseDefaultDomain;
|
||||
BOOL bWinbindTrustedDomainsOnly;
|
||||
BOOL bWinbindNestedGroups;
|
||||
char *szWinbindBackend;
|
||||
char *szIdmapBackend;
|
||||
char *szAddShareCommand;
|
||||
@ -1168,6 +1169,7 @@ static struct parm_struct parm_table[] = {
|
||||
{"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED},
|
||||
|
||||
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
|
||||
};
|
||||
@ -1515,6 +1517,7 @@ static void init_globals(void)
|
||||
Globals.bWinbindEnumGroups = True;
|
||||
Globals.bWinbindUseDefaultDomain = False;
|
||||
Globals.bWinbindTrustedDomainsOnly = False;
|
||||
Globals.bWinbindNestedGroups = False;
|
||||
|
||||
Globals.bEnableRidAlgorithm = True;
|
||||
|
||||
@ -1687,6 +1690,7 @@ FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
|
||||
FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
|
||||
FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
|
||||
FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
|
||||
FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
|
||||
|
||||
FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
|
||||
FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm)
|
||||
|
@ -452,6 +452,156 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
|
||||
num_entries, unix_only);
|
||||
}
|
||||
|
||||
static NTSTATUS context_find_alias(struct pdb_context *context,
|
||||
const char *name, DOM_SID *sid)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->find_alias(context->pdb_methods,
|
||||
name, sid);
|
||||
}
|
||||
|
||||
static NTSTATUS context_create_alias(struct pdb_context *context,
|
||||
const char *name, uint32 *rid)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->create_alias(context->pdb_methods,
|
||||
name, rid);
|
||||
}
|
||||
|
||||
static NTSTATUS context_delete_alias(struct pdb_context *context,
|
||||
const DOM_SID *sid)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->delete_alias(context->pdb_methods, sid);
|
||||
}
|
||||
|
||||
static NTSTATUS context_enum_aliases(struct pdb_context *context,
|
||||
const DOM_SID *sid,
|
||||
uint32 start_idx, uint32 max_entries,
|
||||
uint32 *num_aliases,
|
||||
struct acct_info **info)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->enum_aliases(context->pdb_methods,
|
||||
sid, start_idx, max_entries,
|
||||
num_aliases, info);
|
||||
}
|
||||
|
||||
static NTSTATUS context_get_aliasinfo(struct pdb_context *context,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->get_aliasinfo(context->pdb_methods,
|
||||
sid, info);
|
||||
}
|
||||
|
||||
static NTSTATUS context_set_aliasinfo(struct pdb_context *context,
|
||||
const DOM_SID *sid,
|
||||
struct acct_info *info)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->set_aliasinfo(context->pdb_methods,
|
||||
sid, info);
|
||||
}
|
||||
|
||||
static NTSTATUS context_add_aliasmem(struct pdb_context *context,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->add_aliasmem(context->pdb_methods,
|
||||
alias, member);
|
||||
}
|
||||
|
||||
static NTSTATUS context_del_aliasmem(struct pdb_context *context,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->del_aliasmem(context->pdb_methods,
|
||||
alias, member);
|
||||
}
|
||||
|
||||
static NTSTATUS context_enum_aliasmem(struct pdb_context *context,
|
||||
const DOM_SID *alias, DOM_SID **members,
|
||||
int *num)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->enum_aliasmem(context->pdb_methods,
|
||||
alias, members, num);
|
||||
}
|
||||
|
||||
static NTSTATUS context_enum_alias_memberships(struct pdb_context *context,
|
||||
const DOM_SID *sid,
|
||||
DOM_SID **aliases, int *num)
|
||||
{
|
||||
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if ((!context) || (!context->pdb_methods)) {
|
||||
DEBUG(0, ("invalid pdb_context specified!\n"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return context->pdb_methods->
|
||||
enum_alias_memberships(context->pdb_methods, sid, aliases,
|
||||
num);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Free and cleanup a pdb context, any associated data and anything
|
||||
that the attached modules might have associated.
|
||||
@ -568,6 +718,17 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
|
||||
(*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
|
||||
(*context)->pdb_enum_group_mapping = context_enum_group_mapping;
|
||||
|
||||
(*context)->pdb_find_alias = context_find_alias;
|
||||
(*context)->pdb_create_alias = context_create_alias;
|
||||
(*context)->pdb_delete_alias = context_delete_alias;
|
||||
(*context)->pdb_enum_aliases = context_enum_aliases;
|
||||
(*context)->pdb_get_aliasinfo = context_get_aliasinfo;
|
||||
(*context)->pdb_set_aliasinfo = context_set_aliasinfo;
|
||||
(*context)->pdb_add_aliasmem = context_add_aliasmem;
|
||||
(*context)->pdb_del_aliasmem = context_del_aliasmem;
|
||||
(*context)->pdb_enum_aliasmem = context_enum_aliasmem;
|
||||
(*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
|
||||
|
||||
(*context)->free_fn = free_pdb_context;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
@ -850,6 +1011,135 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
|
||||
rmap, num_entries, unix_only));
|
||||
}
|
||||
|
||||
BOOL pdb_find_alias(const char *name, DOM_SID *sid)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->pdb_find_alias(pdb_context,
|
||||
name, sid));
|
||||
}
|
||||
|
||||
BOOL pdb_create_alias(const char *name, uint32 *rid)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->pdb_create_alias(pdb_context,
|
||||
name, rid));
|
||||
}
|
||||
|
||||
BOOL pdb_delete_alias(const DOM_SID *sid)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->pdb_delete_alias(pdb_context,
|
||||
sid));
|
||||
|
||||
}
|
||||
|
||||
BOOL pdb_enum_aliases(const DOM_SID *sid, uint32 start_idx, uint32 max_entries,
|
||||
uint32 *num_aliases, struct acct_info **info)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->pdb_enum_aliases(pdb_context, sid,
|
||||
start_idx,
|
||||
max_entries,
|
||||
num_aliases,
|
||||
info));
|
||||
}
|
||||
|
||||
BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->pdb_get_aliasinfo(pdb_context, sid,
|
||||
info));
|
||||
}
|
||||
|
||||
BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->pdb_set_aliasinfo(pdb_context, sid,
|
||||
info));
|
||||
}
|
||||
|
||||
BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->
|
||||
pdb_add_aliasmem(pdb_context, alias, member));
|
||||
}
|
||||
|
||||
BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->
|
||||
pdb_del_aliasmem(pdb_context, alias, member));
|
||||
}
|
||||
|
||||
BOOL pdb_enum_aliasmem(const DOM_SID *alias,
|
||||
DOM_SID **members, int *num_members)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->
|
||||
pdb_enum_aliasmem(pdb_context, alias,
|
||||
members, num_members));
|
||||
}
|
||||
|
||||
BOOL pdb_enum_alias_memberships(const DOM_SID *sid,
|
||||
DOM_SID **aliases, int *num)
|
||||
{
|
||||
struct pdb_context *pdb_context = pdb_get_static_context(False);
|
||||
|
||||
if (!pdb_context) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return NT_STATUS_IS_OK(pdb_context->
|
||||
pdb_enum_alias_memberships(pdb_context, sid,
|
||||
aliases, num));
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Initialize the static context (at smbd startup etc).
|
||||
|
||||
@ -933,6 +1223,16 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
|
||||
(*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)->find_alias = pdb_default_find_alias;
|
||||
(*methods)->create_alias = pdb_default_create_alias;
|
||||
(*methods)->delete_alias = pdb_default_delete_alias;
|
||||
(*methods)->enum_aliases = pdb_default_enum_aliases;
|
||||
(*methods)->get_aliasinfo = pdb_default_get_aliasinfo;
|
||||
(*methods)->set_aliasinfo = pdb_default_set_aliasinfo;
|
||||
(*methods)->add_aliasmem = pdb_default_add_aliasmem;
|
||||
(*methods)->del_aliasmem = pdb_default_del_aliasmem;
|
||||
(*methods)->enum_aliasmem = pdb_default_enum_aliasmem;
|
||||
(*methods)->enum_alias_memberships = pdb_default_alias_memberships;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -1989,8 +1989,8 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
|
||||
{
|
||||
pstring filter;
|
||||
|
||||
pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
|
||||
LDAP_OBJ_POSIXGROUP,
|
||||
pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))",
|
||||
LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
|
||||
get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
|
||||
(unsigned long)gid);
|
||||
|
||||
@ -2031,6 +2031,37 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
|
||||
|
||||
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
|
||||
|
||||
if ( count == 0 ) {
|
||||
/* There's no posixGroup account, let's try to find an
|
||||
* appropriate idmap entry for aliases */
|
||||
|
||||
pstring suffix;
|
||||
pstring filter;
|
||||
char **attr_list;
|
||||
|
||||
ldap_msgfree(result);
|
||||
|
||||
pstrcpy( suffix, lp_ldap_idmap_suffix() );
|
||||
pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
|
||||
LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
|
||||
map->gid);
|
||||
|
||||
attr_list = get_attr_list( sidmap_attr_list );
|
||||
rc = smbldap_search(ldap_state->smbldap_state, suffix,
|
||||
LDAP_SCOPE_SUBTREE, filter, attr_list,
|
||||
0, &result);
|
||||
|
||||
free_attr_list(attr_list);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
DEBUG(3,("Failure looking up entry (%s)\n",
|
||||
ldap_err2string(rc) ));
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
|
||||
if ( count == 0 ) {
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
@ -2306,6 +2337,254 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member,
|
||||
int modop)
|
||||
{
|
||||
struct ldapsam_privates *ldap_state =
|
||||
(struct ldapsam_privates *)methods->private_data;
|
||||
char *dn;
|
||||
LDAPMessage *result = NULL;
|
||||
LDAPMessage *entry = NULL;
|
||||
int count;
|
||||
LDAPMod **mods = NULL;
|
||||
int rc;
|
||||
|
||||
pstring filter;
|
||||
|
||||
pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
|
||||
LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
|
||||
get_attr_key2string(groupmap_attr_list,
|
||||
LDAP_ATTR_GROUP_SID),
|
||||
sid_string_static(alias));
|
||||
|
||||
if (ldapsam_search_one_group(ldap_state, filter,
|
||||
&result) != LDAP_SUCCESS)
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
|
||||
result);
|
||||
|
||||
if (count < 1) {
|
||||
DEBUG(4, ("ldapsam_add_aliasmem: Did not find alias\n"));
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
|
||||
"count=%d\n", filter, count));
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
|
||||
result);
|
||||
|
||||
if (!entry) {
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
|
||||
if (!dn) {
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
smbldap_set_mod(&mods, modop,
|
||||
get_attr_key2string(groupmap_attr_list,
|
||||
LDAP_ATTR_SID_LIST),
|
||||
sid_string_static(member));
|
||||
|
||||
rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
|
||||
|
||||
ldap_mods_free(mods, True);
|
||||
ldap_msgfree(result);
|
||||
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
char *ld_error = NULL;
|
||||
ldap_get_option(ldap_state->smbldap_state->ldap_struct,
|
||||
LDAP_OPT_ERROR_STRING,&ld_error);
|
||||
|
||||
DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes "
|
||||
"for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
|
||||
ld_error?ld_error:"unknown"));
|
||||
SAFE_FREE(ld_error);
|
||||
SAFE_FREE(dn);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
SAFE_FREE(dn);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member)
|
||||
{
|
||||
return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
|
||||
const DOM_SID *alias,
|
||||
const DOM_SID *member)
|
||||
{
|
||||
return ldapsam_modify_aliasmem(methods, alias, member,
|
||||
LDAP_MOD_DELETE);
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
|
||||
const DOM_SID *alias, DOM_SID **members,
|
||||
int *num_members)
|
||||
{
|
||||
struct ldapsam_privates *ldap_state =
|
||||
(struct ldapsam_privates *)methods->private_data;
|
||||
LDAPMessage *result = NULL;
|
||||
LDAPMessage *entry = NULL;
|
||||
int count;
|
||||
char **values;
|
||||
int i;
|
||||
pstring filter;
|
||||
|
||||
*members = NULL;
|
||||
*num_members = 0;
|
||||
|
||||
pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
|
||||
LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
|
||||
get_attr_key2string(groupmap_attr_list,
|
||||
LDAP_ATTR_GROUP_SID),
|
||||
sid_string_static(alias));
|
||||
|
||||
if (ldapsam_search_one_group(ldap_state, filter,
|
||||
&result) != LDAP_SUCCESS)
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
|
||||
result);
|
||||
|
||||
if (count < 1) {
|
||||
DEBUG(4, ("ldapsam_add_aliasmem: Did not find alias\n"));
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
|
||||
"count=%d\n", filter, count));
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
|
||||
result);
|
||||
|
||||
if (!entry) {
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
values = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
|
||||
entry,
|
||||
get_attr_key2string(groupmap_attr_list,
|
||||
LDAP_ATTR_SID_LIST));
|
||||
|
||||
if (values == NULL) {
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
count = ldap_count_values(values);
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
DOM_SID member;
|
||||
|
||||
if (!string_to_sid(&member, values[i]))
|
||||
continue;
|
||||
|
||||
add_sid_to_array(&member, members, num_members);
|
||||
}
|
||||
|
||||
ldap_value_free(values);
|
||||
ldap_msgfree(result);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
|
||||
const DOM_SID *sid,
|
||||
DOM_SID **aliases, int *num)
|
||||
{
|
||||
struct ldapsam_privates *ldap_state =
|
||||
(struct ldapsam_privates *)methods->private_data;
|
||||
|
||||
fstring sid_string;
|
||||
const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
|
||||
|
||||
LDAPMessage *result = NULL;
|
||||
LDAPMessage *entry = NULL;
|
||||
int count;
|
||||
int rc;
|
||||
pstring filter;
|
||||
|
||||
sid_to_string(sid_string, sid);
|
||||
pstr_sprintf(filter, "(&(|(objectclass=%s)(objectclass=%s))(%s=%s))",
|
||||
LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
|
||||
get_attr_key2string(groupmap_attr_list,
|
||||
LDAP_ATTR_SID_LIST), sid_string);
|
||||
|
||||
rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
|
||||
LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
|
||||
|
||||
if (rc != LDAP_SUCCESS)
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
*aliases = NULL;
|
||||
*num = 0;
|
||||
|
||||
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
|
||||
result);
|
||||
|
||||
if (count < 1) {
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
for (entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
|
||||
result);
|
||||
entry != NULL;
|
||||
entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
|
||||
entry))
|
||||
{
|
||||
DOM_SID alias;
|
||||
char **vals;
|
||||
vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
|
||||
entry, LDAP_ATTRIBUTE_SID);
|
||||
|
||||
if (vals == NULL)
|
||||
continue;
|
||||
|
||||
if (vals[0] == NULL) {
|
||||
ldap_value_free(vals);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string_to_sid(&alias, vals[0])) {
|
||||
ldap_value_free(vals);
|
||||
continue;
|
||||
}
|
||||
|
||||
add_sid_to_array(&alias, aliases, num);
|
||||
ldap_value_free(vals);
|
||||
}
|
||||
|
||||
ldap_msgfree(result);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Housekeeping
|
||||
*********************************************************************/
|
||||
@ -2444,6 +2723,11 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
|
||||
|
||||
(*pdb_method)->name = "ldapsam";
|
||||
|
||||
(*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
|
||||
(*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
|
||||
(*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
|
||||
(*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
|
||||
|
||||
ldap_state = (*pdb_method)->private_data;
|
||||
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
|
||||
|
||||
|
@ -305,3 +305,16 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num)
|
||||
{
|
||||
*sids = Realloc(*sids, ((*num)+1) * sizeof(DOM_SID));
|
||||
|
||||
if (*sids == NULL)
|
||||
return;
|
||||
|
||||
sid_copy(&((*sids)[*num]), sid);
|
||||
*num += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -171,6 +171,11 @@ static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
|
||||
status = lookup_name(dom_name, user, &sid, &name_type);
|
||||
}
|
||||
|
||||
if (name_type == SID_NAME_WKN_GRP) {
|
||||
/* BUILTIN aliases are still aliases :-) */
|
||||
name_type = SID_NAME_ALIAS;
|
||||
}
|
||||
|
||||
DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" :
|
||||
"not found"));
|
||||
|
||||
|
@ -879,7 +879,7 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST
|
||||
Get the group entries - similar to get_sampwd_entries().
|
||||
******************************************************************/
|
||||
|
||||
static NTSTATUS get_group_entries( enum SID_NAME_USE type, TALLOC_CTX *ctx,
|
||||
static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx,
|
||||
DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
|
||||
uint32 *p_num_entries, uint32 max_entries )
|
||||
{
|
||||
@ -894,7 +894,8 @@ static NTSTATUS get_group_entries( enum SID_NAME_USE type, TALLOC_CTX *ctx,
|
||||
needed for some passdb backends to enumerate groups */
|
||||
|
||||
become_root();
|
||||
pdb_enum_group_mapping(type, &map, (int *)&group_entries, ENUM_ONLY_MAPPED);
|
||||
pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries,
|
||||
ENUM_ONLY_MAPPED);
|
||||
unbecome_root();
|
||||
|
||||
num_entries=group_entries-start_idx;
|
||||
@ -915,51 +916,57 @@ static NTSTATUS get_group_entries( enum SID_NAME_USE type, TALLOC_CTX *ctx,
|
||||
fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
|
||||
fstrcpy((*d_grp)[i].comment, map[i+start_idx].comment);
|
||||
sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
|
||||
(*d_grp)[i].attr=type;
|
||||
(*d_grp)[i].attr=SID_NAME_DOM_GRP;
|
||||
}
|
||||
|
||||
SAFE_FREE(map);
|
||||
|
||||
*p_num_entries = num_entries;
|
||||
|
||||
DEBUG(10,("get_group_entries: returning %d entries\n", *p_num_entries));
|
||||
DEBUG(10,("get_group_domain_entries: returning %d entries\n",
|
||||
*p_num_entries));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Wrapper for enuemrating domain groups
|
||||
******************************************************************/
|
||||
|
||||
static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
|
||||
DOM_SID *sid, uint32 start_idx,
|
||||
uint32 *p_num_entries, uint32 max_entries )
|
||||
{
|
||||
return get_group_entries( SID_NAME_DOM_GRP, ctx, d_grp, sid, start_idx,
|
||||
p_num_entries, max_entries );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Wrapper for enumerating local groups
|
||||
******************************************************************/
|
||||
|
||||
static NTSTATUS get_group_alias_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
|
||||
DOM_SID *sid, uint32 start_idx,
|
||||
uint32 *p_num_entries, uint32 max_entries)
|
||||
static NTSTATUS get_alias_entries( TALLOC_CTX *ctx, DOMAIN_GRP **d_grp,
|
||||
const DOM_SID *sid, uint32 start_idx,
|
||||
uint32 *p_num_entries, uint32 max_entries )
|
||||
{
|
||||
if ( sid_equal(sid, &global_sid_Builtin) ) {
|
||||
return get_group_entries( SID_NAME_WKN_GRP, ctx, d_grp,
|
||||
sid, start_idx, p_num_entries, max_entries );
|
||||
}
|
||||
else if ( sid_equal(sid, get_global_sam_sid()) ) {
|
||||
return get_group_entries( SID_NAME_ALIAS, ctx, d_grp,
|
||||
sid, start_idx, p_num_entries, max_entries );
|
||||
struct acct_info *info;
|
||||
int i;
|
||||
BOOL res;
|
||||
|
||||
become_root();
|
||||
res = pdb_enum_aliases(sid, start_idx, max_entries,
|
||||
p_num_entries, &info);
|
||||
unbecome_root();
|
||||
|
||||
if (!res)
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
if (*p_num_entries == 0)
|
||||
return NT_STATUS_OK;
|
||||
|
||||
*d_grp = talloc(ctx, sizeof(DOMAIN_GRP) * (*p_num_entries));
|
||||
|
||||
if (*d_grp == NULL) {
|
||||
SAFE_FREE(info);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* can't do anything with this SID */
|
||||
|
||||
*p_num_entries = 0;
|
||||
for (i=0; i<*p_num_entries; i++) {
|
||||
fstrcpy((*d_grp)[i].name, info[i].acct_name);
|
||||
fstrcpy((*d_grp)[i].comment, info[i].acct_desc);
|
||||
(*d_grp)[i].rid = info[i].rid;
|
||||
(*d_grp)[i].attr = SID_NAME_ALIAS;
|
||||
}
|
||||
|
||||
SAFE_FREE(info);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -1025,9 +1032,9 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S
|
||||
sid_to_string(sid_str, &sid);
|
||||
DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
|
||||
|
||||
status = get_group_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx,
|
||||
&num_entries, MAX_SAM_ENTRIES);
|
||||
if (NT_STATUS_IS_ERR(status)) return status;
|
||||
status = get_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx,
|
||||
&num_entries, MAX_SAM_ENTRIES);
|
||||
if (!NT_STATUS_IS_OK(status)) return status;
|
||||
|
||||
make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp);
|
||||
|
||||
@ -1244,7 +1251,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
|
||||
NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u)
|
||||
{
|
||||
DOM_SID sid;
|
||||
GROUP_MAP map;
|
||||
struct acct_info info;
|
||||
uint32 acc_granted;
|
||||
BOOL ret;
|
||||
|
||||
@ -1259,12 +1266,8 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM
|
||||
return r_u->status;
|
||||
}
|
||||
|
||||
if (!sid_check_is_in_our_domain(&sid) &&
|
||||
!sid_check_is_in_builtin(&sid))
|
||||
return NT_STATUS_OBJECT_TYPE_MISMATCH;
|
||||
|
||||
become_root();
|
||||
ret = pdb_getgrsid(&map, sid);
|
||||
ret = pdb_get_aliasinfo(&sid, &info);
|
||||
unbecome_root();
|
||||
|
||||
if ( !ret )
|
||||
@ -1274,12 +1277,13 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM
|
||||
case 1:
|
||||
r_u->ptr = 1;
|
||||
r_u->ctr.switch_value1 = 1;
|
||||
init_samr_alias_info1(&r_u->ctr.alias.info1, map.nt_name, 1, map.comment);
|
||||
init_samr_alias_info1(&r_u->ctr.alias.info1,
|
||||
info.acct_name, 1, info.acct_desc);
|
||||
break;
|
||||
case 3:
|
||||
r_u->ptr = 1;
|
||||
r_u->ctr.switch_value1 = 3;
|
||||
init_samr_alias_info3(&r_u->ctr.alias.info3, map.comment);
|
||||
init_samr_alias_info3(&r_u->ctr.alias.info3, info.acct_desc);
|
||||
break;
|
||||
default:
|
||||
return NT_STATUS_INVALID_INFO_CLASS;
|
||||
@ -3191,15 +3195,11 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
|
||||
{
|
||||
int i;
|
||||
|
||||
GROUP_MAP map;
|
||||
int num_sids = 0;
|
||||
DOM_SID2 *sid;
|
||||
DOM_SID *sids=NULL;
|
||||
|
||||
DOM_SID alias_sid;
|
||||
DOM_SID als_sid;
|
||||
uint32 alias_rid;
|
||||
fstring alias_sid_str;
|
||||
|
||||
uint32 acc_granted;
|
||||
|
||||
@ -3211,35 +3211,12 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
|
||||
access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_GET_MEMBERS, "_samr_query_aliasmem"))) {
|
||||
return r_u->status;
|
||||
}
|
||||
|
||||
sid_copy(&als_sid, &alias_sid);
|
||||
sid_to_string(alias_sid_str, &alias_sid);
|
||||
sid_split_rid(&alias_sid, &alias_rid);
|
||||
|
||||
DEBUG(10, ("sid is %s\n", alias_sid_str));
|
||||
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
|
||||
|
||||
if (sid_equal(&alias_sid, &global_sid_Builtin)) {
|
||||
DEBUG(10, ("lookup on Builtin SID (S-1-5-32)\n"));
|
||||
if(!get_builtin_group_from_sid(&als_sid, &map))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
} else {
|
||||
if (sid_equal(&alias_sid, get_global_sam_sid())) {
|
||||
DEBUG(10, ("lookup on Server SID\n"));
|
||||
if(!get_local_group_from_sid(&als_sid, &map)) {
|
||||
fstring alias_sid_string;
|
||||
DEBUG(10, ("Alias %s not found\n", sid_to_string(alias_sid_string, &als_sid)));
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_sid_list_of_group(map.gid, &sids, &num_sids)) {
|
||||
fstring alias_sid_string;
|
||||
DEBUG(10, ("Alias %s found, but member list unavailable\n", sid_to_string(alias_sid_string, &als_sid)));
|
||||
if (!pdb_enum_aliasmem(&alias_sid, &sids, &num_sids))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
DEBUG(10, ("sid is %s\n", alias_sid_str));
|
||||
sid = (DOM_SID2 *)talloc_zero(p->mem_ctx, sizeof(DOM_SID2) * num_sids);
|
||||
if (num_sids!=0 && sid == NULL) {
|
||||
SAFE_FREE(sids);
|
||||
@ -3250,7 +3227,6 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
|
||||
init_dom_sid2(&sid[i], &sids[i]);
|
||||
}
|
||||
|
||||
DEBUG(10, ("sid is %s\n", alias_sid_str));
|
||||
init_samr_r_query_aliasmem(r_u, num_sids, sid, NT_STATUS_OK);
|
||||
|
||||
SAFE_FREE(sids);
|
||||
@ -3258,20 +3234,89 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static void add_uid_to_array_unique(uid_t uid, uid_t **uids, int *num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((*num) >= groups_max())
|
||||
return;
|
||||
|
||||
for (i=0; i<*num; i++) {
|
||||
if ((*uids)[i] == uid)
|
||||
return;
|
||||
}
|
||||
|
||||
*uids = Realloc(*uids, (*num+1) * sizeof(uid_t));
|
||||
|
||||
if (*uids == NULL)
|
||||
return;
|
||||
|
||||
(*uids)[*num] = uid;
|
||||
*num += 1;
|
||||
}
|
||||
|
||||
|
||||
static BOOL get_memberuids(gid_t gid, uid_t **uids, int *num)
|
||||
{
|
||||
struct group *grp;
|
||||
char **gr;
|
||||
struct sys_pwent *userlist, *user;
|
||||
|
||||
*uids = NULL;
|
||||
*num = 0;
|
||||
|
||||
/* We only look at our own sam, so don't care about imported stuff */
|
||||
|
||||
winbind_off();
|
||||
|
||||
if ((grp = getgrgid(gid)) == NULL) {
|
||||
winbind_on();
|
||||
return False;
|
||||
}
|
||||
|
||||
/* 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(user->pw_uid, uids, num);
|
||||
}
|
||||
|
||||
pwent_free(userlist);
|
||||
|
||||
/* Secondary group members */
|
||||
|
||||
gr = grp->gr_mem;
|
||||
while ((*gr != NULL) && ((*gr)[0] != '\0')) {
|
||||
struct passwd *pw = getpwnam(*gr);
|
||||
|
||||
if (pw == NULL)
|
||||
continue;
|
||||
|
||||
add_uid_to_array_unique(pw->pw_uid, uids, num);
|
||||
|
||||
gr += 1;
|
||||
}
|
||||
|
||||
winbind_on();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
_samr_query_groupmem
|
||||
*********************************************************************/
|
||||
|
||||
NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_R_QUERY_GROUPMEM *r_u)
|
||||
{
|
||||
int num_sids = 0;
|
||||
int final_num_sids = 0;
|
||||
int i;
|
||||
int final_num_rids, i;
|
||||
DOM_SID group_sid;
|
||||
fstring group_sid_str;
|
||||
DOM_SID *sids=NULL;
|
||||
|
||||
GROUP_MAP map;
|
||||
uid_t *uids;
|
||||
int num;
|
||||
gid_t gid;
|
||||
|
||||
uint32 *rid=NULL;
|
||||
uint32 *attr=NULL;
|
||||
@ -3296,35 +3341,46 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
|
||||
|
||||
DEBUG(10, ("lookup on Domain SID\n"));
|
||||
|
||||
if(!get_domain_group_from_sid(group_sid, &map))
|
||||
if (!NT_STATUS_IS_OK(sid_to_gid(&group_sid, &gid)))
|
||||
return NT_STATUS_NO_SUCH_GROUP;
|
||||
|
||||
if(!get_sid_list_of_group(map.gid, &sids, &num_sids))
|
||||
if(!get_memberuids(gid, &uids, &num))
|
||||
return NT_STATUS_NO_SUCH_GROUP;
|
||||
|
||||
rid=talloc_zero(p->mem_ctx, sizeof(uint32)*num_sids);
|
||||
attr=talloc_zero(p->mem_ctx, sizeof(uint32)*num_sids);
|
||||
rid=talloc_zero(p->mem_ctx, sizeof(uint32)*num);
|
||||
attr=talloc_zero(p->mem_ctx, sizeof(uint32)*num);
|
||||
|
||||
if (num_sids!=0 && (rid==NULL || attr==NULL))
|
||||
if (num!=0 && (rid==NULL || attr==NULL))
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
|
||||
for (i=0; i<num_sids; i++) {
|
||||
uint32 urid;
|
||||
final_num_rids = 0;
|
||||
|
||||
if (sid_peek_check_rid(get_global_sam_sid(), &sids[i], &urid)) {
|
||||
rid[final_num_sids] = urid;
|
||||
attr[final_num_sids] = SID_NAME_USER;
|
||||
final_num_sids++;
|
||||
} else {
|
||||
fstring user_sid_str, domain_sid_str;
|
||||
DEBUG(1, ("_samr_query_groupmem: SID %s in group %s is not in our domain %s\n",
|
||||
sid_to_string(user_sid_str, &sids[i]),
|
||||
sid_to_string(group_sid_str, &group_sid),
|
||||
sid_to_string(domain_sid_str, get_global_sam_sid())));
|
||||
for (i=0; i<num; i++) {
|
||||
DOM_SID sid;
|
||||
|
||||
if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
|
||||
DEBUG(1, ("Could not map member uid to SID\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sid_check_is_in_our_domain(&sid)) {
|
||||
DEBUG(1, ("Inconsistent SAM -- group member uid not "
|
||||
"in our domain\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
sid_peek_rid(&sid, &rid[final_num_rids]);
|
||||
|
||||
/* Hmm. In a trace I got the constant 7 here from NT. */
|
||||
attr[final_num_rids] = SID_NAME_USER;
|
||||
|
||||
final_num_rids += 1;
|
||||
}
|
||||
|
||||
init_samr_r_query_groupmem(r_u, final_num_sids, rid, attr, NT_STATUS_OK);
|
||||
SAFE_FREE(uids);
|
||||
|
||||
init_samr_r_query_groupmem(r_u, final_num_rids, rid, attr,
|
||||
NT_STATUS_OK);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -3336,15 +3392,6 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
|
||||
NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_ADD_ALIASMEM *r_u)
|
||||
{
|
||||
DOM_SID alias_sid;
|
||||
fstring alias_sid_str;
|
||||
uid_t uid;
|
||||
struct passwd *pwd;
|
||||
struct group *grp;
|
||||
fstring grp_name;
|
||||
GROUP_MAP map;
|
||||
NTSTATUS ret;
|
||||
SAM_ACCOUNT *sam_user = NULL;
|
||||
BOOL check;
|
||||
uint32 acc_granted;
|
||||
|
||||
/* Find the policy handle. Open a policy on it. */
|
||||
@ -3355,74 +3402,11 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
|
||||
return r_u->status;
|
||||
}
|
||||
|
||||
sid_to_string(alias_sid_str, &alias_sid);
|
||||
DEBUG(10, ("sid is %s\n", alias_sid_str));
|
||||
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
|
||||
|
||||
if (sid_compare(&alias_sid, get_global_sam_sid())>0) {
|
||||
DEBUG(10, ("adding member on Server SID\n"));
|
||||
if(!get_local_group_from_sid(&alias_sid, &map))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
} else {
|
||||
if (sid_compare(&alias_sid, &global_sid_Builtin)>0) {
|
||||
DEBUG(10, ("adding member on BUILTIN SID\n"));
|
||||
if( !get_builtin_group_from_sid(&alias_sid, &map))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
if (!pdb_add_aliasmem(&alias_sid, &q_u->sid.sid))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
} else
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
ret = pdb_init_sam(&sam_user);
|
||||
if (!NT_STATUS_IS_OK(ret))
|
||||
return ret;
|
||||
|
||||
check = pdb_getsampwsid(sam_user, &q_u->sid.sid);
|
||||
|
||||
if (check != True) {
|
||||
pdb_free_sam(&sam_user);
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
/* check a real user exist before we run the script to add a user to a group */
|
||||
if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) {
|
||||
pdb_free_sam(&sam_user);
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
pdb_free_sam(&sam_user);
|
||||
|
||||
if ((pwd=getpwuid_alloc(uid)) == NULL) {
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
if ((grp=getgrgid(map.gid)) == NULL) {
|
||||
passwd_free(&pwd);
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
/* we need to copy the name otherwise it's overloaded in user_in_group_list */
|
||||
fstrcpy(grp_name, grp->gr_name);
|
||||
|
||||
/* if the user is already in the group */
|
||||
if(user_in_unix_group_list(pwd->pw_name, grp_name)) {
|
||||
passwd_free(&pwd);
|
||||
return NT_STATUS_MEMBER_IN_ALIAS;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(grp_name, pwd->pw_name);
|
||||
|
||||
/* check if the user has been added then ... */
|
||||
if(!user_in_unix_group_list(pwd->pw_name, grp_name)) {
|
||||
passwd_free(&pwd);
|
||||
return NT_STATUS_MEMBER_NOT_IN_ALIAS; /* don't know what to reply else */
|
||||
}
|
||||
|
||||
passwd_free(&pwd);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -3433,11 +3417,6 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
|
||||
NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DEL_ALIASMEM *r_u)
|
||||
{
|
||||
DOM_SID alias_sid;
|
||||
fstring alias_sid_str;
|
||||
struct group *grp;
|
||||
fstring grp_name;
|
||||
GROUP_MAP map;
|
||||
SAM_ACCOUNT *sam_pass=NULL;
|
||||
uint32 acc_granted;
|
||||
|
||||
/* Find the policy handle. Open a policy on it. */
|
||||
@ -3448,47 +3427,12 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
|
||||
return r_u->status;
|
||||
}
|
||||
|
||||
sid_to_string(alias_sid_str, &alias_sid);
|
||||
DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str));
|
||||
DEBUG(10, ("_samr_del_aliasmem:sid is %s\n",
|
||||
sid_string_static(&alias_sid)));
|
||||
|
||||
if (!sid_check_is_in_our_domain(&alias_sid) &&
|
||||
!sid_check_is_in_builtin(&alias_sid)) {
|
||||
DEBUG(10, ("_samr_del_aliasmem:invalid alias group\n"));
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
}
|
||||
|
||||
if( !get_local_group_from_sid(&alias_sid, &map))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
if ((grp=getgrgid(map.gid)) == NULL)
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
/* we need to copy the name otherwise it's overloaded in user_in_unix_group_list */
|
||||
fstrcpy(grp_name, grp->gr_name);
|
||||
|
||||
/* check if the user exists before trying to remove it from the group */
|
||||
pdb_init_sam(&sam_pass);
|
||||
if(!pdb_getsampwsid(sam_pass, &q_u->sid.sid)) {
|
||||
DEBUG(5,("_samr_del_aliasmem:User %s doesn't exist.\n", pdb_get_username(sam_pass)));
|
||||
pdb_free_sam(&sam_pass);
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
/* if the user is not in the group */
|
||||
if(!user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
|
||||
pdb_free_sam(&sam_pass);
|
||||
return NT_STATUS_MEMBER_NOT_IN_ALIAS;
|
||||
}
|
||||
|
||||
smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
|
||||
|
||||
/* check if the user has been removed then ... */
|
||||
if(user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
|
||||
pdb_free_sam(&sam_pass);
|
||||
return NT_STATUS_MEMBER_NOT_IN_ALIAS; /* don't know what to reply else */
|
||||
}
|
||||
|
||||
pdb_free_sam(&sam_pass);
|
||||
if (!pdb_del_aliasmem(&alias_sid, &q_u->sid.sid))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -3815,12 +3759,6 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
|
||||
NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, SAMR_R_DELETE_DOM_ALIAS *r_u)
|
||||
{
|
||||
DOM_SID alias_sid;
|
||||
DOM_SID dom_sid;
|
||||
uint32 alias_rid;
|
||||
fstring alias_sid_str;
|
||||
gid_t gid;
|
||||
struct group *grp;
|
||||
GROUP_MAP map;
|
||||
uint32 acc_granted;
|
||||
|
||||
DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__));
|
||||
@ -3832,38 +3770,18 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
|
||||
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_alias"))) {
|
||||
return r_u->status;
|
||||
}
|
||||
|
||||
sid_copy(&dom_sid, &alias_sid);
|
||||
sid_to_string(alias_sid_str, &dom_sid);
|
||||
sid_split_rid(&dom_sid, &alias_rid);
|
||||
|
||||
DEBUG(10, ("sid is %s\n", alias_sid_str));
|
||||
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
|
||||
|
||||
/* we check if it's our SID before deleting */
|
||||
if (!sid_equal(&dom_sid, get_global_sam_sid()))
|
||||
if (!sid_check_is_in_our_domain(&alias_sid))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
|
||||
DEBUG(10, ("lookup on Local SID\n"));
|
||||
|
||||
if(!get_local_group_from_sid(&alias_sid, &map))
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
gid=map.gid;
|
||||
|
||||
/* check if group really exists */
|
||||
if ( (grp=getgrgid(gid)) == NULL)
|
||||
return NT_STATUS_NO_SUCH_ALIAS;
|
||||
|
||||
/* we can delete the UNIX group */
|
||||
smb_delete_group(grp->gr_name);
|
||||
|
||||
/* check if the group has been successfully deleted */
|
||||
if ( (grp=getgrgid(gid)) != NULL)
|
||||
/* Have passdb delete the alias */
|
||||
if (!pdb_delete_alias(&alias_sid))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
/* don't check if we removed it as it could be an un-mapped group */
|
||||
pdb_delete_group_mapping_entry(alias_sid);
|
||||
|
||||
if (!close_policy_hnd(p, &q_u->alias_pol))
|
||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
@ -3941,7 +3859,6 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
|
||||
DOM_SID dom_sid;
|
||||
DOM_SID info_sid;
|
||||
fstring name;
|
||||
fstring sid_string;
|
||||
struct group *grp;
|
||||
struct samr_info *info;
|
||||
uint32 acc_granted;
|
||||
@ -3962,28 +3879,20 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
|
||||
|
||||
unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
|
||||
|
||||
/* check if group already exists */
|
||||
if ( (grp=getgrnam(name)) != NULL)
|
||||
return NT_STATUS_ALIAS_EXISTS;
|
||||
/* Have passdb create the alias */
|
||||
if (!pdb_create_alias(name, &r_u->rid))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
/* we can create the UNIX group */
|
||||
if (smb_create_group(name, &gid) != 0)
|
||||
sid_copy(&info_sid, get_global_sam_sid());
|
||||
sid_append_rid(&info_sid, r_u->rid);
|
||||
|
||||
if (!NT_STATUS_IS_OK(sid_to_gid(&info_sid, &gid)))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
/* check if the group has been successfully created */
|
||||
if ((grp=getgrgid(gid)) == NULL)
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
|
||||
|
||||
sid_copy(&info_sid, get_global_sam_sid());
|
||||
sid_append_rid(&info_sid, r_u->rid);
|
||||
sid_to_string(sid_string, &info_sid);
|
||||
|
||||
/* add the group to the mapping table */
|
||||
if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL))
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
|
||||
@ -4006,7 +3915,8 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
|
||||
DOM_SID group_sid;
|
||||
GROUP_MAP map;
|
||||
DOM_SID *sids=NULL;
|
||||
int num_sids=0;
|
||||
uid_t *uids;
|
||||
int num=0;
|
||||
GROUP_INFO_CTR *ctr;
|
||||
uint32 acc_granted;
|
||||
BOOL ret;
|
||||
@ -4031,9 +3941,10 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
|
||||
switch (q_u->switch_level) {
|
||||
case 1:
|
||||
ctr->switch_value1 = 1;
|
||||
if(!get_sid_list_of_group(map.gid, &sids, &num_sids))
|
||||
if(!get_memberuids(map.gid, &uids, &num))
|
||||
return NT_STATUS_NO_SUCH_GROUP;
|
||||
init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num_sids);
|
||||
SAFE_FREE(uids);
|
||||
init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num);
|
||||
SAFE_FREE(sids);
|
||||
break;
|
||||
case 3:
|
||||
@ -4105,7 +4016,7 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
|
||||
NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_SET_ALIASINFO *r_u)
|
||||
{
|
||||
DOM_SID group_sid;
|
||||
GROUP_MAP map;
|
||||
struct acct_info info;
|
||||
ALIAS_INFO_CTR *ctr;
|
||||
uint32 acc_granted;
|
||||
|
||||
@ -4116,22 +4027,20 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
|
||||
return r_u->status;
|
||||
}
|
||||
|
||||
if (!get_local_group_from_sid(&group_sid, &map) &&
|
||||
!get_builtin_group_from_sid(&group_sid, &map))
|
||||
return NT_STATUS_NO_SUCH_GROUP;
|
||||
|
||||
ctr=&q_u->ctr;
|
||||
|
||||
switch (ctr->switch_value1) {
|
||||
case 3:
|
||||
unistr2_to_ascii(map.comment, &(ctr->alias.info3.uni_acct_desc), sizeof(map.comment)-1);
|
||||
unistr2_to_ascii(info.acct_desc,
|
||||
&(ctr->alias.info3.uni_acct_desc),
|
||||
sizeof(info.acct_desc)-1);
|
||||
break;
|
||||
default:
|
||||
return NT_STATUS_INVALID_INFO_CLASS;
|
||||
}
|
||||
|
||||
if(!pdb_update_group_mapping_entry(&map)) {
|
||||
return NT_STATUS_NO_SUCH_GROUP;
|
||||
if(!pdb_set_aliasinfo(&group_sid, &info)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
|
@ -608,6 +608,102 @@ static int net_groupmap_cleanup(int argc, const char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_groupmap_addmem(int argc, const char **argv)
|
||||
{
|
||||
DOM_SID alias, member;
|
||||
|
||||
if ( (argc != 2) ||
|
||||
!string_to_sid(&alias, argv[0]) ||
|
||||
!string_to_sid(&member, argv[1]) ) {
|
||||
d_printf("Usage: net groupmap addmem alias-sid member-sid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pdb_add_aliasmem(&alias, &member)) {
|
||||
d_printf("Could not add sid %s to alias %s\n",
|
||||
argv[1], argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_groupmap_delmem(int argc, const char **argv)
|
||||
{
|
||||
DOM_SID alias, member;
|
||||
|
||||
if ( (argc != 2) ||
|
||||
!string_to_sid(&alias, argv[0]) ||
|
||||
!string_to_sid(&member, argv[1]) ) {
|
||||
d_printf("Usage: net groupmap delmem alias-sid member-sid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pdb_del_aliasmem(&alias, &member)) {
|
||||
d_printf("Could not delete sid %s from alias %s\n",
|
||||
argv[1], argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_groupmap_listmem(int argc, const char **argv)
|
||||
{
|
||||
DOM_SID alias;
|
||||
DOM_SID *members;
|
||||
int i, num;
|
||||
NTSTATUS result;
|
||||
|
||||
if ( (argc != 1) ||
|
||||
!string_to_sid(&alias, argv[0]) ) {
|
||||
d_printf("Usage: net groupmap listmem alias-sid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pdb_enum_aliasmem(&alias, &members, &num)) {
|
||||
d_printf("Could not list members for sid %s: %s\n",
|
||||
argv[0], nt_errstr(result));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
printf("%s\n", sid_string_static(&(members[i])));
|
||||
}
|
||||
|
||||
SAFE_FREE(members);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_groupmap_memberships(int argc, const char **argv)
|
||||
{
|
||||
DOM_SID member;
|
||||
DOM_SID *aliases;
|
||||
int i, num;
|
||||
NTSTATUS result;
|
||||
|
||||
if ( (argc != 1) ||
|
||||
!string_to_sid(&member, argv[0]) ) {
|
||||
d_printf("Usage: net groupmap memberof sid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pdb_enum_alias_memberships(&member, &aliases, &num)) {
|
||||
d_printf("Could not list memberships for sid %s: %s\n",
|
||||
argv[0], nt_errstr(result));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
printf("%s\n", sid_string_static(&(aliases[i])));
|
||||
}
|
||||
|
||||
SAFE_FREE(aliases);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_help_groupmap(int argc, const char **argv)
|
||||
{
|
||||
d_printf("net groupmap add"\
|
||||
@ -616,6 +712,14 @@ int net_help_groupmap(int argc, const char **argv)
|
||||
"\n Update a group mapping\n");
|
||||
d_printf("net groupmap delete"\
|
||||
"\n Remove a group mapping\n");
|
||||
d_printf("net groupmap addmember"\
|
||||
"\n Add a foreign alias member\n");
|
||||
d_printf("net groupmap delmember"\
|
||||
"\n Delete a foreign alias member\n");
|
||||
d_printf("net groupmap listmembers"\
|
||||
"\n List foreign group members\n");
|
||||
d_printf("net groupmap memberships"\
|
||||
"\n List foreign group memberships\n");
|
||||
d_printf("net groupmap list"\
|
||||
"\n List current group map\n");
|
||||
d_printf("net groupmap set"\
|
||||
@ -638,6 +742,10 @@ int net_groupmap(int argc, const char **argv)
|
||||
{"delete", net_groupmap_delete},
|
||||
{"set", net_groupmap_set},
|
||||
{"cleanup", net_groupmap_cleanup},
|
||||
{"addmem", net_groupmap_addmem},
|
||||
{"delmem", net_groupmap_delmem},
|
||||
{"listmem", net_groupmap_listmem},
|
||||
{"memberships", net_groupmap_memberships},
|
||||
{"list", net_groupmap_list},
|
||||
{"help", net_help_groupmap},
|
||||
{NULL, NULL}
|
||||
|
Loading…
Reference in New Issue
Block a user