3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
8 * PROGRAMMERS: No programmer listed.
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 PSE_EXPORTS SeExports
= NULL
;
20 SE_EXPORTS SepExports
;
22 static ERESOURCE SepSubjectContextLock
;
25 /* PROTOTYPES ***************************************************************/
27 static BOOLEAN
SepInitExports(VOID
);
29 #if defined (ALLOC_PRAGMA)
30 #pragma alloc_text(INIT, SeInit1)
31 #pragma alloc_text(INIT, SeInit2)
32 #pragma alloc_text(INIT, SepInitExports)
35 /* FUNCTIONS ****************************************************************/
44 if (!SepInitSecurityIDs())
55 if (!SepInitExports())
58 /* Initialize the subject context lock */
59 ExInitializeResource(&SepSubjectContextLock
);
70 SepInitializeTokenImplementation();
80 OBJECT_ATTRIBUTES ObjectAttributes
;
82 HANDLE DirectoryHandle
;
86 /* Create '\Security' directory */
87 RtlInitUnicodeString(&Name
,
89 InitializeObjectAttributes(&ObjectAttributes
,
94 Status
= ZwCreateDirectoryObject(&DirectoryHandle
,
97 if (!NT_SUCCESS(Status
))
99 DPRINT1("Failed to create 'Security' directory!\n");
103 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
104 RtlInitUnicodeString(&Name
,
105 L
"\\LSA_AUTHENTICATION_INITALIZED");
106 InitializeObjectAttributes(&ObjectAttributes
,
111 Status
= ZwCreateEvent(&EventHandle
,
114 SynchronizationEvent
,
116 if (!NT_SUCCESS(Status
))
118 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
119 NtClose(DirectoryHandle
);
123 ZwClose(EventHandle
);
124 ZwClose(DirectoryHandle
);
126 /* FIXME: Create SRM port and listener thread */
132 static BOOLEAN INIT_FUNCTION
135 SepExports
.SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
136 SepExports
.SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
137 SepExports
.SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
138 SepExports
.SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
139 SepExports
.SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
140 SepExports
.SeTcbPrivilege
= SeTcbPrivilege
;
141 SepExports
.SeSecurityPrivilege
= SeSecurityPrivilege
;
142 SepExports
.SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
143 SepExports
.SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
144 SepExports
.SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
145 SepExports
.SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
146 SepExports
.SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
147 SepExports
.SeSystemtimePrivilege
= SeSystemtimePrivilege
;
148 SepExports
.SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
149 SepExports
.SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
150 SepExports
.SeBackupPrivilege
= SeBackupPrivilege
;
151 SepExports
.SeRestorePrivilege
= SeRestorePrivilege
;
152 SepExports
.SeShutdownPrivilege
= SeShutdownPrivilege
;
153 SepExports
.SeDebugPrivilege
= SeDebugPrivilege
;
154 SepExports
.SeAuditPrivilege
= SeAuditPrivilege
;
155 SepExports
.SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
156 SepExports
.SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
157 SepExports
.SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
159 SepExports
.SeNullSid
= SeNullSid
;
160 SepExports
.SeWorldSid
= SeWorldSid
;
161 SepExports
.SeLocalSid
= SeLocalSid
;
162 SepExports
.SeCreatorOwnerSid
= SeCreatorOwnerSid
;
163 SepExports
.SeCreatorGroupSid
= SeCreatorGroupSid
;
164 SepExports
.SeNtAuthoritySid
= SeNtAuthoritySid
;
165 SepExports
.SeDialupSid
= SeDialupSid
;
166 SepExports
.SeNetworkSid
= SeNetworkSid
;
167 SepExports
.SeBatchSid
= SeBatchSid
;
168 SepExports
.SeInteractiveSid
= SeInteractiveSid
;
169 SepExports
.SeLocalSystemSid
= SeLocalSystemSid
;
170 SepExports
.SeAliasAdminsSid
= SeAliasAdminsSid
;
171 SepExports
.SeAliasUsersSid
= SeAliasUsersSid
;
172 SepExports
.SeAliasGuestsSid
= SeAliasGuestsSid
;
173 SepExports
.SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
174 SepExports
.SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
175 SepExports
.SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
176 SepExports
.SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
177 SepExports
.SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
178 SepExports
.SeAuthenticatedUsersSid
= SeAuthenticatedUsersSid
;
179 SepExports
.SeRestrictedSid
= SeRestrictedSid
;
180 SepExports
.SeAnonymousLogonSid
= SeAnonymousLogonSid
;
182 SepExports
.SeUndockPrivilege
= SeUndockPrivilege
;
183 SepExports
.SeSyncAgentPrivilege
= SeSyncAgentPrivilege
;
184 SepExports
.SeEnableDelegationPrivilege
= SeEnableDelegationPrivilege
;
186 SeExports
= &SepExports
;
191 VOID
SepReferenceLogonSession(PLUID AuthenticationId
)
196 VOID
SepDeReferenceLogonSession(PLUID AuthenticationId
)
203 SeDefaultObjectMethod(PVOID Object
,
204 SECURITY_OPERATION_CODE OperationType
,
205 SECURITY_INFORMATION SecurityInformation
,
206 PSECURITY_DESCRIPTOR _SecurityDescriptor
,
208 PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
210 PGENERIC_MAPPING GenericMapping
)
212 PISECURITY_DESCRIPTOR ObjectSd
;
213 PISECURITY_DESCRIPTOR NewSd
;
214 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
215 PROS_OBJECT_HEADER Header
= BODY_TO_HEADER(Object
);
220 ULONG OwnerLength
= 0;
221 ULONG GroupLength
= 0;
222 ULONG DaclLength
= 0;
223 ULONG SaclLength
= 0;
228 if (OperationType
== SetSecurityDescriptor
)
230 ObjectSd
= Header
->SecurityDescriptor
;
232 /* Get owner and owner size */
233 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
235 if (SecurityDescriptor
->Owner
!= NULL
)
237 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
238 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
239 (ULONG_PTR
)SecurityDescriptor
);
241 Owner
= (PSID
)SecurityDescriptor
->Owner
;
242 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
244 Control
|= (SecurityDescriptor
->Control
& SE_OWNER_DEFAULTED
);
248 if (ObjectSd
->Owner
!= NULL
)
250 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
251 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
253 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
256 /* Get group and group size */
257 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
259 if (SecurityDescriptor
->Group
!= NULL
)
261 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
262 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
263 (ULONG_PTR
)SecurityDescriptor
);
265 Group
= (PSID
)SecurityDescriptor
->Group
;
266 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
268 Control
|= (SecurityDescriptor
->Control
& SE_GROUP_DEFAULTED
);
272 if (ObjectSd
->Group
!= NULL
)
274 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
275 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
277 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
280 /* Get DACL and DACL size */
281 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
283 if ((SecurityDescriptor
->Control
& SE_DACL_PRESENT
) &&
284 (SecurityDescriptor
->Dacl
!= NULL
))
286 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
287 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Dacl
+
288 (ULONG_PTR
)SecurityDescriptor
);
290 Dacl
= (PACL
)SecurityDescriptor
->Dacl
;
292 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
294 Control
|= (SecurityDescriptor
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
298 if ((ObjectSd
->Control
& SE_DACL_PRESENT
) &&
299 (ObjectSd
->Dacl
!= NULL
))
301 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
302 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
304 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
307 /* Get SACL and SACL size */
308 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
310 if ((SecurityDescriptor
->Control
& SE_SACL_PRESENT
) &&
311 (SecurityDescriptor
->Sacl
!= NULL
))
313 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
314 Sacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Sacl
+
315 (ULONG_PTR
)SecurityDescriptor
);
317 Sacl
= (PACL
)SecurityDescriptor
->Sacl
;
318 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
320 Control
|= (SecurityDescriptor
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
324 if ((ObjectSd
->Control
& SE_SACL_PRESENT
) &&
325 (ObjectSd
->Sacl
!= NULL
))
327 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
328 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
330 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
333 NewSd
= ExAllocatePool(NonPagedPool
,
334 sizeof(SECURITY_DESCRIPTOR
) + OwnerLength
+ GroupLength
+
335 DaclLength
+ SaclLength
);
338 ObDereferenceObject(Object
);
339 return STATUS_INSUFFICIENT_RESOURCES
;
342 RtlCreateSecurityDescriptor(NewSd
,
343 SECURITY_DESCRIPTOR_REVISION1
);
344 /* We always build a self-relative descriptor */
345 NewSd
->Control
= Control
| SE_SELF_RELATIVE
;
347 Current
= (ULONG_PTR
)NewSd
+ sizeof(SECURITY_DESCRIPTOR
);
349 if (OwnerLength
!= 0)
351 RtlCopyMemory((PVOID
)Current
,
354 NewSd
->Owner
= (PSID
)(Current
- (ULONG_PTR
)NewSd
);
355 Current
+= OwnerLength
;
358 if (GroupLength
!= 0)
360 RtlCopyMemory((PVOID
)Current
,
363 NewSd
->Group
= (PSID
)(Current
- (ULONG_PTR
)NewSd
);
364 Current
+= GroupLength
;
369 RtlCopyMemory((PVOID
)Current
,
372 NewSd
->Dacl
= (PACL
)(Current
- (ULONG_PTR
)NewSd
);
373 Current
+= DaclLength
;
378 RtlCopyMemory((PVOID
)Current
,
381 NewSd
->Sacl
= (PACL
)(Current
- (ULONG_PTR
)NewSd
);
382 Current
+= SaclLength
;
386 Status
= ObpAddSecurityDescriptor(NewSd
,
387 &Header
->SecurityDescriptor
);
388 if (NT_SUCCESS(Status
))
390 /* Remove the old security descriptor */
391 ObpRemoveSecurityDescriptor(ObjectSd
);
395 /* Restore the old security descriptor */
396 Header
->SecurityDescriptor
= ObjectSd
;
401 else if (OperationType
== QuerySecurityDescriptor
)
403 Status
= SeQuerySecurityDescriptorInfo(&SecurityInformation
,
406 &Header
->SecurityDescriptor
);
408 else if (OperationType
== AssignSecurityDescriptor
)
410 /* Assign the security descriptor to the object header */
411 Status
= ObpAddSecurityDescriptor(SecurityDescriptor
,
412 &Header
->SecurityDescriptor
);
416 return STATUS_SUCCESS
;
423 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
427 BOOLEAN EffectiveOnly
;
431 Thread
= PsGetCurrentThread();
434 SubjectContext
->ProcessAuditId
= 0;
435 SubjectContext
->PrimaryToken
= NULL
;
436 SubjectContext
->ClientToken
= NULL
;
437 SubjectContext
->ImpersonationLevel
= 0;
441 SubjectContext
->ProcessAuditId
= Thread
->ThreadsProcess
;
442 SubjectContext
->ClientToken
=
443 PsReferenceImpersonationToken(Thread
,
446 &SubjectContext
->ImpersonationLevel
);
447 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
456 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
460 KeEnterCriticalRegion();
461 ExAcquireResourceExclusiveLite(&SepSubjectContextLock
, TRUE
);
469 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
473 ExReleaseResourceLite(&SepSubjectContextLock
);
474 KeLeaveCriticalRegion();
482 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
486 if (SubjectContext
->PrimaryToken
!= NULL
)
488 ObDereferenceObject(SubjectContext
->PrimaryToken
);
491 if (SubjectContext
->ClientToken
!= NULL
)
493 ObDereferenceObject(SubjectContext
->ClientToken
);
502 SeDeassignSecurity(PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
506 if (*SecurityDescriptor
!= NULL
)
508 ExFreePool(*SecurityDescriptor
);
509 *SecurityDescriptor
= NULL
;
512 return STATUS_SUCCESS
;
520 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
521 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
522 OUT PSECURITY_DESCRIPTOR
*NewDescriptor
,
523 IN GUID
*ObjectType OPTIONAL
,
524 IN BOOLEAN IsDirectoryObject
,
525 IN ULONG AutoInheritFlags
,
526 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
527 IN PGENERIC_MAPPING GenericMapping
,
528 IN POOL_TYPE PoolType
)
531 return STATUS_NOT_IMPLEMENTED
;
536 * FUNCTION: Creates a security descriptor for a new object.
539 * ExplicitDescriptor =
541 * IsDirectoryObject =
550 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL
,
551 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL
,
552 PSECURITY_DESCRIPTOR
*NewDescriptor
,
553 BOOLEAN IsDirectoryObject
,
554 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
555 PGENERIC_MAPPING GenericMapping
,
558 PISECURITY_DESCRIPTOR ParentDescriptor
= _ParentDescriptor
;
559 PISECURITY_DESCRIPTOR ExplicitDescriptor
= _ExplicitDescriptor
;
560 PISECURITY_DESCRIPTOR Descriptor
;
562 ULONG OwnerLength
= 0;
563 ULONG GroupLength
= 0;
564 ULONG DaclLength
= 0;
565 ULONG SaclLength
= 0;
576 /* Lock subject context */
577 SeLockSubjectContext(SubjectContext
);
579 if (SubjectContext
->ClientToken
!= NULL
)
581 Token
= SubjectContext
->ClientToken
;
585 Token
= SubjectContext
->PrimaryToken
;
589 /* Inherit the Owner SID */
590 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Owner
!= NULL
)
592 DPRINT("Use explicit owner sid!\n");
593 Owner
= ExplicitDescriptor
->Owner
;
595 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
597 Owner
= (PSID
)(((ULONG_PTR
)Owner
) + (ULONG_PTR
)ExplicitDescriptor
);
605 DPRINT("Use token owner sid!\n");
606 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
610 DPRINT("Use default owner sid!\n");
611 Owner
= SeLocalSystemSid
;
614 Control
|= SE_OWNER_DEFAULTED
;
617 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
620 /* Inherit the Group SID */
621 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Group
!= NULL
)
623 DPRINT("Use explicit group sid!\n");
624 Group
= ExplicitDescriptor
->Group
;
625 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
627 Group
= (PSID
)(((ULONG_PTR
)Group
) + (ULONG_PTR
)ExplicitDescriptor
);
634 DPRINT("Use token group sid!\n");
635 Group
= Token
->PrimaryGroup
;
639 DPRINT("Use default group sid!\n");
640 Group
= SeLocalSystemSid
;
643 Control
|= SE_OWNER_DEFAULTED
;
646 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
649 /* Inherit the DACL */
650 if (ExplicitDescriptor
!= NULL
&&
651 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
652 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
654 DPRINT("Use explicit DACL!\n");
655 Dacl
= ExplicitDescriptor
->Dacl
;
656 if (Dacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
658 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ExplicitDescriptor
);
661 Control
|= SE_DACL_PRESENT
;
663 else if (ParentDescriptor
!= NULL
&&
664 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
666 DPRINT("Use parent DACL!\n");
668 Dacl
= ParentDescriptor
->Dacl
;
669 if (Dacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
671 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ParentDescriptor
);
673 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
675 else if (Token
!= NULL
&& Token
->DefaultDacl
!= NULL
)
677 DPRINT("Use token default DACL!\n");
679 Dacl
= Token
->DefaultDacl
;
680 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
684 DPRINT("Use NULL DACL!\n");
686 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
689 DaclLength
= (Dacl
!= NULL
) ? ROUND_UP(Dacl
->AclSize
, 4) : 0;
692 /* Inherit the SACL */
693 if (ExplicitDescriptor
!= NULL
&&
694 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
) &&
695 !(ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
))
697 DPRINT("Use explicit SACL!\n");
698 Sacl
= ExplicitDescriptor
->Sacl
;
699 if (Sacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
701 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ExplicitDescriptor
);
704 Control
|= SE_SACL_PRESENT
;
706 else if (ParentDescriptor
!= NULL
&&
707 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
709 DPRINT("Use parent SACL!\n");
711 Sacl
= ParentDescriptor
->Sacl
;
712 if (Sacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
714 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ParentDescriptor
);
716 Control
|= (SE_SACL_PRESENT
| SE_SACL_DEFAULTED
);
719 SaclLength
= (Sacl
!= NULL
) ? ROUND_UP(Sacl
->AclSize
, 4) : 0;
722 /* Allocate and initialize the new security descriptor */
723 Length
= sizeof(SECURITY_DESCRIPTOR
) +
724 OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
726 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
727 sizeof(SECURITY_DESCRIPTOR
),
733 Descriptor
= ExAllocatePool(PagedPool
,
735 if (Descriptor
== NULL
)
737 DPRINT1("ExAlloctePool() failed\n");
738 /* FIXME: Unlock subject context */
739 return STATUS_INSUFFICIENT_RESOURCES
;
742 RtlZeroMemory( Descriptor
, Length
);
743 RtlCreateSecurityDescriptor(Descriptor
,
744 SECURITY_DESCRIPTOR_REVISION
);
746 Descriptor
->Control
= Control
| SE_SELF_RELATIVE
;
748 Current
= (ULONG_PTR
)Descriptor
+ sizeof(SECURITY_DESCRIPTOR
);
752 RtlCopyMemory((PVOID
)Current
,
755 Descriptor
->Sacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
756 Current
+= SaclLength
;
761 RtlCopyMemory((PVOID
)Current
,
764 Descriptor
->Dacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
765 Current
+= DaclLength
;
768 if (OwnerLength
!= 0)
770 RtlCopyMemory((PVOID
)Current
,
773 Descriptor
->Owner
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
774 Current
+= OwnerLength
;
775 DPRINT("Owner of %x at %x\n", Descriptor
, Descriptor
->Owner
);
778 DPRINT("Owner of %x is zero length\n", Descriptor
);
780 if (GroupLength
!= 0)
782 memmove((PVOID
)Current
,
785 Descriptor
->Group
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
788 /* Unlock subject context */
789 SeUnlockSubjectContext(SubjectContext
);
791 *NewDescriptor
= Descriptor
;
793 DPRINT("Descrptor %x\n", Descriptor
);
794 ASSERT(RtlLengthSecurityDescriptor(Descriptor
));
796 return STATUS_SUCCESS
;
801 SepSidInToken(PACCESS_TOKEN _Token
,
805 PTOKEN Token
= (PTOKEN
)_Token
;
809 if (Token
->UserAndGroupCount
== 0)
814 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
816 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
818 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
832 * FUNCTION: Determines whether the requested access rights can be granted
833 * to an object protected by a security descriptor and an object owner
835 * SecurityDescriptor = Security descriptor protecting the object
836 * SubjectSecurityContext = Subject's captured security context
837 * SubjectContextLocked = Indicates the user's subject context is locked
838 * DesiredAccess = Access rights the caller is trying to acquire
839 * PreviouslyGrantedAccess = Specified the access rights already granted
841 * GenericMapping = Generic mapping associated with the object
842 * AccessMode = Access mode used for the check
843 * GrantedAccess (OUT) = On return specifies the access granted
844 * AccessStatus (OUT) = Status indicating why access was denied
845 * RETURNS: If access was granted, returns TRUE
850 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
851 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
852 IN BOOLEAN SubjectContextLocked
,
853 IN ACCESS_MASK DesiredAccess
,
854 IN ACCESS_MASK PreviouslyGrantedAccess
,
855 OUT PPRIVILEGE_SET
* Privileges
,
856 IN PGENERIC_MAPPING GenericMapping
,
857 IN KPROCESSOR_MODE AccessMode
,
858 OUT PACCESS_MASK GrantedAccess
,
859 OUT PNTSTATUS AccessStatus
)
861 LUID_AND_ATTRIBUTES Privilege
;
862 ACCESS_MASK CurrentAccess
;
874 CurrentAccess
= PreviouslyGrantedAccess
;
876 if (SubjectContextLocked
== FALSE
)
878 SeLockSubjectContext(SubjectSecurityContext
);
881 Token
= SubjectSecurityContext
->ClientToken
?
882 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
885 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
889 if (!NT_SUCCESS(Status
))
891 if (SubjectContextLocked
== FALSE
)
893 SeUnlockSubjectContext(SubjectSecurityContext
);
896 *AccessStatus
= Status
;
900 /* RULE 1: Grant desired access if the object is unprotected */
901 if (Present
== TRUE
&& Dacl
== NULL
)
903 if (SubjectContextLocked
== FALSE
)
905 SeUnlockSubjectContext(SubjectSecurityContext
);
908 *GrantedAccess
= DesiredAccess
;
909 *AccessStatus
= STATUS_SUCCESS
;
913 CurrentAccess
= PreviouslyGrantedAccess
;
915 /* RULE 2: Check token for 'take ownership' privilege */
916 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
917 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
919 if (SepPrivilegeCheck(Token
,
922 PRIVILEGE_SET_ALL_NECESSARY
,
925 CurrentAccess
|= WRITE_OWNER
;
926 if (DesiredAccess
== CurrentAccess
)
928 if (SubjectContextLocked
== FALSE
)
930 SeUnlockSubjectContext(SubjectSecurityContext
);
933 *GrantedAccess
= CurrentAccess
;
934 *AccessStatus
= STATUS_SUCCESS
;
939 /* RULE 3: Check whether the token is the owner */
940 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
943 if (!NT_SUCCESS(Status
))
945 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
946 if (SubjectContextLocked
== FALSE
)
948 SeUnlockSubjectContext(SubjectSecurityContext
);
951 *AccessStatus
= Status
;
955 if (SepSidInToken(Token
, Sid
))
957 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
958 if (DesiredAccess
== CurrentAccess
)
960 if (SubjectContextLocked
== FALSE
)
962 SeUnlockSubjectContext(SubjectSecurityContext
);
965 *GrantedAccess
= CurrentAccess
;
966 *AccessStatus
= STATUS_SUCCESS
;
971 /* Fail if DACL is absent */
972 if (Present
== FALSE
)
974 if (SubjectContextLocked
== FALSE
)
976 SeUnlockSubjectContext(SubjectSecurityContext
);
980 *AccessStatus
= STATUS_ACCESS_DENIED
;
984 /* RULE 4: Grant rights according to the DACL */
985 CurrentAce
= (PACE
)(Dacl
+ 1);
986 for (i
= 0; i
< Dacl
->AceCount
; i
++)
988 Sid
= (PSID
)(CurrentAce
+ 1);
989 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
991 if (SepSidInToken(Token
, Sid
))
993 if (SubjectContextLocked
== FALSE
)
995 SeUnlockSubjectContext(SubjectSecurityContext
);
999 *AccessStatus
= STATUS_ACCESS_DENIED
;
1004 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
1006 if (SepSidInToken(Token
, Sid
))
1008 CurrentAccess
|= CurrentAce
->AccessMask
;
1013 if (SubjectContextLocked
== FALSE
)
1015 SeUnlockSubjectContext(SubjectSecurityContext
);
1018 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1019 CurrentAccess
, DesiredAccess
);
1021 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
1024 (*GrantedAccess
== DesiredAccess
) ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
1031 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1032 IN HANDLE TokenHandle
,
1033 IN ACCESS_MASK DesiredAccess
,
1034 IN PGENERIC_MAPPING GenericMapping
,
1035 OUT PPRIVILEGE_SET PrivilegeSet
,
1036 OUT PULONG ReturnLength
,
1037 OUT PACCESS_MASK GrantedAccess
,
1038 OUT PNTSTATUS AccessStatus
)
1040 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
= {0};
1041 KPROCESSOR_MODE PreviousMode
;
1047 DPRINT("NtAccessCheck() called\n");
1049 PreviousMode
= KeGetPreviousMode();
1050 if (PreviousMode
== KernelMode
)
1052 *GrantedAccess
= DesiredAccess
;
1053 *AccessStatus
= STATUS_SUCCESS
;
1054 return STATUS_SUCCESS
;
1057 Status
= ObReferenceObjectByHandle(TokenHandle
,
1063 if (!NT_SUCCESS(Status
))
1065 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
1069 /* Check token type */
1070 if (Token
->TokenType
!= TokenImpersonation
)
1072 DPRINT1("No impersonation token\n");
1073 ObDereferenceObject(Token
);
1074 return STATUS_ACCESS_VIOLATION
;
1077 /* Check impersonation level */
1078 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
1080 DPRINT1("Invalid impersonation level\n");
1081 ObDereferenceObject(Token
);
1082 return STATUS_ACCESS_VIOLATION
;
1085 SubjectSecurityContext
.ClientToken
= Token
;
1086 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
1088 /* Lock subject context */
1089 SeLockSubjectContext(&SubjectSecurityContext
);
1091 if (SeAccessCheck(SecurityDescriptor
,
1092 &SubjectSecurityContext
,
1102 Status
= *AccessStatus
;
1106 Status
= STATUS_ACCESS_DENIED
;
1109 /* Unlock subject context */
1110 SeUnlockSubjectContext(&SubjectSecurityContext
);
1112 ObDereferenceObject(Token
);
1114 DPRINT("NtAccessCheck() done\n");
1120 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
1121 OUT PACCESS_MASK DesiredAccess
)
1123 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
1124 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
1126 *DesiredAccess
|= READ_CONTROL
;
1128 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
1130 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1135 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
1136 OUT PACCESS_MASK DesiredAccess
)
1138 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1140 *DesiredAccess
|= WRITE_OWNER
;
1142 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
1144 *DesiredAccess
|= WRITE_DAC
;
1146 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
1148 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;