server: Don't depend on the TOKEN_GROUPS structure on the server side.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2022-01-25 12:35:48 +01:00
parent 990cc1c64b
commit 868af0c500
6 changed files with 59 additions and 107 deletions

View File

@ -233,43 +233,38 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c
{
/* reply buffer is always shorter than output one */
void *buffer = malloc( length );
TOKEN_GROUPS *groups = info;
ULONG i, count, needed_size;
SERVER_START_REQ( get_token_groups )
{
TOKEN_GROUPS *groups = info;
req->handle = wine_server_obj_handle( token );
wine_server_set_reply( req, buffer, length );
status = wine_server_call( req );
if (status == STATUS_BUFFER_TOO_SMALL)
count = reply->attr_len / sizeof(unsigned int);
needed_size = offsetof( TOKEN_GROUPS, Groups[count] ) + reply->sid_len;
if (status == STATUS_SUCCESS && needed_size > length) status = STATUS_BUFFER_TOO_SMALL;
if (status == STATUS_SUCCESS)
{
if (retlen) *retlen = reply->user_len;
}
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 int));
SID *sids = (SID *)((char *)info + FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ));
unsigned int *attr = buffer;
SID *sids = (SID *)&groups->Groups[count];
if (retlen) *retlen = reply->user_len;
groups->GroupCount = tg->count;
memcpy( sids, (char *)buffer + non_sid_portion,
reply->user_len - offsetof( TOKEN_GROUPS, Groups[tg->count] ));
for (i = 0; i < tg->count; i++)
groups->GroupCount = count;
memcpy( sids, attr + count, reply->sid_len );
for (i = 0; i < count; i++)
{
groups->Groups[i].Attributes = attr[i];
groups->Groups[i].Sid = sids;
sids = (SID *)((char *)sids + offsetof( SID, SubAuthority[sids->SubAuthorityCount] ));
}
}
else if (retlen) *retlen = 0;
else if (status != STATUS_BUFFER_TOO_SMALL) needed_size = 0;
}
SERVER_END_REQ;
free( buffer );
if (retlen) *retlen = needed_size;
break;
}

View File

@ -439,13 +439,6 @@ struct object_type_info
};
struct token_groups
{
unsigned int count;
};
enum select_op
{
SELECT_NONE,
@ -4470,9 +4463,10 @@ struct get_token_groups_request
struct get_token_groups_reply
{
struct reply_header __header;
data_size_t user_len;
/* VARARG(user,token_groups); */
char __pad_12[4];
data_size_t attr_len;
data_size_t sid_len;
/* VARARG(attrs,uints,attr_len); */
/* VARARG(sids,sids); */
};
struct get_token_default_dacl_request

View File

@ -455,13 +455,6 @@ struct object_type_info
/* VARARG(name,unicode_str); */
};
struct token_groups
{
unsigned int count;
/* unsigned int attributes[count]; */
/* VARARG(sids,sid); */
};
enum select_op
{
SELECT_NONE,
@ -3174,8 +3167,10 @@ enum caret_state
@REQ(get_token_groups)
obj_handle_t handle; /* handle to the token */
@REPLY
data_size_t user_len; /* length needed to store user */
VARARG(user,token_groups); /* groups the token's user belongs to */
data_size_t attr_len; /* length needed to store attrs */
data_size_t sid_len; /* length needed to store sids */
VARARG(attrs,uints,attr_len); /* group attributes */
VARARG(sids,sids); /* group sids */
@END
@REQ(get_token_default_dacl)

View File

@ -1957,7 +1957,8 @@ C_ASSERT( FIELD_OFFSET(struct get_token_sid_reply, sid_len) == 8 );
C_ASSERT( sizeof(struct get_token_sid_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_groups_request, handle) == 12 );
C_ASSERT( sizeof(struct get_token_groups_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_groups_reply, user_len) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_token_groups_reply, attr_len) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_token_groups_reply, sid_len) == 12 );
C_ASSERT( sizeof(struct get_token_groups_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_token_default_dacl_request, handle) == 12 );
C_ASSERT( sizeof(struct get_token_default_dacl_request) == 16 );

