1 /* $Id: semgr.c,v 1.37 2004/07/21 23:38:15 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 *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ps.h>
16 #include <internal/se.h>
19 #include <internal/debug.h>
21 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
24 /* GLOBALS ******************************************************************/
26 PSE_EXPORTS EXPORTED SeExports
= NULL
;
29 /* PROTOTYPES ***************************************************************/
31 static BOOLEAN
SepInitExports(VOID
);
33 /* FUNCTIONS ****************************************************************/
41 if (!SepInitSecurityIDs())
52 if (!SepInitExports())
62 SepInitializeTokenImplementation();
71 OBJECT_ATTRIBUTES ObjectAttributes
;
73 HANDLE DirectoryHandle
;
77 /* Create '\Security' directory */
78 RtlInitUnicodeString(&Name
,
80 InitializeObjectAttributes(&ObjectAttributes
,
85 Status
= NtCreateDirectoryObject(&DirectoryHandle
,
88 if (!NT_SUCCESS(Status
))
90 DPRINT1("Failed to create 'Security' directory!\n");
94 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
95 RtlInitUnicodeString(&Name
,
96 L
"\\LSA_AUTHENTICATION_INITALIZED");
97 InitializeObjectAttributes(&ObjectAttributes
,
102 Status
= NtCreateEvent(&EventHandle
,
107 if (!NT_SUCCESS(Status
))
109 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
110 NtClose(DirectoryHandle
);
114 NtClose(EventHandle
);
115 NtClose(DirectoryHandle
);
117 /* FIXME: Create SRM port and listener thread */
123 static BOOLEAN INIT_FUNCTION
126 SeExports
= ExAllocatePoolWithTag(NonPagedPool
,
129 if (SeExports
== NULL
)
132 SeExports
->SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
133 SeExports
->SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
134 SeExports
->SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
135 SeExports
->SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
136 SeExports
->SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
137 SeExports
->SeTcbPrivilege
= SeTcbPrivilege
;
138 SeExports
->SeSecurityPrivilege
= SeSecurityPrivilege
;
139 SeExports
->SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
140 SeExports
->SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
141 SeExports
->SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
142 SeExports
->SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
143 SeExports
->SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
144 SeExports
->SeSystemtimePrivilege
= SeSystemtimePrivilege
;
145 SeExports
->SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
146 SeExports
->SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
147 SeExports
->SeBackupPrivilege
= SeBackupPrivilege
;
148 SeExports
->SeRestorePrivilege
= SeRestorePrivilege
;
149 SeExports
->SeShutdownPrivilege
= SeShutdownPrivilege
;
150 SeExports
->SeDebugPrivilege
= SeDebugPrivilege
;
151 SeExports
->SeAuditPrivilege
= SeAuditPrivilege
;
152 SeExports
->SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
153 SeExports
->SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
154 SeExports
->SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
156 SeExports
->SeNullSid
= SeNullSid
;
157 SeExports
->SeWorldSid
= SeWorldSid
;
158 SeExports
->SeLocalSid
= SeLocalSid
;
159 SeExports
->SeCreatorOwnerSid
= SeCreatorOwnerSid
;
160 SeExports
->SeCreatorGroupSid
= SeCreatorGroupSid
;
161 SeExports
->SeNtAuthoritySid
= SeNtAuthoritySid
;
162 SeExports
->SeDialupSid
= SeDialupSid
;
163 SeExports
->SeNetworkSid
= SeNetworkSid
;
164 SeExports
->SeBatchSid
= SeBatchSid
;
165 SeExports
->SeInteractiveSid
= SeInteractiveSid
;
166 SeExports
->SeLocalSystemSid
= SeLocalSystemSid
;
167 SeExports
->SeAliasAdminsSid
= SeAliasAdminsSid
;
168 SeExports
->SeAliasUsersSid
= SeAliasUsersSid
;
169 SeExports
->SeAliasGuestsSid
= SeAliasGuestsSid
;
170 SeExports
->SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
171 SeExports
->SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
172 SeExports
->SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
173 SeExports
->SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
174 SeExports
->SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
180 VOID
SepReferenceLogonSession(PLUID AuthenticationId
)
185 VOID
SepDeReferenceLogonSession(PLUID AuthenticationId
)
196 NtAllocateUuids(PULARGE_INTEGER Time
,
201 return(STATUS_NOT_IMPLEMENTED
);
209 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
213 BOOLEAN EffectiveOnly
;
215 Thread
= PsGetCurrentThread();
218 SubjectContext
->ProcessAuditId
= 0;
219 SubjectContext
->PrimaryToken
= NULL
;
220 SubjectContext
->ClientToken
= NULL
;
221 SubjectContext
->ImpersonationLevel
= 0;
225 SubjectContext
->ProcessAuditId
= Thread
->ThreadsProcess
;
226 SubjectContext
->ClientToken
=
227 PsReferenceImpersonationToken(Thread
,
230 &SubjectContext
->ImpersonationLevel
);
231 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
240 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
250 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
252 if (SubjectContext
->PrimaryToken
!= NULL
)
254 ObDereferenceObject(SubjectContext
->PrimaryToken
);
257 if (SubjectContext
->ClientToken
!= NULL
)
259 ObDereferenceObject(SubjectContext
->ClientToken
);
268 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
278 SeDeassignSecurity(PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
280 if (*SecurityDescriptor
!= NULL
)
282 ExFreePool(*SecurityDescriptor
);
283 *SecurityDescriptor
= NULL
;
286 return STATUS_SUCCESS
;
294 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
295 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
296 PSECURITY_DESCRIPTOR
*NewDescriptor
,
297 BOOLEAN IsDirectoryObject
,
298 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
299 PGENERIC_MAPPING GenericMapping
,
302 PSECURITY_DESCRIPTOR Descriptor
;
304 ULONG OwnerLength
= 0;
305 ULONG GroupLength
= 0;
306 ULONG DaclLength
= 0;
307 ULONG SaclLength
= 0;
316 /* FIXME: Lock subject context */
318 if (SubjectContext
->ClientToken
!= NULL
)
320 Token
= SubjectContext
->ClientToken
;
324 Token
= SubjectContext
->PrimaryToken
;
328 /* Inherit the Owner SID */
329 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Owner
!= NULL
)
331 DPRINT("Use explicit owner sid!\n");
332 Owner
= ExplicitDescriptor
->Owner
;
333 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
335 Owner
= (PSID
)(((ULONG_PTR
)Owner
) + (ULONG_PTR
)ExplicitDescriptor
);
342 DPRINT("Use token owner sid!\n");
343 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
347 DPRINT("Use default owner sid!\n");
348 Owner
= SeLocalSystemSid
;
351 Control
|= SE_OWNER_DEFAULTED
;
354 OwnerLength
= RtlLengthSid(Owner
);
357 /* Inherit the Group SID */
358 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Group
!= NULL
)
360 DPRINT("Use explicit group sid!\n");
361 Group
= ExplicitDescriptor
->Group
;
362 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
364 Group
= (PSID
)(((ULONG_PTR
)Group
) + (ULONG_PTR
)ExplicitDescriptor
);
371 DPRINT("Use token group sid!\n");
372 Group
= Token
->PrimaryGroup
;
376 DPRINT("Use default group sid!\n");
377 Group
= SeLocalSystemSid
;
380 Control
|= SE_OWNER_DEFAULTED
;
383 GroupLength
= RtlLengthSid(Group
);
386 /* Inherit the DACL */
387 if (ExplicitDescriptor
!= NULL
&&
388 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
389 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
391 DPRINT("Use explicit DACL!\n");
392 Dacl
= ExplicitDescriptor
->Dacl
;
393 if (Dacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
395 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ExplicitDescriptor
);
398 Control
|= SE_DACL_PRESENT
;
400 else if (ParentDescriptor
!= NULL
&&
401 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
403 DPRINT("Use parent DACL!\n");
405 Dacl
= ParentDescriptor
->Dacl
;
406 if (Dacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
408 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ParentDescriptor
);
410 Control
|= SE_DACL_PRESENT
;
412 else if (Token
!= NULL
&& Token
->DefaultDacl
!= NULL
)
414 DPRINT("Use token default DACL!\n");
416 Dacl
= Token
->DefaultDacl
;
417 Control
|= SE_DACL_PRESENT
;
421 DPRINT("Use NULL DACL!\n");
423 Control
|= SE_DACL_PRESENT
;
426 DaclLength
= (Dacl
!= NULL
) ? Dacl
->AclSize
: 0;
430 /* Inherit the SACL */
433 if (ExplicitDescriptor
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
))
435 DPRINT("Use explicit SACL!\n");
436 Sacl
= ExplicitDescriptor
->Sacl
;
437 if (Sacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
439 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ExplicitDescriptor
);
442 Control
|= SE_SACL_PRESENT
;
443 SaclLength
= Sacl
->AclSize
;
447 DPRINT("No SACL!\n");
453 /* Allocate and initialize the new security descriptor */
454 Length
= sizeof(SECURITY_DESCRIPTOR
) + OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
456 Descriptor
= ExAllocatePool(NonPagedPool
,
458 if (Descriptor
== NULL
)
460 DPRINT1("ExAlloctePool() failed\n");
461 /* FIXME: Unlock subject context */
462 return STATUS_INSUFFICIENT_RESOURCES
;
465 RtlCreateSecurityDescriptor(Descriptor
,
466 SECURITY_DESCRIPTOR_REVISION
);
468 Descriptor
->Control
= Control
| SE_SELF_RELATIVE
;
470 Current
= (ULONG
)Descriptor
+ sizeof(SECURITY_DESCRIPTOR
);
474 RtlCopyMemory((PVOID
)Current
,
477 Descriptor
->Sacl
= (PACL
)((ULONG
)Current
- (ULONG
)Descriptor
);
478 Current
+= SaclLength
;
483 RtlCopyMemory((PVOID
)Current
,
486 Descriptor
->Dacl
= (PACL
)((ULONG
)Current
- (ULONG
)Descriptor
);
487 Current
+= DaclLength
;
490 if (OwnerLength
!= 0)
492 RtlCopyMemory((PVOID
)Current
,
495 Descriptor
->Owner
= (PSID
)((ULONG
)Current
- (ULONG
)Descriptor
);
496 Current
+= OwnerLength
;
499 if (GroupLength
!= 0)
501 memmove((PVOID
)Current
,
504 Descriptor
->Group
= (PSID
)((ULONG
)Current
- (ULONG
)Descriptor
);
507 /* FIXME: Unlock subject context */
509 *NewDescriptor
= Descriptor
;
511 return STATUS_SUCCESS
;
516 SepSidInToken(PACCESS_TOKEN Token
,
521 if (Token
->UserAndGroupCount
== 0)
526 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
528 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
530 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
544 * FUNCTION: Determines whether the requested access rights can be granted
545 * to an object protected by a security descriptor and an object owner
547 * SecurityDescriptor = Security descriptor protecting the object
548 * SubjectSecurityContext = Subject's captured security context
549 * SubjectContextLocked = Indicates the user's subject context is locked
550 * DesiredAccess = Access rights the caller is trying to acquire
551 * PreviouslyGrantedAccess = Specified the access rights already granted
553 * GenericMapping = Generic mapping associated with the object
554 * AccessMode = Access mode used for the check
555 * GrantedAccess (OUT) = On return specifies the access granted
556 * AccessStatus (OUT) = Status indicating why access was denied
557 * RETURNS: If access was granted, returns TRUE
562 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
563 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
564 IN BOOLEAN SubjectContextLocked
,
565 IN ACCESS_MASK DesiredAccess
,
566 IN ACCESS_MASK PreviouslyGrantedAccess
,
567 OUT PPRIVILEGE_SET
* Privileges
,
568 IN PGENERIC_MAPPING GenericMapping
,
569 IN KPROCESSOR_MODE AccessMode
,
570 OUT PACCESS_MASK GrantedAccess
,
571 OUT PNTSTATUS AccessStatus
)
573 LUID_AND_ATTRIBUTES Privilege
;
574 ACCESS_MASK CurrentAccess
;
584 CurrentAccess
= PreviouslyGrantedAccess
;
586 Token
= SubjectSecurityContext
->ClientToken
?
587 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
590 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
594 if (!NT_SUCCESS(Status
))
596 *AccessStatus
= Status
;
600 /* RULE 1: Grant desired access if the object is unprotected */
603 *GrantedAccess
= DesiredAccess
;
604 *AccessStatus
= STATUS_SUCCESS
;
608 CurrentAccess
= PreviouslyGrantedAccess
;
610 /* RULE 2: Check token for 'take ownership' privilege */
611 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
612 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
614 if (SepPrivilegeCheck(Token
,
617 PRIVILEGE_SET_ALL_NECESSARY
,
620 CurrentAccess
|= WRITE_OWNER
;
621 if (DesiredAccess
== CurrentAccess
)
623 *GrantedAccess
= CurrentAccess
;
624 *AccessStatus
= STATUS_SUCCESS
;
629 /* RULE 3: Check whether the token is the owner */
630 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
633 if (!NT_SUCCESS(Status
))
635 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
636 *AccessStatus
= Status
;
640 if (SepSidInToken(Token
, Sid
))
642 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
643 if (DesiredAccess
== CurrentAccess
)
645 *GrantedAccess
= CurrentAccess
;
646 *AccessStatus
= STATUS_SUCCESS
;
651 /* RULE 4: Grant rights according to the DACL */
652 CurrentAce
= (PACE
)(Dacl
+ 1);
653 for (i
= 0; i
< Dacl
->AceCount
; i
++)
655 Sid
= (PSID
)(CurrentAce
+ 1);
656 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
658 if (SepSidInToken(Token
, Sid
))
661 *AccessStatus
= STATUS_ACCESS_DENIED
;
666 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
668 if (SepSidInToken(Token
, Sid
))
670 CurrentAccess
|= CurrentAce
->AccessMask
;
675 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
676 CurrentAccess
, DesiredAccess
);
678 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
681 (*GrantedAccess
== DesiredAccess
) ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
688 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
689 IN HANDLE TokenHandle
,
690 IN ACCESS_MASK DesiredAccess
,
691 IN PGENERIC_MAPPING GenericMapping
,
692 OUT PPRIVILEGE_SET PrivilegeSet
,
693 OUT PULONG ReturnLength
,
694 OUT PACCESS_MASK GrantedAccess
,
695 OUT PNTSTATUS AccessStatus
)
697 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
698 KPROCESSOR_MODE PreviousMode
;
702 DPRINT("NtAccessCheck() called\n");
704 PreviousMode
= KeGetPreviousMode();
705 if (PreviousMode
== KernelMode
)
707 *GrantedAccess
= DesiredAccess
;
708 *AccessStatus
= STATUS_SUCCESS
;
709 return STATUS_SUCCESS
;
712 Status
= ObReferenceObjectByHandle(TokenHandle
,
718 if (!NT_SUCCESS(Status
))
720 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
724 /* Check token type */
725 if (Token
->TokenType
!= TokenImpersonation
)
727 DPRINT1("No impersonation token\n");
728 ObDereferenceObject(Token
);
729 return STATUS_ACCESS_VIOLATION
;
732 /* Check impersonation level */
733 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
735 DPRINT1("Invalid impersonation level\n");
736 ObDereferenceObject(Token
);
737 return STATUS_ACCESS_VIOLATION
;
740 RtlZeroMemory(&SubjectSecurityContext
,
741 sizeof(SECURITY_SUBJECT_CONTEXT
));
742 SubjectSecurityContext
.ClientToken
= Token
;
743 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
745 /* FIXME: Lock subject context */
747 if (!SeAccessCheck(SecurityDescriptor
,
748 &SubjectSecurityContext
,
758 Status
= *AccessStatus
;
762 Status
= STATUS_SUCCESS
;
765 /* FIXME: Unlock subject context */
767 ObDereferenceObject(Token
);
769 DPRINT("NtAccessCheck() done\n");