1
0
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:
Gerald Carter 2004-04-07 12:43:44 +00:00 committed by Gerald (Jerry) Carter
parent f79e40072a
commit 7af3777ab3
24 changed files with 2004 additions and 342 deletions

View File

@ -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

View File

@ -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
*********************************************************************/

View File

@ -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
*/

View File

@ -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 **);

View File

@ -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;

View File

@ -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 }
};

View File

@ -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);
}

View File

@ -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;

View File

@ -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. */

View File

@ -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");

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View 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
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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"));

View File

@ -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;

View File

@ -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}