1 /* $Id: semgr.c,v 1.34 2004/07/18 13:02:28 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 Process
= PsGetCurrentThread ()->ThreadsProcess
;
217 SubjectContext
->ProcessAuditId
= Process
;
218 SubjectContext
->ClientToken
=
219 PsReferenceImpersonationToken (PsGetCurrentThread(),
222 &SubjectContext
->ImpersonationLevel
);
223 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken (Process
);
231 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
241 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
243 ObDereferenceObject (SubjectContext
->PrimaryToken
);
244 if (SubjectContext
->ClientToken
!= NULL
)
246 ObDereferenceObject (SubjectContext
->ClientToken
);
255 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
265 SeDeassignSecurity(PSECURITY_DESCRIPTOR
* SecurityDescriptor
)
267 if ((*SecurityDescriptor
) != NULL
)
269 ExFreePool(*SecurityDescriptor
);
270 (*SecurityDescriptor
) = NULL
;
272 return(STATUS_SUCCESS
);
278 SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext
,
282 PSID
* ProcessPrimaryGroup
,
287 if (SubjectContext
->ClientToken
!= NULL
)
289 Token
= SubjectContext
->ClientToken
;
293 Token
= SubjectContext
->PrimaryToken
;
295 *Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
296 *PrimaryGroup
= Token
->PrimaryGroup
;
297 *DefaultDacl
= Token
->DefaultDacl
;
298 *ProcessOwner
= SubjectContext
->PrimaryToken
->
299 UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
300 *ProcessPrimaryGroup
= SubjectContext
->PrimaryToken
->PrimaryGroup
;
305 SepInheritAcl(PACL Acl
,
306 BOOLEAN IsDirectoryObject
,
312 PGENERIC_MAPPING GenericMapping
)
316 return(STATUS_UNSUCCESSFUL
);
319 if (Acl
->AclRevision
!= 2 &&
320 Acl
->AclRevision
!= 3 )
322 return(STATUS_UNSUCCESSFUL
);
333 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
334 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
335 PSECURITY_DESCRIPTOR
*NewDescriptor
,
336 BOOLEAN IsDirectoryObject
,
337 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
338 PGENERIC_MAPPING GenericMapping
,
341 PSECURITY_DESCRIPTOR Descriptor
;
345 if (ExplicitDescriptor
!= NULL
)
347 Length
= RtlLengthSecurityDescriptor(ExplicitDescriptor
);
351 DPRINT("No explicit security descriptor\n");
352 return STATUS_UNSUCCESSFUL
;
355 Descriptor
= ExAllocatePool(NonPagedPool
,
357 if (Descriptor
== NULL
)
359 DPRINT1("ExAlloctePool() failed\n");
360 return STATUS_UNSUCCESSFUL
;
363 Status
= RtlMakeSelfRelativeSD(ExplicitDescriptor
,
366 if (!NT_SUCCESS(Status
))
368 DPRINT1("RtlMakeSelfRelativeSD() failed (Status %lx)\n", Status
);
372 *NewDescriptor
= Descriptor
;
374 return STATUS_SUCCESS
;
381 PSID ProcessPrimaryGroup
;
384 if (ExplicitDescriptor
== NULL
)
386 RtlCreateSecurityDescriptor(&Descriptor
, 1);
390 Descriptor
= ExplicitDescriptor
;
393 SeLockSubjectContext(SubjectContext
);
395 SepGetDefaultsSubjectContext(SubjectContext
,
400 &ProcessPrimaryGroup
);
402 if (Descriptor
->Control
& SE_SACL_PRESENT
||
403 Descriptor
->Control
& SE_SACL_DEFAULTED
)
405 if (ParentDescriptor
== NULL
)
409 if (Descriptor
->Control
& SE_SACL_PRESENT
||
410 Descriptor
->Sacl
== NULL
||)
416 Sacl
= Descriptor
->Sacl
;
417 if (Descriptor
->Control
& SE_SELF_RELATIVE
)
419 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)Descriptor
);
436 SepSidInToken(PACCESS_TOKEN Token
,
441 if (Token
->UserAndGroupCount
== 0)
446 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
448 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
450 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
464 * FUNCTION: Determines whether the requested access rights can be granted
465 * to an object protected by a security descriptor and an object owner
467 * SecurityDescriptor = Security descriptor protecting the object
468 * SubjectSecurityContext = Subject's captured security context
469 * SubjectContextLocked = Indicates the user's subject context is locked
470 * DesiredAccess = Access rights the caller is trying to acquire
471 * PreviouslyGrantedAccess = Specified the access rights already granted
473 * GenericMapping = Generic mapping associated with the object
474 * AccessMode = Access mode used for the check
475 * GrantedAccess (OUT) = On return specifies the access granted
476 * AccessStatus (OUT) = Status indicating why access was denied
477 * RETURNS: If access was granted, returns TRUE
482 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
483 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
484 IN BOOLEAN SubjectContextLocked
,
485 IN ACCESS_MASK DesiredAccess
,
486 IN ACCESS_MASK PreviouslyGrantedAccess
,
487 OUT PPRIVILEGE_SET
* Privileges
,
488 IN PGENERIC_MAPPING GenericMapping
,
489 IN KPROCESSOR_MODE AccessMode
,
490 OUT PACCESS_MASK GrantedAccess
,
491 OUT PNTSTATUS AccessStatus
)
493 LUID_AND_ATTRIBUTES Privilege
;
494 ACCESS_MASK CurrentAccess
;
504 CurrentAccess
= PreviouslyGrantedAccess
;
506 Token
= SubjectSecurityContext
->ClientToken
?
507 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
510 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
514 if (!NT_SUCCESS(Status
))
516 *AccessStatus
= Status
;
520 /* RULE 1: Grant desired access if the object is unprotected */
523 *GrantedAccess
= DesiredAccess
;
524 *AccessStatus
= STATUS_SUCCESS
;
528 CurrentAccess
= PreviouslyGrantedAccess
;
530 /* RULE 2: Check token for 'take ownership' privilege */
531 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
532 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
534 if (SepPrivilegeCheck(Token
,
537 PRIVILEGE_SET_ALL_NECESSARY
,
540 CurrentAccess
|= WRITE_OWNER
;
541 if (DesiredAccess
== CurrentAccess
)
543 *GrantedAccess
= CurrentAccess
;
544 *AccessStatus
= STATUS_SUCCESS
;
549 /* RULE 3: Check whether the token is the owner */
550 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
553 if (!NT_SUCCESS(Status
))
555 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
556 *AccessStatus
= Status
;
560 if (SepSidInToken(Token
, Sid
))
562 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
563 if (DesiredAccess
== CurrentAccess
)
565 *GrantedAccess
= CurrentAccess
;
566 *AccessStatus
= STATUS_SUCCESS
;
571 /* RULE 4: Grant rights according to the DACL */
572 CurrentAce
= (PACE
)(Dacl
+ 1);
573 for (i
= 0; i
< Dacl
->AceCount
; i
++)
575 Sid
= (PSID
)(CurrentAce
+ 1);
576 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
578 if (SepSidInToken(Token
, Sid
))
581 *AccessStatus
= STATUS_ACCESS_DENIED
;
586 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
588 if (SepSidInToken(Token
, Sid
))
590 CurrentAccess
|= CurrentAce
->AccessMask
;
595 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
596 CurrentAccess
, DesiredAccess
);
598 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
601 (*GrantedAccess
== DesiredAccess
) ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
608 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
609 IN HANDLE TokenHandle
,
610 IN ACCESS_MASK DesiredAccess
,
611 IN PGENERIC_MAPPING GenericMapping
,
612 OUT PPRIVILEGE_SET PrivilegeSet
,
613 OUT PULONG ReturnLength
,
614 OUT PACCESS_MASK GrantedAccess
,
615 OUT PNTSTATUS AccessStatus
)
617 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
618 KPROCESSOR_MODE PreviousMode
;
622 DPRINT("NtAccessCheck() called\n");
624 PreviousMode
= KeGetPreviousMode();
625 if (PreviousMode
== KernelMode
)
627 *GrantedAccess
= DesiredAccess
;
628 *AccessStatus
= STATUS_SUCCESS
;
629 return STATUS_SUCCESS
;
632 Status
= ObReferenceObjectByHandle(TokenHandle
,
638 if (!NT_SUCCESS(Status
))
640 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
644 /* Check token type */
645 if (Token
->TokenType
!= TokenImpersonation
)
647 DPRINT1("No impersonation token\n");
648 ObDereferenceObject(Token
);
649 return STATUS_ACCESS_VIOLATION
;
652 /* Check impersonation level */
653 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
655 DPRINT1("Invalid impersonation level\n");
656 ObDereferenceObject(Token
);
657 return STATUS_ACCESS_VIOLATION
;
660 RtlZeroMemory(&SubjectSecurityContext
,
661 sizeof(SECURITY_SUBJECT_CONTEXT
));
662 SubjectSecurityContext
.ClientToken
= Token
;
663 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
665 /* FIXME: Lock subject context */
667 if (!SeAccessCheck(SecurityDescriptor
,
668 &SubjectSecurityContext
,
678 Status
= *AccessStatus
;
682 Status
= STATUS_SUCCESS
;
685 /* FIXME: Unlock subject context */
687 ObDereferenceObject(Token
);
689 DPRINT("NtAccessCheck() done\n");