server: Retrieve the groups for a token from the server.
This commit is contained in:
parent
07d032b24b
commit
3396a66ee7
|
@ -252,22 +252,69 @@ NTSTATUS WINAPI NtQueryInformationToken(
|
|||
SERVER_END_REQ;
|
||||
break;
|
||||
case TokenGroups:
|
||||
if (tokeninfo)
|
||||
{
|
||||
TOKEN_GROUPS *tgroups = tokeninfo;
|
||||
SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
|
||||
{
|
||||
char stack_buffer[256];
|
||||
unsigned int server_buf_len = sizeof(stack_buffer);
|
||||
void *buffer = stack_buffer;
|
||||
BOOLEAN need_more_memory = FALSE;
|
||||
|
||||
/* 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));
|
||||
}
|
||||
/* 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
|
||||
{
|
||||
SERVER_START_REQ( get_token_groups )
|
||||
{
|
||||
TOKEN_GROUPS *groups = tokeninfo;
|
||||
|
||||
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",
|
||||
|
|
Loading…
Reference in New Issue