Commit 3396a66e authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

server: Retrieve the groups for a token from the server.

parent 07d032b2
......@@ -252,22 +252,69 @@ NTSTATUS WINAPI NtQueryInformationToken(
SERVER_END_REQ;
break;
case TokenGroups:
if (tokeninfo)
{
char stack_buffer[256];
unsigned int server_buf_len = sizeof(stack_buffer);
void *buffer = stack_buffer;
BOOLEAN need_more_memory = FALSE;
/* we cannot work out the size of the server buffer required for the
* input size, since there are two factors affecting how much can be
* stored in the buffer - number of groups and lengths of sids */
do
{
TOKEN_GROUPS *tgroups = tokeninfo;
SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
SERVER_START_REQ( get_token_groups )
{
TOKEN_GROUPS *groups = tokeninfo;
/* we need to show admin privileges ! */
tgroups->GroupCount = 1;
tgroups->Groups->Attributes = SE_GROUP_ENABLED;
RtlAllocateAndInitializeSid( &sid,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&(tgroups->Groups->Sid));
}
req->handle = token;
wine_server_set_reply( req, buffer, server_buf_len );
status = wine_server_call( req );
if (status == STATUS_BUFFER_TOO_SMALL)
{
if (buffer == stack_buffer)
buffer = RtlAllocateHeap(GetProcessHeap(), 0, reply->user_len);
else
buffer = RtlReAllocateHeap(GetProcessHeap(), 0, buffer, reply->user_len);
if (!buffer) return STATUS_NO_MEMORY;
server_buf_len = reply->user_len;
need_more_memory = TRUE;
}
else if (status == STATUS_SUCCESS)
{
struct token_groups *tg = buffer;
unsigned int *attr = (unsigned int *)(tg + 1);
ULONG i;
const int non_sid_portion = (sizeof(struct token_groups) + tg->count * sizeof(unsigned long));
SID *sids = (SID *)((char *)tokeninfo + FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ));
ULONG needed_bytes = FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ) +
reply->user_len - non_sid_portion;
if (retlen) *retlen = needed_bytes;
if (needed_bytes <= tokeninfolength)
{
groups->GroupCount = tg->count;
memcpy( sids, (char *)buffer + non_sid_portion,
reply->user_len - non_sid_portion );
for (i = 0; i < tg->count; i++)
{
groups->Groups[i].Attributes = attr[i];
groups->Groups[i].Sid = sids;
sids = (SID *)((char *)sids + RtlLengthSid(sids));
}
}
else status = STATUS_BUFFER_TOO_SMALL;
}
else if (retlen) *retlen = 0;
}
SERVER_END_REQ;
} while (need_more_memory);
if (buffer != stack_buffer) RtlFreeHeap(GetProcessHeap(), 0, buffer);
break;
}
case TokenPrimaryGroup:
if (tokeninfo)
{
......
......@@ -177,6 +177,13 @@ struct security_descriptor
};
struct token_groups
{
unsigned int count;
};
......@@ -3574,6 +3581,18 @@ struct get_token_user_reply
/* VARARG(user,SID); */
};
struct get_token_groups_request
{
struct request_header __header;
obj_handle_t handle;
};
struct get_token_groups_reply
{
struct reply_header __header;
size_t user_len;
/* VARARG(user,token_groups); */
};
struct create_mailslot_request
{
......@@ -3913,6 +3932,7 @@ enum request
REQ_duplicate_token,
REQ_access_check,
REQ_get_token_user,
REQ_get_token_groups,
REQ_create_mailslot,
REQ_open_mailslot,
REQ_set_mailslot_info,
......@@ -4132,6 +4152,7 @@ union generic_request
struct duplicate_token_request duplicate_token_request;
struct access_check_request access_check_request;
struct get_token_user_request get_token_user_request;
struct get_token_groups_request get_token_groups_request;
struct create_mailslot_request create_mailslot_request;
struct open_mailslot_request open_mailslot_request;
struct set_mailslot_info_request set_mailslot_info_request;
......@@ -4349,6 +4370,7 @@ union generic_reply
struct duplicate_token_reply duplicate_token_reply;
struct access_check_reply access_check_reply;
struct get_token_user_reply get_token_user_reply;
struct get_token_groups_reply get_token_groups_reply;
struct create_mailslot_reply create_mailslot_reply;
struct open_mailslot_reply open_mailslot_reply;
struct set_mailslot_info_reply set_mailslot_info_reply;
......@@ -4359,6 +4381,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
#define SERVER_PROTOCOL_VERSION 232
#define SERVER_PROTOCOL_VERSION 233
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -193,6 +193,13 @@ struct security_descriptor
/* VARARGS(dacl,ACL); */
};
struct token_groups
{
unsigned int count;
/* unsigned int attributes[count]; */
/* VARARGS(sids,SID); */
};
/****************************************************************/
/* Request declarations */
......@@ -2509,6 +2516,13 @@ enum message_type
VARARG(user,SID); /* sid of the user the token represents */
@END
@REQ(get_token_groups)
obj_handle_t handle; /* handle to the token */
@REPLY
size_t user_len; /* length needed to store user */
VARARG(user,token_groups); /* groups the token's user belongs to */
@END
/* Create a mailslot */
@REQ(create_mailslot)
unsigned int access; /* wanted access rights */
......
......@@ -314,6 +314,7 @@ DECL_HANDLER(check_token_privileges);
DECL_HANDLER(duplicate_token);
DECL_HANDLER(access_check);
DECL_HANDLER(get_token_user);
DECL_HANDLER(get_token_groups);
DECL_HANDLER(create_mailslot);
DECL_HANDLER(open_mailslot);
DECL_HANDLER(set_mailslot_info);
......@@ -532,6 +533,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_duplicate_token,
(req_handler)req_access_check,
(req_handler)req_get_token_user,
(req_handler)req_get_token_groups,
(req_handler)req_create_mailslot,
(req_handler)req_open_mailslot,
(req_handler)req_set_mailslot_info,
......
......@@ -93,7 +93,7 @@ struct privilege
unsigned def : 1; /* is the privilege enabled by default? */
};
struct sid_and_attributes
struct group
{
struct list entry;
unsigned enabled : 1; /* is the sid currently enabled? */
......@@ -397,7 +397,7 @@ static void token_destroy( struct object *obj )
LIST_FOR_EACH_SAFE( cursor, cursor_next, &token->groups )
{
struct sid_and_attributes *group = LIST_ENTRY( cursor, struct sid_and_attributes, entry );
struct group *group = LIST_ENTRY( cursor, struct group, entry );
list_remove( &group->entry );
free( group );
}
......@@ -436,8 +436,8 @@ static struct token *create_token( unsigned primary, const SID *user,
/* copy groups */
for (i = 0; i < group_count; i++)
{
size_t size = FIELD_OFFSET( struct sid_and_attributes, sid.SubAuthority[((const SID *)groups[i].Sid)->SubAuthorityCount] );
struct sid_and_attributes *group = mem_alloc( size );
size_t size = FIELD_OFFSET( struct group, sid.SubAuthority[((const SID *)groups[i].Sid)->SubAuthorityCount] );
struct group *group = mem_alloc( size );
if (!group)
{
......@@ -696,11 +696,11 @@ int token_check_privileges( struct token *token, int all_required,
static int token_sid_present( struct token *token, const SID *sid, int deny )
{
struct sid_and_attributes *group;
struct group *group;
if (security_equal_sid( token->user, sid )) return TRUE;
LIST_FOR_EACH_ENTRY( group, &token->groups, struct sid_and_attributes, entry )
LIST_FOR_EACH_ENTRY( group, &token->groups, struct group, entry )
{
if (!group->enabled) continue;
if (group->deny_only && !deny) continue;
......@@ -1023,14 +1023,14 @@ DECL_HANDLER(duplicate_token)
if (token)
{
struct privilege *privilege;
struct sid_and_attributes *group;
struct group *group;
unsigned int access;
/* copy groups */
LIST_FOR_EACH_ENTRY( group, &src_token->groups, struct sid_and_attributes, entry )
LIST_FOR_EACH_ENTRY( group, &src_token->groups, struct group, entry )
{
size_t size = FIELD_OFFSET( struct sid_and_attributes, sid.SubAuthority[group->sid.SubAuthorityCount] );
struct sid_and_attributes *newgroup = mem_alloc( size );
size_t size = FIELD_OFFSET( struct group, sid.SubAuthority[group->sid.SubAuthorityCount] );
struct group *newgroup = mem_alloc( size );
if (!newgroup)
{
release_object( token );
......@@ -1132,7 +1132,7 @@ DECL_HANDLER(access_check)
}
}
/* */
/* retrives the SID of the user that the token represents */
DECL_HANDLER(get_token_user)
{
struct token *token;
......@@ -1157,3 +1157,61 @@ DECL_HANDLER(get_token_user)
release_object( token );
}
}
/* retrieves the groups that the user represented by the token belongs to */
DECL_HANDLER(get_token_groups)
{
struct token *token;
reply->user_len = 0;
if ((token = (struct token *)get_handle_obj( current->process, req->handle,
TOKEN_QUERY,
&token_ops )))
{
size_t size_needed = sizeof(struct token_groups);
unsigned int group_count = 0;
const struct group *group;
LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
{
group_count++;
size_needed += FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]);
}
size_needed += sizeof(unsigned int) * group_count;
reply->user_len = size_needed;
if (size_needed <= get_reply_max_size())
{
struct token_groups *tg = set_reply_data_size( size_needed );
if (tg)
{
unsigned int *attr_ptr = (unsigned int *)(tg + 1);
SID *sid_ptr = (SID *)(attr_ptr + group_count);
tg->count = group_count;
LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
{
*attr_ptr = 0;
if (group->mandatory) *attr_ptr |= SE_GROUP_MANDATORY;
if (group->def) *attr_ptr |= SE_GROUP_ENABLED_BY_DEFAULT;
if (group->enabled) *attr_ptr |= SE_GROUP_ENABLED;
if (group->owner) *attr_ptr |= SE_GROUP_OWNER;
if (group->deny_only) *attr_ptr |= SE_GROUP_USE_FOR_DENY_ONLY;
if (group->resource) *attr_ptr |= SE_GROUP_RESOURCE;
memcpy(sid_ptr, &group->sid, FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]));
sid_ptr = (SID *)((char *)sid_ptr + FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]));
attr_ptr++;
}
}
}
else set_error( STATUS_BUFFER_TOO_SMALL );
release_object( token );
}
}
......@@ -560,6 +560,43 @@ static void dump_varargs_security_descriptor( size_t size )
remove_data( size );
}
static void dump_varargs_token_groups( size_t size )
{
const struct token_groups *tg = cur_data;
fputc( '{', stderr );
if (size >= sizeof(struct token_groups))
{
size_t offset = sizeof(*tg);
fprintf( stderr, "count=%08x,", tg->count );
if (tg->count * sizeof(unsigned int) <= size)
{
unsigned int i;
const unsigned int *attr = (const unsigned int *)(tg + 1);
offset += tg->count * sizeof(unsigned int);
fputc( '[', stderr );
for (i = 0; i < tg->count; i++)
{
const SID *sid = (const SID *)((const char *)cur_data + offset);
if (i != 0)
fputc( ',', stderr );
fputc( '{', stderr );
fprintf( stderr, "attributes=%08x", attr[i] );
fprintf( stderr, ",sid=" );
dump_inline_sid( sid, size - offset );
if ((offset + FIELD_OFFSET(SID, SubAuthority[0]) > size) ||
(offset + FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) > size))
break;
offset += FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
fputc( '}', stderr );
}
fputc( ']', stderr );
}
}
fputc( '}', stderr );
}
typedef void (*dump_func)( const void *req );
/* Everything below this line is generated automatically by tools/make_requests */
......@@ -3096,6 +3133,18 @@ static void dump_get_token_user_reply( const struct get_token_user_reply *req )
dump_varargs_SID( cur_size );
}
static void dump_get_token_groups_request( const struct get_token_groups_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_get_token_groups_reply( const struct get_token_groups_reply *req )
{
fprintf( stderr, " user_len=%lu,", (unsigned long)req->user_len );
fprintf( stderr, " user=" );
dump_varargs_token_groups( cur_size );
}
static void dump_create_mailslot_request( const struct create_mailslot_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
......@@ -3418,6 +3467,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_duplicate_token_request,
(dump_func)dump_access_check_request,
(dump_func)dump_get_token_user_request,
(dump_func)dump_get_token_groups_request,
(dump_func)dump_create_mailslot_request,
(dump_func)dump_open_mailslot_request,
(dump_func)dump_set_mailslot_info_request,
......@@ -3633,6 +3683,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_duplicate_token_reply,
(dump_func)dump_access_check_reply,
(dump_func)dump_get_token_user_reply,
(dump_func)dump_get_token_groups_reply,
(dump_func)dump_create_mailslot_reply,
(dump_func)dump_open_mailslot_reply,
(dump_func)dump_set_mailslot_info_reply,
......@@ -3848,6 +3899,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"duplicate_token",
"access_check",
"get_token_user",
"get_token_groups",
"create_mailslot",
"open_mailslot",
"set_mailslot_info",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment