Sync with trunk r63786.
[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 #define OLD_ACCESS_CHECK
22
23 BOOLEAN NTAPI
24 SepAccessCheckEx(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
25 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
26 IN ACCESS_MASK DesiredAccess,
27 IN POBJECT_TYPE_LIST ObjectTypeList,
28 IN ULONG ObjectTypeListLength,
29 IN ACCESS_MASK PreviouslyGrantedAccess,
30 OUT PPRIVILEGE_SET* Privileges,
31 IN PGENERIC_MAPPING GenericMapping,
32 IN KPROCESSOR_MODE AccessMode,
33 OUT PACCESS_MASK GrantedAccessList,
34 OUT PNTSTATUS AccessStatusList,
35 IN BOOLEAN UseResultList)
36 {
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, ResultListLength;
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 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 #ifdef OLD_ACCESS_CHECK
214 PreviouslyGrantedAccess = 0;
215 Status = STATUS_ACCESS_DENIED;
216 goto ReturnCommonStatus;
217 #else
218 /* Map access rights from the ACE */
219 TempAccess = CurrentAce->AccessMask;
220 RtlMapGenericMask(&TempAccess, GenericMapping);
221
222 /* Leave if a remaining right must be denied */
223 if (RemainingAccess & TempAccess)
224 break;
225 #endif
226 }
227 }
228 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
229 {
230 if (SepSidInToken(Token, Sid))
231 {
232 #ifdef OLD_ACCESS_CHECK
233 TempAccess = CurrentAce->AccessMask;
234 RtlMapGenericMask(&TempAccess, GenericMapping);
235 PreviouslyGrantedAccess |= TempAccess;
236 #else
237 /* Map access rights from the ACE */
238 TempAccess = CurrentAce->AccessMask;
239 RtlMapGenericMask(&TempAccess, GenericMapping);
240
241 /* Remove granted rights */
242 RemainingAccess &= ~TempAccess;
243 #endif
244 }
245 }
246 else
247 {
248 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
249 }
250 }
251
252 /* Get the next ACE */
253 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
254 }
255
256 #ifdef OLD_ACCESS_CHECK
257 DPRINT("PreviouslyGrantedAccess %08lx\n DesiredAccess %08lx\n",
258 PreviouslyGrantedAccess, DesiredAccess);
259
260 PreviouslyGrantedAccess &= DesiredAccess;
261
262 if ((PreviouslyGrantedAccess & ~VALID_INHERIT_FLAGS) ==
263 (DesiredAccess & ~VALID_INHERIT_FLAGS))
264 {
265 Status = STATUS_SUCCESS;
266 goto ReturnCommonStatus;
267 }
268 else
269 {
270 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
271 PreviouslyGrantedAccess, DesiredAccess, GenericMapping);
272 //*AccessStatus = STATUS_ACCESS_DENIED;
273 //return FALSE;
274 PreviouslyGrantedAccess = DesiredAccess;
275 Status = STATUS_SUCCESS;
276 goto ReturnCommonStatus;
277 }
278 #else
279 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
280 DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
281
282 /* Fail if some rights have not been granted */
283 if (RemainingAccess != 0)
284 {
285 *GrantedAccess = 0;
286 Status = STATUS_ACCESS_DENIED;
287 goto ReturnCommonStatus;
288 }
289
290 /* Set granted access rights */
291 PreviouslyGrantedAccess |= DesiredAccess;
292
293 DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
294
295 /* Fail if no rights have been granted */
296 if (PreviouslyGrantedAccess == 0)
297 {
298 Status = STATUS_ACCESS_DENIED;
299 goto ReturnCommonStatus;
300 }
301
302 Status = STATUS_SUCCESS;
303 goto ReturnCommonStatus;
304 #endif
305
306 ReturnCommonStatus:
307
308 ResultListLength = UseResultList ? ObjectTypeListLength : 1;
309 for (i = 0; i < ResultListLength; i++)
310 {
311 GrantedAccessList[i] = PreviouslyGrantedAccess;
312 AccessStatusList[i] = Status;
313 }
314
315 return NT_SUCCESS(Status);
316 }
317
318 BOOLEAN NTAPI
319 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
320 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
321 IN ACCESS_MASK DesiredAccess,
322 IN ACCESS_MASK PreviouslyGrantedAccess,
323 OUT PPRIVILEGE_SET* Privileges,
324 IN PGENERIC_MAPPING GenericMapping,
325 IN KPROCESSOR_MODE AccessMode,
326 OUT PACCESS_MASK GrantedAccess,
327 OUT PNTSTATUS AccessStatus)
328 {
329 return SepAccessCheckEx(SecurityDescriptor,
330 SubjectSecurityContext,
331 DesiredAccess,
332 NULL,
333 0,
334 PreviouslyGrantedAccess,
335 Privileges,
336 GenericMapping,
337 AccessMode,
338 GrantedAccess,
339 AccessStatus,
340 FALSE);
341 }
342
343 static PSID
344 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
345 {
346 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
347 PSID Owner;
348
349 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
350 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
351 (ULONG_PTR)SecurityDescriptor);
352 else
353 Owner = (PSID)SecurityDescriptor->Owner;
354
355 return Owner;
356 }
357
358 static PSID
359 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
360 {
361 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
362 PSID Group;
363
364 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
365 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
366 (ULONG_PTR)SecurityDescriptor);
367 else
368 Group = (PSID)SecurityDescriptor->Group;
369
370 return Group;
371 }
372
373
374 /* PUBLIC FUNCTIONS ***********************************************************/
375
376 /*
377 * @implemented
378 */
379 BOOLEAN
380 NTAPI
381 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
382 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
383 IN BOOLEAN SubjectContextLocked,
384 IN ACCESS_MASK DesiredAccess,
385 IN ACCESS_MASK PreviouslyGrantedAccess,
386 OUT PPRIVILEGE_SET* Privileges,
387 IN PGENERIC_MAPPING GenericMapping,
388 IN KPROCESSOR_MODE AccessMode,
389 OUT PACCESS_MASK GrantedAccess,
390 OUT PNTSTATUS AccessStatus)
391 {
392 BOOLEAN ret;
393
394 PAGED_CODE();
395
396 /* Check if this is kernel mode */
397 if (AccessMode == KernelMode)
398 {
399 /* Check if kernel wants everything */
400 if (DesiredAccess & MAXIMUM_ALLOWED)
401 {
402 /* Give it */
403 *GrantedAccess = GenericMapping->GenericAll;
404 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
405 *GrantedAccess |= PreviouslyGrantedAccess;
406 }
407 else
408 {
409 /* Give the desired and previous access */
410 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
411 }
412
413 /* Success */
414 *AccessStatus = STATUS_SUCCESS;
415 return TRUE;
416 }
417
418 /* Check if we didn't get an SD */
419 if (!SecurityDescriptor)
420 {
421 /* Automatic failure */
422 *AccessStatus = STATUS_ACCESS_DENIED;
423 return FALSE;
424 }
425
426 /* Check for invalid impersonation */
427 if ((SubjectSecurityContext->ClientToken) &&
428 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
429 {
430 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
431 return FALSE;
432 }
433
434 /* Acquire the lock if needed */
435 if (!SubjectContextLocked)
436 SeLockSubjectContext(SubjectSecurityContext);
437
438 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
439 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
440 {
441 PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
442 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
443
444 if (SepTokenIsOwner(Token,
445 SecurityDescriptor,
446 FALSE))
447 {
448 if (DesiredAccess & MAXIMUM_ALLOWED)
449 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
450 else
451 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
452
453 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
454 }
455 }
456
457 if (DesiredAccess == 0)
458 {
459 *GrantedAccess = PreviouslyGrantedAccess;
460 *AccessStatus = STATUS_SUCCESS;
461 ret = TRUE;
462 }
463 else
464 {
465 /* Call the internal function */
466 ret = SepAccessCheck(SecurityDescriptor,
467 SubjectSecurityContext,
468 DesiredAccess,
469 PreviouslyGrantedAccess,
470 Privileges,
471 GenericMapping,
472 AccessMode,
473 GrantedAccess,
474 AccessStatus);
475 }
476
477 /* Release the lock if needed */
478 if (!SubjectContextLocked)
479 SeUnlockSubjectContext(SubjectSecurityContext);
480
481 return ret;
482 }
483
484 /*
485 * @implemented
486 */
487 BOOLEAN
488 NTAPI
489 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
490 IN PACCESS_STATE AccessState,
491 IN ACCESS_MASK DesiredAccess,
492 IN KPROCESSOR_MODE AccessMode)
493 {
494 PACL Dacl;
495 ULONG AceIndex;
496 PKNOWN_ACE Ace;
497
498 PAGED_CODE();
499
500 NT_ASSERT(AccessMode != KernelMode);
501
502 if (SecurityDescriptor == NULL)
503 return FALSE;
504
505 /* Get DACL */
506 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
507 /* If no DACL, grant access */
508 if (Dacl == NULL)
509 return TRUE;
510
511 /* No ACE -> Deny */
512 if (!Dacl->AceCount)
513 return FALSE;
514
515 /* Can't perform the check on restricted token */
516 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
517 return FALSE;
518
519 /* Browse the ACEs */
520 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
521 AceIndex < Dacl->AceCount;
522 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
523 {
524 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
525 continue;
526
527 /* If access-allowed ACE */
528 if (Ace->Header.AceType & ACCESS_ALLOWED_ACE_TYPE)
529 {
530 /* Check if all accesses are granted */
531 if (!(Ace->Mask & DesiredAccess))
532 continue;
533
534 /* Check SID and grant access if matching */
535 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
536 return TRUE;
537 }
538 /* If access-denied ACE */
539 else if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE)
540 {
541 /* Here, only check if it denies all the access wanted and deny if so */
542 if (Ace->Mask & DesiredAccess)
543 return FALSE;
544 }
545 }
546
547 /* Faulty, deny */
548 return FALSE;
549 }
550
551 /* SYSTEM CALLS ***************************************************************/
552
553 /*
554 * @implemented
555 */
556 NTSTATUS
557 NTAPI
558 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
559 IN HANDLE TokenHandle,
560 IN ACCESS_MASK DesiredAccess,
561 IN PGENERIC_MAPPING GenericMapping,
562 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
563 IN OUT PULONG PrivilegeSetLength,
564 OUT PACCESS_MASK GrantedAccess,
565 OUT PNTSTATUS AccessStatus)
566 {
567 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
568 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
569 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
570 ACCESS_MASK PreviouslyGrantedAccess = 0;
571 PTOKEN Token;
572 NTSTATUS Status;
573 PAGED_CODE();
574
575 /* Check if this is kernel mode */
576 if (PreviousMode == KernelMode)
577 {
578 /* Check if kernel wants everything */
579 if (DesiredAccess & MAXIMUM_ALLOWED)
580 {
581 /* Give it */
582 *GrantedAccess = GenericMapping->GenericAll;
583 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
584 }
585 else
586 {
587 /* Just give the desired access */
588 *GrantedAccess = DesiredAccess;
589 }
590
591 /* Success */
592 *AccessStatus = STATUS_SUCCESS;
593 return STATUS_SUCCESS;
594 }
595
596 /* Protect probe in SEH */
597 _SEH2_TRY
598 {
599 /* Probe all pointers */
600 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
601 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
602 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
603 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
604 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
605
606 /* Initialize the privilege set */
607 PrivilegeSet->PrivilegeCount = 0;
608 }
609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
610 {
611 /* Return the exception code */
612 _SEH2_YIELD(return _SEH2_GetExceptionCode());
613 }
614 _SEH2_END;
615
616 /* Check for unmapped access rights */
617 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
618 return STATUS_GENERIC_NOT_MAPPED;
619
620 /* Reference the token */
621 Status = ObReferenceObjectByHandle(TokenHandle,
622 TOKEN_QUERY,
623 SeTokenObjectType,
624 PreviousMode,
625 (PVOID*)&Token,
626 NULL);
627 if (!NT_SUCCESS(Status))
628 {
629 DPRINT("Failed to reference token (Status %lx)\n", Status);
630 return Status;
631 }
632
633 /* Check token type */
634 if (Token->TokenType != TokenImpersonation)
635 {
636 DPRINT("No impersonation token\n");
637 ObDereferenceObject(Token);
638 return STATUS_NO_IMPERSONATION_TOKEN;
639 }
640
641 /* Check the impersonation level */
642 if (Token->ImpersonationLevel < SecurityIdentification)
643 {
644 DPRINT("Impersonation level < SecurityIdentification\n");
645 ObDereferenceObject(Token);
646 return STATUS_BAD_IMPERSONATION_LEVEL;
647 }
648
649 /* Capture the security descriptor */
650 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
651 PreviousMode,
652 PagedPool,
653 FALSE,
654 &CapturedSecurityDescriptor);
655 if (!NT_SUCCESS(Status))
656 {
657 DPRINT("Failed to capture the Security Descriptor\n");
658 ObDereferenceObject(Token);
659 return Status;
660 }
661
662 /* Check the captured security descriptor */
663 if (CapturedSecurityDescriptor == NULL)
664 {
665 DPRINT("Security Descriptor is NULL\n");
666 ObDereferenceObject(Token);
667 return STATUS_INVALID_SECURITY_DESCR;
668 }
669
670 /* Check security descriptor for valid owner and group */
671 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
672 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
673 {
674 DPRINT("Security Descriptor does not have a valid group or owner\n");
675 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
676 PreviousMode,
677 FALSE);
678 ObDereferenceObject(Token);
679 return STATUS_INVALID_SECURITY_DESCR;
680 }
681
682 /* Set up the subject context, and lock it */
683 SeCaptureSubjectContext(&SubjectSecurityContext);
684
685 /* Lock the token */
686 SepAcquireTokenLockShared(Token);
687
688 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
689 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
690 {
691 if (SepTokenIsOwner(Token, SecurityDescriptor, FALSE)) // FIXME: use CapturedSecurityDescriptor
692 {
693 if (DesiredAccess & MAXIMUM_ALLOWED)
694 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
695 else
696 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
697
698 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
699 }
700 }
701
702 if (DesiredAccess == 0)
703 {
704 *GrantedAccess = PreviouslyGrantedAccess;
705 *AccessStatus = STATUS_SUCCESS;
706 }
707 else
708 {
709 /* Now perform the access check */
710 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
711 &SubjectSecurityContext,
712 DesiredAccess,
713 PreviouslyGrantedAccess,
714 &PrivilegeSet, //FIXME
715 GenericMapping,
716 PreviousMode,
717 GrantedAccess,
718 AccessStatus);
719 }
720
721 /* Release subject context and unlock the token */
722 SeReleaseSubjectContext(&SubjectSecurityContext);
723 SepReleaseTokenLock(Token);
724
725 /* Release the captured security descriptor */
726 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
727 PreviousMode,
728 FALSE);
729
730 /* Dereference the token */
731 ObDereferenceObject(Token);
732
733 /* Check succeeded */
734 return STATUS_SUCCESS;
735 }
736
737
738 NTSTATUS
739 NTAPI
740 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
741 IN PSID PrincipalSelfSid,
742 IN HANDLE ClientToken,
743 IN ACCESS_MASK DesiredAccess,
744 IN POBJECT_TYPE_LIST ObjectTypeList,
745 IN ULONG ObjectTypeLength,
746 IN PGENERIC_MAPPING GenericMapping,
747 IN PPRIVILEGE_SET PrivilegeSet,
748 IN OUT PULONG PrivilegeSetLength,
749 OUT PACCESS_MASK GrantedAccess,
750 OUT PNTSTATUS AccessStatus)
751 {
752 UNIMPLEMENTED;
753 return STATUS_NOT_IMPLEMENTED;
754 }
755
756 NTSTATUS
757 NTAPI
758 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
759 IN PSID PrincipalSelfSid,
760 IN HANDLE ClientToken,
761 IN ACCESS_MASK DesiredAccess,
762 IN POBJECT_TYPE_LIST ObjectTypeList,
763 IN ULONG ObjectTypeLength,
764 IN PGENERIC_MAPPING GenericMapping,
765 IN PPRIVILEGE_SET PrivilegeSet,
766 IN OUT PULONG PrivilegeSetLength,
767 OUT PACCESS_MASK GrantedAccess,
768 OUT PNTSTATUS AccessStatus)
769 {
770 UNIMPLEMENTED;
771 return STATUS_NOT_IMPLEMENTED;
772 }
773
774 /* EOF */