server: Retrieve the groups for a token from the server.
diff --git a/server/protocol.def b/server/protocol.def
index ef9acb1..e08db4c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -193,6 +193,13 @@
/* VARARGS(dacl,ACL); */
};
+struct token_groups
+{
+ unsigned int count;
+ /* unsigned int attributes[count]; */
+ /* VARARGS(sids,SID); */
+};
+
/****************************************************************/
/* Request declarations */
@@ -2509,6 +2516,13 @@
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 */
diff --git a/server/request.h b/server/request.h
index f6df040..5b69712 100644
--- a/server/request.h
+++ b/server/request.h
@@ -314,6 +314,7 @@
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 @@
(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,
diff --git a/server/token.c b/server/token.c
index aedba6a..c7c5970 100644
--- a/server/token.c
+++ b/server/token.c
@@ -93,7 +93,7 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
}
}
-/* */
+/* retrives the SID of the user that the token represents */
DECL_HANDLER(get_token_user)
{
struct token *token;
@@ -1157,3 +1157,61 @@
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 );
+ }
+}
diff --git a/server/trace.c b/server/trace.c
index 350b2ac..f4de26b 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -560,6 +560,43 @@
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 @@
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 @@
(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 @@
(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 @@
"duplicate_token",
"access_check",
"get_token_user",
+ "get_token_groups",
"create_mailslot",
"open_mailslot",
"set_mailslot_info",