* Sync up to trunk head (r65074).
[reactos.git] / 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 DPRINT1("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 *AccessStatus = STATUS_SUCCESS;
429 ret = TRUE;
430 }
431 else
432 {
433 /* Call the internal function */
434 ret = SepAccessCheck(SecurityDescriptor,
435 SubjectSecurityContext,
436 DesiredAccess,
437 PreviouslyGrantedAccess,
438 Privileges,
439 GenericMapping,
440 AccessMode,
441 GrantedAccess,
442 AccessStatus);
443 }
444
445 /* Release the lock if needed */
446 if (!SubjectContextLocked)
447 SeUnlockSubjectContext(SubjectSecurityContext);
448
449 return ret;
450 }
451
452 /*
453 * @implemented
454 */
455 BOOLEAN
456 NTAPI
457 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
458 IN PACCESS_STATE AccessState,
459 IN ACCESS_MASK DesiredAccess,
460 IN KPROCESSOR_MODE AccessMode)
461 {
462 PACL Dacl;
463 ULONG AceIndex;
464 PKNOWN_ACE Ace;
465
466 PAGED_CODE();
467
468 NT_ASSERT(AccessMode != KernelMode);
469
470 if (SecurityDescriptor == NULL)
471 return FALSE;
472
473 /* Get DACL */
474 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
475 /* If no DACL, grant access */
476 if (Dacl == NULL)
477 return TRUE;
478
479 /* No ACE -> Deny */
480 if (!Dacl->AceCount)
481 return FALSE;
482
483 /* Can't perform the check on restricted token */
484 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
485 return FALSE;
486
487 /* Browse the ACEs */
488 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
489 AceIndex < Dacl->AceCount;
490 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
491 {
492 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
493 continue;
494
495 /* If access-allowed ACE */
496 if (Ace->Header.AceType & ACCESS_ALLOWED_ACE_TYPE)
497 {
498 /* Check if all accesses are granted */
499 if (!(Ace->Mask & DesiredAccess))
500 continue;
501
502 /* Check SID and grant access if matching */
503 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
504 return TRUE;
505 }
506 /* If access-denied ACE */
507 else if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE)
508 {
509 /* Here, only check if it denies all the access wanted and deny if so */
510 if (Ace->Mask & DesiredAccess)
511 return FALSE;
512 }
513 }
514
515 /* Faulty, deny */
516 return FALSE;
517 }
518
519 /* SYSTEM CALLS ***************************************************************/
520
521 /*
522 * @implemented
523 */
524 NTSTATUS
525 NTAPI
526 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
527 IN HANDLE TokenHandle,
528 IN ACCESS_MASK DesiredAccess,
529 IN PGENERIC_MAPPING GenericMapping,
530 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
531 IN OUT PULONG PrivilegeSetLength,
532 OUT PACCESS_MASK GrantedAccess,
533 OUT PNTSTATUS AccessStatus)
534 {
535 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
536 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
537 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
538 ACCESS_MASK PreviouslyGrantedAccess = 0;
539 PTOKEN Token;
540 NTSTATUS Status;
541 PAGED_CODE();
542
543 /* Check if this is kernel mode */
544 if (PreviousMode == KernelMode)
545 {
546 /* Check if kernel wants everything */
547 if (DesiredAccess & MAXIMUM_ALLOWED)
548 {
549 /* Give it */
550 *GrantedAccess = GenericMapping->GenericAll;
551 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
552 }
553 else
554 {
555 /* Just give the desired access */
556 *GrantedAccess = DesiredAccess;
557 }
558
559 /* Success */
560 *AccessStatus = STATUS_SUCCESS;
561 return STATUS_SUCCESS;
562 }
563
564 /* Protect probe in SEH */
565 _SEH2_TRY
566 {
567 /* Probe all pointers */
568 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
569 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
570 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
571 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
572 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
573
574 /* Initialize the privilege set */
575 PrivilegeSet->PrivilegeCount = 0;
576 }
577 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
578 {
579 /* Return the exception code */
580 _SEH2_YIELD(return _SEH2_GetExceptionCode());
581 }
582 _SEH2_END;
583
584 /* Check for unmapped access rights */
585 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
586 return STATUS_GENERIC_NOT_MAPPED;
587
588 /* Reference the token */
589 Status = ObReferenceObjectByHandle(TokenHandle,
590 TOKEN_QUERY,
591 SeTokenObjectType,
592 PreviousMode,
593 (PVOID*)&Token,
594 NULL);
595 if (!NT_SUCCESS(Status))
596 {
597 DPRINT("Failed to reference token (Status %lx)\n", Status);
598 return Status;
599 }
600
601 /* Check token type */
602 if (Token->TokenType != TokenImpersonation)
603 {
604 DPRINT("No impersonation token\n");
605 ObDereferenceObject(Token);
606 return STATUS_NO_IMPERSONATION_TOKEN;
607 }
608
609 /* Check the impersonation level */
610 if (Token->ImpersonationLevel < SecurityIdentification)
611 {
612 DPRINT("Impersonation level < SecurityIdentification\n");
613 ObDereferenceObject(Token);
614 return STATUS_BAD_IMPERSONATION_LEVEL;
615 }
616
617 /* Capture the security descriptor */
618 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
619 PreviousMode,
620 PagedPool,
621 FALSE,
622 &CapturedSecurityDescriptor);
623 if (!NT_SUCCESS(Status))
624 {
625 DPRINT("Failed to capture the Security Descriptor\n");
626 ObDereferenceObject(Token);
627 return Status;
628 }
629
630 /* Check the captured security descriptor */
631 if (CapturedSecurityDescriptor == NULL)
632 {
633 DPRINT("Security Descriptor is NULL\n");
634 ObDereferenceObject(Token);
635 return STATUS_INVALID_SECURITY_DESCR;
636 }
637
638 /* Check security descriptor for valid owner and group */
639 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
640 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
641 {
642 DPRINT("Security Descriptor does not have a valid group or owner\n");
643 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
644 PreviousMode,
645 FALSE);
646 ObDereferenceObject(Token);
647 return STATUS_INVALID_SECURITY_DESCR;
648 }
649
650 /* Set up the subject context, and lock it */
651 SeCaptureSubjectContext(&SubjectSecurityContext);
652
653 /* Lock the token */
654 SepAcquireTokenLockShared(Token);
655
656 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
657 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
658 {
659 if (SepTokenIsOwner(Token, SecurityDescriptor, FALSE)) // FIXME: use CapturedSecurityDescriptor
660 {
661 if (DesiredAccess & MAXIMUM_ALLOWED)
662 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
663 else
664 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
665
666 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
667 }
668 }
669
670 if (DesiredAccess == 0)
671 {
672 *GrantedAccess = PreviouslyGrantedAccess;
673 *AccessStatus = STATUS_SUCCESS;
674 }
675 else
676 {
677 /* Now perform the access check */
678 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
679 &SubjectSecurityContext,
680 DesiredAccess,
681 PreviouslyGrantedAccess,
682 &PrivilegeSet, //FIXME
683 GenericMapping,
684 PreviousMode,
685 GrantedAccess,
686 AccessStatus);
687 }
688
689 /* Release subject context and unlock the token */
690 SeReleaseSubjectContext(&SubjectSecurityContext);
691 SepReleaseTokenLock(Token);
692
693 /* Release the captured security descriptor */
694 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
695 PreviousMode,
696 FALSE);
697
698 /* Dereference the token */
699 ObDereferenceObject(Token);
700
701 /* Check succeeded */
702 return STATUS_SUCCESS;
703 }
704
705
706 NTSTATUS
707 NTAPI
708 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
709 IN PSID PrincipalSelfSid,
710 IN HANDLE ClientToken,
711 IN ACCESS_MASK DesiredAccess,
712 IN POBJECT_TYPE_LIST ObjectTypeList,
713 IN ULONG ObjectTypeLength,
714 IN PGENERIC_MAPPING GenericMapping,
715 IN PPRIVILEGE_SET PrivilegeSet,
716 IN OUT PULONG PrivilegeSetLength,
717 OUT PACCESS_MASK GrantedAccess,
718 OUT PNTSTATUS AccessStatus)
719 {
720 UNIMPLEMENTED;
721 return STATUS_NOT_IMPLEMENTED;
722 }
723
724 NTSTATUS
725 NTAPI
726 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
727 IN PSID PrincipalSelfSid,
728 IN HANDLE ClientToken,
729 IN ACCESS_MASK DesiredAccess,
730 IN POBJECT_TYPE_LIST ObjectTypeList,
731 IN ULONG ObjectTypeLength,
732 IN PGENERIC_MAPPING GenericMapping,
733 IN PPRIVILEGE_SET PrivilegeSet,
734 IN OUT PULONG PrivilegeSetLength,
735 OUT PACCESS_MASK GrantedAccess,
736 OUT PNTSTATUS AccessStatus)
737 {
738 UNIMPLEMENTED;
739 return STATUS_NOT_IMPLEMENTED;
740 }
741
742 /* EOF */