Added some security related functions to winbase.h.
[wine.git] / server / token.c
blob05c1af7382d24c26e757061e94a01b602e559b68
1 /*
2 * Tokens
4 * Copyright (C) 1998 Alexandre Julliard
5 * Copyright (C) 2003 Mike McCormack
6 * Copyright (C) 2005 Robert Shearman
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdlib.h>
29 #include "windef.h"
31 #include "handle.h"
32 #include "thread.h"
33 #include "process.h"
34 #include "request.h"
35 #include "security.h"
37 #define MAX_SUBAUTH_COUNT 1
39 const LUID SeIncreaseQuotaPrivilege = { 5, 0 };
40 const LUID SeSecurityPrivilege = { 8, 0 };
41 const LUID SeTakeOwnershipPrivilege = { 9, 0 };
42 const LUID SeLoadDriverPrivilege = { 10, 0 };
43 const LUID SeSystemProfilePrivilege = { 11, 0 };
44 const LUID SeSystemtimePrivilege = { 12, 0 };
45 const LUID SeProfileSingleProcessPrivilege = { 13, 0 };
46 const LUID SeIncreaseBasePriorityPrivilege = { 14, 0 };
47 const LUID SeCreatePagefilePrivilege = { 15, 0 };
48 const LUID SeBackupPrivilege = { 17, 0 };
49 const LUID SeRestorePrivilege = { 18, 0 };
50 const LUID SeShutdownPrivilege = { 19, 0 };
51 const LUID SeDebugPrivilege = { 20, 0 };
52 const LUID SeSystemEnvironmentPrivilege = { 22, 0 };
53 const LUID SeChangeNotifyPrivilege = { 23, 0 };
54 const LUID SeRemoteShutdownPrivilege = { 24, 0 };
55 const LUID SeUndockPrivilege = { 25, 0 };
56 const LUID SeManageVolumePrivilege = { 28, 0 };
57 const LUID SeImpersonatePrivilege = { 29, 0 };
58 const LUID SeCreateGlobalPrivilege = { 30, 0 };
60 struct token
62 struct object obj; /* object header */
63 struct list privileges; /* privileges available to the token */
64 struct list groups; /* groups that the user of this token belongs to (sid_and_attributes) */
65 SID *user; /* SID of user this token represents */
68 struct privilege
70 struct list entry;
71 LUID luid;
72 unsigned enabled : 1; /* is the privilege currently enabled? */
73 unsigned def : 1; /* is the privilege enabled by default? */
76 struct sid_and_attributes
78 struct list entry;
79 int enabled : 1; /* is the sid currently enabled? */
80 int def : 1; /* is the sid enabled by default? */
81 int logon : 1; /* is this a logon sid? */
82 int mandatory: 1; /* is this sid always enabled? */
83 int owner : 1; /* can this sid be an owner of an object? */
84 int resource : 1; /* is this a domain-local group? */
85 int deny_only: 1; /* is this a sid that should be use for denying only? */
86 SID sid;
89 static void token_dump( struct object *obj, int verbose );
90 static void token_destroy( struct object *obj );
92 static const struct object_ops token_ops =
94 sizeof(struct token), /* size */
95 token_dump, /* dump */
96 no_add_queue, /* add_queue */
97 NULL, /* remove_queue */
98 NULL, /* signaled */
99 NULL, /* satisfied */
100 no_signal, /* signal */
101 no_get_fd, /* get_fd */
102 token_destroy /* destroy */
106 static void token_dump( struct object *obj, int verbose )
108 fprintf( stderr, "Security token\n" );
109 /* FIXME: dump token members */
112 static SID *security_sid_alloc( const SID_IDENTIFIER_AUTHORITY *idauthority, int subauthcount, const unsigned int subauth[] )
114 int i;
115 SID *sid = mem_alloc( FIELD_OFFSET(SID, SubAuthority[subauthcount]) );
116 if (!sid) return NULL;
117 sid->Revision = MAX_ACL_REVISION;
118 sid->SubAuthorityCount = subauthcount;
119 sid->IdentifierAuthority = *idauthority;
120 for (i = 0; i < subauthcount; i++)
121 sid->SubAuthority[i] = subauth[i];
122 return sid;
125 static inline int security_equal_sid( const SID *sid1, const SID *sid2 )
127 return ((sid1->SubAuthorityCount == sid2->SubAuthorityCount) &&
128 !memcmp( sid1, sid2, FIELD_OFFSET(SID, SubAuthority[sid1->SubAuthorityCount]) ));
131 static const ACE_HEADER *ace_next( const ACE_HEADER *ace )
133 return (const ACE_HEADER *)((const char *)ace + ace->AceSize);
136 static int acl_is_valid( const ACL *acl, size_t size )
138 ULONG i;
139 const ACE_HEADER *ace;
141 if (size < sizeof(ACL))
142 return FALSE;
144 size = min(size, MAX_ACL_LEN);
146 size -= sizeof(ACL);
148 ace = (const ACE_HEADER *)(acl + 1);
149 for (i = 0; i < acl->AceCount; i++)
151 const SID *sid;
153 if (size < sizeof(ACE_HEADER))
154 return FALSE;
155 if (size < ace->AceSize)
156 return FALSE;
157 size -= ace->AceSize;
158 switch (ace->AceType)
160 case ACCESS_DENIED_ACE_TYPE:
161 sid = (const SID *)&((const ACCESS_DENIED_ACE *)ace)->SidStart;
162 break;
163 case ACCESS_ALLOWED_ACE_TYPE:
164 sid = (const SID *)&((const ACCESS_ALLOWED_ACE *)ace)->SidStart;
165 break;
166 case SYSTEM_AUDIT_ACE_TYPE:
167 sid = (const SID *)&((const SYSTEM_AUDIT_ACE *)ace)->SidStart;
168 break;
169 case SYSTEM_ALARM_ACE_TYPE:
170 sid = (const SID *)&((const SYSTEM_ALARM_ACE *)ace)->SidStart;
171 break;
172 default:
173 return FALSE;
175 if (size < sizeof(SID) ||
176 size < FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]))
177 return FALSE;
178 ace = ace_next( ace );
180 return TRUE;
183 /* gets the discretionary access control list from a security descriptor */
184 static inline const ACL *sd_get_dacl( const struct security_descriptor *sd, int *present )
186 *present = (sd->control & SE_DACL_PRESENT ? TRUE : FALSE);
188 if (sd->dacl_len)
189 return (const ACL *)((const char *)(sd + 1) +
190 sd->owner_len + sd->group_len + sd->sacl_len);
191 else
192 return NULL;
195 /* gets the system access control list from a security descriptor */
196 static inline const ACL *sd_get_sacl( const struct security_descriptor *sd, int *present )
198 *present = (sd->control & SE_SACL_PRESENT ? TRUE : FALSE);
200 if (sd->sacl_len)
201 return (const ACL *)((const char *)(sd + 1) +
202 sd->owner_len + sd->group_len);
203 else
204 return NULL;
207 /* gets the owner from a security descriptor */
208 static inline const SID *sd_get_owner( const struct security_descriptor *sd )
210 if (sd->owner_len)
211 return (const SID *)(sd + 1);
212 else
213 return NULL;
216 /* gets the primary group from a security descriptor */
217 static inline const SID *sd_get_group( const struct security_descriptor *sd )
219 if (sd->group_len)
220 return (const SID *)((const char *)(sd + 1) + sd->owner_len);
221 else
222 return NULL;
225 /* checks whether all members of a security descriptor fit inside the size
226 * of memory specified */
227 static int sd_is_valid( const struct security_descriptor *sd, size_t size )
229 size_t offset = sizeof(struct security_descriptor);
230 const SID *group;
231 const SID *owner;
232 const ACL *sacl;
233 const ACL *dacl;
234 int dummy;
236 if (size < offset)
237 return FALSE;
239 if ((sd->owner_len >= FIELD_OFFSET(SID, SubAuthority[255])) ||
240 (offset + sd->owner_len > size))
241 return FALSE;
242 owner = sd_get_owner( sd );
243 if (owner)
245 size_t needed_size = FIELD_OFFSET(SID, SubAuthority[owner->SubAuthorityCount]);
246 if ((sd->owner_len < sizeof(SID)) || (needed_size > sd->owner_len))
247 return FALSE;
249 offset += sd->owner_len;
251 if ((sd->group_len >= FIELD_OFFSET(SID, SubAuthority[255])) ||
252 (offset + sd->group_len > size))
253 return FALSE;
254 group = sd_get_group( sd );
255 if (group)
257 size_t needed_size = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
258 if ((sd->owner_len < sizeof(SID)) || (needed_size > sd->owner_len))
259 return FALSE;
261 offset += sd->group_len;
263 if ((sd->sacl_len >= MAX_ACL_LEN) || (offset + sd->sacl_len > size))
264 return FALSE;
265 sacl = sd_get_sacl( sd, &dummy );
266 if (sacl && !acl_is_valid( sacl, sd->sacl_len ))
267 return FALSE;
268 offset += sd->sacl_len;
270 if ((sd->dacl_len >= MAX_ACL_LEN) || (offset + sd->dacl_len > size))
271 return FALSE;
272 dacl = sd_get_dacl( sd, &dummy );
273 if (dacl && !acl_is_valid( dacl, sd->dacl_len ))
274 return FALSE;
275 offset += sd->dacl_len;
277 return TRUE;
280 /* maps from generic rights to specific rights as given by a mapping */
281 static inline void map_generic_mask(unsigned int *mask, const GENERIC_MAPPING *mapping)
283 if (*mask & GENERIC_READ) *mask |= mapping->GenericRead;
284 if (*mask & GENERIC_WRITE) *mask |= mapping->GenericWrite;
285 if (*mask & GENERIC_EXECUTE) *mask |= mapping->GenericExecute;
286 if (*mask & GENERIC_ALL) *mask |= mapping->GenericAll;
287 *mask &= 0x0FFFFFFF;
290 static inline int is_equal_luid( const LUID *luid1, const LUID *luid2 )
292 return (luid1->LowPart == luid2->LowPart && luid1->HighPart == luid2->HighPart);
295 static inline void luid_and_attr_from_privilege( LUID_AND_ATTRIBUTES *out, const struct privilege *in)
297 out->Luid = in->luid;
298 out->Attributes =
299 (in->enabled ? SE_PRIVILEGE_ENABLED : 0) |
300 (in->def ? SE_PRIVILEGE_ENABLED_BY_DEFAULT : 0);
303 static struct privilege *privilege_add( struct token *token, const LUID *luid, int enabled )
305 struct privilege *privilege = mem_alloc( sizeof(*privilege) );
306 if (privilege)
308 privilege->luid = *luid;
309 privilege->def = privilege->enabled = (enabled != 0);
310 list_add_tail( &token->privileges, &privilege->entry );
312 return privilege;
315 static inline void privilege_remove( struct privilege *privilege )
317 list_remove( &privilege->entry );
318 free( privilege );
321 static void token_destroy( struct object *obj )
323 struct token* token;
324 struct list *cursor, *cursor_next;
326 assert( obj->ops == &token_ops );
327 token = (struct token *)obj;
329 free( token->user );
331 LIST_FOR_EACH_SAFE( cursor, cursor_next, &token->privileges )
333 struct privilege *privilege = LIST_ENTRY( cursor, struct privilege, entry );
334 privilege_remove( privilege );
337 LIST_FOR_EACH_SAFE( cursor, cursor_next, &token->groups )
339 struct sid_and_attributes *group = LIST_ENTRY( cursor, struct sid_and_attributes, entry );
340 list_remove( &group->entry );
341 free( group );
345 static struct token *create_token( const SID *user, const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count )
347 struct token *token = alloc_object( &token_ops );
348 if (token)
350 int i;
351 list_init( &token->privileges );
352 list_init( &token->groups );
353 /* copy user */
354 token->user = memdup( user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
355 if (!token->user)
357 release_object( token );
358 return NULL;
361 /* FIXME: copy groups */
363 /* copy privileges */
364 for (i = 0; i < priv_count; i++)
366 /* note: we don't check uniqueness: the caller must make sure
367 * privs doesn't contain any duplicate luids */
368 if (!privilege_add( token, &privs[i].Luid,
369 privs[i].Attributes & SE_PRIVILEGE_ENABLED ))
371 release_object( token );
372 return NULL;
376 return token;
379 struct sid_data
381 SID_IDENTIFIER_AUTHORITY idauth;
382 int count;
383 unsigned int subauth[MAX_SUBAUTH_COUNT];
386 struct token *token_create_admin( void )
388 struct token *token;
389 const LUID_AND_ATTRIBUTES admin_privs[] =
391 { SeChangeNotifyPrivilege , SE_PRIVILEGE_ENABLED },
392 { SeSecurityPrivilege , 0 },
393 { SeBackupPrivilege , 0 },
394 { SeRestorePrivilege , 0 },
395 { SeSystemtimePrivilege , 0 },
396 { SeShutdownPrivilege , 0 },
397 { SeRemoteShutdownPrivilege , 0 },
398 { SeTakeOwnershipPrivilege , 0 },
399 { SeDebugPrivilege , 0 },
400 { SeSystemEnvironmentPrivilege , 0 },
401 { SeSystemProfilePrivilege , 0 },
402 { SeProfileSingleProcessPrivilege, 0 },
403 { SeIncreaseBasePriorityPrivilege, 0 },
404 { SeLoadDriverPrivilege , 0 },
405 { SeCreatePagefilePrivilege , 0 },
406 { SeIncreaseQuotaPrivilege , 0 },
407 { SeUndockPrivilege , 0 },
408 { SeManageVolumePrivilege , 0 },
409 { SeImpersonatePrivilege , SE_PRIVILEGE_ENABLED },
410 { SeCreateGlobalPrivilege , SE_PRIVILEGE_ENABLED },
412 static const struct sid_data well_known_sid_data[] =
414 { { SECURITY_NT_AUTHORITY }, 1, { SECURITY_LOCAL_SYSTEM_RID } }, /* LOCAL_SYSTEM */
416 SID *local_system_sid = security_sid_alloc(
417 &well_known_sid_data[0].idauth,
418 well_known_sid_data[0].count,
419 well_known_sid_data[0].subauth );
420 if (!local_system_sid) return NULL;
421 token = create_token( local_system_sid, admin_privs, sizeof(admin_privs)/sizeof(admin_privs[0]) );
422 free( local_system_sid );
423 return token;
426 static struct privilege *token_find_privilege( struct token *token, const LUID *luid, int enabled_only)
428 struct privilege *privilege;
429 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
431 if (is_equal_luid( luid, &privilege->luid ))
433 if (enabled_only && !privilege->enabled)
434 return NULL;
435 return privilege;
438 return NULL;
441 static unsigned int token_adjust_privileges( struct token *token, const LUID_AND_ATTRIBUTES *privs,
442 unsigned int count, LUID_AND_ATTRIBUTES *mod_privs,
443 unsigned int mod_privs_count)
445 int i;
446 unsigned int modified_count = 0;
448 for (i = 0; i < count; i++)
450 struct privilege *privilege =
451 token_find_privilege( token, &privs[i].Luid, FALSE );
452 if (!privilege)
454 set_error( STATUS_NOT_ALL_ASSIGNED );
455 continue;
458 if (privs[i].Attributes & SE_PRIVILEGE_REMOVE)
459 privilege_remove( privilege );
460 else
462 /* save previous state for caller */
463 if (mod_privs_count)
465 luid_and_attr_from_privilege(mod_privs, privilege);
466 mod_privs++;
467 mod_privs_count--;
468 modified_count++;
471 if (privs[i].Attributes & SE_PRIVILEGE_ENABLED)
472 privilege->enabled = TRUE;
473 else
474 privilege->enabled = FALSE;
477 return modified_count;
480 static void token_disable_privileges( struct token *token )
482 struct privilege *privilege;
483 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
484 privilege->enabled = FALSE;
487 int token_check_privileges( struct token *token, int all_required,
488 const LUID_AND_ATTRIBUTES *reqprivs,
489 unsigned int count, LUID_AND_ATTRIBUTES *usedprivs)
491 int i;
492 unsigned int enabled_count = 0;
494 for (i = 0; i < count; i++)
496 struct privilege *privilege =
497 token_find_privilege( token, &reqprivs[i].Luid, TRUE );
499 if (usedprivs)
500 usedprivs[i] = reqprivs[i];
502 if (privilege && privilege->enabled)
504 enabled_count++;
505 if (usedprivs)
506 usedprivs[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
510 if (all_required)
511 return (enabled_count == count);
512 else
513 return (enabled_count > 0);
516 static int token_sid_present( struct token *token, const SID *sid, int deny )
518 struct sid_and_attributes *group;
520 if (security_equal_sid( token->user, sid )) return TRUE;
522 LIST_FOR_EACH_ENTRY( group, &token->groups, struct sid_and_attributes, entry )
524 if (!group->enabled) continue;
525 if (group->deny_only && !deny) continue;
527 if (security_equal_sid( &group->sid, sid )) return TRUE;
530 return FALSE;
533 /* checks access to a security descriptor. sd must have been validated by caller.
534 * it returns STATUS_SUCCESS if access was granted to the object, or an error
535 * status code if not, giving the reason. errors not relating to giving access
536 * to the object are returned in the status parameter. granted_access and
537 * status always have a valid value stored in them on return. */
538 static unsigned int token_access_check( struct token *token,
539 const struct security_descriptor *sd,
540 unsigned int desired_access,
541 LUID_AND_ATTRIBUTES *privs,
542 unsigned int *priv_count,
543 const GENERIC_MAPPING *mapping,
544 unsigned int *granted_access,
545 unsigned int *status )
547 unsigned int current_access = 0;
548 unsigned int denied_access = 0;
549 ULONG i;
550 const ACL *dacl;
551 int dacl_present;
552 const ACE_HEADER *ace;
553 const SID *owner;
555 /* assume success, but no access rights */
556 *status = STATUS_SUCCESS;
557 *granted_access = 0;
559 /* fail if desired_access contains generic rights */
560 if (desired_access & (GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|GENERIC_ALL))
562 *priv_count = 0;
563 *status = STATUS_GENERIC_NOT_MAPPED;
564 return STATUS_ACCESS_DENIED;
567 dacl = sd_get_dacl( sd, &dacl_present );
568 owner = sd_get_owner( sd );
569 if (!owner || !sd_get_group( sd ))
571 *priv_count = 0;
572 *status = STATUS_INVALID_SECURITY_DESCR;
573 return STATUS_ACCESS_DENIED;
576 /* 1: Grant desired access if the object is unprotected */
577 if (!dacl_present)
579 *priv_count = 0;
580 *granted_access = desired_access;
581 return STATUS_SUCCESS;
583 if (!dacl)
585 *priv_count = 0;
586 return STATUS_ACCESS_DENIED;
589 /* 2: Check if caller wants access to system security part. Note: access
590 * is only granted if specifically asked for */
591 if (desired_access & ACCESS_SYSTEM_SECURITY)
593 const LUID_AND_ATTRIBUTES security_priv = { SeSecurityPrivilege, 0 };
594 LUID_AND_ATTRIBUTES retpriv = security_priv;
595 if (token_check_privileges( token, TRUE, &security_priv, 1, &retpriv ))
597 if (priv_count)
599 /* assumes that there will only be one privilege to return */
600 if (*priv_count >= 1)
602 *priv_count = 1;
603 *privs = retpriv;
605 else
607 *priv_count = 1;
608 return STATUS_BUFFER_TOO_SMALL;
611 current_access |= ACCESS_SYSTEM_SECURITY;
612 if (desired_access == current_access)
614 *granted_access = current_access;
615 return STATUS_SUCCESS;
618 else
620 *priv_count = 0;
621 return STATUS_PRIVILEGE_NOT_HELD;
624 else if (priv_count) *priv_count = 0;
626 /* 3: Check whether the token is the owner */
627 /* NOTE: SeTakeOwnershipPrivilege is not checked for here - it is instead
628 * checked when a "set owner" call is made, overriding the access rights
629 * determined here. */
630 if (token_sid_present( token, owner, FALSE ))
632 current_access |= (READ_CONTROL | WRITE_DAC);
633 if (desired_access == current_access)
635 *granted_access = current_access;
636 return STATUS_SUCCESS;
640 /* 4: Grant rights according to the DACL */
641 ace = (const ACE_HEADER *)(dacl + 1);
642 for (i = 0; i < dacl->AceCount; i++)
644 const ACCESS_ALLOWED_ACE *aa_ace;
645 const ACCESS_DENIED_ACE *ad_ace;
646 const SID *sid;
647 switch (ace->AceType)
649 case ACCESS_DENIED_ACE_TYPE:
650 ad_ace = (const ACCESS_DENIED_ACE *)ace;
651 sid = (const SID *)&ad_ace->SidStart;
652 if (token_sid_present( token, sid, TRUE ))
654 unsigned int access = ad_ace->Mask;
655 map_generic_mask(&access, mapping);
656 if (desired_access & MAXIMUM_ALLOWED)
657 denied_access |= access;
658 else
660 denied_access |= (access & ~current_access);
661 if (desired_access & access)
663 *granted_access = 0;
664 return STATUS_SUCCESS;
668 break;
669 case ACCESS_ALLOWED_ACE_TYPE:
670 aa_ace = (const ACCESS_ALLOWED_ACE *)ace;
671 sid = (const SID *)&aa_ace->SidStart;
672 if (token_sid_present( token, sid, FALSE ))
674 unsigned int access = aa_ace->Mask;
675 map_generic_mask(&access, mapping);
676 if (desired_access & MAXIMUM_ALLOWED)
677 current_access |= access;
678 else
679 current_access |= (access & ~denied_access);
681 break;
684 /* don't bother carrying on checking if we've already got all of
685 * rights we need */
686 if (desired_access == *granted_access)
687 break;
689 ace = ace_next( ace );
692 if (desired_access & MAXIMUM_ALLOWED)
694 *granted_access = current_access & ~denied_access;
695 if (*granted_access)
696 return STATUS_SUCCESS;
697 else
698 return STATUS_ACCESS_DENIED;
700 else
702 if ((current_access & desired_access) == desired_access)
704 *granted_access = current_access & desired_access;
705 return STATUS_SUCCESS;
707 else
708 return STATUS_ACCESS_DENIED;
712 /* open a security token */
713 DECL_HANDLER(open_token)
715 if( req->flags & OPEN_TOKEN_THREAD )
717 struct thread *thread = get_thread_from_handle( req->handle, 0 );
718 if (thread)
720 if (thread->token)
721 reply->token = alloc_handle( current->process, thread->token, TOKEN_ALL_ACCESS, 0);
722 else
723 set_error(STATUS_NO_TOKEN);
724 release_object( thread );
727 else
729 struct process *process = get_process_from_handle( req->handle, 0 );
730 if (process)
732 if (process->token)
733 reply->token = alloc_handle( current->process, process->token, TOKEN_ALL_ACCESS, 0);
734 else
735 set_error(STATUS_NO_TOKEN);
736 release_object( process );
741 /* adjust the privileges held by a token */
742 DECL_HANDLER(adjust_token_privileges)
744 struct token *token;
745 unsigned int access = TOKEN_ADJUST_PRIVILEGES;
747 if (req->get_modified_state) access |= TOKEN_QUERY;
749 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
750 access, &token_ops )))
752 const LUID_AND_ATTRIBUTES *privs = get_req_data();
753 LUID_AND_ATTRIBUTES *modified_privs = NULL;
754 unsigned int priv_count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
755 unsigned int modified_priv_count = 0;
757 if (req->get_modified_state && !req->disable_all)
759 int i;
760 /* count modified privs */
761 for (i = 0; i < priv_count; i++)
763 struct privilege *privilege =
764 token_find_privilege( token, &privs[i].Luid, FALSE );
765 if (privilege && req->get_modified_state)
766 modified_priv_count++;
768 reply->len = modified_priv_count;
769 modified_priv_count = min( modified_priv_count, get_reply_max_size() / sizeof(*modified_privs) );
770 if (modified_priv_count)
771 modified_privs = set_reply_data_size( modified_priv_count * sizeof(*modified_privs) );
773 reply->len = modified_priv_count * sizeof(*modified_privs);
775 if (req->disable_all)
776 token_disable_privileges( token );
777 else
778 modified_priv_count = token_adjust_privileges( token, privs,
779 priv_count, modified_privs, modified_priv_count );
781 release_object( token );
785 /* retrieves the list of privileges that may be held be the token */
786 DECL_HANDLER(get_token_privileges)
788 struct token *token;
790 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
791 TOKEN_QUERY,
792 &token_ops )))
794 int priv_count = 0;
795 LUID_AND_ATTRIBUTES *privs;
796 struct privilege *privilege;
798 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
799 priv_count++;
801 reply->len = priv_count * sizeof(*privs);
802 if (reply->len <= get_reply_max_size())
804 privs = set_reply_data_size( priv_count * sizeof(*privs) );
805 if (privs)
807 int i = 0;
808 LIST_FOR_EACH_ENTRY( privilege, &token->privileges, struct privilege, entry )
810 luid_and_attr_from_privilege( &privs[i], privilege );
811 i++;
815 else
816 set_error(STATUS_BUFFER_TOO_SMALL);
818 release_object( token );
822 /* creates a duplicate of the token */
823 DECL_HANDLER(duplicate_token)
825 struct token *src_token;
826 if ((src_token = (struct token *)get_handle_obj( current->process, req->handle,
827 TOKEN_DUPLICATE,
828 &token_ops )))
830 /* FIXME: use req->primary and req->impersonation_level */
831 struct token *token = create_token( src_token->user, NULL, 0 );
832 if (token)
834 struct privilege *privilege;
835 unsigned int access;
837 LIST_FOR_EACH_ENTRY( privilege, &src_token->privileges, struct privilege, entry )
838 privilege_add( token, &privilege->luid, privilege->enabled );
840 access = req->access;
841 if (access & MAXIMUM_ALLOWED) access = TOKEN_ALL_ACCESS; /* FIXME: needs general solution */
842 reply->new_handle = alloc_handle( current->process, token, access, req->inherit);
843 release_object( token );
845 release_object( src_token );
849 /* checks the specified privileges are held by the token */
850 DECL_HANDLER(check_token_privileges)
852 struct token *token;
854 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
855 TOKEN_QUERY,
856 &token_ops )))
858 unsigned int count = get_req_data_size() / sizeof(LUID_AND_ATTRIBUTES);
859 if (get_reply_max_size() >= count * sizeof(LUID_AND_ATTRIBUTES))
861 LUID_AND_ATTRIBUTES *usedprivs = set_reply_data_size( count * sizeof(*usedprivs) );
862 reply->has_privileges = token_check_privileges( token, req->all_required, get_req_data(), count, usedprivs );
864 else
865 set_error( STATUS_BUFFER_OVERFLOW );
866 release_object( token );
870 /* checks that a user represented by a token is allowed to access an object
871 * represented by a security descriptor */
872 DECL_HANDLER(access_check)
874 size_t sd_size = get_req_data_size();
875 const struct security_descriptor *sd = get_req_data();
876 struct token *token;
878 if (!sd_is_valid( sd, sd_size ))
880 set_error( STATUS_ACCESS_VIOLATION );
881 return;
884 if ((token = (struct token *)get_handle_obj( current->process, req->handle,
885 TOKEN_QUERY,
886 &token_ops )))
888 GENERIC_MAPPING mapping;
889 unsigned int status;
890 LUID_AND_ATTRIBUTES priv;
891 unsigned int priv_count = 1;
893 memset(&priv, 0, sizeof(priv));
895 /* FIXME: check token is an impersonation token, if not return
896 * STATUS_NO_IMPERSONATION_TOKEN */
898 mapping.GenericRead = req->mapping_read;
899 mapping.GenericWrite = req->mapping_write;
900 mapping.GenericExecute = req->mapping_execute;
901 mapping.GenericAll = req->mapping_all;
903 reply->access_status = token_access_check(
904 token, sd, req->desired_access, &priv, &priv_count, &mapping,
905 &reply->access_granted, &status );
907 reply->privileges_len = priv_count*sizeof(LUID_AND_ATTRIBUTES);
909 if ((priv_count > 0) && (reply->privileges_len <= get_reply_max_size()))
911 LUID_AND_ATTRIBUTES *privs = set_reply_data_size( priv_count * sizeof(*privs) );
912 memcpy( privs, &priv, sizeof(priv) );
915 if (status != STATUS_SUCCESS)
916 set_error( status );
918 release_object( token );