Merge 15329:15546 from trunk
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PSE_EXPORTS EXPORTED SeExports = NULL;
20 SE_EXPORTS SepExports;
21
22 static ERESOURCE SepSubjectContextLock;
23
24
25 /* PROTOTYPES ***************************************************************/
26
27 static BOOLEAN SepInitExports(VOID);
28
29
30 /* FUNCTIONS ****************************************************************/
31
32 BOOLEAN INIT_FUNCTION
33 SeInit1(VOID)
34 {
35 SepInitLuid();
36
37 if (!SepInitSecurityIDs())
38 return FALSE;
39
40 if (!SepInitDACLs())
41 return FALSE;
42
43 if (!SepInitSDs())
44 return FALSE;
45
46 SepInitPrivileges();
47
48 if (!SepInitExports())
49 return FALSE;
50
51 /* Initialize the subject context lock */
52 ExInitializeResource(&SepSubjectContextLock);
53
54 return TRUE;
55 }
56
57
58 BOOLEAN INIT_FUNCTION
59 SeInit2(VOID)
60 {
61 SepInitializeTokenImplementation();
62
63 return TRUE;
64 }
65
66
67 BOOLEAN
68 SeInitSRM(VOID)
69 {
70 OBJECT_ATTRIBUTES ObjectAttributes;
71 UNICODE_STRING Name;
72 HANDLE DirectoryHandle;
73 HANDLE EventHandle;
74 NTSTATUS Status;
75
76 /* Create '\Security' directory */
77 RtlInitUnicodeString(&Name,
78 L"\\Security");
79 InitializeObjectAttributes(&ObjectAttributes,
80 &Name,
81 OBJ_PERMANENT,
82 0,
83 NULL);
84 Status = ZwCreateDirectoryObject(&DirectoryHandle,
85 DIRECTORY_ALL_ACCESS,
86 &ObjectAttributes);
87 if (!NT_SUCCESS(Status))
88 {
89 DPRINT1("Failed to create 'Security' directory!\n");
90 return FALSE;
91 }
92
93 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
94 RtlInitUnicodeString(&Name,
95 L"\\LSA_AUTHENTICATION_INITALIZED");
96 InitializeObjectAttributes(&ObjectAttributes,
97 &Name,
98 OBJ_PERMANENT,
99 DirectoryHandle,
100 SePublicDefaultSd);
101 Status = ZwCreateEvent(&EventHandle,
102 EVENT_ALL_ACCESS,
103 &ObjectAttributes,
104 SynchronizationEvent,
105 FALSE);
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
109 NtClose(DirectoryHandle);
110 return FALSE;
111 }
112
113 ZwClose(EventHandle);
114 ZwClose(DirectoryHandle);
115
116 /* FIXME: Create SRM port and listener thread */
117
118 return TRUE;
119 }
120
121
122 static BOOLEAN INIT_FUNCTION
123 SepInitExports(VOID)
124 {
125 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
126 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
127 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
128 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
129 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
130 SepExports.SeTcbPrivilege = SeTcbPrivilege;
131 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
132 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
133 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
134 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
135 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
136 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
137 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
138 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
139 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
140 SepExports.SeBackupPrivilege = SeBackupPrivilege;
141 SepExports.SeRestorePrivilege = SeRestorePrivilege;
142 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
143 SepExports.SeDebugPrivilege = SeDebugPrivilege;
144 SepExports.SeAuditPrivilege = SeAuditPrivilege;
145 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
146 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
147 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
148
149 SepExports.SeNullSid = SeNullSid;
150 SepExports.SeWorldSid = SeWorldSid;
151 SepExports.SeLocalSid = SeLocalSid;
152 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
153 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
154 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
155 SepExports.SeDialupSid = SeDialupSid;
156 SepExports.SeNetworkSid = SeNetworkSid;
157 SepExports.SeBatchSid = SeBatchSid;
158 SepExports.SeInteractiveSid = SeInteractiveSid;
159 SepExports.SeLocalSystemSid = SeLocalSystemSid;
160 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
161 SepExports.SeAliasUsersSid = SeAliasUsersSid;
162 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
163 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
164 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
165 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
166 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
167 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
168
169 SeExports = &SepExports;
170 return TRUE;
171 }
172
173
174 VOID SepReferenceLogonSession(PLUID AuthenticationId)
175 {
176 UNIMPLEMENTED;
177 }
178
179 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
180 {
181 UNIMPLEMENTED;
182 }
183
184
185 /*
186 * @implemented
187 */
188 VOID STDCALL
189 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
190 {
191 PETHREAD Thread;
192 BOOLEAN CopyOnOpen;
193 BOOLEAN EffectiveOnly;
194
195 PAGED_CODE();
196
197 Thread = PsGetCurrentThread();
198 if (Thread == NULL)
199 {
200 SubjectContext->ProcessAuditId = 0;
201 SubjectContext->PrimaryToken = NULL;
202 SubjectContext->ClientToken = NULL;
203 SubjectContext->ImpersonationLevel = 0;
204 }
205 else
206 {
207 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
208 SubjectContext->ClientToken =
209 PsReferenceImpersonationToken(Thread,
210 &CopyOnOpen,
211 &EffectiveOnly,
212 &SubjectContext->ImpersonationLevel);
213 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
214 }
215 }
216
217
218 /*
219 * @implemented
220 */
221 VOID STDCALL
222 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
223 {
224 PAGED_CODE();
225
226 KeEnterCriticalRegion();
227 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
228 }
229
230
231 /*
232 * @implemented
233 */
234 VOID STDCALL
235 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
236 {
237 PAGED_CODE();
238
239 ExReleaseResourceLite(&SepSubjectContextLock);
240 KeLeaveCriticalRegion();
241 }
242
243
244 /*
245 * @implemented
246 */
247 VOID STDCALL
248 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
249 {
250 PAGED_CODE();
251
252 if (SubjectContext->PrimaryToken != NULL)
253 {
254 ObDereferenceObject(SubjectContext->PrimaryToken);
255 }
256
257 if (SubjectContext->ClientToken != NULL)
258 {
259 ObDereferenceObject(SubjectContext->ClientToken);
260 }
261 }
262
263
264 /*
265 * @implemented
266 */
267 NTSTATUS STDCALL
268 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
269 {
270 PAGED_CODE();
271
272 if (*SecurityDescriptor != NULL)
273 {
274 ExFreePool(*SecurityDescriptor);
275 *SecurityDescriptor = NULL;
276 }
277
278 return STATUS_SUCCESS;
279 }
280
281
282 /*
283 * @unimplemented
284 */
285 NTSTATUS STDCALL
286 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
287 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
288 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
289 IN GUID *ObjectType OPTIONAL,
290 IN BOOLEAN IsDirectoryObject,
291 IN ULONG AutoInheritFlags,
292 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
293 IN PGENERIC_MAPPING GenericMapping,
294 IN POOL_TYPE PoolType)
295 {
296 UNIMPLEMENTED;
297 return STATUS_NOT_IMPLEMENTED;
298 }
299
300
301 /*
302 * FUNCTION: Creates a security descriptor for a new object.
303 * ARGUMENTS:
304 * ParentDescriptor =
305 * ExplicitDescriptor =
306 * NewDescriptor =
307 * IsDirectoryObject =
308 * SubjectContext =
309 * GeneralMapping =
310 * PoolType =
311 * RETURNS: Status
312 *
313 * @implemented
314 */
315 NTSTATUS STDCALL
316 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
317 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
318 PSECURITY_DESCRIPTOR *NewDescriptor,
319 BOOLEAN IsDirectoryObject,
320 PSECURITY_SUBJECT_CONTEXT SubjectContext,
321 PGENERIC_MAPPING GenericMapping,
322 POOL_TYPE PoolType)
323 {
324 PSECURITY_DESCRIPTOR Descriptor;
325 PTOKEN Token;
326 ULONG OwnerLength = 0;
327 ULONG GroupLength = 0;
328 ULONG DaclLength = 0;
329 ULONG SaclLength = 0;
330 ULONG Length = 0;
331 ULONG Control = 0;
332 ULONG_PTR Current;
333 PSID Owner = NULL;
334 PSID Group = NULL;
335 PACL Dacl = NULL;
336 PACL Sacl = NULL;
337
338 PAGED_CODE();
339
340 /* Lock subject context */
341 SeLockSubjectContext(SubjectContext);
342
343 if (SubjectContext->ClientToken != NULL)
344 {
345 Token = SubjectContext->ClientToken;
346 }
347 else
348 {
349 Token = SubjectContext->PrimaryToken;
350 }
351
352
353 /* Inherit the Owner SID */
354 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
355 {
356 DPRINT("Use explicit owner sid!\n");
357 Owner = ExplicitDescriptor->Owner;
358
359 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
360 {
361 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
362
363 }
364 }
365 else
366 {
367 if (Token != NULL)
368 {
369 DPRINT("Use token owner sid!\n");
370 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
371 }
372 else
373 {
374 DPRINT("Use default owner sid!\n");
375 Owner = SeLocalSystemSid;
376 }
377
378 Control |= SE_OWNER_DEFAULTED;
379 }
380
381 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
382
383
384 /* Inherit the Group SID */
385 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
386 {
387 DPRINT("Use explicit group sid!\n");
388 Group = ExplicitDescriptor->Group;
389 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
390 {
391 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
392 }
393 }
394 else
395 {
396 if (Token != NULL)
397 {
398 DPRINT("Use token group sid!\n");
399 Group = Token->PrimaryGroup;
400 }
401 else
402 {
403 DPRINT("Use default group sid!\n");
404 Group = SeLocalSystemSid;
405 }
406
407 Control |= SE_OWNER_DEFAULTED;
408 }
409
410 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
411
412
413 /* Inherit the DACL */
414 if (ExplicitDescriptor != NULL &&
415 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
416 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
417 {
418 DPRINT("Use explicit DACL!\n");
419 Dacl = ExplicitDescriptor->Dacl;
420 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
421 {
422 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
423 }
424
425 Control |= SE_DACL_PRESENT;
426 }
427 else if (ParentDescriptor != NULL &&
428 (ParentDescriptor->Control & SE_DACL_PRESENT))
429 {
430 DPRINT("Use parent DACL!\n");
431 /* FIXME: Inherit */
432 Dacl = ParentDescriptor->Dacl;
433 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
434 {
435 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
436 }
437 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
438 }
439 else if (Token != NULL && Token->DefaultDacl != NULL)
440 {
441 DPRINT("Use token default DACL!\n");
442 /* FIXME: Inherit */
443 Dacl = Token->DefaultDacl;
444 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
445 }
446 else
447 {
448 DPRINT("Use NULL DACL!\n");
449 Dacl = NULL;
450 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
451 }
452
453 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
454
455
456 /* Inherit the SACL */
457 if (ExplicitDescriptor != NULL &&
458 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
459 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
460 {
461 DPRINT("Use explicit SACL!\n");
462 Sacl = ExplicitDescriptor->Sacl;
463 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
464 {
465 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
466 }
467
468 Control |= SE_SACL_PRESENT;
469 }
470 else if (ParentDescriptor != NULL &&
471 (ParentDescriptor->Control & SE_SACL_PRESENT))
472 {
473 DPRINT("Use parent SACL!\n");
474 /* FIXME: Inherit */
475 Sacl = ParentDescriptor->Sacl;
476 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
477 {
478 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
479 }
480 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
481 }
482
483 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
484
485
486 /* Allocate and initialize the new security descriptor */
487 Length = sizeof(SECURITY_DESCRIPTOR) +
488 OwnerLength + GroupLength + DaclLength + SaclLength;
489
490 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
491 sizeof(SECURITY_DESCRIPTOR),
492 OwnerLength,
493 GroupLength,
494 DaclLength,
495 SaclLength);
496
497 Descriptor = ExAllocatePool(PagedPool,
498 Length);
499 RtlZeroMemory( Descriptor, Length );
500
501 if (Descriptor == NULL)
502 {
503 DPRINT1("ExAlloctePool() failed\n");
504 /* FIXME: Unlock subject context */
505 return STATUS_INSUFFICIENT_RESOURCES;
506 }
507
508 RtlCreateSecurityDescriptor(Descriptor,
509 SECURITY_DESCRIPTOR_REVISION);
510
511 Descriptor->Control = Control | SE_SELF_RELATIVE;
512
513 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
514
515 if (SaclLength != 0)
516 {
517 RtlCopyMemory((PVOID)Current,
518 Sacl,
519 SaclLength);
520 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
521 Current += SaclLength;
522 }
523
524 if (DaclLength != 0)
525 {
526 RtlCopyMemory((PVOID)Current,
527 Dacl,
528 DaclLength);
529 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
530 Current += DaclLength;
531 }
532
533 if (OwnerLength != 0)
534 {
535 RtlCopyMemory((PVOID)Current,
536 Owner,
537 OwnerLength);
538 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
539 Current += OwnerLength;
540 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
541 }
542 else
543 DPRINT("Owner of %x is zero length\n", Descriptor);
544
545 if (GroupLength != 0)
546 {
547 memmove((PVOID)Current,
548 Group,
549 GroupLength);
550 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
551 }
552
553 /* Unlock subject context */
554 SeUnlockSubjectContext(SubjectContext);
555
556 *NewDescriptor = Descriptor;
557
558 DPRINT("Descrptor %x\n", Descriptor);
559 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
560
561 return STATUS_SUCCESS;
562 }
563
564
565 static BOOLEAN
566 SepSidInToken(PACCESS_TOKEN _Token,
567 PSID Sid)
568 {
569 ULONG i;
570 PTOKEN Token = (PTOKEN)_Token;
571
572 PAGED_CODE();
573
574 if (Token->UserAndGroupCount == 0)
575 {
576 return FALSE;
577 }
578
579 for (i=0; i<Token->UserAndGroupCount; i++)
580 {
581 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
582 {
583 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
584 {
585 return TRUE;
586 }
587
588 return FALSE;
589 }
590 }
591
592 return FALSE;
593 }
594
595
596 /*
597 * FUNCTION: Determines whether the requested access rights can be granted
598 * to an object protected by a security descriptor and an object owner
599 * ARGUMENTS:
600 * SecurityDescriptor = Security descriptor protecting the object
601 * SubjectSecurityContext = Subject's captured security context
602 * SubjectContextLocked = Indicates the user's subject context is locked
603 * DesiredAccess = Access rights the caller is trying to acquire
604 * PreviouslyGrantedAccess = Specified the access rights already granted
605 * Privileges = ?
606 * GenericMapping = Generic mapping associated with the object
607 * AccessMode = Access mode used for the check
608 * GrantedAccess (OUT) = On return specifies the access granted
609 * AccessStatus (OUT) = Status indicating why access was denied
610 * RETURNS: If access was granted, returns TRUE
611 *
612 * @implemented
613 */
614 BOOLEAN STDCALL
615 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
616 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
617 IN BOOLEAN SubjectContextLocked,
618 IN ACCESS_MASK DesiredAccess,
619 IN ACCESS_MASK PreviouslyGrantedAccess,
620 OUT PPRIVILEGE_SET* Privileges,
621 IN PGENERIC_MAPPING GenericMapping,
622 IN KPROCESSOR_MODE AccessMode,
623 OUT PACCESS_MASK GrantedAccess,
624 OUT PNTSTATUS AccessStatus)
625 {
626 LUID_AND_ATTRIBUTES Privilege;
627 ACCESS_MASK CurrentAccess;
628 PACCESS_TOKEN Token;
629 ULONG i;
630 PACL Dacl;
631 BOOLEAN Present;
632 BOOLEAN Defaulted;
633 PACE CurrentAce;
634 PSID Sid;
635 NTSTATUS Status;
636
637 PAGED_CODE();
638
639 CurrentAccess = PreviouslyGrantedAccess;
640
641 if (SubjectContextLocked == FALSE)
642 {
643 SeLockSubjectContext(SubjectSecurityContext);
644 }
645
646 Token = SubjectSecurityContext->ClientToken ?
647 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
648
649 /* Get the DACL */
650 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
651 &Present,
652 &Dacl,
653 &Defaulted);
654 if (!NT_SUCCESS(Status))
655 {
656 if (SubjectContextLocked == FALSE)
657 {
658 SeUnlockSubjectContext(SubjectSecurityContext);
659 }
660
661 *AccessStatus = Status;
662 return FALSE;
663 }
664
665 /* RULE 1: Grant desired access if the object is unprotected */
666 if (Present == TRUE && Dacl == NULL)
667 {
668 if (SubjectContextLocked == FALSE)
669 {
670 SeUnlockSubjectContext(SubjectSecurityContext);
671 }
672
673 *GrantedAccess = DesiredAccess;
674 *AccessStatus = STATUS_SUCCESS;
675 return TRUE;
676 }
677
678 CurrentAccess = PreviouslyGrantedAccess;
679
680 /* RULE 2: Check token for 'take ownership' privilege */
681 Privilege.Luid = SeTakeOwnershipPrivilege;
682 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
683
684 if (SepPrivilegeCheck(Token,
685 &Privilege,
686 1,
687 PRIVILEGE_SET_ALL_NECESSARY,
688 AccessMode))
689 {
690 CurrentAccess |= WRITE_OWNER;
691 if (DesiredAccess == CurrentAccess)
692 {
693 if (SubjectContextLocked == FALSE)
694 {
695 SeUnlockSubjectContext(SubjectSecurityContext);
696 }
697
698 *GrantedAccess = CurrentAccess;
699 *AccessStatus = STATUS_SUCCESS;
700 return TRUE;
701 }
702 }
703
704 /* RULE 3: Check whether the token is the owner */
705 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
706 &Sid,
707 &Defaulted);
708 if (!NT_SUCCESS(Status))
709 {
710 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
711 if (SubjectContextLocked == FALSE)
712 {
713 SeUnlockSubjectContext(SubjectSecurityContext);
714 }
715
716 *AccessStatus = Status;
717 return FALSE;
718 }
719
720 if (SepSidInToken(Token, Sid))
721 {
722 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
723 if (DesiredAccess == CurrentAccess)
724 {
725 if (SubjectContextLocked == FALSE)
726 {
727 SeUnlockSubjectContext(SubjectSecurityContext);
728 }
729
730 *GrantedAccess = CurrentAccess;
731 *AccessStatus = STATUS_SUCCESS;
732 return TRUE;
733 }
734 }
735
736 /* Fail if DACL is absent */
737 if (Present == FALSE)
738 {
739 if (SubjectContextLocked == FALSE)
740 {
741 SeUnlockSubjectContext(SubjectSecurityContext);
742 }
743
744 *GrantedAccess = 0;
745 *AccessStatus = STATUS_ACCESS_DENIED;
746 return TRUE;
747 }
748
749 /* RULE 4: Grant rights according to the DACL */
750 CurrentAce = (PACE)(Dacl + 1);
751 for (i = 0; i < Dacl->AceCount; i++)
752 {
753 Sid = (PSID)(CurrentAce + 1);
754 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
755 {
756 if (SepSidInToken(Token, Sid))
757 {
758 if (SubjectContextLocked == FALSE)
759 {
760 SeUnlockSubjectContext(SubjectSecurityContext);
761 }
762
763 *GrantedAccess = 0;
764 *AccessStatus = STATUS_ACCESS_DENIED;
765 return TRUE;
766 }
767 }
768
769 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
770 {
771 if (SepSidInToken(Token, Sid))
772 {
773 CurrentAccess |= CurrentAce->AccessMask;
774 }
775 }
776 }
777
778 if (SubjectContextLocked == FALSE)
779 {
780 SeUnlockSubjectContext(SubjectSecurityContext);
781 }
782
783 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
784 CurrentAccess, DesiredAccess);
785
786 *GrantedAccess = CurrentAccess & DesiredAccess;
787
788 *AccessStatus =
789 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
790
791 return TRUE;
792 }
793
794
795 NTSTATUS STDCALL
796 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
797 IN HANDLE TokenHandle,
798 IN ACCESS_MASK DesiredAccess,
799 IN PGENERIC_MAPPING GenericMapping,
800 OUT PPRIVILEGE_SET PrivilegeSet,
801 OUT PULONG ReturnLength,
802 OUT PACCESS_MASK GrantedAccess,
803 OUT PNTSTATUS AccessStatus)
804 {
805 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
806 KPROCESSOR_MODE PreviousMode;
807 PTOKEN Token;
808 NTSTATUS Status;
809
810 PAGED_CODE();
811
812 DPRINT("NtAccessCheck() called\n");
813
814 PreviousMode = KeGetPreviousMode();
815 if (PreviousMode == KernelMode)
816 {
817 *GrantedAccess = DesiredAccess;
818 *AccessStatus = STATUS_SUCCESS;
819 return STATUS_SUCCESS;
820 }
821
822 Status = ObReferenceObjectByHandle(TokenHandle,
823 TOKEN_QUERY,
824 SepTokenObjectType,
825 PreviousMode,
826 (PVOID*)&Token,
827 NULL);
828 if (!NT_SUCCESS(Status))
829 {
830 DPRINT1("Failed to reference token (Status %lx)\n", Status);
831 return Status;
832 }
833
834 /* Check token type */
835 if (Token->TokenType != TokenImpersonation)
836 {
837 DPRINT1("No impersonation token\n");
838 ObDereferenceObject(Token);
839 return STATUS_ACCESS_VIOLATION;
840 }
841
842 /* Check impersonation level */
843 if (Token->ImpersonationLevel < SecurityAnonymous)
844 {
845 DPRINT1("Invalid impersonation level\n");
846 ObDereferenceObject(Token);
847 return STATUS_ACCESS_VIOLATION;
848 }
849
850 RtlZeroMemory(&SubjectSecurityContext,
851 sizeof(SECURITY_SUBJECT_CONTEXT));
852 SubjectSecurityContext.ClientToken = Token;
853 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
854
855 /* Lock subject context */
856 SeLockSubjectContext(&SubjectSecurityContext);
857
858 if (SeAccessCheck(SecurityDescriptor,
859 &SubjectSecurityContext,
860 TRUE,
861 DesiredAccess,
862 0,
863 &PrivilegeSet,
864 GenericMapping,
865 PreviousMode,
866 GrantedAccess,
867 AccessStatus))
868 {
869 Status = *AccessStatus;
870 }
871 else
872 {
873 Status = STATUS_ACCESS_DENIED;
874 }
875
876 /* Unlock subject context */
877 SeUnlockSubjectContext(&SubjectSecurityContext);
878
879 ObDereferenceObject(Token);
880
881 DPRINT("NtAccessCheck() done\n");
882
883 return Status;
884 }
885
886 /* EOF */