1 /* $Id: semgr.c,v 1.43 2004/09/08 11:39:59 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Security manager
6 * FILE: kernel/se/semgr.c
9 * 26/07/98: Added stubs for security functions
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
21 /* GLOBALS ******************************************************************/
23 PSE_EXPORTS EXPORTED SeExports
= NULL
;
26 /* PROTOTYPES ***************************************************************/
28 static BOOLEAN
SepInitExports(VOID
);
30 /* FUNCTIONS ****************************************************************/
38 if (!SepInitSecurityIDs())
49 if (!SepInitExports())
59 SepInitializeTokenImplementation();
68 OBJECT_ATTRIBUTES ObjectAttributes
;
70 HANDLE DirectoryHandle
;
74 /* Create '\Security' directory */
75 RtlInitUnicodeString(&Name
,
77 InitializeObjectAttributes(&ObjectAttributes
,
82 Status
= NtCreateDirectoryObject(&DirectoryHandle
,
85 if (!NT_SUCCESS(Status
))
87 DPRINT1("Failed to create 'Security' directory!\n");
91 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
92 RtlInitUnicodeString(&Name
,
93 L
"\\LSA_AUTHENTICATION_INITALIZED");
94 InitializeObjectAttributes(&ObjectAttributes
,
99 Status
= NtCreateEvent(&EventHandle
,
104 if (!NT_SUCCESS(Status
))
106 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
107 NtClose(DirectoryHandle
);
111 NtClose(EventHandle
);
112 NtClose(DirectoryHandle
);
114 /* FIXME: Create SRM port and listener thread */
120 static BOOLEAN INIT_FUNCTION
123 SeExports
= ExAllocatePoolWithTag(NonPagedPool
,
126 if (SeExports
== NULL
)
129 SeExports
->SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
130 SeExports
->SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
131 SeExports
->SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
132 SeExports
->SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
133 SeExports
->SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
134 SeExports
->SeTcbPrivilege
= SeTcbPrivilege
;
135 SeExports
->SeSecurityPrivilege
= SeSecurityPrivilege
;
136 SeExports
->SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
137 SeExports
->SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
138 SeExports
->SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
139 SeExports
->SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
140 SeExports
->SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
141 SeExports
->SeSystemtimePrivilege
= SeSystemtimePrivilege
;
142 SeExports
->SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
143 SeExports
->SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
144 SeExports
->SeBackupPrivilege
= SeBackupPrivilege
;
145 SeExports
->SeRestorePrivilege
= SeRestorePrivilege
;
146 SeExports
->SeShutdownPrivilege
= SeShutdownPrivilege
;
147 SeExports
->SeDebugPrivilege
= SeDebugPrivilege
;
148 SeExports
->SeAuditPrivilege
= SeAuditPrivilege
;
149 SeExports
->SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
150 SeExports
->SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
151 SeExports
->SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
153 SeExports
->SeNullSid
= SeNullSid
;
154 SeExports
->SeWorldSid
= SeWorldSid
;
155 SeExports
->SeLocalSid
= SeLocalSid
;
156 SeExports
->SeCreatorOwnerSid
= SeCreatorOwnerSid
;
157 SeExports
->SeCreatorGroupSid
= SeCreatorGroupSid
;
158 SeExports
->SeNtAuthoritySid
= SeNtAuthoritySid
;
159 SeExports
->SeDialupSid
= SeDialupSid
;
160 SeExports
->SeNetworkSid
= SeNetworkSid
;
161 SeExports
->SeBatchSid
= SeBatchSid
;
162 SeExports
->SeInteractiveSid
= SeInteractiveSid
;
163 SeExports
->SeLocalSystemSid
= SeLocalSystemSid
;
164 SeExports
->SeAliasAdminsSid
= SeAliasAdminsSid
;
165 SeExports
->SeAliasUsersSid
= SeAliasUsersSid
;
166 SeExports
->SeAliasGuestsSid
= SeAliasGuestsSid
;
167 SeExports
->SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
168 SeExports
->SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
169 SeExports
->SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
170 SeExports
->SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
171 SeExports
->SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
177 VOID
SepReferenceLogonSession(PLUID AuthenticationId
)
182 VOID
SepDeReferenceLogonSession(PLUID AuthenticationId
)
193 NtAllocateUuids(PULARGE_INTEGER Time
,
198 return(STATUS_NOT_IMPLEMENTED
);
206 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
210 BOOLEAN EffectiveOnly
;
212 Thread
= PsGetCurrentThread();
215 SubjectContext
->ProcessAuditId
= 0;
216 SubjectContext
->PrimaryToken
= NULL
;
217 SubjectContext
->ClientToken
= NULL
;
218 SubjectContext
->ImpersonationLevel
= 0;
222 SubjectContext
->ProcessAuditId
= Thread
->ThreadsProcess
;
223 SubjectContext
->ClientToken
=
224 PsReferenceImpersonationToken(Thread
,
227 &SubjectContext
->ImpersonationLevel
);
228 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
237 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
247 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
249 if (SubjectContext
->PrimaryToken
!= NULL
)
251 ObDereferenceObject(SubjectContext
->PrimaryToken
);
254 if (SubjectContext
->ClientToken
!= NULL
)
256 ObDereferenceObject(SubjectContext
->ClientToken
);
265 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
275 SeDeassignSecurity(PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
277 if (*SecurityDescriptor
!= NULL
)
279 ExFreePool(*SecurityDescriptor
);
280 *SecurityDescriptor
= NULL
;
283 return STATUS_SUCCESS
;
291 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
292 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
293 OUT PSECURITY_DESCRIPTOR
*NewDescriptor
,
294 IN GUID
*ObjectType OPTIONAL
,
295 IN BOOLEAN IsDirectoryObject
,
296 IN ULONG AutoInheritFlags
,
297 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
298 IN PGENERIC_MAPPING GenericMapping
,
299 IN POOL_TYPE PoolType
)
302 return STATUS_NOT_IMPLEMENTED
;
307 * FUNCTION: Creates a security descriptor for a new object.
310 * ExplicitDescriptor =
312 * IsDirectoryObject =
321 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
322 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
323 PSECURITY_DESCRIPTOR
*NewDescriptor
,
324 BOOLEAN IsDirectoryObject
,
325 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
326 PGENERIC_MAPPING GenericMapping
,
329 PSECURITY_DESCRIPTOR Descriptor
;
331 ULONG OwnerLength
= 0;
332 ULONG GroupLength
= 0;
333 ULONG DaclLength
= 0;
334 ULONG SaclLength
= 0;
343 /* FIXME: Lock subject context */
345 if (SubjectContext
->ClientToken
!= NULL
)
347 Token
= SubjectContext
->ClientToken
;
351 Token
= SubjectContext
->PrimaryToken
;
355 /* Inherit the Owner SID */
356 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Owner
!= NULL
)
358 DPRINT("Use explicit owner sid!\n");
359 Owner
= ExplicitDescriptor
->Owner
;
360 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
362 Owner
= (PSID
)(((ULONG_PTR
)Owner
) + (ULONG_PTR
)ExplicitDescriptor
);
369 DPRINT("Use token owner sid!\n");
370 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
374 DPRINT("Use default owner sid!\n");
375 Owner
= SeLocalSystemSid
;
378 Control
|= SE_OWNER_DEFAULTED
;
381 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
384 /* Inherit the Group SID */
385 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Group
!= NULL
)
387 DPRINT("Use explicit group sid!\n");
388 Group
= ExplicitDescriptor
->Group
;
389 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
391 Group
= (PSID
)(((ULONG_PTR
)Group
) + (ULONG_PTR
)ExplicitDescriptor
);
398 DPRINT("Use token group sid!\n");
399 Group
= Token
->PrimaryGroup
;
403 DPRINT("Use default group sid!\n");
404 Group
= SeLocalSystemSid
;
407 Control
|= SE_OWNER_DEFAULTED
;
410 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
413 /* Inherit the DACL */
414 if (ExplicitDescriptor
!= NULL
&&
415 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
416 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
418 DPRINT("Use explicit DACL!\n");
419 Dacl
= ExplicitDescriptor
->Dacl
;
420 if (Dacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
422 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ExplicitDescriptor
);
425 Control
|= SE_DACL_PRESENT
;
427 else if (ParentDescriptor
!= NULL
&&
428 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
430 DPRINT("Use parent DACL!\n");
432 Dacl
= ParentDescriptor
->Dacl
;
433 if (Dacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
435 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ParentDescriptor
);
437 Control
|= (SE_DACL_PRESENT
& SE_DACL_DEFAULTED
);
439 else if (Token
!= NULL
&& Token
->DefaultDacl
!= NULL
)
441 DPRINT("Use token default DACL!\n");
443 Dacl
= Token
->DefaultDacl
;
444 Control
|= (SE_DACL_PRESENT
& SE_DACL_DEFAULTED
);
448 DPRINT("Use NULL DACL!\n");
450 Control
|= (SE_DACL_PRESENT
& SE_DACL_DEFAULTED
);
453 DaclLength
= (Dacl
!= NULL
) ? ROUND_UP(Dacl
->AclSize
, 4) : 0;
456 /* Inherit the SACL */
457 if (ExplicitDescriptor
!= NULL
&&
458 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
) &&
459 !(ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
))
461 DPRINT("Use explicit SACL!\n");
462 Sacl
= ExplicitDescriptor
->Sacl
;
463 if (Sacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
465 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ExplicitDescriptor
);
468 Control
|= SE_SACL_PRESENT
;
470 else if (ParentDescriptor
!= NULL
&&
471 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
473 DPRINT("Use parent SACL!\n");
475 Sacl
= ParentDescriptor
->Sacl
;
476 if (Sacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
478 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ParentDescriptor
);
480 Control
|= (SE_SACL_PRESENT
& SE_SACL_DEFAULTED
);
483 SaclLength
= (Sacl
!= NULL
) ? ROUND_UP(Sacl
->AclSize
, 4) : 0;
486 /* Allocate and initialize the new security descriptor */
487 Length
= sizeof(SECURITY_DESCRIPTOR
) + OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
489 Descriptor
= ExAllocatePool(NonPagedPool
,
491 if (Descriptor
== NULL
)
493 DPRINT1("ExAlloctePool() failed\n");
494 /* FIXME: Unlock subject context */
495 return STATUS_INSUFFICIENT_RESOURCES
;
498 RtlCreateSecurityDescriptor(Descriptor
,
499 SECURITY_DESCRIPTOR_REVISION
);
501 Descriptor
->Control
= Control
| SE_SELF_RELATIVE
;
503 Current
= (ULONG_PTR
)Descriptor
+ sizeof(SECURITY_DESCRIPTOR
);
507 RtlCopyMemory((PVOID
)Current
,
510 Descriptor
->Sacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
511 Current
+= SaclLength
;
516 RtlCopyMemory((PVOID
)Current
,
519 Descriptor
->Dacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
520 Current
+= DaclLength
;
523 if (OwnerLength
!= 0)
525 RtlCopyMemory((PVOID
)Current
,
528 Descriptor
->Owner
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
529 Current
+= OwnerLength
;
532 if (GroupLength
!= 0)
534 memmove((PVOID
)Current
,
537 Descriptor
->Group
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
540 /* FIXME: Unlock subject context */
542 *NewDescriptor
= Descriptor
;
544 return STATUS_SUCCESS
;
549 SepSidInToken(PACCESS_TOKEN Token
,
554 if (Token
->UserAndGroupCount
== 0)
559 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
561 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
563 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
577 * FUNCTION: Determines whether the requested access rights can be granted
578 * to an object protected by a security descriptor and an object owner
580 * SecurityDescriptor = Security descriptor protecting the object
581 * SubjectSecurityContext = Subject's captured security context
582 * SubjectContextLocked = Indicates the user's subject context is locked
583 * DesiredAccess = Access rights the caller is trying to acquire
584 * PreviouslyGrantedAccess = Specified the access rights already granted
586 * GenericMapping = Generic mapping associated with the object
587 * AccessMode = Access mode used for the check
588 * GrantedAccess (OUT) = On return specifies the access granted
589 * AccessStatus (OUT) = Status indicating why access was denied
590 * RETURNS: If access was granted, returns TRUE
595 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
596 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
597 IN BOOLEAN SubjectContextLocked
,
598 IN ACCESS_MASK DesiredAccess
,
599 IN ACCESS_MASK PreviouslyGrantedAccess
,
600 OUT PPRIVILEGE_SET
* Privileges
,
601 IN PGENERIC_MAPPING GenericMapping
,
602 IN KPROCESSOR_MODE AccessMode
,
603 OUT PACCESS_MASK GrantedAccess
,
604 OUT PNTSTATUS AccessStatus
)
606 LUID_AND_ATTRIBUTES Privilege
;
607 ACCESS_MASK CurrentAccess
;
617 CurrentAccess
= PreviouslyGrantedAccess
;
619 Token
= SubjectSecurityContext
->ClientToken
?
620 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
623 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
627 if (!NT_SUCCESS(Status
))
629 *AccessStatus
= Status
;
633 /* RULE 1: Grant desired access if the object is unprotected */
636 *GrantedAccess
= DesiredAccess
;
637 *AccessStatus
= STATUS_SUCCESS
;
641 CurrentAccess
= PreviouslyGrantedAccess
;
643 /* RULE 2: Check token for 'take ownership' privilege */
644 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
645 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
647 if (SepPrivilegeCheck(Token
,
650 PRIVILEGE_SET_ALL_NECESSARY
,
653 CurrentAccess
|= WRITE_OWNER
;
654 if (DesiredAccess
== CurrentAccess
)
656 *GrantedAccess
= CurrentAccess
;
657 *AccessStatus
= STATUS_SUCCESS
;
662 /* RULE 3: Check whether the token is the owner */
663 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
666 if (!NT_SUCCESS(Status
))
668 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
669 *AccessStatus
= Status
;
673 if (SepSidInToken(Token
, Sid
))
675 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
676 if (DesiredAccess
== CurrentAccess
)
678 *GrantedAccess
= CurrentAccess
;
679 *AccessStatus
= STATUS_SUCCESS
;
684 /* RULE 4: Grant rights according to the DACL */
685 CurrentAce
= (PACE
)(Dacl
+ 1);
686 for (i
= 0; i
< Dacl
->AceCount
; i
++)
688 Sid
= (PSID
)(CurrentAce
+ 1);
689 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
691 if (SepSidInToken(Token
, Sid
))
694 *AccessStatus
= STATUS_ACCESS_DENIED
;
699 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
701 if (SepSidInToken(Token
, Sid
))
703 CurrentAccess
|= CurrentAce
->AccessMask
;
708 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
709 CurrentAccess
, DesiredAccess
);
711 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
714 (*GrantedAccess
== DesiredAccess
) ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
721 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
722 IN HANDLE TokenHandle
,
723 IN ACCESS_MASK DesiredAccess
,
724 IN PGENERIC_MAPPING GenericMapping
,
725 OUT PPRIVILEGE_SET PrivilegeSet
,
726 OUT PULONG ReturnLength
,
727 OUT PACCESS_MASK GrantedAccess
,
728 OUT PNTSTATUS AccessStatus
)
730 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
731 KPROCESSOR_MODE PreviousMode
;
735 DPRINT("NtAccessCheck() called\n");
737 PreviousMode
= KeGetPreviousMode();
738 if (PreviousMode
== KernelMode
)
740 *GrantedAccess
= DesiredAccess
;
741 *AccessStatus
= STATUS_SUCCESS
;
742 return STATUS_SUCCESS
;
745 Status
= ObReferenceObjectByHandle(TokenHandle
,
751 if (!NT_SUCCESS(Status
))
753 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
757 /* Check token type */
758 if (Token
->TokenType
!= TokenImpersonation
)
760 DPRINT1("No impersonation token\n");
761 ObDereferenceObject(Token
);
762 return STATUS_ACCESS_VIOLATION
;
765 /* Check impersonation level */
766 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
768 DPRINT1("Invalid impersonation level\n");
769 ObDereferenceObject(Token
);
770 return STATUS_ACCESS_VIOLATION
;
773 RtlZeroMemory(&SubjectSecurityContext
,
774 sizeof(SECURITY_SUBJECT_CONTEXT
));
775 SubjectSecurityContext
.ClientToken
= Token
;
776 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
778 /* FIXME: Lock subject context */
780 if (!SeAccessCheck(SecurityDescriptor
,
781 &SubjectSecurityContext
,
791 Status
= *AccessStatus
;
795 Status
= STATUS_ACCESS_DENIED
;
798 /* FIXME: Unlock subject context */
800 ObDereferenceObject(Token
);
802 DPRINT("NtAccessCheck() done\n");