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