msxml3: Remove redundant NULL checks before HeapFree and fix a memleak (Smatch).
[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     int            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                                    int 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                                int 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 (!primary &&
519         (impersonation_level < SecurityAnonymous ||
520          impersonation_level > SecurityDelegation ||
521          (!src_token->primary && (impersonation_level > src_token->impersonation_level))))
522     {
523         set_error( STATUS_BAD_IMPERSONATION_LEVEL );
524         return NULL;
525     }
526
527     token = create_token( primary, src_token->user, NULL, 0,
528                           NULL, 0, src_token->default_dacl,
529                           src_token->source, modified_id,
530                           impersonation_level );
531     if (!token) return token;
532
533     /* copy groups */
534     LIST_FOR_EACH_ENTRY( group, &src_token->groups, struct group, entry )
535     {
536         size_t size = FIELD_OFFSET( struct group, sid.SubAuthority[group->sid.SubAuthorityCount] );
537         struct group *newgroup = mem_alloc( size );
538         if (!newgroup)
539         {
540             release_object( token );
541             return NULL;
542         }
543         memcpy( newgroup, group, size );
544         list_add_tail( &token->groups, &newgroup->entry );
545     }
546     token->primary_group = src_token->primary_group;
547     assert( token->primary_group );
548
549     /* copy privileges */
550     LIST_FOR_EACH_ENTRY( privilege, &src_token->privileges, struct privilege, entry )
551         if (!privilege_add( token, &privilege->luid, privilege->enabled ))
552         {
553             release_object( token );
554             return NULL;
555         }
556
557     return token;
558 }
559
560 static ACL *create_default_dacl( const SID *user )
561 {
562     ACCESS_ALLOWED_ACE *aaa;
563     ACL *default_dacl;
564     SID *sid;
565     size_t default_dacl_size = sizeof(ACL) +
566                                2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
567                                sizeof(local_system_sid) +
568                                FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
569
570     default_dacl = mem_alloc( default_dacl_size );
571     if (!default_dacl) return NULL;
572
573     default_dacl->AclRevision = ACL_REVISION;
574     default_dacl->Sbz1 = 0;
575     default_dacl->AclSize = default_dacl_size;
576     default_dacl->AceCount = 2;
577     default_dacl->Sbz2 = 0;
578
579     /* GENERIC_ALL for Local System */
580     aaa = (ACCESS_ALLOWED_ACE *)(default_dacl + 1);
581     aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
582     aaa->Header.AceFlags = 0;
583     aaa->Header.AceSize = (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
584                           sizeof(local_system_sid);
585     aaa->Mask = GENERIC_ALL;
586     sid = (SID *)&aaa->SidStart;
587     memcpy( sid, &local_system_sid, sizeof(local_system_sid) );
588
589     /* GENERIC_ALL for specified user */
590     aaa = (ACCESS_ALLOWED_ACE *)((char *)aaa + aaa->Header.AceSize);
591     aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
592     aaa->Header.AceFlags = 0;
593     aaa->Header.AceSize = (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
594                           FIELD_OFFSET( SID, SubAuthority[user->SubAuthorityCount] );
595     aaa->Mask = GENERIC_ALL;
596     sid = (SID *)&aaa->SidStart;
597     memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
598
599     return default_dacl;
600 }
601
602 struct sid_data
603 {
604     SID_IDENTIFIER_AUTHORITY idauth;
605     int count;
606     unsigned int subauth[MAX_SUBAUTH_COUNT];
607 };
608
609 struct token *token_create_admin( void )
610 {
611     struct token *token = NULL;
612     static const SID_IDENTIFIER_AUTHORITY nt_authority = { SECURITY_NT_AUTHORITY };
613     static const unsigned int alias_admins_subauth[] = { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS };
614     static const unsigned int alias_users_subauth[] = { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS };
615     /* on Windows, this value changes every time the user logs on */
616     static const unsigned int logon_subauth[] = { SECURITY_LOGON_IDS_RID, 0, 1 /* FIXME: should be randomly generated when tokens are inherited by new processes */ };
617     PSID alias_admins_sid;
618     PSID alias_users_sid;
619     PSID logon_sid;
620     /* note: should be the owner specified in the token */
621     ACL *default_dacl = create_default_dacl( &interactive_sid );
622
623     alias_admins_sid = security_sid_alloc( &nt_authority, sizeof(alias_admins_subauth)/sizeof(alias_admins_subauth[0]),
624                                            alias_admins_subauth );
625     alias_users_sid = security_sid_alloc( &nt_authority, sizeof(alias_users_subauth)/sizeof(alias_users_subauth[0]),
626                                           alias_users_subauth );
627     logon_sid = security_sid_alloc( &nt_authority, sizeof(logon_subauth)/sizeof(logon_subauth[0]),
628                                     logon_subauth );
629
630     if (alias_admins_sid && alias_users_sid && logon_sid && default_dacl)
631     {
632         const LUID_AND_ATTRIBUTES admin_privs[] =
633         {
634             { SeChangeNotifyPrivilege        , SE_PRIVILEGE_ENABLED },
635             { SeSecurityPrivilege            , 0                    },
636             { SeBackupPrivilege              , 0                    },
637             { SeRestorePrivilege             , 0                    },
638             { SeSystemtimePrivilege          , 0                    },
639             { SeShutdownPrivilege            , 0                    },
640             { SeRemoteShutdownPrivilege      , 0                    },
641             { SeTakeOwnershipPrivilege       , 0                    },
642             { SeDebugPrivilege               , 0                    },
643             { SeSystemEnvironmentPrivilege   , 0                    },
644             { SeSystemProfilePrivilege       , 0                    },
645             { SeProfileSingleProcessPrivilege, 0                    },
646             { SeIncreaseBasePriorityPrivilege, 0                    },
647             { SeLoadDriverPrivilege          , SE_PRIVILEGE_ENABLED },
648             { SeCreatePagefilePrivilege      , 0                    },
649             { SeIncreaseQuotaPrivilege       , 0                    },
650             { SeUndockPrivilege              , 0                    },
651             { SeManageVolumePrivilege        , 0                    },
652             { SeImpersonatePrivilege         , SE_PRIVILEGE_ENABLED },
653             { SeCreateGlobalPrivilege        , SE_PRIVILEGE_ENABLED },
654         };
655         /* note: we don't include non-builtin groups here for the user -
656          * telling us these is the job of a client-side program */
657         const SID_AND_ATTRIBUTES admin_groups[] =
658         {
659             { security_world_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
660             { security_local_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
661             { security_interactive_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
662             { security_authenticated_user_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
663             { alias_admins_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY|SE_GROUP_OWNER },
664             { alias_users_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY },
665             { logon_sid, SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY|SE_GROUP_LOGON_ID },
666         };
667         static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}};
668         token = create_token( TRUE, security_unix_uid_to_sid( getuid() ),
669                             admin_groups, sizeof(admin_groups)/sizeof(admin_groups[0]),
670                             admin_privs, sizeof(admin_privs)/sizeof(admin_privs[0]),
671                             default_dacl, admin_source, NULL, -1 );
672         /* we really need a primary group */
673         assert( token->primary_group );
674     }
675
676     free( logon_sid );
677     free( alias_admins_sid );
678     free( alias_users_sid );
679     free( default_dacl );
680
681     return token;
682 }
683
684 static struct privilege *token_find_privilege( struct token *token, const LUID *luid, int enabled_only )
685 {
686     struct privilege *privilege;
687     LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
688     {
689         if (is_equal_luid( luid, &privilege->luid ))
690         {
691             if (enabled_only && !privilege->enabled)
692                 return NULL;
693             return privilege;
694         }
695     }
696     return NULL;
697 }
698
699 static unsigned int token_adjust_privileges( struct token *token, const LUID_AND_ATTRIBUTES *privs,
700                                              unsigned int count, LUID_AND_ATTRIBUTES *mod_privs,
701                                              unsigned int mod_privs_count )
702 {
703     unsigned int i, modified_count = 0;
704
705     /* mark as modified */
706     allocate_luid( &token->modified_id );
707
708     for (i = 0; i < count; i++)
709     {
710         struct privilege *privilege =
711             token_find_privilege( token, &privs[i].Luid, FALSE );
712         if (!privilege)
713         {
714             set_error( STATUS_NOT_ALL_ASSIGNED );
715             continue;
716         }
717
718         if (privs[i].Attributes & SE_PRIVILEGE_REMOVE)
719             privilege_remove( privilege );
720         else
721         {
722             /* save previous state for caller */
723             if (mod_privs_count)
724             {
725                 luid_and_attr_from_privilege(mod_privs, privilege);
726                 mod_privs++;
727                 mod_privs_count--;
728                 modified_count++;
729             }
730
731             if (privs[i].Attributes & SE_PRIVILEGE_ENABLED)
732                 privilege->enabled = TRUE;
733             else
734                 privilege->enabled = FALSE;
735         }
736     }
737     return modified_count;
738 }
739
740 static void token_disable_privileges( struct token *token )
741 {
742     struct privilege *privilege;
743
744     /* mark as modified */
745     allocate_luid( &token->modified_id );
746
747     LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
748         privilege->enabled = FALSE;
749 }
750
751 int token_check_privileges( struct token *token, int all_required,
752                             const LUID_AND_ATTRIBUTES *reqprivs,
753                             unsigned int count, LUID_AND_ATTRIBUTES *usedprivs)
754 {
755     unsigned int i, enabled_count = 0;
756
757     for (i = 0; i < count; i++)
758     {
759         struct privilege *privilege = 
760             token_find_privilege( token, &reqprivs[i].Luid, TRUE );
761
762         if (usedprivs)
763             usedprivs[i] = reqprivs[i];
764
765         if (privilege && privilege->enabled)
766         {
767             enabled_count++;
768             if (usedprivs)
769                 usedprivs[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
770         }
771     }
772
773     if (all_required)
774         return (enabled_count == count);
775     else
776         return (enabled_count > 0);
777 }
778
779 static int token_sid_present( struct token *token, const SID *sid, int deny )
780 {
781     struct group *group;
782
783     if (security_equal_sid( token->user, sid )) return TRUE;
784
785     LIST_FOR_EACH_ENTRY( group, &token->groups, struct group, entry )
786     {
787         if (!group->enabled) continue;
788         if (group->deny_only && !deny) continue;
789
790         if (security_equal_sid( &group->sid, sid )) return TRUE;
791     }
792
793     return FALSE;
794 }
795
796 /* Checks access to a security descriptor. 'sd' must have been validated by
797  * caller. It returns STATUS_SUCCESS if call succeeded or an error indicating
798  * the reason. 'status' parameter will indicate if access is granted or denied.
799  *
800  * If both returned value and 'status' are STATUS_SUCCESS then access is granted.
801  */
802 static unsigned int token_access_check( struct token *token,
803                                  const struct security_descriptor *sd,
804                                  unsigned int desired_access,
805                                  LUID_AND_ATTRIBUTES *privs,
806                                  unsigned int *priv_count,
807                                  const GENERIC_MAPPING *mapping,
808                                  unsigned int *granted_access,
809                                  unsigned int *status )
810 {
811     unsigned int current_access = 0;
812     unsigned int denied_access = 0;
813     ULONG i;
814     const ACL *dacl;
815     int dacl_present;
816     const ACE_HEADER *ace;
817     const SID *owner;
818
819     /* assume no access rights */
820     *granted_access = 0;
821
822     /* fail if desired_access contains generic rights */
823     if (desired_access & (GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|GENERIC_ALL))
824     {
825         *priv_count = 0;
826         return STATUS_GENERIC_NOT_MAPPED;
827     }
828
829     dacl = sd_get_dacl( sd, &dacl_present );
830     owner = sd_get_owner( sd );
831     if (!owner || !sd_get_group( sd ))
832     {
833         *priv_count = 0;
834         return STATUS_INVALID_SECURITY_DESCR;
835     }
836
837     /* 1: Grant desired access if the object is unprotected */
838     if (!dacl_present || !dacl)
839     {
840         *priv_count = 0;
841         *granted_access = desired_access;
842         return *status = STATUS_SUCCESS;
843     }
844
845     /* 2: Check if caller wants access to system security part. Note: access
846      * is only granted if specifically asked for */
847     if (desired_access & ACCESS_SYSTEM_SECURITY)
848     {
849         const LUID_AND_ATTRIBUTES security_priv = { SeSecurityPrivilege, 0 };
850         LUID_AND_ATTRIBUTES retpriv = security_priv;
851         if (token_check_privileges( token, TRUE, &security_priv, 1, &retpriv ))
852         {
853             if (priv_count)
854             {
855                 /* assumes that there will only be one privilege to return */
856                 if (*priv_count >= 1)
857                 {
858                     *priv_count = 1;
859                     *privs = retpriv;
860                 }
861                 else
862                 {
863                     *priv_count = 1;
864                     return STATUS_BUFFER_TOO_SMALL;
865                 }
866             }
867             current_access |= ACCESS_SYSTEM_SECURITY;
868             if (desired_access == current_access)
869             {
870                 *granted_access = current_access;
871                 return *status = STATUS_SUCCESS;
872             }
873         }
874         else
875         {
876             *priv_count = 0;
877             *status = STATUS_PRIVILEGE_NOT_HELD;
878             return STATUS_SUCCESS;
879         }
880     }
881     else if (priv_count) *priv_count = 0;
882
883     /* 3: Check whether the token is the owner */
884     /* NOTE: SeTakeOwnershipPrivilege is not checked for here - it is instead
885      * checked when a "set owner" call is made, overriding the access rights
886      * determined here. */
887     if (token_sid_present( token, owner, FALSE ))
888     {
889         current_access |= (READ_CONTROL | WRITE_DAC);
890         if (desired_access == current_access)
891         {
892             *granted_access = current_access;
893             return *status = STATUS_SUCCESS;
894         }
895     }
896
897     /* 4: Grant rights according to the DACL */
898     ace = (const ACE_HEADER *)(dacl + 1);
899     for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
900     {
901         const ACCESS_ALLOWED_ACE *aa_ace;
902         const ACCESS_DENIED_ACE *ad_ace;
903         const SID *sid;
904
905         if (ace->AceFlags & INHERIT_ONLY_ACE)
906             continue;
907
908         switch (ace->AceType)
909         {
910         case ACCESS_DENIED_ACE_TYPE:
911             ad_ace = (const ACCESS_DENIED_ACE *)ace;
912             sid = (const SID *)&ad_ace->SidStart;
913             if (token_sid_present( token, sid, TRUE ))
914             {
915                 unsigned int access = ad_ace->Mask;
916                 map_generic_mask(&access, mapping);
917                 if (desired_access & MAXIMUM_ALLOWED)
918                     denied_access |= access;
919                 else
920                 {
921                     denied_access |= (access & ~current_access);
922                     if (desired_access & access) goto done;
923                 }
924             }
925             break;
926         case ACCESS_ALLOWED_ACE_TYPE:
927             aa_ace = (const ACCESS_ALLOWED_ACE *)ace;
928             sid = (const SID *)&aa_ace->SidStart;
929             if (token_sid_present( token, sid, FALSE ))
930             {
931                 unsigned int access = aa_ace->Mask;
932                 map_generic_mask(&access, mapping);
933                 if (desired_access & MAXIMUM_ALLOWED)
934                     current_access |= access;
935                 else
936                     current_access |= (access & ~denied_access);
937             }
938             break;
939         }
940
941         /* don't bother carrying on checking if we've already got all of
942             * rights we need */
943         if (desired_access == *granted_access)
944             break;
945     }
946
947 done:
948     if (desired_access & MAXIMUM_ALLOWED)
949         *granted_access = current_access & ~denied_access;
950     else
951         if ((current_access & desired_access) == desired_access)
952             *granted_access = current_access & desired_access;
953         else
954             *granted_access = 0;
955
956     *status = *granted_access ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
957     return STATUS_SUCCESS;
958 }
959
960 const ACL *token_get_default_dacl( struct token *token )
961 {
962     return token->default_dacl;
963 }
964
965 const SID *token_get_user( struct token *token )
966 {
967     return token->user;
968 }
969
970 const SID *token_get_primary_group( struct token *token )
971 {
972     return token->primary_group;
973 }
974
975 int check_object_access(struct object *obj, unsigned int *access)
976 {
977     GENERIC_MAPPING mapping;
978     struct token *token = current->token ? current->token : current->process->token;
979     LUID_AND_ATTRIBUTES priv;
980     unsigned int status, priv_count = 1;
981     int res;
982
983     mapping.GenericAll = obj->ops->map_access( obj, GENERIC_ALL );
984
985     if (!obj->sd)
986     {
987         if (*access & MAXIMUM_ALLOWED)
988             *access = mapping.GenericAll;
989         return TRUE;
990     }
991
992     mapping.GenericRead  = obj->ops->map_access( obj, GENERIC_READ );
993     mapping.GenericWrite = obj->ops->map_access( obj, GENERIC_WRITE );
994     mapping.GenericExecute = obj->ops->map_access( obj, GENERIC_EXECUTE );
995
996     res = token_access_check( token, obj->sd, *access, &priv, &priv_count,
997                               &mapping, access, &status ) == STATUS_SUCCESS &&
998           status == STATUS_SUCCESS;
999
1000     if (!res) set_error( STATUS_ACCESS_DENIED );
1001     return res;
1002 }
1003
1004
1005 /* open a security token */
1006 DECL_HANDLER(open_token)
1007 {
1008     if (req->flags & OPEN_TOKEN_THREAD)
1009     {
1010         struct thread *thread = get_thread_from_handle( req->handle, 0 );
1011         if (thread)
1012         {
1013             if (thread->token)
1014             {
1015                 if (!thread->token->primary && thread->token->impersonation_level <= SecurityAnonymous)
1016                     set_error( STATUS_CANT_OPEN_ANONYMOUS );
1017                 else
1018                     reply->token = alloc_handle( current->process, thread->token,
1019                                                  req->access, req->attributes );
1020             }
1021             else
1022                 set_error( STATUS_NO_TOKEN );
1023             release_object( thread );
1024         }
1025     }
1026     else
1027     {
1028         struct process *process = get_process_from_handle( req->handle, 0 );
1029         if (process)
1030         {
1031             if (process->token)
1032                 reply->token = alloc_handle( current->process, process->token, req->access,
1033                                              req->attributes );
1034             else
1035                 set_error( STATUS_NO_TOKEN );
1036             release_object( process );
1037         }
1038     }
1039 }
1040
1041 /* adjust the privileges held by a token */
1042 DECL_HANDLER(adjust_token_privileges)
1043 {
1044     struct token *token;
1045     unsigned int access = TOKEN_ADJUST_PRIVILEGES;
1046
1047     if (req->get_modified_state) access |= TOKEN_QUERY;
1048
1049     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1050                                                  access, &token_ops )))
1051     {
1052         const LUID_AND_ATTRIBUTES *privs = get_req_data();
1053         LUID_AND_ATTRIBUTES *modified_privs = NULL;
1054         unsigned int priv_count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
1055         unsigned int modified_priv_count = 0;
1056
1057         if (req->get_modified_state && !req->disable_all)
1058         {
1059             unsigned int i;
1060             /* count modified privs */
1061             for (i = 0; i < priv_count; i++)
1062             {
1063                 struct privilege *privilege =
1064                     token_find_privilege( token, &privs[i].Luid, FALSE );
1065                 if (privilege && req->get_modified_state)
1066                     modified_priv_count++;
1067             }
1068             reply->len = modified_priv_count;
1069             modified_priv_count = min( modified_priv_count, get_reply_max_size() / sizeof(*modified_privs) );
1070             if (modified_priv_count)
1071                 modified_privs = set_reply_data_size( modified_priv_count * sizeof(*modified_privs) );
1072         }
1073         reply->len = modified_priv_count * sizeof(*modified_privs);
1074
1075         if (req->disable_all)
1076             token_disable_privileges( token );
1077         else
1078             modified_priv_count = token_adjust_privileges( token, privs,
1079                 priv_count, modified_privs, modified_priv_count );
1080
1081         release_object( token );
1082     }
1083 }
1084
1085 /* retrieves the list of privileges that may be held be the token */
1086 DECL_HANDLER(get_token_privileges)
1087 {
1088     struct token *token;
1089
1090     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1091                                                  TOKEN_QUERY,
1092                                                  &token_ops )))
1093     {
1094         int priv_count = 0;
1095         LUID_AND_ATTRIBUTES *privs;
1096         struct privilege *privilege;
1097
1098         LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
1099             priv_count++;
1100
1101         reply->len = priv_count * sizeof(*privs);
1102         if (reply->len <= get_reply_max_size())
1103         {
1104             privs = set_reply_data_size( priv_count * sizeof(*privs) );
1105             if (privs)
1106             {
1107                 int i = 0;
1108                 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
1109                 {
1110                     luid_and_attr_from_privilege( &privs[i], privilege );
1111                     i++;
1112                 }
1113             }
1114         }
1115         else
1116             set_error(STATUS_BUFFER_TOO_SMALL);
1117
1118         release_object( token );
1119     }
1120 }
1121
1122 /* creates a duplicate of the token */
1123 DECL_HANDLER(duplicate_token)
1124 {
1125     struct token *src_token;
1126
1127     if ((src_token = (struct token *)get_handle_obj( current->process, req->handle,
1128                                                      TOKEN_DUPLICATE,
1129                                                      &token_ops )))
1130     {
1131         struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level );
1132         if (token)
1133         {
1134             reply->new_handle = alloc_handle( current->process, token, req->access, req->attributes);
1135             release_object( token );
1136         }
1137         release_object( src_token );
1138     }
1139 }
1140
1141 /* checks the specified privileges are held by the token */
1142 DECL_HANDLER(check_token_privileges)
1143 {
1144     struct token *token;
1145
1146     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1147                                                  TOKEN_QUERY,
1148                                                  &token_ops )))
1149     {
1150         unsigned int count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
1151
1152         if (!token->primary && token->impersonation_level <= SecurityAnonymous)
1153             set_error( STATUS_BAD_IMPERSONATION_LEVEL );
1154         else if (get_reply_max_size() >= count * sizeof(LUID_AND_ATTRIBUTES))
1155         {
1156             LUID_AND_ATTRIBUTES *usedprivs = set_reply_data_size( count * sizeof(*usedprivs) );
1157             reply->has_privileges = token_check_privileges( token, req->all_required, get_req_data(), count, usedprivs );
1158         }
1159         else
1160             set_error( STATUS_BUFFER_OVERFLOW );
1161         release_object( token );
1162     }
1163 }
1164
1165 /* checks that a user represented by a token is allowed to access an object
1166  * represented by a security descriptor */
1167 DECL_HANDLER(access_check)
1168 {
1169     data_size_t sd_size = get_req_data_size();
1170     const struct security_descriptor *sd = get_req_data();
1171     struct token *token;
1172
1173     if (!sd_is_valid( sd, sd_size ))
1174     {
1175         set_error( STATUS_ACCESS_VIOLATION );
1176         return;
1177     }
1178
1179     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1180                                                  TOKEN_QUERY,
1181                                                  &token_ops )))
1182     {
1183         GENERIC_MAPPING mapping;
1184         unsigned int status;
1185         LUID_AND_ATTRIBUTES priv;
1186         unsigned int priv_count = 1;
1187
1188         memset(&priv, 0, sizeof(priv));
1189
1190         /* only impersonation tokens may be used with this function */
1191         if (token->primary)
1192         {
1193             set_error( STATUS_NO_IMPERSONATION_TOKEN );
1194             release_object( token );
1195             return;
1196         }
1197         /* anonymous impersonation tokens can't be used */
1198         if (token->impersonation_level <= SecurityAnonymous)
1199         {
1200             set_error( STATUS_BAD_IMPERSONATION_LEVEL );
1201             release_object( token );
1202             return;
1203         }
1204
1205         mapping.GenericRead = req->mapping_read;
1206         mapping.GenericWrite = req->mapping_write;
1207         mapping.GenericExecute = req->mapping_execute;
1208         mapping.GenericAll = req->mapping_all;
1209
1210         status = token_access_check(
1211             token, sd, req->desired_access, &priv, &priv_count, &mapping,
1212             &reply->access_granted, &reply->access_status );
1213
1214         reply->privileges_len = priv_count*sizeof(LUID_AND_ATTRIBUTES);
1215
1216         if ((priv_count > 0) && (reply->privileges_len <= get_reply_max_size()))
1217         {
1218             LUID_AND_ATTRIBUTES *privs = set_reply_data_size( priv_count * sizeof(*privs) );
1219             memcpy( privs, &priv, sizeof(priv) );
1220         }
1221
1222         set_error( status );
1223         release_object( token );
1224     }
1225 }
1226
1227 /* retrieves the SID of the user that the token represents */
1228 DECL_HANDLER(get_token_user)
1229 {
1230     struct token *token;
1231
1232     reply->user_len = 0;
1233
1234     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1235                                                  TOKEN_QUERY,
1236                                                  &token_ops )))
1237     {
1238         const SID *user = token->user;
1239
1240         reply->user_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
1241         if (reply->user_len <= get_reply_max_size())
1242         {
1243             SID *user_reply = set_reply_data_size( reply->user_len );
1244             if (user_reply)
1245                 memcpy( user_reply, user, reply->user_len );
1246         }
1247         else set_error( STATUS_BUFFER_TOO_SMALL );
1248
1249         release_object( token );
1250     }
1251 }
1252
1253 /* retrieves the groups that the user represented by the token belongs to */
1254 DECL_HANDLER(get_token_groups)
1255 {
1256     struct token *token;
1257
1258     reply->user_len = 0;
1259
1260     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1261                                                  TOKEN_QUERY,
1262                                                  &token_ops )))
1263     {
1264         size_t size_needed = sizeof(struct token_groups);
1265         unsigned int group_count = 0;
1266         const struct group *group;
1267
1268         LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
1269         {
1270             group_count++;
1271             size_needed += FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]);
1272         }
1273         size_needed += sizeof(unsigned int) * group_count;
1274
1275         reply->user_len = size_needed;
1276
1277         if (size_needed <= get_reply_max_size())
1278         {
1279             struct token_groups *tg = set_reply_data_size( size_needed );
1280             if (tg)
1281             {
1282                 unsigned int *attr_ptr = (unsigned int *)(tg + 1);
1283                 SID *sid_ptr = (SID *)(attr_ptr + group_count);
1284
1285                 tg->count = group_count;
1286
1287                 LIST_FOR_EACH_ENTRY( group, &token->groups, const struct group, entry )
1288                 {
1289
1290                     *attr_ptr = 0;
1291                     if (group->mandatory) *attr_ptr |= SE_GROUP_MANDATORY;
1292                     if (group->def) *attr_ptr |= SE_GROUP_ENABLED_BY_DEFAULT;
1293                     if (group->enabled) *attr_ptr |= SE_GROUP_ENABLED;
1294                     if (group->owner) *attr_ptr |= SE_GROUP_OWNER;
1295                     if (group->deny_only) *attr_ptr |= SE_GROUP_USE_FOR_DENY_ONLY;
1296                     if (group->resource) *attr_ptr |= SE_GROUP_RESOURCE;
1297                     if (group->logon) *attr_ptr |= SE_GROUP_LOGON_ID;
1298
1299                     memcpy(sid_ptr, &group->sid, FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]));
1300
1301                     sid_ptr = (SID *)((char *)sid_ptr + FIELD_OFFSET(SID, SubAuthority[group->sid.SubAuthorityCount]));
1302                     attr_ptr++;
1303                 }
1304             }
1305         }
1306         else set_error( STATUS_BUFFER_TOO_SMALL );
1307
1308         release_object( token );
1309     }
1310 }
1311
1312 DECL_HANDLER(get_token_impersonation_level)
1313 {
1314     struct token *token;
1315
1316     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1317                                                  TOKEN_QUERY,
1318                                                  &token_ops )))
1319     {
1320         if (token->primary)
1321             set_error( STATUS_INVALID_PARAMETER );
1322         else
1323             reply->impersonation_level = token->impersonation_level;
1324
1325         release_object( token );
1326     }
1327 }
1328
1329 DECL_HANDLER(get_token_statistics)
1330 {
1331     struct token *token;
1332
1333     if ((token = (struct token *)get_handle_obj( current->process, req->handle,
1334                                                  TOKEN_QUERY,
1335                                                  &token_ops )))
1336     {
1337         reply->token_id = token->token_id;
1338         reply->modified_id = token->modified_id;
1339         reply->primary = token->primary;
1340         reply->impersonation_level = token->impersonation_level;
1341         reply->group_count = list_count( &token->groups );
1342         reply->privilege_count = list_count( &token->privileges );
1343
1344         release_object( token );
1345     }
1346 }