server: Retrieve the groups for a token from the server.
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 );
+ }
+}