View File

@ -1390,49 +1390,27 @@ 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 )))
if ((token = (struct token *)get_handle_obj( current->process, req->handle, TOKEN_QUERY, &token_ops )))
{
size_t size_needed = sizeof(struct token_groups);
size_t sid_size = 0;
unsigned int group_count = 0;
const struct group *group;
LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
{
group_count++;
sid_size += sid_len( &group->sid );
reply->sid_len += sid_len( &group->sid );
}
size_needed += sid_size;
/* attributes size */
size_needed += sizeof(unsigned int) * group_count;
reply->attr_len = sizeof(unsigned int) * group_count;
/* reply buffer contains size_needed bytes formatted as:
unsigned int count;
unsigned int attrib[count];
char sid_data[];
user_len includes extra data needed for TOKEN_GROUPS representation,
required caller buffer size calculated here to avoid extra server call */
reply->user_len = FIELD_OFFSET( TOKEN_GROUPS, Groups[group_count] ) + sid_size;
if (reply->user_len <= get_reply_max_size())
if (reply->attr_len + reply->sid_len <= get_reply_max_size())
{
struct token_groups *tg = set_reply_data_size( size_needed );
if (tg)
unsigned int *attr_ptr = set_reply_data_size( reply->attr_len + reply->sid_len );
struct sid *sid = (struct sid *)(attr_ptr + group_count);
if (attr_ptr)
{
unsigned int *attr_ptr = (unsigned int *)(tg + 1);
struct sid *sid = (struct 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;

View File

@ -1040,6 +1040,28 @@ static void dump_varargs_sid( const char *prefix, data_size_t size )
remove_data( size );
}
static void dump_varargs_sids( const char *prefix, data_size_t size )
{
const struct sid *sid = cur_data;
data_size_t len = size;
fprintf( stderr,"%s{", prefix );
while (len > 0)
{
if (!sid_valid_size( sid, len ))
{
fprintf( stderr, "bad len %u", len);
break;
}
dump_inline_sid( "", sid, size );
len -= sid_len( sid );
sid = (const struct sid *)((const char *)sid + sid_len( sid ));
if (len) fputc( ',', stderr );
}
fputc( '}', stderr );
remove_data( size );
}
static void dump_inline_acl( const char *prefix, const struct acl *acl, data_size_t size )
{
const struct ace *ace;
@ -1131,41 +1153,6 @@ static void dump_varargs_security_descriptor( const char *prefix, data_size_t si
remove_data( size );
}
static void dump_varargs_token_groups( const char *prefix, data_size_t size )
{
const struct token_groups *tg = cur_data;
fprintf( stderr,"%s{", prefix );
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 struct sid *sid = (const struct sid *)((const char *)cur_data + offset);
if (i != 0)
fputc( ',', stderr );
fputc( '{', stderr );
fprintf( stderr, "attributes=%08x", attr[i] );
dump_inline_sid( ",sid=", sid, size - offset );
if (!sid_valid_size( sid, size - offset )) break;
offset += sid_len( sid );
fputc( '}', stderr );
}
fputc( ']', stderr );
}
}
fputc( '}', stderr );
}
static void dump_varargs_process_info( const char *prefix, data_size_t size )
{
data_size_t pos = 0;
@ -3869,8 +3856,10 @@ static void dump_get_token_groups_request( const struct get_token_groups_request
static void dump_get_token_groups_reply( const struct get_token_groups_reply *req )
{
fprintf( stderr, " user_len=%u", req->user_len );
dump_varargs_token_groups( ", user=", cur_size );
fprintf( stderr, " attr_len=%u", req->attr_len );
fprintf( stderr, ", sid_len=%u", req->sid_len );
dump_varargs_uints( ", attrs=", min(cur_size,req->attr_len) );
dump_varargs_sids( ", sids=", cur_size );
}
static void dump_get_token_default_dacl_request( const struct get_token_default_dacl_request *req )