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 POBJECT_HEADER Header
= OBJECT_TO_OBJECT_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
;
421 SeCaptureSubjectContextEx(IN PETHREAD Thread
,
422 IN PEPROCESS Process
,
423 OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
425 BOOLEAN CopyOnOpen
, EffectiveOnly
;
431 SubjectContext
->PrimaryToken
= NULL
;
432 SubjectContext
->ProcessAuditId
= 0;
433 SubjectContext
->ClientToken
= NULL
;
437 /* Save the unique ID */
438 SubjectContext
->ProcessAuditId
= Process
->UniqueProcessId
;
440 /* Check if we have a thread */
443 /* We don't, so no token */
444 SubjectContext
->ClientToken
= NULL
;
448 /* Get the impersonation token */
449 SubjectContext
->ClientToken
=
450 PsReferenceImpersonationToken(Thread
,
453 &SubjectContext
->ImpersonationLevel
);
456 /* Get the primary token */
457 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Process
);
465 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
467 /* Call the internal API */
468 SeCaptureSubjectContextEx(PsGetCurrentThread(),
469 PsGetCurrentProcess(),
478 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
482 KeEnterCriticalRegion();
483 ExAcquireResourceExclusiveLite(&SepSubjectContextLock
, TRUE
);
491 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
495 ExReleaseResourceLite(&SepSubjectContextLock
);
496 KeLeaveCriticalRegion();
504 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
508 if (SubjectContext
->PrimaryToken
!= NULL
)
510 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, SubjectContext
->PrimaryToken
);
513 if (SubjectContext
->ClientToken
!= NULL
)
515 ObDereferenceObject(SubjectContext
->ClientToken
);
524 SeDeassignSecurity(PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
528 if (*SecurityDescriptor
!= NULL
)
530 ExFreePool(*SecurityDescriptor
);
531 *SecurityDescriptor
= NULL
;
534 return STATUS_SUCCESS
;
542 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
543 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
544 OUT PSECURITY_DESCRIPTOR
*NewDescriptor
,
545 IN GUID
*ObjectType OPTIONAL
,
546 IN BOOLEAN IsDirectoryObject
,
547 IN ULONG AutoInheritFlags
,
548 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
549 IN PGENERIC_MAPPING GenericMapping
,
550 IN POOL_TYPE PoolType
)
553 return STATUS_NOT_IMPLEMENTED
;
558 * FUNCTION: Creates a security descriptor for a new object.
561 * ExplicitDescriptor =
563 * IsDirectoryObject =
572 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL
,
573 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL
,
574 PSECURITY_DESCRIPTOR
*NewDescriptor
,
575 BOOLEAN IsDirectoryObject
,
576 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
577 PGENERIC_MAPPING GenericMapping
,
580 PISECURITY_DESCRIPTOR ParentDescriptor
= _ParentDescriptor
;
581 PISECURITY_DESCRIPTOR ExplicitDescriptor
= _ExplicitDescriptor
;
582 PISECURITY_DESCRIPTOR Descriptor
;
584 ULONG OwnerLength
= 0;
585 ULONG GroupLength
= 0;
586 ULONG DaclLength
= 0;
587 ULONG SaclLength
= 0;
598 /* Lock subject context */
599 SeLockSubjectContext(SubjectContext
);
601 if (SubjectContext
->ClientToken
!= NULL
)
603 Token
= SubjectContext
->ClientToken
;
607 Token
= SubjectContext
->PrimaryToken
;
611 /* Inherit the Owner SID */
612 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Owner
!= NULL
)
614 DPRINT("Use explicit owner sid!\n");
615 Owner
= ExplicitDescriptor
->Owner
;
617 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
619 Owner
= (PSID
)(((ULONG_PTR
)Owner
) + (ULONG_PTR
)ExplicitDescriptor
);
627 DPRINT("Use token owner sid!\n");
628 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
632 DPRINT("Use default owner sid!\n");
633 Owner
= SeLocalSystemSid
;
636 Control
|= SE_OWNER_DEFAULTED
;
639 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
642 /* Inherit the Group SID */
643 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Group
!= NULL
)
645 DPRINT("Use explicit group sid!\n");
646 Group
= ExplicitDescriptor
->Group
;
647 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
649 Group
= (PSID
)(((ULONG_PTR
)Group
) + (ULONG_PTR
)ExplicitDescriptor
);
656 DPRINT("Use token group sid!\n");
657 Group
= Token
->PrimaryGroup
;
661 DPRINT("Use default group sid!\n");
662 Group
= SeLocalSystemSid
;
665 Control
|= SE_OWNER_DEFAULTED
;
668 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
671 /* Inherit the DACL */
672 if (ExplicitDescriptor
!= NULL
&&
673 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
674 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
676 DPRINT("Use explicit DACL!\n");
677 Dacl
= ExplicitDescriptor
->Dacl
;
678 if (Dacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
680 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ExplicitDescriptor
);
683 Control
|= SE_DACL_PRESENT
;
685 else if (ParentDescriptor
!= NULL
&&
686 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
688 DPRINT("Use parent DACL!\n");
690 Dacl
= ParentDescriptor
->Dacl
;
691 if (Dacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
693 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ParentDescriptor
);
695 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
697 else if (Token
!= NULL
&& Token
->DefaultDacl
!= NULL
)
699 DPRINT("Use token default DACL!\n");
701 Dacl
= Token
->DefaultDacl
;
702 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
706 DPRINT("Use NULL DACL!\n");
708 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
711 DaclLength
= (Dacl
!= NULL
) ? ROUND_UP(Dacl
->AclSize
, 4) : 0;
714 /* Inherit the SACL */
715 if (ExplicitDescriptor
!= NULL
&&
716 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
) &&
717 !(ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
))
719 DPRINT("Use explicit SACL!\n");
720 Sacl
= ExplicitDescriptor
->Sacl
;
721 if (Sacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
723 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ExplicitDescriptor
);
726 Control
|= SE_SACL_PRESENT
;
728 else if (ParentDescriptor
!= NULL
&&
729 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
731 DPRINT("Use parent SACL!\n");
733 Sacl
= ParentDescriptor
->Sacl
;
734 if (Sacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
736 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ParentDescriptor
);
738 Control
|= (SE_SACL_PRESENT
| SE_SACL_DEFAULTED
);
741 SaclLength
= (Sacl
!= NULL
) ? ROUND_UP(Sacl
->AclSize
, 4) : 0;
744 /* Allocate and initialize the new security descriptor */
745 Length
= sizeof(SECURITY_DESCRIPTOR
) +
746 OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
748 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
749 sizeof(SECURITY_DESCRIPTOR
),
755 Descriptor
= ExAllocatePool(PagedPool
,
757 if (Descriptor
== NULL
)
759 DPRINT1("ExAlloctePool() failed\n");
760 /* FIXME: Unlock subject context */
761 return STATUS_INSUFFICIENT_RESOURCES
;
764 RtlZeroMemory( Descriptor
, Length
);
765 RtlCreateSecurityDescriptor(Descriptor
,
766 SECURITY_DESCRIPTOR_REVISION
);
768 Descriptor
->Control
= Control
| SE_SELF_RELATIVE
;
770 Current
= (ULONG_PTR
)Descriptor
+ sizeof(SECURITY_DESCRIPTOR
);
774 RtlCopyMemory((PVOID
)Current
,
777 Descriptor
->Sacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
778 Current
+= SaclLength
;
783 RtlCopyMemory((PVOID
)Current
,
786 Descriptor
->Dacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
787 Current
+= DaclLength
;
790 if (OwnerLength
!= 0)
792 RtlCopyMemory((PVOID
)Current
,
795 Descriptor
->Owner
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
796 Current
+= OwnerLength
;
797 DPRINT("Owner of %x at %x\n", Descriptor
, Descriptor
->Owner
);
800 DPRINT("Owner of %x is zero length\n", Descriptor
);
802 if (GroupLength
!= 0)
804 memmove((PVOID
)Current
,
807 Descriptor
->Group
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
810 /* Unlock subject context */
811 SeUnlockSubjectContext(SubjectContext
);
813 *NewDescriptor
= Descriptor
;
815 DPRINT("Descrptor %x\n", Descriptor
);
816 ASSERT(RtlLengthSecurityDescriptor(Descriptor
));
818 return STATUS_SUCCESS
;
823 SepSidInToken(PACCESS_TOKEN _Token
,
827 PTOKEN Token
= (PTOKEN
)_Token
;
831 if (Token
->UserAndGroupCount
== 0)
836 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
838 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
840 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
854 * FUNCTION: Determines whether the requested access rights can be granted
855 * to an object protected by a security descriptor and an object owner
857 * SecurityDescriptor = Security descriptor protecting the object
858 * SubjectSecurityContext = Subject's captured security context
859 * SubjectContextLocked = Indicates the user's subject context is locked
860 * DesiredAccess = Access rights the caller is trying to acquire
861 * PreviouslyGrantedAccess = Specified the access rights already granted
863 * GenericMapping = Generic mapping associated with the object
864 * AccessMode = Access mode used for the check
865 * GrantedAccess (OUT) = On return specifies the access granted
866 * AccessStatus (OUT) = Status indicating why access was denied
867 * RETURNS: If access was granted, returns TRUE
872 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
873 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
874 IN BOOLEAN SubjectContextLocked
,
875 IN ACCESS_MASK DesiredAccess
,
876 IN ACCESS_MASK PreviouslyGrantedAccess
,
877 OUT PPRIVILEGE_SET
* Privileges
,
878 IN PGENERIC_MAPPING GenericMapping
,
879 IN KPROCESSOR_MODE AccessMode
,
880 OUT PACCESS_MASK GrantedAccess
,
881 OUT PNTSTATUS AccessStatus
)
883 LUID_AND_ATTRIBUTES Privilege
;
884 ACCESS_MASK CurrentAccess
;
896 /* Check if we didn't get an SD */
897 if (!SecurityDescriptor
)
899 /* Automatic failure */
900 *AccessStatus
= STATUS_ACCESS_DENIED
;
904 CurrentAccess
= PreviouslyGrantedAccess
;
906 if (SubjectContextLocked
== FALSE
)
908 SeLockSubjectContext(SubjectSecurityContext
);
911 Token
= SubjectSecurityContext
->ClientToken
?
912 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
915 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
919 if (!NT_SUCCESS(Status
))
921 if (SubjectContextLocked
== FALSE
)
923 SeUnlockSubjectContext(SubjectSecurityContext
);
926 *AccessStatus
= Status
;
930 /* RULE 1: Grant desired access if the object is unprotected */
931 if (Present
== TRUE
&& Dacl
== NULL
)
933 if (SubjectContextLocked
== FALSE
)
935 SeUnlockSubjectContext(SubjectSecurityContext
);
938 *GrantedAccess
= DesiredAccess
;
939 *AccessStatus
= STATUS_SUCCESS
;
943 CurrentAccess
= PreviouslyGrantedAccess
;
945 /* RULE 2: Check token for 'take ownership' privilege */
946 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
947 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
949 if (SepPrivilegeCheck(Token
,
952 PRIVILEGE_SET_ALL_NECESSARY
,
955 CurrentAccess
|= WRITE_OWNER
;
956 if (DesiredAccess
== CurrentAccess
)
958 if (SubjectContextLocked
== FALSE
)
960 SeUnlockSubjectContext(SubjectSecurityContext
);
963 *GrantedAccess
= CurrentAccess
;
964 *AccessStatus
= STATUS_SUCCESS
;
969 /* RULE 3: Check whether the token is the owner */
970 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
973 if (!NT_SUCCESS(Status
))
975 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
976 if (SubjectContextLocked
== FALSE
)
978 SeUnlockSubjectContext(SubjectSecurityContext
);
981 *AccessStatus
= Status
;
985 if (SepSidInToken(Token
, Sid
))
987 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
988 if (DesiredAccess
== CurrentAccess
)
990 if (SubjectContextLocked
== FALSE
)
992 SeUnlockSubjectContext(SubjectSecurityContext
);
995 *GrantedAccess
= CurrentAccess
;
996 *AccessStatus
= STATUS_SUCCESS
;
1001 /* Fail if DACL is absent */
1002 if (Present
== FALSE
)
1004 if (SubjectContextLocked
== FALSE
)
1006 SeUnlockSubjectContext(SubjectSecurityContext
);
1010 *AccessStatus
= STATUS_ACCESS_DENIED
;
1014 /* RULE 4: Grant rights according to the DACL */
1015 CurrentAce
= (PACE
)(Dacl
+ 1);
1016 for (i
= 0; i
< Dacl
->AceCount
; i
++)
1018 Sid
= (PSID
)(CurrentAce
+ 1);
1019 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
1021 if (SepSidInToken(Token
, Sid
))
1023 if (SubjectContextLocked
== FALSE
)
1025 SeUnlockSubjectContext(SubjectSecurityContext
);
1029 *AccessStatus
= STATUS_ACCESS_DENIED
;
1034 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
1036 if (SepSidInToken(Token
, Sid
))
1038 CurrentAccess
|= CurrentAce
->AccessMask
;
1043 if (SubjectContextLocked
== FALSE
)
1045 SeUnlockSubjectContext(SubjectSecurityContext
);
1048 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1049 CurrentAccess
, DesiredAccess
);
1051 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
1054 (*GrantedAccess
== DesiredAccess
) ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
1061 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1062 IN HANDLE TokenHandle
,
1063 IN ACCESS_MASK DesiredAccess
,
1064 IN PGENERIC_MAPPING GenericMapping
,
1065 OUT PPRIVILEGE_SET PrivilegeSet
,
1066 OUT PULONG ReturnLength
,
1067 OUT PACCESS_MASK GrantedAccess
,
1068 OUT PNTSTATUS AccessStatus
)
1070 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
= {0};
1071 KPROCESSOR_MODE PreviousMode
;
1077 DPRINT("NtAccessCheck() called\n");
1079 PreviousMode
= KeGetPreviousMode();
1080 if (PreviousMode
== KernelMode
)
1082 *GrantedAccess
= DesiredAccess
;
1083 *AccessStatus
= STATUS_SUCCESS
;
1084 return STATUS_SUCCESS
;
1087 Status
= ObReferenceObjectByHandle(TokenHandle
,
1093 if (!NT_SUCCESS(Status
))
1095 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
1099 /* Check token type */
1100 if (Token
->TokenType
!= TokenImpersonation
)
1102 DPRINT1("No impersonation token\n");
1103 ObDereferenceObject(Token
);
1104 return STATUS_ACCESS_VIOLATION
;
1107 /* Check impersonation level */
1108 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
1110 DPRINT1("Invalid impersonation level\n");
1111 ObDereferenceObject(Token
);
1112 return STATUS_ACCESS_VIOLATION
;
1115 SubjectSecurityContext
.ClientToken
= Token
;
1116 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
1118 /* Lock subject context */
1119 SeLockSubjectContext(&SubjectSecurityContext
);
1121 if (SeAccessCheck(SecurityDescriptor
,
1122 &SubjectSecurityContext
,
1132 Status
= *AccessStatus
;
1136 Status
= STATUS_ACCESS_DENIED
;
1139 /* Unlock subject context */
1140 SeUnlockSubjectContext(&SubjectSecurityContext
);
1142 ObDereferenceObject(Token
);
1144 DPRINT("NtAccessCheck() done\n");
1150 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
1151 OUT PACCESS_MASK DesiredAccess
)
1153 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
1154 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
1156 *DesiredAccess
|= READ_CONTROL
;
1158 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
1160 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1165 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
1166 OUT PACCESS_MASK DesiredAccess
)
1168 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1170 *DesiredAccess
|= WRITE_OWNER
;
1172 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
1174 *DesiredAccess
|= WRITE_DAC
;
1176 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
1178 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;