server: Don't drop the SE_GROUP_LOGON_ID attribute.
[wine] / server / token.c
1 /*
2  * Tokens
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  * Copyright (C) 2003 Mike McCormack
6  * Copyright (C) 2005 Robert Shearman
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "windef.h"
34 #include "winternl.h"
35
36 #include "handle.h"
37 #include "thread.h"
38 #include "process.h"
39 #include "request.h"
40 #include "security.h"
41
42 #include "wine/unicode.h"
43
44 #define MAX_SUBAUTH_COUNT 1
45
46 const LUID SeIncreaseQuotaPrivilege        = {  5, 0 };
47 const LUID SeSecurityPrivilege             = {  8, 0 };
48 const LUID SeTakeOwnershipPrivilege        = {  9, 0 };
49 const LUID SeLoadDriverPrivilege           = { 10, 0 };
50 const LUID SeSystemProfilePrivilege        = { 11, 0 };
51 const LUID SeSystemtimePrivilege           = { 12, 0 };
52 const LUID SeProfileSingleProcessPrivilege = { 13, 0 };
53 const LUID SeIncreaseBasePriorityPrivilege = { 14, 0 };
54 const LUID SeCreatePagefilePrivilege       = { 15, 0 };
55 const LUID SeBackupPrivilege               = { 17, 0 };
56 const LUID SeRestorePrivilege              = { 18, 0 };
57 const LUID SeShutdownPrivilege             = { 19, 0 };
58 const LUID SeDebugPrivilege                = { 20, 0 };
59 const LUID SeSystemEnvironmentPrivilege    = { 22, 0 };
60 const LUID SeChangeNotifyPrivilege         = { 23, 0 };
61 const LUID SeRemoteShutdownPrivilege       = { 24, 0 };
62 const LUID SeUndockPrivilege               = { 25, 0 };
63 const LUID SeManageVolumePrivilege         = { 28, 0 };
64 const LUID SeImpersonatePrivilege          = { 29, 0 };
65 const LUID SeCreateGlobalPrivilege         = { 30, 0 };
66
67 static const SID world_sid = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } };
68 static const SID local_sid = { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } };
69 static const SID interactive_sid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } };
70 static const SID anonymous_logon_sid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } };
71 static const SID authenticated_user_sid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } };
72 static const SID local_system_sid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } };
73 const PSID security_world_sid = (PSID)&world_sid;
74 static const PSID security_local_sid = (PSID)&local_sid;
75 const PSID security_interactive_sid = (PSID)&interactive_sid;
76 static const PSID security_authenticated_user_sid = (PSID)&authenticated_user_sid;
77 const PSID security_local_system_sid = (PSID)&local_system_sid;
78
79 static luid_t prev_luid_value = { 1000, 0 };
80
81 struct token
82 {
83     struct object  obj;             /* object header */
84     luid_t         token_id;        /* system-unique id of token */
85     luid_t         modified_id;     /* new id allocated every time token is modified */
86     struct list    privileges;      /* privileges available to the token */
87     struct list    groups;          /* groups that the user of this token belongs to (sid_and_attributes) */
88     SID           *user;            /* SID of user this token represents */
89     SID           *primary_group;   /* SID of user's primary group */
90     unsigned       primary;         /* is this a primary or impersonation token? */
91     ACL           *default_dacl;    /* the default DACL to assign to objects created by this user */
92     TOKEN_SOURCE   source;          /* source of the token */
93     SECURITY_IMPERSONATION_LEVEL impersonation_level; /* impersonation level this token is capable of if non-primary token */
94 };
95
96 struct privilege
97 {
98     struct list entry;
99     LUID        luid;
100     unsigned    enabled  : 1; /* is the privilege currently enabled? */
101     unsigned    def      : 1; /* is the privilege enabled by default? */
102 };
103
104 struct group
105 {
106     struct list entry;
107     unsigned    enabled  : 1; /* is the sid currently enabled? */
108     unsigned    def      : 1; /* is the sid enabled by default? */
109     unsigned    logon    : 1; /* is this a logon sid? */
110     unsigned    mandatory: 1; /* is this sid always enabled? */
111     unsigned    owner    : 1; /* can this sid be an owner of an object? */
112     unsigned    resource : 1; /* is this a domain-local group? */
113     unsigned    deny_only: 1; /* is this a sid that should be use for denying only? */
114     SID         sid;
115 };
116
117 static void token_dump( struct object *obj, int verbose );
118 static unsigned int token_map_access( struct object *obj, unsigned int access );
119 static void token_destroy( struct object *obj );
120
121 static const struct object_ops token_ops =
122 {
123     sizeof(struct token),      /* size */
124     token_dump,                /* dump */
125     no_get_type,               /* get_type */
126     no_add_queue,              /* add_queue */
127     NULL,                      /* remove_queue */
128     NULL,                      /* signaled */
129     NULL,                      /* satisfied */
130     no_signal,                 /* signal */
131     no_get_fd,                 /* get_fd */
132     token_map_access,          /* map_access */
133     default_get_sd,            /* get_sd */
134     default_set_sd,            /* set_sd */
135     no_lookup_name,            /* lookup_name */
136     no_open_file,              /* open_file */
137     no_close_handle,           /* close_handle */
138     token_destroy              /* destroy */
139 };
140
141
142 static void token_dump( struct object *obj, int verbose )
143 {
144     fprintf( stderr, "Security token\n" );
145     /* FIXME: dump token members */
146 }
147
148 static unsigned int token_map_access( struct object *obj, unsigned int access )
149 {
150     if (access & GENERIC_READ)    access |= TOKEN_READ;
151     if (access & GENERIC_WRITE)   access |= TOKEN_WRITE;
152     if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
153     if (access & GENERIC_ALL)     access |= TOKEN_ALL_ACCESS;
154     return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
155 }
156
157 static SID *security_sid_alloc( const SID_IDENTIFIER_AUTHORITY *idauthority, int subauthcount, const unsigned int subauth[] )
158 {
159     int i;
160     SID *sid = mem_alloc( FIELD_OFFSET(SID, SubAuthority[subauthcount]) );
161     if (!sid) return NULL;
162     sid->Revision = SID_REVISION;
163     sid->SubAuthorityCount = subauthcount;
164     sid->IdentifierAuthority = *idauthority;
165     for (i = 0; i < subauthcount; i++)
166         sid->SubAuthority[i] = subauth[i];
167     return sid;
168 }
169
170 void security_set_thread_token( struct thread *thread, obj_handle_t handle )
171 {
172     if (!handle)
173     {
174         if (thread->token)
175             release_object( thread->token );
176         thread->token = NULL;
177     }
178     else
179     {
180         struct token *token = (struct token *)get_handle_obj( current->process,
181                                                               handle,
182                                                               TOKEN_IMPERSONATE,
183                                                               &token_ops );
184         if (token)
185         {
186             if (thread->token)
187                 release_object( thread->token );
188             thread->token = token;
189         }
190     }
191 }
192
193 const SID *security_unix_uid_to_sid( uid_t uid )
194 {
195     /* very simple mapping: either the current user or not the current user */
196     if (uid == getuid())
197         return &interactive_sid;
198     else
199         return &anonymous_logon_sid;
200 }
201
202 static int acl_is_valid( const ACL *acl, data_size_t size )
203 {
204     ULONG i;
205     const ACE_HEADER *ace;
206
207     if (size < sizeof(ACL))
208         return FALSE;
209
210     size = min(size, MAX_ACL_LEN);
211
212     size -= sizeof(ACL);
213
214     ace = (const ACE_HEADER *)(acl + 1);
215     for (i = 0; i < acl->AceCount; i++)
216     {
217         const SID *sid;
218         data_size_t sid_size;
219
220         if (size < sizeof(ACE_HEADER))
221             return FALSE;
222         if (size < ace->AceSize)
223             return FALSE;
224         size -= ace->AceSize;
225         switch (ace->AceType)
226         {
227         case ACCESS_DENIED_ACE_TYPE:
228             sid = (const SID *)&((const ACCESS_DENIED_ACE *)ace)->SidStart;
229             sid_size = ace->AceSize - FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart);
230             break;
231         case ACCESS_ALLOWED_ACE_TYPE:
232             sid = (const SID *)&((const ACCESS_ALLOWED_ACE *)ace)->SidStart;
233             sid_size = ace->AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
234             break;
235         case SYSTEM_AUDIT_ACE_TYPE:
236             sid = (const SID *)&((const SYSTEM_AUDIT_ACE *)ace)->SidStart;
237             sid_size = ace->AceSize - FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart);
238             break;
239         case SYSTEM_ALARM_ACE_TYPE:
240             sid = (const SID *)&((const SYSTEM_ALARM_ACE *)ace)->SidStart;
241             sid_size = ace->AceSize - FIELD_OFFSET(SYSTEM_ALARM_ACE, SidStart);
242             break;
243         default:
244             return FALSE;
245         }
246         if (sid_size < FIELD_OFFSET(SID, SubAuthority[0]) ||
247             sid_size < FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]))
248             return FALSE;
249         ace = ace_next( ace );
250     }
251     return TRUE;
252 }
253
254 /* checks whether all members of a security descriptor fit inside the size
255  * of memory specified */
256 int sd_is_valid( const struct security_descriptor *sd, data_size_t size )
257 {
258     size_t offset = sizeof(struct security_descriptor);
259     const SID *group;
260     const SID *owner;
261     const ACL *sacl;
262     const ACL *dacl;
263     int dummy;
264
265     if (size < offset)
266         return FALSE;
267
268     if ((sd->owner_len >= FIELD_OFFSET(SID, SubAuthority[255])) ||
269         (offset + sd->owner_len > size))
270         return FALSE;
271     owner = sd_get_owner( sd );
272     if (owner)
273     {
274         size_t needed_size = FIELD_OFFSET(SID, SubAuthority[owner->SubAuthorityCount]);
275         if ((sd->owner_len < sizeof(SID)) || (needed_size > sd->owner_len))
276             return FALSE;
277     }
278     offset += sd->owner_len;
279
280     if ((sd->group_len >= FIELD_OFFSET(SID, SubAuthority[255])) ||
281         (offset + sd->group_len > size))
282         return FALSE;
283     group = sd_get_group( sd );
284     if (group)
285     {
286         size_t needed_size = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
287         if ((sd->group_len < sizeof(SID)) || (needed_size > sd->group_len))
288             return FALSE;
289     }
290     offset += sd->group_len;
291
292     if ((sd->sacl_len >= MAX_ACL_LEN) || (offset + sd->sacl_len > size))
293         return FALSE;
294     sacl = sd_get_sacl( sd, &dummy );
295     if (sacl && !acl_is_valid( sacl, sd->sacl_len ))
296         return FALSE;
297     offset += sd->sacl_len;
298
299     if ((sd->dacl_len >= MAX_ACL_LEN) || (offset + sd->dacl_len > size))
300         return FALSE;
301     dacl = sd_get_dacl( sd, &dummy );
302     if (dacl && !acl_is_valid( dacl, sd->dacl_len ))
303         return FALSE;
304     offset += sd->dacl_len;
305
306     return TRUE;
307 }
308
309 /* determines whether an object_attributes struct is valid in a buffer
310  * and calls set_error appropriately */
311 int objattr_is_valid( const struct object_attributes *objattr, data_size_t size )
312 {
313     if ((size < sizeof(*objattr)) || (size - sizeof(*objattr) < objattr->sd_len) ||
314         (size - sizeof(*objattr) - objattr->sd_len < objattr->name_len))
315     {
316         set_error( STATUS_ACCESS_VIOLATION );
317         return FALSE;
318     }
319
320     if (objattr->sd_len)
321     {
322         const struct security_descriptor *sd = (const struct security_descriptor *)(objattr + 1);
323         if (!sd_is_valid( sd, objattr->sd_len ))
324         {
325             set_error( STATUS_INVALID_SECURITY_DESCR );
326             return FALSE;
327         }
328     }
329
330     return TRUE;
331 }
332
333 /* maps from generic rights to specific rights as given by a mapping */
334 static inline void map_generic_mask(unsigned int *mask, const GENERIC_MAPPING *mapping)
335 {
336     if (*mask & GENERIC_READ) *mask |= mapping->GenericRead;
337     if (*mask & GENERIC_WRITE) *mask |= mapping->GenericWrite;
338     if (*mask & GENERIC_EXECUTE) *mask |= mapping->GenericExecute;
339     if (*mask & GENERIC_ALL) *mask |= mapping->GenericAll;
340     *mask &= 0x0FFFFFFF;
341 }
342
343 static inline int is_equal_luid( const LUID *luid1, const LUID *luid2 )
344 {
345     return (luid1->LowPart == luid2->LowPart && luid1->HighPart == luid2->HighPart);
346 }
347
348 static inline void allocate_luid( luid_t *luid )
349 {
350     prev_luid_value.low_part++;
351     *luid = prev_luid_value;
352 }
353
354 DECL_HANDLER( allocate_locally_unique_id )
355 {
356     allocate_luid( &reply->luid );
357 }
358
359 static inline void luid_and_attr_from_privilege( LUID_AND_ATTRIBUTES *out, const struct privilege *in)
360 {
361     out->Luid = in->luid;
362     out->Attributes =
363         (in->enabled ? SE_PRIVILEGE_ENABLED : 0) |
364         (in->def ? SE_PRIVILEGE_ENABLED_BY_DEFAULT : 0);
365 }
366
367 static struct privilege *privilege_add( struct token *token, const LUID *luid, int enabled )
368 {
369     struct privilege *privilege = mem_alloc( sizeof(*privilege) );
370     if (privilege)
371     {
372         privilege->luid = *luid;
373         privilege->def = privilege->enabled = (enabled != 0);
374         list_add_tail( &token->privileges, &privilege->entry );
375     }
376     return privilege;
377 }
378
379 static inline void privilege_remove( struct privilege *privilege )
380 {
381     list_remove( &privilege->entry );
382     free( privilege );
383 }
384
385 static void token_destroy( struct object *obj )
386 {
387     struct token* token;
388     struct list *cursor, *cursor_next;
389
390     assert( obj->ops == &token_ops );
391     token = (struct token *)obj;
392
393     free( token->user );
394
395     LIST_FOR_EACH_SAFE( cursor, cursor_next, &token->privileges )
396     {
397         struct privilege *privilege = LIST_ENTRY( cursor, struct privilege, entry );
398         privilege_remove( privilege );
399     }
400
401     LIST_FOR_EACH_SAFE( cursor, cursor_next, &token->groups )
402     {
403         struct group *group = LIST_ENTRY( cursor, struct group, entry );
404         list_remove( &group->entry );
405         free( group );
406     }
407
408     free( token->default_dacl );
409 }
410
411 /* creates a new token.
412  *  groups may be NULL if group_count is 0.
413  *  privs may be NULL if priv_count is 0.
414  *  default_dacl may be NULL, indicating that all objects created by the user
415  *   are unsecured.
416  *  modified_id may be NULL, indicating that a new modified_id luid should be
417  *   allocated.
418  */
419 static struct token *create_token( unsigned primary, const SID *user,
420                                    const SID_AND_ATTRIBUTES *groups, unsigned int group_count,
421                                    const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count,
422                                    const ACL *default_dacl, TOKEN_SOURCE source,
423                                    const luid_t *modified_id,
424                                    SECURITY_IMPERSONATION_LEVEL impersonation_level )
425 {
426     struct token *token = alloc_object( &token_ops );
427     if (token)
428     {
429         unsigned int i;
430
431         allocate_luid( &token->token_id );
432         if (modified_id)
433             token->modified_id = *modified_id;
434         else
435             allocate_luid( &token->modified_id );
436         list_init( &token->privileges );
437         list_init( &token->groups );
438         token->primary = primary;
439         /* primary tokens don't have impersonation levels */
440         if (primary)
441             token->impersonation_level = -1;
442         else
443             token->impersonation_level = impersonation_level;
444         token->default_dacl = NULL;
445         token->primary_group = NULL;
446
447         /* copy user */
448         token->user = memdup( user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
449         if (!token->user)
450         {
451             release_object( token );
452             return NULL;
453         }
454
455         /* copy groups */
456         for (i = 0; i < group_count; i++)
457         {
458             size_t size = FIELD_OFFSET( struct group, sid.SubAuthority[((const SID *)groups[i].Sid)->SubAuthorityCount] );
459             struct group *group = mem_alloc( size );
460
461             if (!group)
462             {
463                 release_object( token );
464                 return NULL;
465             }
466             memcpy( &group->sid, groups[i].Sid, FIELD_OFFSET( SID, SubAuthority[((const SID *)groups[i].Sid)->SubAuthorityCount] ) );
467             group->enabled = TRUE;
468             group->def = TRUE;
469             group->logon = (groups[i].Attributes & SE_GROUP_LOGON_ID) ? TRUE : FALSE;
470             group->mandatory = (groups[i].Attributes & SE_GROUP_MANDATORY) ? TRUE : FALSE;
471             group->owner = groups[i].Attributes & SE_GROUP_OWNER ? TRUE : FALSE;
472             group->resource = FALSE;
473             group->deny_only = FALSE;
474             list_add_tail( &token->groups, &group->entry );
475             /* Use first owner capable group as an owner */
476             if (!token->primary_group && group->owner)
477                 token->primary_group = &group->sid;
478         }
479
480         /* copy privileges */
481         for (i = 0; i < priv_count; i++)
482         {
483             /* note: we don't check uniqueness: the caller must make sure
484              * privs doesn't contain any duplicate luids */
485             if (!privilege_add( token, &privs[i].Luid,
486                                 privs[i].Attributes & SE_PRIVILEGE_ENABLED ))
487             {
488                 release_object( token );
489                 return NULL;
490             }
491         }
492
493         if (default_dacl)
494         {
495             token->default_dacl = memdup( default_dacl, default_dacl->AclSize );
496             if (!token->default_dacl)
497             {
498                 release_object( token );
499                 return NULL;
500             }
501         }
502
503         token->source = source;
504     }
505     return token;
506 }
507
508 struct token *token_duplicate( struct token *src_token, unsigned primary,
509                                SECURITY_IMPERSONATION_LEVEL impersonation_level )
510 {
511     const luid_t *modified_id =
512         primary || (impersonation_level == src_token->impersonation_level) ?
513             &src_token->modified_id : NULL;
514     struct token *token = NULL;
515     struct privilege *privilege;
516     struct group *group;
517
518     if ((impersonation_level < SecurityAnonymous) ||
519         (impersonation_level > SecurityDelegation))
520     {
521         set_error( STATUS_BAD_IMPERSONATION_LEVEL );
522         return NULL;
523     }
524
525     if (primary || (impersonation_level <= src_token->impersonation_level))
526         token = create_token( primary, src_token->user, NULL, 0,
527                               NULL, 0, src_token->default_dacl,
528                               src_token->source, modified_id,
529                               impersonation_level );
530     else set_error( STATUS_BAD_IMPERSONATION_LEVEL );
531
532     if (!token) return token;
533
534     /* copy groups */
535     LIST_FOR_EACH_ENTRY( group, &src_token->groups, struct group, entry )
536     {
537         size_t size = FIELD_OFFSET( struct group, sid.SubAuthority[group->sid.SubAuthorityCount] );
538         struct group *newgroup = mem_alloc( size );
539         if (!newgroup)
540         {
541             release_object( token );
542             return NULL;
543         }
544         memcpy( newgroup, group, size );
545         list_add_tail( &token->groups, &newgroup->entry );
546     }
547     token->primary_group = src_token->primary_group;
548     assert( token->primary_group );
549
550     /* copy privileges */
551     LIST_FOR_EACH_ENTRY( privilege, &src_token->privileges, struct privilege, entry )
552         if (!privilege_add( token, &privilege->luid, privilege->enabled ))
553         {
554             release_object( token );
555             return NULL;
556         }
557
558     return token;
559 }
560
561 static ACL *create_default_dacl( const SID *user )
562 {
563     ACCESS_ALLOWED_ACE *aaa;
564     ACL *default_dacl;
565     SID *sid;
566     size_t default_dacl_size = sizeof(ACL) +
567                                2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
568                                sizeof(local_system_sid) +
569                                FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
570
571     default_dacl = mem_alloc( default_dacl_size );
572     if (!default_dacl) return NULL;
573
574     default_dacl->AclRevision = ACL_REVISION;
575     default_dacl->Sbz1 = 0;
576     default_dacl->AclSize = default_dacl_size;
577     default_dacl->AceCount = 2;
578     default_dacl->Sbz2 = 0;
579
580     /* GENERIC_ALL for Local System */
581     aaa = (ACCESS_ALLOWED_ACE *)(default_dacl + 1);
582     aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
583     aaa->Header.AceFlags = 0;
584     aaa->Header.AceSize = (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
585                           sizeof(local_system_sid);
586     aaa->Mask = GENERIC_ALL;
587     sid = (SID *)&aaa->SidStart;
588     memcpy( sid, &local_system_sid, sizeof(local_system_sid) );
589
590     /* GENERIC_ALL for specified user */
591     aaa = (ACCESS_ALLOWED_ACE *)((char *)aaa + aaa->Header.AceSize);
592     aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
593     aaa->Header.AceFlags = 0;
594     aaa->Header.AceSize = (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
595                           FIELD_OFFSET( SID, SubAuthority[user->SubAuthorityCount] );
596     aaa->Mask = GENERIC_ALL;
597     sid = (SID *)&aaa->SidStart;
598     memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
599
600     return default_dacl;
601 }
602
603 struct sid_data
604 {
605     SID_IDENTIFIER_AUTHORITY idauth;
606     int count;
607     unsigned int subauth[MAX_SUBAUTH_COUNT];
608 };
609
610 struct token *token_create_admin( void )
611 {
612     struct token *token = NULL;
613     static const SID_IDENTIFIER_AUTHORITY nt_authority = { SECURITY_NT_AUTHORITY };
614     static const unsigned int alias_admins_subauth[] = { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS };
615     static const unsigned int alias_users_subauth[] = { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS };
616     /* on Windows, this value changes every time the user logs on */
617     static const unsigned int logon_subauth[] = { SECURITY_LOGON_IDS_RID, 0, 1 /* FIXME: should be randomly generated when tokens are inherited by new processes */ };
618     PSID alias_admins_sid;
619     PSID alias_users_sid;
620     PSID logon_sid;
621     /* note: should be the owner specified in the token */
622     ACL *default_dacl = create_default_dacl( &interactive_sid );
623
624     alias_admins_sid = security_sid_alloc( &nt_authority, sizeof(alias_admins_subauth)/sizeof(alias_admins_subauth[0]),
625                                            alias_admins_subauth );
626     alias_users_sid = security_sid_alloc( &nt_authority, sizeof(alias_users_subauth)/sizeof(alias_users_subauth[0]),
627                                           alias_users_subauth );
628     logon_sid = security_sid_alloc( &nt_authority, sizeof(logon_subauth)/sizeof(logon_subauth[0]),
629                                     logon_subauth );
630
631     if (alias_admins_sid && alias_users_sid && logon_sid && default_dacl)
632     {
633         const LUID_AND_ATTRIBUTES admin_privs[] =
634         {
635             { SeChangeNotifyPrivilege        , SE_PRIVILEGE_ENABLED },
636             { SeSecurityPrivilege            , 0                    },
637             { SeBackupPrivilege              , 0                    },
638             { SeRestorePrivilege             , 0                    },
639             { SeSystemtimePrivilege          , 0                    },
640             { SeShutdownPrivilege            , 0                    },
641             { SeRemoteShutdownPrivilege      , 0                    },
642             { SeTakeOwnershipPrivilege       , 0                    },
643             { SeDebugPrivilege               , 0                    },
644             { SeSystemEnvironmentPrivilege   , 0                    },
645             { SeSystemProfilePrivilege       , 0                    },
646             { SeProfileSingleProcessPrivilege, 0                    },
647             { SeIncreaseBasePriorityPrivilege, 0                    },
648             { SeLoadDriverPrivilege          , SE_PRIVILEGE_ENABLED },
649             { SeCreatePagefilePrivilege      , 0                    },
650             { SeIncreaseQuotaPrivilege       , 0                    },
651             { SeUndockPrivilege              , 0                    },
652             { SeManageVolumePrivilege        , 0                    },
653             { SeImpersonatePrivilege         , SE_PRIVILEGE_ENABLED },
654             { SeCreateGlobalPrivilege        , SE_PRIVILEGE_ENABLED },
655         };
656         /* note: we don't include non-builtin groups here for the user -
657          * telling us these is the job of a client-side program */
658         const SID_AND_ATTRIBUTES admin_groups[] =
659         {
660             { security_world_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
661             { security_local_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
662             { security_interactive_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
663             { security_authenticated_user_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
664             { alias_admins_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY|SE_GROUP_OWNER },
665             { alias_users_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
666             { logon_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY|SE_GROUP_LOGON_ID },
667         };
668         static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}};
669         token = create_token( TRUE, security_unix_uid_to_sid( getuid() ),
670                             admin_groups, sizeof(admin_groups)/sizeof(admin_groups[0]),
671                             admin_privs, sizeof(admin_privs)/sizeof(admin_privs[0]),
672                             default_dacl, admin_source, NULL, -1 );
673         /* we really need a primary group */
674         assert( token->primary_group );
675     }
676
677     free( logon_sid );
678     free( alias_admins_sid );
679     free( alias_users_sid );
680     free( default_dacl );
681
682     return token;
683 }
684
685 static struct privilege *token_find_privilege( struct token *token, const LUID *luid, int enabled_only )
686 {
687     struct privilege *privilege;
688     LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
689     {
690         if (is_equal_luid( luid, &privilege->luid ))
691         {
692             if (enabled_only && !privilege->enabled)
693                 return NULL;
694             return privilege;
695         }
696     }
697     return NULL;
698 }
699
700 static unsigned int token_adjust_privileges( struct token *token, const LUID_AND_ATTRIBUTES *privs,
701                                              unsigned int count, LUID_AND_ATTRIBUTES *mod_privs,
702                                              unsigned int mod_privs_count )
703 {
704     unsigned int i, modified_count = 0;
705
706     /* mark as modified */
707     allocate_luid( &token->modified_id );
708
709     for (i = 0; i < count; i++)
710     {
711         struct privilege *privilege =
712             token_find_privilege( token, &privs[i].Luid, FALSE );
713         if (!privilege)
714         {
715             set_error( STATUS_NOT_ALL_ASSIGNED );
716             continue;
717         }
718
719         if (privs[i].Attributes & SE_PRIVILEGE_REMOVE)
720             privilege_remove( privilege );
721         else
722         {
723             /* save previous state for caller */
724             if (mod_privs_count)
725             {
726                 luid_and_attr_from_privilege(mod_privs, privilege);
727                 mod_privs++;
728                 mod_privs_count--;
729                 modified_count++;
730             }
731
732             if (privs[i].Attributes & SE_PRIVILEGE_ENABLED)
733                 privilege->enabled = TRUE;
734             else
735                 privilege->enabled = FALSE;
736         }
737     }
738     return modified_count;
739 }
740
741 static void token_disable_privileges( struct token *token )
742 {
743     struct privilege *privilege;
744
745     /* mark as modified */
746     allocate_luid( &token->modified_id );
747
748     LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
749         privilege->enabled = FALSE;
750 }
751
752 int token_check_privileges( struct token *token, int all_required,
753                             const LUID_AND_ATTRIBUTES *reqprivs,
754                             unsigned int count, LUID_AND_ATTRIBUTES *usedprivs)
755 {
756     unsigned int i, enabled_count = 0;
757
758     for (i = 0; i < count; i++)
759     {
760         struct privilege *privilege = 
761             token_find_privilege( token, &reqprivs[i].Luid, TRUE );
762
763         if (usedprivs)
764             usedprivs[i] = reqprivs[i];
765
766         if (privilege && privilege->enabled)
767         {
768             enabled_count++;
769             if (usedprivs)
770                 usedprivs[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
771         }
772     }
773
774     if (all_required)
775         return (enabled_count == count);
776     else
777         return (enabled_count > 0);
778 }
779
780 static int token_sid_present( struct token *token, const SID *sid, int deny )
781 {
782     struct group *group;
783
784     if (security_equal_sid( token->user, sid )) return TRUE;
785
786     LIST_FOR_EACH_ENTRY( group, &token->groups, struct group, entry )
787     {
788         if (!group->enabled) continue;
789         if (group->deny_only && !deny) continue;
790
791         if (security_equal_sid( &group->sid, sid )) return TRUE;
792     }
793
794     return FALSE;
795 }
796
797 /* Checks access to a security descriptor. 'sd' must have been validated by
798  * caller. It returns STATUS_SUCCESS if call succeeded or an error indicating
799  * the reason. 'status' parameter will indicate if access is granted or denied.
800  *
801  * If both returned value and 'status' are STATUS_SUCCESS then access is granted.
802  */
803 static unsigned int token_access_check( struct token *token,
804                                  const struct security_descriptor *sd,
805                                  unsigned int desired_access,
806                                  LUID_AND_ATTRIBUTES *privs,
807                                  unsigned int *priv_count,
808                                  const GENERIC_MAPPING *mapping,
809                                  unsigned int *granted_access,
810                                  unsigned int *status )
811 {
812     unsigned int current_access = 0;
813     unsigned int denied_access = 0;
814     ULONG i;
815     const ACL *dacl;
816     int dacl_present;
817     const ACE_HEADER *ace;
818     const SID *owner;
819
820     /* assume no access rights */
821     *granted_access = 0;
822
823     /* fail if desired_access contains generic rights */
824     if (desired_access & (GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|GENERIC_ALL))
825     {
826         *priv_count = 0;
827         return STATUS_GENERIC_NOT_MAPPED;
828     }
829
830     dacl = sd_get_dacl( sd, &dacl_present );
831     owner = sd_get_owner( sd );
832     if (!owner || !sd_get_group( sd ))
833     {
834         *priv_count = 0;
835         return STATUS_INVALID_SECURITY_DESCR;
836     }
837
838     /* 1: Grant desired access if the object is unprotected */
839     if (!dacl_present || !dacl)
840     {
841         *priv_count = 0;
842         *granted_access = desired_access;
843         return *status = STATUS_SUCCESS;
844     }
845
846     /* 2: Check if caller wants access to system security part. Note: access
847      * is only granted if specifically asked for */
848     if (desired_access & ACCESS_SYSTEM_SECURITY)
849     {
850         const LUID_AND_ATTRIBUTES security_priv = { SeSecurityPrivilege, 0 };
851         LUID_AND_ATTRIBUTES retpriv = security_priv;
852         if (token_check_privileges( token, TRUE, &security_priv, 1, &retpriv ))
853         {
854             if (priv_count)
855             {
856                 /* assumes that there will only be one privilege to return */
857                 if (*priv_count >= 1)
858                 {
859                     *priv_count = 1;
860                     *privs = retpriv;
861                 }
862                 else
863                 {
864                     *priv_count = 1;
865                     return STATUS_BUFFER_TOO_SMALL;
866                 }
867             }
868             current_access |= ACCESS_SYSTEM_SECURITY;
869             if (desired_access == current_access)
870             {
871                 *granted_access = current_access;
872                 return *status = STATUS_SUCCESS;
873             }
874         }
875         else
876         {
877             *priv_count = 0;
878             *status = STATUS_PRIVILEGE_NOT_HELD;
879             return STATUS_SUCCESS;
880         }
881     }
882     else if (priv_count) *priv_count = 0;
883
884     /* 3: Check whether the token is the owner */
885     /* NOTE: SeTakeOwnershipPrivilege is not checked for here - it is instead
886      * checked when a "set owner" call is made, overriding the access rights
887      * determined here. */
888     if (token_sid_present( token, owner, FALSE ))
889     {
890         current_access |= (READ_CONTROL | WRITE_DAC);
891         if (desired_access == current_access)
892         {
893             *granted_access = current_access;
894             return *status = STATUS_SUCCESS;
895         }
896     }
897
898     /* 4: Grant rights according to the DACL */
899     ace = (const ACE_HEADER *)(dacl + 1);
900     for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
901     {
902         const ACCESS_ALLOWED_ACE *aa_ace;
903         const ACCESS_DENIED_ACE *ad_ace;
904         const SID *sid;
905
906         if (ace->AceFlags & INHERIT_ONLY_ACE)
907             continue;
908
909         switch (ace->AceType)
910         {
911         case ACCESS_DENIED_ACE_TYPE:
912             ad_ace = (const ACCESS_DENIED_ACE *)ace;
913             sid = (const SID *)&ad_ace->SidStart;
914             if (token_sid_present( token, sid, TRUE ))
915             {
916                 unsigned int access = ad_ace->Mask;
917                 map_generic_mask(&access, mapping);
918                 if (desired_access & MAXIMUM_ALLOWED)
919                     denied_access |= access;
920                 else
921                 {
922                     denied_access |= (access & ~current_access);
923                     if (desired_access & access) goto done;
924                 }
925             }
926             break;
927         case ACCESS_ALLOWED_ACE_TYPE:
928             aa_ace = (const ACCESS_ALLOWED_ACE *)ace;
929             sid = (const SID *)&aa_ace->SidStart;
930             if (token_sid_present( token, sid, FALSE ))
931             {
932                 unsigned int access = aa_ace->Mask;
933                 map_generic_mask(&access, mapping);
934                 if (desired_access & MAXIMUM_ALLOWED)
935                     current_access |= access;
936                 else
937                     current_access |= (access & ~denied_access);
938             }
939             break;
940         }
941
942         /* don't bother carrying on checking if we've already got all of
943             * rights we need */
944         if (desired_access == *granted_access)
945             break;
946     }
947
948 done:
949     if (desired_access & MAXIMUM_ALLOWED)
950         *granted_access = current_access & ~denied_access;
951     else
952         if ((current_access & desired_access) == desired_access)
953             *granted_access = current_access & desired_access;
954         else
955             *granted_access = 0;
956
957     *status = *granted_access ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
958     return STATUS_SUCCESS;
959 }
960
961 const ACL *token_get_default_dacl( struct token *token )
962 {
963     return token->default_dacl;
964 }
965
966 const SID *token_get_user( struct token *token )
967 {
968     return token->user;
969 }
970
971 const SID *token_get_primary_group( struct token *token )
972 {
973     return token->primary_group;
974 }
975
976 int check_object_access(struct object *obj, unsigned int *access)
977 {
978     GENERIC_MAPPING mapping;
979     struct token *token = current->token ? current->token : current->process->token;
980     LUID_AND_ATTRIBUTES priv;
981     unsigned int status, priv_count = 1;
982     int res;
983
984     mapping.GenericAll = obj->ops->map_access( obj, GENERIC_ALL );
985
986     if (!obj->sd)
987     {
988         if (*access & MAXIMUM_ALLOWED)
989             *access = mapping.GenericAll;
990         return TRUE;
991     }
992
993     mapping.GenericRead  = obj->ops->map_access( obj, GENERIC_READ );
994     mapping.GenericWrite = obj->ops->map_access( obj, GENERIC_WRITE );
995     mapping.GenericExecute = obj->ops->map_access( obj, GENERIC_EXECUTE );
996
997     res = token_access_check( token, obj->sd, *access, &priv, &priv_count,
998                               &mapping, access, &status ) == STATUS_SUCCESS &&
999           status == STATUS_SUCCESS;
1000
1001     if (!res) set_error( STATUS_ACCESS_DENIED );
1002     return res;
1003 }
1004
1005
1006 /* open a security token */
1007 DECL_HANDLER(open_token)
1008 {
1009     if (req->flags & OPEN_TOKEN_THREAD)
1010     {
1011         struct thread *thread = get_thread_from_handle( req->handle, 0 );
1012         if (thread)
1013         {
1014             if (thread->token)
1015             {
1016                 if (thread->token->impersonation_level <= SecurityAnonymous)
1017                     set_error( STATUS_CANT_OPEN_ANONYMOUS );
1018                 else
1019                     reply->token = alloc_handle( current->process, thread->token,
1020                                                  req->access, req->attributes );
1021             }
1022             else
1023                 set_error( STATUS_NO_TOKEN );
1024             release_object( thread );
1025         }
1026     }
1027     else
1028     {
1029         struct process *process = get_process_from_handle( req->handle, 0 );
1030         if (process)
1031         {
1032             if (process->token)
1033                 reply->token = alloc_handle( current->process, process->token, req->access,
1034                                              req->attributes );
1035             else
1036                 set_error( STATUS_NO_TOKEN );
1037             release_object( process );
1038         }
1039     }
1040 }
1041
1042 /* adjust the privileges held by a token */
1043 DECL_HANDLER(adjust_token_privileges)
1044 {
1045     struct token *token;
1046     unsigned int access = TOKEN_ADJUST_PRIVILEGES;
1047
1048     if (req->get_modified_state) access |= TOKEN_QUERY;
1049
1050     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1051                                                  access, &token_ops )))
1052     {
1053         const LUID_AND_ATTRIBUTES *privs = get_req_data();
1054         LUID_AND_ATTRIBUTES *modified_privs = NULL;
1055         unsigned int priv_count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
1056         unsigned int modified_priv_count = 0;
1057
1058         if (req->get_modified_state && !req->disable_all)
1059         {
1060             unsigned int i;
1061             /* count modified privs */
1062             for (i = 0; i < priv_count; i++)
1063             {
1064                 struct privilege *privilege =
1065                     token_find_privilege( token, &privs[i].Luid, FALSE );
1066                 if (privilege && req->get_modified_state)
1067                     modified_priv_count++;
1068             }
1069             reply->len = modified_priv_count;
1070             modified_priv_count = min( modified_priv_count, get_reply_max_size() / sizeof(*modified_privs) );
1071             if (modified_priv_count)
1072                 modified_privs = set_reply_data_size( modified_priv_count * sizeof(*modified_privs) );
1073         }
1074         reply->len = modified_priv_count * sizeof(*modified_privs);
1075
1076         if (req->disable_all)
1077             token_disable_privileges( token );
1078         else
1079             modified_priv_count = token_adjust_privileges( token, privs,
1080                 priv_count, modified_privs, modified_priv_count );
1081
1082         release_object( token );
1083     }
1084 }
1085
1086 /* retrieves the list of privileges that may be held be the token */
1087 DECL_HANDLER(get_token_privileges)
1088 {
1089     struct token *token;
1090
1091     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1092                                                  TOKEN_QUERY,
1093                                                  &token_ops )))
1094     {
1095         int priv_count = 0;
1096         LUID_AND_ATTRIBUTES *privs;
1097         struct privilege *privilege;
1098
1099         LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
1100             priv_count++;
1101
1102         reply->len = priv_count * sizeof(*privs);
1103         if (reply->len <= get_reply_max_size())
1104         {
1105             privs = set_reply_data_size( priv_count * sizeof(*privs) );
1106             if (privs)
1107             {
1108                 int i = 0;
1109                 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
1110                 {
1111                     luid_and_attr_from_privilege( &privs[i], privilege );
1112                     i++;
1113                 }
1114             }
1115         }
1116         else
1117             set_error(STATUS_BUFFER_TOO_SMALL);
1118
1119         release_object( token );
1120     }
1121 }
1122
1123 /* creates a duplicate of the token */
1124 DECL_HANDLER(duplicate_token)
1125 {
1126     struct token *src_token;
1127
1128     if ((src_token = (struct token *)get_handle_obj( current->process, req->handle,
1129                                                      TOKEN_DUPLICATE,
1130                                                      &token_ops )))
1131     {
1132         struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level );
1133         if (token)
1134         {
1135             reply->new_handle = alloc_handle( current->process, token, req->access, req->attributes);
1136             release_object( token );
1137         }
1138         release_object( src_token );
1139     }
1140 }
1141
1142 /* checks the specified privileges are held by the token */
1143 DECL_HANDLER(check_token_privileges)
1144 {
1145     struct token *token;
1146
1147     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1148                                                  TOKEN_QUERY,
1149                                                  &token_ops )))
1150     {
1151         unsigned int count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
1152
1153         if (!token->primary && token->impersonation_level <= SecurityAnonymous)
1154             set_error( STATUS_BAD_IMPERSONATION_LEVEL );
1155         else if (get_reply_max_size() >= count * sizeof(LUID_AND_ATTRIBUTES))
1156         {
1157             LUID_AND_ATTRIBUTES *usedprivs = set_reply_data_size( count * sizeof(*usedprivs) );
1158             reply->has_privileges = token_check_privileges( token, req->all_required, get_req_data(), count, usedprivs );
1159         }
1160         else
1161             set_error( STATUS_BUFFER_OVERFLOW );
1162         release_object( token );
1163     }
1164 }
1165
1166 /* checks that a user represented by a token is allowed to access an object
1167  * represented by a security descriptor */
1168 DECL_HANDLER(access_check)
1169 {
1170     data_size_t sd_size = get_req_data_size();
1171     const struct security_descriptor *sd = get_req_data();
1172     struct token *token;
1173
1174     if (!sd_is_valid( sd, sd_size ))
1175     {
1176         set_error( STATUS_ACCESS_VIOLATION );
1177         return;
1178     }
1179
1180     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1181                                                  TOKEN_QUERY,
1182                                                  &token_ops )))
1183     {
1184         GENERIC_MAPPING mapping;
1185         unsigned int status;
1186         LUID_AND_ATTRIBUTES priv;
1187         unsigned int priv_count = 1;
1188
1189         memset(&priv, 0, sizeof(priv));
1190
1191         /* only impersonation tokens may be used with this function */
1192         if (token->primary)
1193         {
1194             set_error( STATUS_NO_IMPERSONATION_TOKEN );
1195             release_object( token );
1196             return;
1197         }
1198         /* anonymous impersonation tokens can't be used */
1199         if (token->impersonation_level <= SecurityAnonymous)
1200         {
1201             set_error( STATUS_BAD_IMPERSONATION_LEVEL );
1202             release_object( token );
1203             return;
1204         }
1205
1206         mapping.GenericRead = req->mapping_read;
1207         mapping.GenericWrite = req->mapping_write;
1208         mapping.GenericExecute = req->mapping_execute;
1209         mapping.GenericAll = req->mapping_all;
1210
1211         status = token_access_check(
1212             token, sd, req->desired_access, &priv, &priv_count, &mapping,
1213             &reply->access_granted, &reply->access_status );
1214
1215         reply->privileges_len = priv_count*sizeof(LUID_AND_ATTRIBUTES);
1216
1217         if ((priv_count > 0) && (reply->privileges_len <= get_reply_max_size()))
1218         {
1219             LUID_AND_ATTRIBUTES *privs = set_reply_data_size( priv_count * sizeof(*privs) );
1220             memcpy( privs, &priv, sizeof(priv) );
1221         }
1222
1223         set_error( status );
1224         release_object( token );
1225     }
1226 }
1227
1228 /* retrieves the SID of the user that the token represents */
1229 DECL_HANDLER(get_token_user)
1230 {
1231     struct token *token;
1232
1233     reply->user_len = 0;
1234
1235     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1236                                                  TOKEN_QUERY,
1237                                                  &token_ops )))
1238     {
1239         const SID *user = token->user;
1240
1241         reply->user_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
1242         if (reply->user_len <= get_reply_max_size())
1243         {
1244             SID *user_reply = set_reply_data_size( reply->user_len );
1245             if (user_reply)
1246                 memcpy( user_reply, user, reply->user_len );
1247         }
1248         else set_error( STATUS_BUFFER_TOO_SMALL );
1249
1250         release_object( token );
1251     }
1252 }
1253
1254 /* retrieves the groups that the user represented by the token belongs to */
1255 DECL_HANDLER(get_token_groups)
1256 {
1257     struct token *token;
1258
1259     reply->user_len = 0;
1260
1261     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1262                                                  TOKEN_QUERY,
1263                                                  &token_ops )))
1264     {
1265         size_t size_needed = sizeof(struct token_groups);
1266         unsigned int group_count = 0;
1267         const struct group *group;
1268
1269         LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
1270         {
1271             group_count++;
1272             size_needed += FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]);
1273         }
1274         size_needed += sizeof(unsigned int) * group_count;
1275
1276         reply->user_len = size_needed;
1277
1278         if (size_needed <= get_reply_max_size())
1279         {
1280             struct token_groups *tg = set_reply_data_size( size_needed );
1281             if (tg)
1282             {
1283                 unsigned int *attr_ptr = (unsigned int *)(tg + 1);
1284                 SID *sid_ptr = (SID *)(attr_ptr + group_count);
1285
1286                 tg->count = group_count;
1287
1288                 LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
1289                 {
1290
1291                     *attr_ptr = 0;
1292                     if (group->mandatory) *attr_ptr |= SE_GROUP_MANDATORY;
1293                     if (group->def) *attr_ptr |= SE_GROUP_ENABLED_BY_DEFAULT;
1294                     if (group->enabled) *attr_ptr |= SE_GROUP_ENABLED;
1295                     if (group->owner) *attr_ptr |= SE_GROUP_OWNER;
1296                     if (group->deny_only) *attr_ptr |= SE_GROUP_USE_FOR_DENY_ONLY;
1297                     if (group->resource) *attr_ptr |= SE_GROUP_RESOURCE;
1298                     if (group->logon) *attr_ptr |= SE_GROUP_LOGON_ID;
1299
1300                     memcpy(sid_ptr, &group->sid, FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]));
1301
1302                     sid_ptr = (SID *)((char *)sid_ptr + FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]));
1303                     attr_ptr++;
1304                 }
1305             }
1306         }
1307         else set_error( STATUS_BUFFER_TOO_SMALL );
1308
1309         release_object( token );
1310     }
1311 }
1312
1313 DECL_HANDLER(get_token_impersonation_level)
1314 {
1315     struct token *token;
1316
1317     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1318                                                  TOKEN_QUERY,
1319                                                  &token_ops )))
1320     {
1321         if (token->primary)
1322             set_error( STATUS_INVALID_PARAMETER );
1323         else
1324             reply->impersonation_level = token->impersonation_level;
1325
1326         release_object( token );
1327     }
1328 }
1329
1330 DECL_HANDLER(get_token_statistics)
1331 {
1332     struct token *token;
1333
1334     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1335                                                  TOKEN_QUERY,
1336                                                  &token_ops )))
1337     {
1338         reply->token_id = token->token_id;
1339         reply->modified_id = token->modified_id;
1340         reply->primary = token->primary;
1341         reply->impersonation_level = token->impersonation_level;
1342         reply->group_count = list_count( &token->groups );
1343         reply->privilege_count = list_count( &token->privileges );
1344
1345         release_object( token );
1346     }
1347 }