[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / se / accesschk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/accesschk.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: No programmer listed.
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18
19 /* PRIVATE FUNCTIONS **********************************************************/
20
21 #define OLD_ACCESS_CHECK
22
23 BOOLEAN NTAPI
24 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
25 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
26 IN ACCESS_MASK DesiredAccess,
27 IN ACCESS_MASK PreviouslyGrantedAccess,
28 OUT PPRIVILEGE_SET* Privileges,
29 IN PGENERIC_MAPPING GenericMapping,
30 IN KPROCESSOR_MODE AccessMode,
31 OUT PACCESS_MASK GrantedAccess,
32 OUT PNTSTATUS AccessStatus)
33 {
34 ACCESS_MASK RemainingAccess;
35 ACCESS_MASK TempAccess;
36 ACCESS_MASK TempGrantedAccess = 0;
37 ACCESS_MASK TempDeniedAccess = 0;
38 PACCESS_TOKEN Token;
39 ULONG i;
40 PACL Dacl;
41 BOOLEAN Present;
42 BOOLEAN Defaulted;
43 PACE CurrentAce;
44 PSID Sid;
45 NTSTATUS Status;
46 PAGED_CODE();
47
48 /* Check for no access desired */
49 if (!DesiredAccess)
50 {
51 /* Check if we had no previous access */
52 if (!PreviouslyGrantedAccess)
53 {
54 /* Then there's nothing to give */
55 *AccessStatus = STATUS_ACCESS_DENIED;
56 return FALSE;
57 }
58
59 /* Return the previous access only */
60 *GrantedAccess = PreviouslyGrantedAccess;
61 *AccessStatus = STATUS_SUCCESS;
62 *Privileges = NULL;
63 return TRUE;
64 }
65
66 /* Map given accesses */
67 RtlMapGenericMask(&DesiredAccess, GenericMapping);
68 if (PreviouslyGrantedAccess)
69 RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
70
71 /* Initialize remaining access rights */
72 RemainingAccess = DesiredAccess;
73
74 Token = SubjectSecurityContext->ClientToken ?
75 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
76
77 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
78 Status = SePrivilegePolicyCheck(&RemainingAccess,
79 &PreviouslyGrantedAccess,
80 NULL,
81 Token,
82 NULL,
83 UserMode);
84 if (!NT_SUCCESS(Status))
85 {
86 *AccessStatus = Status;
87 return FALSE;
88 }
89
90 /* Succeed if there are no more rights to grant */
91 if (RemainingAccess == 0)
92 {
93 *GrantedAccess = PreviouslyGrantedAccess;
94 *AccessStatus = STATUS_SUCCESS;
95 return TRUE;
96 }
97
98 /* Get the DACL */
99 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
100 &Present,
101 &Dacl,
102 &Defaulted);
103 if (!NT_SUCCESS(Status))
104 {
105 *AccessStatus = Status;
106 return FALSE;
107 }
108
109 /* RULE 1: Grant desired access if the object is unprotected */
110 if (Present == FALSE || Dacl == NULL)
111 {
112 if (DesiredAccess & MAXIMUM_ALLOWED)
113 {
114 *GrantedAccess = GenericMapping->GenericAll;
115 *GrantedAccess |= (DesiredAccess | PreviouslyGrantedAccess) & ~MAXIMUM_ALLOWED;
116 }
117 else
118 {
119 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
120 }
121
122 *AccessStatus = STATUS_SUCCESS;
123 return TRUE;
124 }
125
126 /* Deny access if the DACL is empty */
127 if (Dacl->AceCount == 0)
128 {
129 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
130 {
131 *GrantedAccess = PreviouslyGrantedAccess;
132 *AccessStatus = STATUS_SUCCESS;
133 return TRUE;
134 }
135 else
136 {
137 *GrantedAccess = 0;
138 *AccessStatus = STATUS_ACCESS_DENIED;
139 return FALSE;
140 }
141 }
142
143 /* Fail if DACL is absent */
144 if (Present == FALSE)
145 {
146 *GrantedAccess = 0;
147 *AccessStatus = STATUS_ACCESS_DENIED;
148 return FALSE;
149 }
150
151 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
152 if (DesiredAccess & MAXIMUM_ALLOWED)
153 {
154 CurrentAce = (PACE)(Dacl + 1);
155 for (i = 0; i < Dacl->AceCount; i++)
156 {
157 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
158 {
159 Sid = (PSID)(CurrentAce + 1);
160 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
161 {
162 if (SepSidInToken(Token, Sid))
163 {
164 /* Map access rights from the ACE */
165 TempAccess = CurrentAce->AccessMask;
166 RtlMapGenericMask(&TempAccess, GenericMapping);
167
168 /* Deny access rights that have not been granted yet */
169 TempDeniedAccess |= (TempAccess & ~TempGrantedAccess);
170 }
171 }
172 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
173 {
174 if (SepSidInToken(Token, Sid))
175 {
176 /* Map access rights from the ACE */
177 TempAccess = CurrentAce->AccessMask;
178 RtlMapGenericMask(&TempAccess, GenericMapping);
179
180 /* Grant access rights that have not been denied yet */
181 TempGrantedAccess |= (TempAccess & ~TempDeniedAccess);
182 }
183 }
184 else
185 {
186 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
187 }
188 }
189
190 /* Get the next ACE */
191 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
192 }
193
194 /* Fail if some rights have not been granted */
195 RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
196 if (RemainingAccess != 0)
197 {
198 *GrantedAccess = 0;
199 *AccessStatus = STATUS_ACCESS_DENIED;
200 return FALSE;
201 }
202
203 /* Set granted access right and access status */
204 *GrantedAccess = TempGrantedAccess | PreviouslyGrantedAccess;
205 if (*GrantedAccess != 0)
206 {
207 *AccessStatus = STATUS_SUCCESS;
208 return TRUE;
209 }
210 else
211 {
212 *AccessStatus = STATUS_ACCESS_DENIED;
213 return FALSE;
214 }
215 }
216
217 /* RULE 4: Grant rights according to the DACL */
218 CurrentAce = (PACE)(Dacl + 1);
219 for (i = 0; i < Dacl->AceCount; i++)
220 {
221 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
222 {
223 Sid = (PSID)(CurrentAce + 1);
224 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
225 {
226 if (SepSidInToken(Token, Sid))
227 {
228 #ifdef OLD_ACCESS_CHECK
229 *GrantedAccess = 0;
230 *AccessStatus = STATUS_ACCESS_DENIED;
231 return FALSE;
232 #else
233 /* Map access rights from the ACE */
234 TempAccess = CurrentAce->AccessMask;
235 RtlMapGenericMask(&TempAccess, GenericMapping);
236
237 /* Leave if a remaining right must be denied */
238 if (RemainingAccess & TempAccess)
239 break;
240 #endif
241 }
242 }
243 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
244 {
245 if (SepSidInToken(Token, Sid))
246 {
247 #ifdef OLD_ACCESS_CHECK
248 TempAccess = CurrentAce->AccessMask;
249 RtlMapGenericMask(&TempAccess, GenericMapping);
250 PreviouslyGrantedAccess |= TempAccess;
251 #else
252 /* Map access rights from the ACE */
253 TempAccess = CurrentAce->AccessMask;
254 RtlMapGenericMask(&TempAccess, GenericMapping);
255
256 /* Remove granted rights */
257 RemainingAccess &= ~TempAccess;
258 #endif
259 }
260 }
261 else
262 {
263 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
264 }
265 }
266
267 /* Get the next ACE */
268 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
269 }
270
271 #ifdef OLD_ACCESS_CHECK
272 DPRINT("PreviouslyGrantedAccess %08lx\n DesiredAccess %08lx\n",
273 PreviouslyGrantedAccess, DesiredAccess);
274
275 *GrantedAccess = PreviouslyGrantedAccess & DesiredAccess;
276
277 if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
278 (DesiredAccess & ~VALID_INHERIT_FLAGS))
279 {
280 *AccessStatus = STATUS_SUCCESS;
281 return TRUE;
282 }
283 else
284 {
285 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
286 *GrantedAccess, DesiredAccess, GenericMapping);
287 //*AccessStatus = STATUS_ACCESS_DENIED;
288 //return FALSE;
289 *GrantedAccess = DesiredAccess;
290 *AccessStatus = STATUS_SUCCESS;
291 return TRUE;
292 }
293 #else
294 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
295 DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
296
297 /* Fail if some rights have not been granted */
298 if (RemainingAccess != 0)
299 {
300 *GrantedAccess = 0;
301 *AccessStatus = STATUS_ACCESS_DENIED;
302 return FALSE;
303 }
304
305 /* Set granted access rights */
306 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
307
308 DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
309
310 /* Fail if no rights have been granted */
311 if (*GrantedAccess == 0)
312 {
313 *AccessStatus = STATUS_ACCESS_DENIED;
314 return FALSE;
315 }
316
317 *AccessStatus = STATUS_SUCCESS;
318 return TRUE;
319 #endif
320 }
321
322 static PSID
323 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
324 {
325 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
326 PSID Owner;
327
328 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
329 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
330 (ULONG_PTR)SecurityDescriptor);
331 else
332 Owner = (PSID)SecurityDescriptor->Owner;
333
334 return Owner;
335 }
336
337 static PSID
338 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
339 {
340 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
341 PSID Group;
342
343 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
344 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
345 (ULONG_PTR)SecurityDescriptor);
346 else
347 Group = (PSID)SecurityDescriptor->Group;
348
349 return Group;
350 }
351
352
353 /* PUBLIC FUNCTIONS ***********************************************************/
354
355 /*
356 * @implemented
357 */
358 BOOLEAN
359 NTAPI
360 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
361 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
362 IN BOOLEAN SubjectContextLocked,
363 IN ACCESS_MASK DesiredAccess,
364 IN ACCESS_MASK PreviouslyGrantedAccess,
365 OUT PPRIVILEGE_SET* Privileges,
366 IN PGENERIC_MAPPING GenericMapping,
367 IN KPROCESSOR_MODE AccessMode,
368 OUT PACCESS_MASK GrantedAccess,
369 OUT PNTSTATUS AccessStatus)
370 {
371 BOOLEAN ret;
372
373 PAGED_CODE();
374
375 /* Check if this is kernel mode */
376 if (AccessMode == KernelMode)
377 {
378 /* Check if kernel wants everything */
379 if (DesiredAccess & MAXIMUM_ALLOWED)
380 {
381 /* Give it */
382 *GrantedAccess = GenericMapping->GenericAll;
383 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
384 *GrantedAccess |= PreviouslyGrantedAccess;
385 }
386 else
387 {
388 /* Give the desired and previous access */
389 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
390 }
391
392 /* Success */
393 *AccessStatus = STATUS_SUCCESS;
394 return TRUE;
395 }
396
397 /* Check if we didn't get an SD */
398 if (!SecurityDescriptor)
399 {
400 /* Automatic failure */
401 *AccessStatus = STATUS_ACCESS_DENIED;
402 return FALSE;
403 }
404
405 /* Check for invalid impersonation */
406 if ((SubjectSecurityContext->ClientToken) &&
407 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
408 {
409 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
410 return FALSE;
411 }
412
413 /* Acquire the lock if needed */
414 if (!SubjectContextLocked)
415 SeLockSubjectContext(SubjectSecurityContext);
416
417 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
418 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
419 {
420 PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
421 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
422
423 if (SepTokenIsOwner(Token,
424 SecurityDescriptor,
425 FALSE))
426 {
427 if (DesiredAccess & MAXIMUM_ALLOWED)
428 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
429 else
430 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
431
432 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
433 }
434 }
435
436 if (DesiredAccess == 0)
437 {
438 *GrantedAccess = PreviouslyGrantedAccess;
439 *AccessStatus = STATUS_SUCCESS;
440 ret = TRUE;
441 }
442 else
443 {
444 /* Call the internal function */
445 ret = SepAccessCheck(SecurityDescriptor,
446 SubjectSecurityContext,
447 DesiredAccess,
448 PreviouslyGrantedAccess,
449 Privileges,
450 GenericMapping,
451 AccessMode,
452 GrantedAccess,
453 AccessStatus);
454 }
455
456 /* Release the lock if needed */
457 if (!SubjectContextLocked)
458 SeUnlockSubjectContext(SubjectSecurityContext);
459
460 return ret;
461 }
462
463 /*
464 * @implemented
465 */
466 BOOLEAN
467 NTAPI
468 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
469 IN PACCESS_STATE AccessState,
470 IN ACCESS_MASK DesiredAccess,
471 IN KPROCESSOR_MODE AccessMode)
472 {
473 PACL Dacl;
474 ULONG AceIndex;
475 PKNOWN_ACE Ace;
476
477 PAGED_CODE();
478
479 NT_ASSERT(AccessMode != KernelMode);
480
481 if (SecurityDescriptor == NULL)
482 return FALSE;
483
484 /* Get DACL */
485 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
486 /* If no DACL, grant access */
487 if (Dacl == NULL)
488 return TRUE;
489
490 /* No ACE -> Deny */
491 if (!Dacl->AceCount)
492 return FALSE;
493
494 /* Can't perform the check on restricted token */
495 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
496 return FALSE;
497
498 /* Browse the ACEs */
499 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
500 AceIndex < Dacl->AceCount;
501 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
502 {
503 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
504 continue;
505
506 /* If access-allowed ACE */
507 if (Ace->Header.AceType & ACCESS_ALLOWED_ACE_TYPE)
508 {
509 /* Check if all accesses are granted */
510 if (!(Ace->Mask & DesiredAccess))
511 continue;
512
513 /* Check SID and grant access if matching */
514 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
515 return TRUE;
516 }
517 /* If access-denied ACE */
518 else if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE)
519 {
520 /* Here, only check if it denies all the access wanted and deny if so */
521 if (Ace->Mask & DesiredAccess)
522 return FALSE;
523 }
524 }
525
526 /* Faulty, deny */
527 return FALSE;
528 }
529
530 /* SYSTEM CALLS ***************************************************************/
531
532 /*
533 * @implemented
534 */
535 NTSTATUS
536 NTAPI
537 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
538 IN HANDLE TokenHandle,
539 IN ACCESS_MASK DesiredAccess,
540 IN PGENERIC_MAPPING GenericMapping,
541 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
542 IN OUT PULONG PrivilegeSetLength,
543 OUT PACCESS_MASK GrantedAccess,
544 OUT PNTSTATUS AccessStatus)
545 {
546 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
547 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
548 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
549 ACCESS_MASK PreviouslyGrantedAccess = 0;
550 PTOKEN Token;
551 NTSTATUS Status;
552 PAGED_CODE();
553
554 /* Check if this is kernel mode */
555 if (PreviousMode == KernelMode)
556 {
557 /* Check if kernel wants everything */
558 if (DesiredAccess & MAXIMUM_ALLOWED)
559 {
560 /* Give it */
561 *GrantedAccess = GenericMapping->GenericAll;
562 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
563 }
564 else
565 {
566 /* Just give the desired access */
567 *GrantedAccess = DesiredAccess;
568 }
569
570 /* Success */
571 *AccessStatus = STATUS_SUCCESS;
572 return STATUS_SUCCESS;
573 }
574
575 /* Protect probe in SEH */
576 _SEH2_TRY
577 {
578 /* Probe all pointers */
579 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
580 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
581 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
582 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
583 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
584 }
585 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
586 {
587 /* Return the exception code */
588 _SEH2_YIELD(return _SEH2_GetExceptionCode());
589 }
590 _SEH2_END;
591
592 /* Check for unmapped access rights */
593 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
594 return STATUS_GENERIC_NOT_MAPPED;
595
596 /* Reference the token */
597 Status = ObReferenceObjectByHandle(TokenHandle,
598 TOKEN_QUERY,
599 SeTokenObjectType,
600 PreviousMode,
601 (PVOID*)&Token,
602 NULL);
603 if (!NT_SUCCESS(Status))
604 {
605 DPRINT("Failed to reference token (Status %lx)\n", Status);
606 return Status;
607 }
608
609 /* Check token type */
610 if (Token->TokenType != TokenImpersonation)
611 {
612 DPRINT("No impersonation token\n");
613 ObDereferenceObject(Token);
614 return STATUS_NO_IMPERSONATION_TOKEN;
615 }
616
617 /* Check the impersonation level */
618 if (Token->ImpersonationLevel < SecurityIdentification)
619 {
620 DPRINT("Impersonation level < SecurityIdentification\n");
621 ObDereferenceObject(Token);
622 return STATUS_BAD_IMPERSONATION_LEVEL;
623 }
624
625 /* Capture the security descriptor */
626 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
627 PreviousMode,
628 PagedPool,
629 FALSE,
630 &CapturedSecurityDescriptor);
631 if (!NT_SUCCESS(Status))
632 {
633 DPRINT("Failed to capture the Security Descriptor\n");
634 ObDereferenceObject(Token);
635 return Status;
636 }
637
638 /* Check the captured security descriptor */
639 if (CapturedSecurityDescriptor == NULL)
640 {
641 DPRINT("Security Descriptor is NULL\n");
642 ObDereferenceObject(Token);
643 return STATUS_INVALID_SECURITY_DESCR;
644 }
645
646 /* Check security descriptor for valid owner and group */
647 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
648 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
649 {
650 DPRINT("Security Descriptor does not have a valid group or owner\n");
651 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
652 PreviousMode,
653 FALSE);
654 ObDereferenceObject(Token);
655 return STATUS_INVALID_SECURITY_DESCR;
656 }
657
658 /* Set up the subject context, and lock it */
659 SeCaptureSubjectContext(&SubjectSecurityContext);
660
661 /* Lock the token */
662 SepAcquireTokenLockShared(Token);
663
664 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
665 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
666 {
667 if (SepTokenIsOwner(Token, SecurityDescriptor, FALSE)) // FIXME: use CapturedSecurityDescriptor
668 {
669 if (DesiredAccess & MAXIMUM_ALLOWED)
670 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
671 else
672 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
673
674 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
675 }
676 }
677
678 if (DesiredAccess == 0)
679 {
680 *GrantedAccess = PreviouslyGrantedAccess;
681 *AccessStatus = STATUS_SUCCESS;
682 }
683 else
684 {
685 /* Now perform the access check */
686 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
687 &SubjectSecurityContext,
688 DesiredAccess,
689 PreviouslyGrantedAccess,
690 &PrivilegeSet, //FIXME
691 GenericMapping,
692 PreviousMode,
693 GrantedAccess,
694 AccessStatus);
695 }
696
697 /* Release subject context and unlock the token */
698 SeReleaseSubjectContext(&SubjectSecurityContext);
699 SepReleaseTokenLock(Token);
700
701 /* Release the captured security descriptor */
702 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
703 PreviousMode,
704 FALSE);
705
706 /* Dereference the token */
707 ObDereferenceObject(Token);
708
709 /* Check succeeded */
710 return STATUS_SUCCESS;
711 }
712
713
714 NTSTATUS
715 NTAPI
716 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
717 IN PSID PrincipalSelfSid,
718 IN HANDLE ClientToken,
719 IN ACCESS_MASK DesiredAccess,
720 IN POBJECT_TYPE_LIST ObjectTypeList,
721 IN ULONG ObjectTypeLength,
722 IN PGENERIC_MAPPING GenericMapping,
723 IN PPRIVILEGE_SET PrivilegeSet,
724 IN OUT PULONG PrivilegeSetLength,
725 OUT PACCESS_MASK GrantedAccess,
726 OUT PNTSTATUS AccessStatus)
727 {
728 UNIMPLEMENTED;
729 return STATUS_NOT_IMPLEMENTED;
730 }
731
732 NTSTATUS
733 NTAPI
734 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
735 IN PSID PrincipalSelfSid,
736 IN HANDLE ClientToken,
737 IN ACCESS_MASK DesiredAccess,
738 IN POBJECT_TYPE_LIST ObjectTypeList,
739 IN ULONG ObjectTypeLength,
740 IN PGENERIC_MAPPING GenericMapping,
741 IN PPRIVILEGE_SET PrivilegeSet,
742 IN OUT PULONG PrivilegeSetLength,
743 OUT PACCESS_MASK GrantedAccess,
744 OUT PNTSTATUS AccessStatus)
745 {
746 UNIMPLEMENTED;
747 return STATUS_NOT_IMPLEMENTED;
748 }
749
750 /* EOF */