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