1 /* $Id: semgr.c,v 1.32 2004/07/13 16:59:35 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>
18 #include <internal/debug.h>
20 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
23 /* GLOBALS ******************************************************************/
25 PSE_EXPORTS EXPORTED SeExports
= NULL
;
28 /* PROTOTYPES ***************************************************************/
30 static BOOLEAN
SepInitExports(VOID
);
32 /* FUNCTIONS ****************************************************************/
40 if (!SepInitSecurityIDs())
51 if (!SepInitExports())
61 SepInitializeTokenImplementation();
70 OBJECT_ATTRIBUTES ObjectAttributes
;
72 HANDLE DirectoryHandle
;
76 /* Create '\Security' directory */
77 RtlInitUnicodeString(&Name
,
79 InitializeObjectAttributes(&ObjectAttributes
,
84 Status
= NtCreateDirectoryObject(&DirectoryHandle
,
87 if (!NT_SUCCESS(Status
))
89 DPRINT1("Failed to create 'Security' directory!\n");
93 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
94 RtlInitUnicodeString(&Name
,
95 L
"\\LSA_AUTHENTICATION_INITALIZED");
96 InitializeObjectAttributes(&ObjectAttributes
,
101 Status
= NtCreateEvent(&EventHandle
,
106 if (!NT_SUCCESS(Status
))
108 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
109 NtClose(DirectoryHandle
);
113 NtClose(EventHandle
);
114 NtClose(DirectoryHandle
);
116 /* FIXME: Create SRM port and listener thread */
122 static BOOLEAN INIT_FUNCTION
125 SeExports
= ExAllocatePoolWithTag(NonPagedPool
,
128 if (SeExports
== NULL
)
131 SeExports
->SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
132 SeExports
->SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
133 SeExports
->SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
134 SeExports
->SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
135 SeExports
->SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
136 SeExports
->SeTcbPrivilege
= SeTcbPrivilege
;
137 SeExports
->SeSecurityPrivilege
= SeSecurityPrivilege
;
138 SeExports
->SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
139 SeExports
->SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
140 SeExports
->SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
141 SeExports
->SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
142 SeExports
->SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
143 SeExports
->SeSystemtimePrivilege
= SeSystemtimePrivilege
;
144 SeExports
->SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
145 SeExports
->SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
146 SeExports
->SeBackupPrivilege
= SeBackupPrivilege
;
147 SeExports
->SeRestorePrivilege
= SeRestorePrivilege
;
148 SeExports
->SeShutdownPrivilege
= SeShutdownPrivilege
;
149 SeExports
->SeDebugPrivilege
= SeDebugPrivilege
;
150 SeExports
->SeAuditPrivilege
= SeAuditPrivilege
;
151 SeExports
->SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
152 SeExports
->SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
153 SeExports
->SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
155 SeExports
->SeNullSid
= SeNullSid
;
156 SeExports
->SeWorldSid
= SeWorldSid
;
157 SeExports
->SeLocalSid
= SeLocalSid
;
158 SeExports
->SeCreatorOwnerSid
= SeCreatorOwnerSid
;
159 SeExports
->SeCreatorGroupSid
= SeCreatorGroupSid
;
160 SeExports
->SeNtAuthoritySid
= SeNtAuthoritySid
;
161 SeExports
->SeDialupSid
= SeDialupSid
;
162 SeExports
->SeNetworkSid
= SeNetworkSid
;
163 SeExports
->SeBatchSid
= SeBatchSid
;
164 SeExports
->SeInteractiveSid
= SeInteractiveSid
;
165 SeExports
->SeLocalSystemSid
= SeLocalSystemSid
;
166 SeExports
->SeAliasAdminsSid
= SeAliasAdminsSid
;
167 SeExports
->SeAliasUsersSid
= SeAliasUsersSid
;
168 SeExports
->SeAliasGuestsSid
= SeAliasGuestsSid
;
169 SeExports
->SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
170 SeExports
->SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
171 SeExports
->SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
172 SeExports
->SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
173 SeExports
->SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
179 VOID
SepReferenceLogonSession(PLUID AuthenticationId
)
184 VOID
SepDeReferenceLogonSession(PLUID AuthenticationId
)
195 NtAllocateUuids(PULARGE_INTEGER Time
,
200 return(STATUS_NOT_IMPLEMENTED
);
208 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
212 BOOLEAN EffectiveOnly
;
214 Process
= PsGetCurrentThread ()->ThreadsProcess
;
216 SubjectContext
->ProcessAuditId
= Process
;
217 SubjectContext
->ClientToken
=
218 PsReferenceImpersonationToken (PsGetCurrentThread(),
221 &SubjectContext
->ImpersonationLevel
);
222 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken (Process
);
230 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
240 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
242 ObDereferenceObject (SubjectContext
->PrimaryToken
);
243 if (SubjectContext
->ClientToken
!= NULL
)
245 ObDereferenceObject (SubjectContext
->ClientToken
);
254 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
264 SeDeassignSecurity(PSECURITY_DESCRIPTOR
* SecurityDescriptor
)
266 if ((*SecurityDescriptor
) != NULL
)
268 ExFreePool(*SecurityDescriptor
);
269 (*SecurityDescriptor
) = NULL
;
271 return(STATUS_SUCCESS
);
276 VOID
SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext
,
280 PSID
* ProcessPrimaryGroup
,
285 if (SubjectContext
->ClientToken
!= NULL
)
287 Token
= SubjectContext
->ClientToken
;
291 Token
= SubjectContext
->PrimaryToken
;
293 *Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
294 *PrimaryGroup
= Token
->PrimaryGroup
;
295 *DefaultDacl
= Token
->DefaultDacl
;
296 *ProcessOwner
= SubjectContext
->PrimaryToken
->
297 UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
298 *ProcessPrimaryGroup
= SubjectContext
->PrimaryToken
->PrimaryGroup
;
301 NTSTATUS
SepInheritAcl(PACL Acl
,
302 BOOLEAN IsDirectoryObject
,
308 PGENERIC_MAPPING GenericMapping
)
312 return(STATUS_UNSUCCESSFUL
);
314 if (Acl
->AclRevision
!= 2 &&
315 Acl
->AclRevision
!= 3 )
317 return(STATUS_UNSUCCESSFUL
);
327 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor
,
328 PSECURITY_DESCRIPTOR ExplicitDescriptor
,
329 PSECURITY_DESCRIPTOR
* NewDescriptor
,
330 BOOLEAN IsDirectoryObject
,
331 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
332 PGENERIC_MAPPING GenericMapping
,
336 PSECURITY_DESCRIPTOR Descriptor
;
341 PSID ProcessPrimaryGroup
;
344 if (ExplicitDescriptor
== NULL
)
346 RtlCreateSecurityDescriptor(&Descriptor
, 1);
350 Descriptor
= ExplicitDescriptor
;
352 SeLockSubjectContext(SubjectContext
);
353 SepGetDefaultsSubjectContext(SubjectContext
,
358 &ProcessPrimaryGroup
);
359 if (Descriptor
->Control
& SE_SACL_PRESENT
||
360 Descriptor
->Control
& SE_SACL_DEFAULTED
)
362 if (ParentDescriptor
== NULL
)
365 if (Descriptor
->Control
& SE_SACL_PRESENT
||
366 Descriptor
->Sacl
== NULL
||)
372 Sacl
= Descriptor
->Sacl
;
373 if (Descriptor
->Control
& SE_SELF_RELATIVE
)
375 Sacl
= (PACL
)(((PVOID
)Sacl
) + (PVOID
)Descriptor
);
388 return(STATUS_NOT_IMPLEMENTED
);
394 SepSidInToken(PACCESS_TOKEN Token
,
399 if (Token
->UserAndGroupCount
== 0)
404 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
406 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
408 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
422 * FUNCTION: Determines whether the requested access rights can be granted
423 * to an object protected by a security descriptor and an object owner
425 * SecurityDescriptor = Security descriptor protecting the object
426 * SubjectSecurityContext = Subject's captured security context
427 * SubjectContextLocked = Indicates the user's subject context is locked
428 * DesiredAccess = Access rights the caller is trying to acquire
429 * PreviouslyGrantedAccess = Specified the access rights already granted
431 * GenericMapping = Generic mapping associated with the object
432 * AccessMode = Access mode used for the check
433 * GrantedAccess (OUT) = On return specifies the access granted
434 * AccessStatus (OUT) = Status indicating why access was denied
435 * RETURNS: If access was granted, returns TRUE
440 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
441 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
442 IN BOOLEAN SubjectContextLocked
,
443 IN ACCESS_MASK DesiredAccess
,
444 IN ACCESS_MASK PreviouslyGrantedAccess
,
445 OUT PPRIVILEGE_SET
* Privileges
,
446 IN PGENERIC_MAPPING GenericMapping
,
447 IN KPROCESSOR_MODE AccessMode
,
448 OUT PACCESS_MASK GrantedAccess
,
449 OUT PNTSTATUS AccessStatus
)
458 ACCESS_MASK CurrentAccess
;
460 CurrentAccess
= PreviouslyGrantedAccess
;
465 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
469 if (!NT_SUCCESS(Status
))
471 *AccessStatus
= Status
;
475 CurrentAce
= (PACE
)(Dacl
+ 1);
476 for (i
= 0; i
< Dacl
->AceCount
; i
++)
478 Sid
= (PSID
)(CurrentAce
+ 1);
479 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
481 if (SepSidInToken(SubjectSecurityContext
->ClientToken
, Sid
))
483 *AccessStatus
= STATUS_ACCESS_DENIED
;
485 return(STATUS_SUCCESS
);
489 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
491 if (SepSidInToken(SubjectSecurityContext
->ClientToken
, Sid
))
493 CurrentAccess
|= CurrentAce
->AccessMask
;
497 if (!(CurrentAccess
& DesiredAccess
) &&
498 !((~CurrentAccess
) & DesiredAccess
))
500 *AccessStatus
= STATUS_ACCESS_DENIED
;
504 *AccessStatus
= STATUS_SUCCESS
;
506 *GrantedAccess
= CurrentAccess
;
513 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
514 IN HANDLE TokenHandle
,
515 IN ACCESS_MASK DesiredAccess
,
516 IN PGENERIC_MAPPING GenericMapping
,
517 OUT PPRIVILEGE_SET PrivilegeSet
,
518 OUT PULONG ReturnLength
,
519 OUT PACCESS_MASK GrantedAccess
,
520 OUT PNTSTATUS AccessStatus
)
522 KPROCESSOR_MODE PreviousMode
;
529 ACCESS_MASK CurrentAccess
;
533 DPRINT("NtAccessCheck() called\n");
535 PreviousMode
= KeGetPreviousMode();
536 if (PreviousMode
== KernelMode
)
538 *GrantedAccess
= DesiredAccess
;
539 *AccessStatus
= STATUS_SUCCESS
;
540 return STATUS_SUCCESS
;
543 Status
= ObReferenceObjectByHandle(TokenHandle
,
549 if (!NT_SUCCESS(Status
))
551 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
555 /* Check token type */
556 if (Token
->TokenType
!= TokenImpersonation
)
558 DPRINT1("No impersonation token\n");
559 ObDereferenceObject(Token
);
560 return STATUS_ACCESS_VIOLATION
;
563 /* Check impersonation level */
564 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
566 DPRINT1("Invalid impersonation level\n");
567 ObDereferenceObject(Token
);
568 return STATUS_ACCESS_VIOLATION
;
572 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
576 if (!NT_SUCCESS(Status
))
578 DPRINT1("RtlGetDaclSecurityDescriptor() failed (Status %lx)\n", Status
);
579 ObDereferenceObject(Token
);
583 /* RULE 1: Grant desired access if the object is unprotected */
586 *GrantedAccess
= DesiredAccess
;
587 *AccessStatus
= STATUS_SUCCESS
;
588 return STATUS_SUCCESS
;
593 /* FIXME: RULE 2: Check token for 'take ownership' privilege */
595 /* RULE 3: Check whether the token is the owner */
596 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
599 if (!NT_SUCCESS(Status
))
601 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
602 ObDereferenceObject(Token
);
606 if (SepSidInToken(Token
, Sid
))
608 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
609 if (DesiredAccess
== CurrentAccess
)
611 *AccessStatus
= STATUS_SUCCESS
;
612 *GrantedAccess
= CurrentAccess
;
613 return STATUS_SUCCESS
;
617 /* RULE 4: Grant rights according to the DACL */
618 CurrentAce
= (PACE
)(Dacl
+ 1);
619 for (i
= 0; i
< Dacl
->AceCount
; i
++)
621 Sid
= (PSID
)(CurrentAce
+ 1);
622 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
624 if (SepSidInToken(Token
, Sid
))
626 *AccessStatus
= STATUS_ACCESS_DENIED
;
628 return STATUS_SUCCESS
;
632 if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
634 if (SepSidInToken(Token
, Sid
))
636 CurrentAccess
|= CurrentAce
->AccessMask
;
641 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
642 CurrentAccess
, DesiredAccess
);
644 ObDereferenceObject(Token
);
646 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
649 (*GrantedAccess
== DesiredAccess
) ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
651 DPRINT("NtAccessCheck() done\n");
653 return STATUS_SUCCESS
;