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