SeAssignSecurity():
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id: semgr.c,v 1.38 2004/08/03 13:58:56 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Security manager
6 * FILE: kernel/se/semgr.c
7 * PROGRAMER: ?
8 * REVISION HISTORY:
9 * 26/07/98: Added stubs for security functions
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ps.h>
16 #include <internal/se.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
22
23
24 /* GLOBALS ******************************************************************/
25
26 PSE_EXPORTS EXPORTED SeExports = NULL;
27
28
29 /* PROTOTYPES ***************************************************************/
30
31 static BOOLEAN SepInitExports(VOID);
32
33 /* FUNCTIONS ****************************************************************/
34
35
36 BOOLEAN INIT_FUNCTION
37 SeInit1(VOID)
38 {
39 SepInitLuid();
40
41 if (!SepInitSecurityIDs())
42 return FALSE;
43
44 if (!SepInitDACLs())
45 return FALSE;
46
47 if (!SepInitSDs())
48 return FALSE;
49
50 SepInitPrivileges();
51
52 if (!SepInitExports())
53 return FALSE;
54
55 return TRUE;
56 }
57
58
59 BOOLEAN INIT_FUNCTION
60 SeInit2(VOID)
61 {
62 SepInitializeTokenImplementation();
63
64 return TRUE;
65 }
66
67
68 BOOLEAN
69 SeInitSRM(VOID)
70 {
71 OBJECT_ATTRIBUTES ObjectAttributes;
72 UNICODE_STRING Name;
73 HANDLE DirectoryHandle;
74 HANDLE EventHandle;
75 NTSTATUS Status;
76
77 /* Create '\Security' directory */
78 RtlInitUnicodeString(&Name,
79 L"\\Security");
80 InitializeObjectAttributes(&ObjectAttributes,
81 &Name,
82 OBJ_PERMANENT,
83 0,
84 NULL);
85 Status = NtCreateDirectoryObject(&DirectoryHandle,
86 DIRECTORY_ALL_ACCESS,
87 &ObjectAttributes);
88 if (!NT_SUCCESS(Status))
89 {
90 DPRINT1("Failed to create 'Security' directory!\n");
91 return FALSE;
92 }
93
94 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
95 RtlInitUnicodeString(&Name,
96 L"\\LSA_AUTHENTICATION_INITALIZED");
97 InitializeObjectAttributes(&ObjectAttributes,
98 &Name,
99 OBJ_PERMANENT,
100 DirectoryHandle,
101 SePublicDefaultSd);
102 Status = NtCreateEvent(&EventHandle,
103 EVENT_ALL_ACCESS,
104 &ObjectAttributes,
105 FALSE,
106 FALSE);
107 if (!NT_SUCCESS(Status))
108 {
109 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
110 NtClose(DirectoryHandle);
111 return FALSE;
112 }
113
114 NtClose(EventHandle);
115 NtClose(DirectoryHandle);
116
117 /* FIXME: Create SRM port and listener thread */
118
119 return TRUE;
120 }
121
122
123 static BOOLEAN INIT_FUNCTION
124 SepInitExports(VOID)
125 {
126 SeExports = ExAllocatePoolWithTag(NonPagedPool,
127 sizeof(SE_EXPORTS),
128 TAG_SXPT);
129 if (SeExports == NULL)
130 return FALSE;
131
132 SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege;
133 SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
134 SeExports->SeLockMemoryPrivilege = SeLockMemoryPrivilege;
135 SeExports->SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
136 SeExports->SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
137 SeExports->SeTcbPrivilege = SeTcbPrivilege;
138 SeExports->SeSecurityPrivilege = SeSecurityPrivilege;
139 SeExports->SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
140 SeExports->SeLoadDriverPrivilege = SeLoadDriverPrivilege;
141 SeExports->SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
142 SeExports->SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
143 SeExports->SeSystemProfilePrivilege = SeSystemProfilePrivilege;
144 SeExports->SeSystemtimePrivilege = SeSystemtimePrivilege;
145 SeExports->SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
146 SeExports->SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
147 SeExports->SeBackupPrivilege = SeBackupPrivilege;
148 SeExports->SeRestorePrivilege = SeRestorePrivilege;
149 SeExports->SeShutdownPrivilege = SeShutdownPrivilege;
150 SeExports->SeDebugPrivilege = SeDebugPrivilege;
151 SeExports->SeAuditPrivilege = SeAuditPrivilege;
152 SeExports->SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
153 SeExports->SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
154 SeExports->SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
155
156 SeExports->SeNullSid = SeNullSid;
157 SeExports->SeWorldSid = SeWorldSid;
158 SeExports->SeLocalSid = SeLocalSid;
159 SeExports->SeCreatorOwnerSid = SeCreatorOwnerSid;
160 SeExports->SeCreatorGroupSid = SeCreatorGroupSid;
161 SeExports->SeNtAuthoritySid = SeNtAuthoritySid;
162 SeExports->SeDialupSid = SeDialupSid;
163 SeExports->SeNetworkSid = SeNetworkSid;
164 SeExports->SeBatchSid = SeBatchSid;
165 SeExports->SeInteractiveSid = SeInteractiveSid;
166 SeExports->SeLocalSystemSid = SeLocalSystemSid;
167 SeExports->SeAliasAdminsSid = SeAliasAdminsSid;
168 SeExports->SeAliasUsersSid = SeAliasUsersSid;
169 SeExports->SeAliasGuestsSid = SeAliasGuestsSid;
170 SeExports->SeAliasPowerUsersSid = SeAliasPowerUsersSid;
171 SeExports->SeAliasAccountOpsSid = SeAliasAccountOpsSid;
172 SeExports->SeAliasSystemOpsSid = SeAliasSystemOpsSid;
173 SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid;
174 SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid;
175
176 return TRUE;
177 }
178
179
180 VOID SepReferenceLogonSession(PLUID AuthenticationId)
181 {
182 UNIMPLEMENTED;
183 }
184
185 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
186 {
187 UNIMPLEMENTED;
188 }
189
190
191
192 /*
193 * @unimplemented
194 */
195 NTSTATUS STDCALL
196 NtAllocateUuids(PULARGE_INTEGER Time,
197 PULONG Range,
198 PULONG Sequence)
199 {
200 UNIMPLEMENTED;
201 return(STATUS_NOT_IMPLEMENTED);
202 }
203
204
205 /*
206 * @implemented
207 */
208 VOID STDCALL
209 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
210 {
211 PETHREAD Thread;
212 BOOLEAN CopyOnOpen;
213 BOOLEAN EffectiveOnly;
214
215 Thread = PsGetCurrentThread();
216 if (Thread == NULL)
217 {
218 SubjectContext->ProcessAuditId = 0;
219 SubjectContext->PrimaryToken = NULL;
220 SubjectContext->ClientToken = NULL;
221 SubjectContext->ImpersonationLevel = 0;
222 }
223 else
224 {
225 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
226 SubjectContext->ClientToken =
227 PsReferenceImpersonationToken(Thread,
228 &CopyOnOpen,
229 &EffectiveOnly,
230 &SubjectContext->ImpersonationLevel);
231 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
232 }
233 }
234
235
236 /*
237 * @unimplemented
238 */
239 VOID STDCALL
240 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
241 {
242 UNIMPLEMENTED;
243 }
244
245
246 /*
247 * @implemented
248 */
249 VOID STDCALL
250 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
251 {
252 if (SubjectContext->PrimaryToken != NULL)
253 {
254 ObDereferenceObject(SubjectContext->PrimaryToken);
255 }
256
257 if (SubjectContext->ClientToken != NULL)
258 {
259 ObDereferenceObject(SubjectContext->ClientToken);
260 }
261 }
262
263
264 /*
265 * @unimplemented
266 */
267 VOID STDCALL
268 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
269 {
270 UNIMPLEMENTED;
271 }
272
273
274 /*
275 * @implemented
276 */
277 NTSTATUS STDCALL
278 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
279 {
280 if (*SecurityDescriptor != NULL)
281 {
282 ExFreePool(*SecurityDescriptor);
283 *SecurityDescriptor = NULL;
284 }
285
286 return STATUS_SUCCESS;
287 }
288
289
290 /*
291 * FUNCTION: Creates a security descriptor for a new object.
292 * ARGUMENTS:
293 * ParentDescriptor =
294 * ExplicitDescriptor =
295 * NewDescriptor =
296 * IsDirectoryObject =
297 * SubjectContext =
298 * GeneralMapping =
299 * PoolType =
300 * RETURNS: Status
301 *
302 * @implemented
303 */
304 NTSTATUS STDCALL
305 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
306 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
307 PSECURITY_DESCRIPTOR *NewDescriptor,
308 BOOLEAN IsDirectoryObject,
309 PSECURITY_SUBJECT_CONTEXT SubjectContext,
310 PGENERIC_MAPPING GenericMapping,
311 POOL_TYPE PoolType)
312 {
313 PSECURITY_DESCRIPTOR Descriptor;
314 PACCESS_TOKEN Token;
315 ULONG OwnerLength = 0;
316 ULONG GroupLength = 0;
317 ULONG DaclLength = 0;
318 ULONG SaclLength = 0;
319 ULONG Length = 0;
320 ULONG Control = 0;
321 ULONG Current;
322 PSID Owner = NULL;
323 PSID Group = NULL;
324 PACL Dacl = NULL;
325 PACL Sacl = NULL;
326
327 /* FIXME: Lock subject context */
328
329 if (SubjectContext->ClientToken != NULL)
330 {
331 Token = SubjectContext->ClientToken;
332 }
333 else
334 {
335 Token = SubjectContext->PrimaryToken;
336 }
337
338
339 /* Inherit the Owner SID */
340 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
341 {
342 DPRINT("Use explicit owner sid!\n");
343 Owner = ExplicitDescriptor->Owner;
344 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
345 {
346 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
347 }
348 }
349 else
350 {
351 if (Token != NULL)
352 {
353 DPRINT("Use token owner sid!\n");
354 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
355 }
356 else
357 {
358 DPRINT("Use default owner sid!\n");
359 Owner = SeLocalSystemSid;
360 }
361
362 Control |= SE_OWNER_DEFAULTED;
363 }
364
365 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
366
367
368 /* Inherit the Group SID */
369 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
370 {
371 DPRINT("Use explicit group sid!\n");
372 Group = ExplicitDescriptor->Group;
373 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
374 {
375 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
376 }
377 }
378 else
379 {
380 if (Token != NULL)
381 {
382 DPRINT("Use token group sid!\n");
383 Group = Token->PrimaryGroup;
384 }
385 else
386 {
387 DPRINT("Use default group sid!\n");
388 Group = SeLocalSystemSid;
389 }
390
391 Control |= SE_OWNER_DEFAULTED;
392 }
393
394 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
395
396
397 /* Inherit the DACL */
398 if (ExplicitDescriptor != NULL &&
399 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
400 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
401 {
402 DPRINT("Use explicit DACL!\n");
403 Dacl = ExplicitDescriptor->Dacl;
404 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
405 {
406 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
407 }
408
409 Control |= SE_DACL_PRESENT;
410 }
411 else if (ParentDescriptor != NULL &&
412 (ParentDescriptor->Control & SE_DACL_PRESENT))
413 {
414 DPRINT("Use parent DACL!\n");
415 /* FIXME: Inherit */
416 Dacl = ParentDescriptor->Dacl;
417 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
418 {
419 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
420 }
421 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
422 }
423 else if (Token != NULL && Token->DefaultDacl != NULL)
424 {
425 DPRINT("Use token default DACL!\n");
426 /* FIXME: Inherit */
427 Dacl = Token->DefaultDacl;
428 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
429 }
430 else
431 {
432 DPRINT("Use NULL DACL!\n");
433 Dacl = NULL;
434 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
435 }
436
437 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
438
439
440 /* Inherit the SACL */
441 if (ExplicitDescriptor != NULL &&
442 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
443 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
444 {
445 DPRINT("Use explicit SACL!\n");
446 Sacl = ExplicitDescriptor->Sacl;
447 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
448 {
449 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
450 }
451
452 Control |= SE_SACL_PRESENT;
453 }
454 else if (ParentDescriptor != NULL &&
455 (ParentDescriptor->Control & SE_SACL_PRESENT))
456 {
457 DPRINT("Use parent SACL!\n");
458 /* FIXME: Inherit */
459 Sacl = ParentDescriptor->Sacl;
460 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
461 {
462 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
463 }
464 Control |= (SE_SACL_PRESENT & SE_SACL_DEFAULTED);
465 }
466
467 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
468
469
470 /* Allocate and initialize the new security descriptor */
471 Length = sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength + DaclLength + SaclLength;
472
473 Descriptor = ExAllocatePool(NonPagedPool,
474 Length);
475 if (Descriptor == NULL)
476 {
477 DPRINT1("ExAlloctePool() failed\n");
478 /* FIXME: Unlock subject context */
479 return STATUS_INSUFFICIENT_RESOURCES;
480 }
481
482 RtlCreateSecurityDescriptor(Descriptor,
483 SECURITY_DESCRIPTOR_REVISION);
484
485 Descriptor->Control = Control | SE_SELF_RELATIVE;
486
487 Current = (ULONG)Descriptor + sizeof(SECURITY_DESCRIPTOR);
488
489 if (SaclLength != 0)
490 {
491 RtlCopyMemory((PVOID)Current,
492 Sacl,
493 SaclLength);
494 Descriptor->Sacl = (PACL)((ULONG)Current - (ULONG)Descriptor);
495 Current += SaclLength;
496 }
497
498 if (DaclLength != 0)
499 {
500 RtlCopyMemory((PVOID)Current,
501 Dacl,
502 DaclLength);
503 Descriptor->Dacl = (PACL)((ULONG)Current - (ULONG)Descriptor);
504 Current += DaclLength;
505 }
506
507 if (OwnerLength != 0)
508 {
509 RtlCopyMemory((PVOID)Current,
510 Owner,
511 OwnerLength);
512 Descriptor->Owner = (PSID)((ULONG)Current - (ULONG)Descriptor);
513 Current += OwnerLength;
514 }
515
516 if (GroupLength != 0)
517 {
518 memmove((PVOID)Current,
519 Group,
520 GroupLength);
521 Descriptor->Group = (PSID)((ULONG)Current - (ULONG)Descriptor);
522 }
523
524 /* FIXME: Unlock subject context */
525
526 *NewDescriptor = Descriptor;
527
528 return STATUS_SUCCESS;
529 }
530
531
532 static BOOLEAN
533 SepSidInToken(PACCESS_TOKEN Token,
534 PSID Sid)
535 {
536 ULONG i;
537
538 if (Token->UserAndGroupCount == 0)
539 {
540 return FALSE;
541 }
542
543 for (i=0; i<Token->UserAndGroupCount; i++)
544 {
545 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
546 {
547 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
548 {
549 return TRUE;
550 }
551
552 return FALSE;
553 }
554 }
555
556 return FALSE;
557 }
558
559
560 /*
561 * FUNCTION: Determines whether the requested access rights can be granted
562 * to an object protected by a security descriptor and an object owner
563 * ARGUMENTS:
564 * SecurityDescriptor = Security descriptor protecting the object
565 * SubjectSecurityContext = Subject's captured security context
566 * SubjectContextLocked = Indicates the user's subject context is locked
567 * DesiredAccess = Access rights the caller is trying to acquire
568 * PreviouslyGrantedAccess = Specified the access rights already granted
569 * Privileges = ?
570 * GenericMapping = Generic mapping associated with the object
571 * AccessMode = Access mode used for the check
572 * GrantedAccess (OUT) = On return specifies the access granted
573 * AccessStatus (OUT) = Status indicating why access was denied
574 * RETURNS: If access was granted, returns TRUE
575 *
576 * @implemented
577 */
578 BOOLEAN STDCALL
579 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
580 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
581 IN BOOLEAN SubjectContextLocked,
582 IN ACCESS_MASK DesiredAccess,
583 IN ACCESS_MASK PreviouslyGrantedAccess,
584 OUT PPRIVILEGE_SET* Privileges,
585 IN PGENERIC_MAPPING GenericMapping,
586 IN KPROCESSOR_MODE AccessMode,
587 OUT PACCESS_MASK GrantedAccess,
588 OUT PNTSTATUS AccessStatus)
589 {
590 LUID_AND_ATTRIBUTES Privilege;
591 ACCESS_MASK CurrentAccess;
592 PACCESS_TOKEN Token;
593 ULONG i;
594 PACL Dacl;
595 BOOLEAN Present;
596 BOOLEAN Defaulted;
597 PACE CurrentAce;
598 PSID Sid;
599 NTSTATUS Status;
600
601 CurrentAccess = PreviouslyGrantedAccess;
602
603 Token = SubjectSecurityContext->ClientToken ?
604 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
605
606 /* Get the DACL */
607 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
608 &Present,
609 &Dacl,
610 &Defaulted);
611 if (!NT_SUCCESS(Status))
612 {
613 *AccessStatus = Status;
614 return FALSE;
615 }
616
617 /* RULE 1: Grant desired access if the object is unprotected */
618 if (Dacl == NULL)
619 {
620 *GrantedAccess = DesiredAccess;
621 *AccessStatus = STATUS_SUCCESS;
622 return TRUE;
623 }
624
625 CurrentAccess = PreviouslyGrantedAccess;
626
627 /* RULE 2: Check token for 'take ownership' privilege */
628 Privilege.Luid = SeTakeOwnershipPrivilege;
629 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
630
631 if (SepPrivilegeCheck(Token,
632 &Privilege,
633 1,
634 PRIVILEGE_SET_ALL_NECESSARY,
635 AccessMode))
636 {
637 CurrentAccess |= WRITE_OWNER;
638 if (DesiredAccess == CurrentAccess)
639 {
640 *GrantedAccess = CurrentAccess;
641 *AccessStatus = STATUS_SUCCESS;
642 return TRUE;
643 }
644 }
645
646 /* RULE 3: Check whether the token is the owner */
647 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
648 &Sid,
649 &Defaulted);
650 if (!NT_SUCCESS(Status))
651 {
652 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
653 *AccessStatus = Status;
654 return FALSE;
655 }
656
657 if (SepSidInToken(Token, Sid))
658 {
659 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
660 if (DesiredAccess == CurrentAccess)
661 {
662 *GrantedAccess = CurrentAccess;
663 *AccessStatus = STATUS_SUCCESS;
664 return TRUE;
665 }
666 }
667
668 /* RULE 4: Grant rights according to the DACL */
669 CurrentAce = (PACE)(Dacl + 1);
670 for (i = 0; i < Dacl->AceCount; i++)
671 {
672 Sid = (PSID)(CurrentAce + 1);
673 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
674 {
675 if (SepSidInToken(Token, Sid))
676 {
677 *GrantedAccess = 0;
678 *AccessStatus = STATUS_ACCESS_DENIED;
679 return TRUE;
680 }
681 }
682
683 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
684 {
685 if (SepSidInToken(Token, Sid))
686 {
687 CurrentAccess |= CurrentAce->AccessMask;
688 }
689 }
690 }
691
692 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
693 CurrentAccess, DesiredAccess);
694
695 *GrantedAccess = CurrentAccess & DesiredAccess;
696
697 *AccessStatus =
698 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
699
700 return TRUE;
701 }
702
703
704 NTSTATUS STDCALL
705 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
706 IN HANDLE TokenHandle,
707 IN ACCESS_MASK DesiredAccess,
708 IN PGENERIC_MAPPING GenericMapping,
709 OUT PPRIVILEGE_SET PrivilegeSet,
710 OUT PULONG ReturnLength,
711 OUT PACCESS_MASK GrantedAccess,
712 OUT PNTSTATUS AccessStatus)
713 {
714 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
715 KPROCESSOR_MODE PreviousMode;
716 PACCESS_TOKEN Token;
717 NTSTATUS Status;
718
719 DPRINT("NtAccessCheck() called\n");
720
721 PreviousMode = KeGetPreviousMode();
722 if (PreviousMode == KernelMode)
723 {
724 *GrantedAccess = DesiredAccess;
725 *AccessStatus = STATUS_SUCCESS;
726 return STATUS_SUCCESS;
727 }
728
729 Status = ObReferenceObjectByHandle(TokenHandle,
730 TOKEN_QUERY,
731 SepTokenObjectType,
732 PreviousMode,
733 (PVOID*)&Token,
734 NULL);
735 if (!NT_SUCCESS(Status))
736 {
737 DPRINT1("Failed to reference token (Status %lx)\n", Status);
738 return Status;
739 }
740
741 /* Check token type */
742 if (Token->TokenType != TokenImpersonation)
743 {
744 DPRINT1("No impersonation token\n");
745 ObDereferenceObject(Token);
746 return STATUS_ACCESS_VIOLATION;
747 }
748
749 /* Check impersonation level */
750 if (Token->ImpersonationLevel < SecurityAnonymous)
751 {
752 DPRINT1("Invalid impersonation level\n");
753 ObDereferenceObject(Token);
754 return STATUS_ACCESS_VIOLATION;
755 }
756
757 RtlZeroMemory(&SubjectSecurityContext,
758 sizeof(SECURITY_SUBJECT_CONTEXT));
759 SubjectSecurityContext.ClientToken = Token;
760 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
761
762 /* FIXME: Lock subject context */
763
764 if (!SeAccessCheck(SecurityDescriptor,
765 &SubjectSecurityContext,
766 TRUE,
767 DesiredAccess,
768 0,
769 &PrivilegeSet,
770 GenericMapping,
771 PreviousMode,
772 GrantedAccess,
773 AccessStatus))
774 {
775 Status = *AccessStatus;
776 }
777 else
778 {
779 Status = STATUS_ACCESS_DENIED;
780 }
781
782 /* FIXME: Unlock subject context */
783
784 ObDereferenceObject(Token);
785
786 DPRINT("NtAccessCheck() done\n");
787
788 return Status;
789 }
790
791 /* EOF */