-/* $Id: semgr.c,v 1.30 2004/05/20 12:42:11 ekohl Exp $
+/* $Id: semgr.c,v 1.35 2004/07/19 12:45:56 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
#include <internal/ps.h>
#include <internal/se.h>
+#define NDEBUG
#include <internal/debug.h>
#define TAG_SXPT TAG('S', 'X', 'P', 'T')
}
-NTSTATUS STDCALL
-NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN HANDLE ClientToken,
- IN ACCESS_MASK DesiredAccess,
- IN PGENERIC_MAPPING GenericMapping,
- OUT PPRIVILEGE_SET PrivilegeSet,
- OUT PULONG ReturnLength,
- OUT PULONG GrantedAccess,
- OUT PBOOLEAN AccessStatus)
-{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
-}
-
-
/*
* @implemented
*/
VOID STDCALL
SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- PEPROCESS Process;
+ PETHREAD Thread;
BOOLEAN CopyOnOpen;
BOOLEAN EffectiveOnly;
- Process = PsGetCurrentThread ()->ThreadsProcess;
-
- SubjectContext->ProcessAuditId = Process;
- SubjectContext->ClientToken =
- PsReferenceImpersonationToken (PsGetCurrentThread(),
- &CopyOnOpen,
- &EffectiveOnly,
- &SubjectContext->ImpersonationLevel);
- SubjectContext->PrimaryToken = PsReferencePrimaryToken (Process);
+ Thread = PsGetCurrentThread();
+ if (Thread == NULL)
+ {
+ SubjectContext->ProcessAuditId = 0;
+ SubjectContext->PrimaryToken = NULL;
+ SubjectContext->ClientToken = NULL;
+ SubjectContext->ImpersonationLevel = 0;
+ }
+ else
+ {
+ SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
+ SubjectContext->ClientToken =
+ PsReferenceImpersonationToken(Thread,
+ &CopyOnOpen,
+ &EffectiveOnly,
+ &SubjectContext->ImpersonationLevel);
+ SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
+ }
}
VOID STDCALL
SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- ObDereferenceObject (SubjectContext->PrimaryToken);
+ if (SubjectContext->PrimaryToken != NULL)
+ {
+ ObDereferenceObject(SubjectContext->PrimaryToken);
+ }
+
if (SubjectContext->ClientToken != NULL)
{
- ObDereferenceObject (SubjectContext->ClientToken);
+ ObDereferenceObject(SubjectContext->ClientToken);
}
}
* @implemented
*/
NTSTATUS STDCALL
-SeDeassignSecurity(PSECURITY_DESCRIPTOR* SecurityDescriptor)
+SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
- if ((*SecurityDescriptor) != NULL)
+ if (*SecurityDescriptor != NULL)
{
ExFreePool(*SecurityDescriptor);
- (*SecurityDescriptor) = NULL;
+ *SecurityDescriptor = NULL;
}
- return(STATUS_SUCCESS);
+
+ return STATUS_SUCCESS;
}
#if 0
-VOID SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext,
- PSID* Owner,
- PSID* PrimaryGroup,
- PSID* ProcessOwner,
- PSID* ProcessPrimaryGroup,
- PACL* DefaultDacl)
+VOID
+SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ PSID* Owner,
+ PSID* PrimaryGroup,
+ PSID* ProcessOwner,
+ PSID* ProcessPrimaryGroup,
+ PACL* DefaultDacl)
{
- PACCESS_TOKEN Token;
-
- if (SubjectContext->ClientToken != NULL)
- {
+ PACCESS_TOKEN Token;
+
+ if (SubjectContext->ClientToken != NULL)
+ {
Token = SubjectContext->ClientToken;
- }
- else
- {
+ }
+ else
+ {
Token = SubjectContext->PrimaryToken;
- }
- *Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
- *PrimaryGroup = Token->PrimaryGroup;
- *DefaultDacl = Token->DefaultDacl;
- *ProcessOwner = SubjectContext->PrimaryToken->
- UserAndGroups[Token->DefaultOwnerIndex].Sid;
- *ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup;
+ }
+ *Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
+ *PrimaryGroup = Token->PrimaryGroup;
+ *DefaultDacl = Token->DefaultDacl;
+ *ProcessOwner = SubjectContext->PrimaryToken->
+ UserAndGroups[Token->DefaultOwnerIndex].Sid;
+ *ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup;
}
-NTSTATUS SepInheritAcl(PACL Acl,
- BOOLEAN IsDirectoryObject,
- PSID Owner,
- PSID PrimaryGroup,
- PACL DefaultAcl,
- PSID ProcessOwner,
- PSID ProcessGroup,
- PGENERIC_MAPPING GenericMapping)
+
+NTSTATUS
+SepInheritAcl(PACL Acl,
+ BOOLEAN IsDirectoryObject,
+ PSID Owner,
+ PSID PrimaryGroup,
+ PACL DefaultAcl,
+ PSID ProcessOwner,
+ PSID ProcessGroup,
+ PGENERIC_MAPPING GenericMapping)
{
- if (Acl == NULL)
- {
+ if (Acl == NULL)
+ {
return(STATUS_UNSUCCESSFUL);
- }
- if (Acl->AclRevision != 2 &&
- Acl->AclRevision != 3 )
- {
+ }
+
+ if (Acl->AclRevision != 2 &&
+ Acl->AclRevision != 3 )
+ {
return(STATUS_UNSUCCESSFUL);
- }
-
+ }
+
}
#endif
+
/*
* @unimplemented
*/
NTSTATUS STDCALL
-SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
- PSECURITY_DESCRIPTOR ExplicitDescriptor,
- PSECURITY_DESCRIPTOR* NewDescriptor,
+SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
+ PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
+ PSECURITY_DESCRIPTOR *NewDescriptor,
BOOLEAN IsDirectoryObject,
PSECURITY_SUBJECT_CONTEXT SubjectContext,
PGENERIC_MAPPING GenericMapping,
POOL_TYPE PoolType)
{
+ PSECURITY_DESCRIPTOR Descriptor;
+ ULONG Length;
+ NTSTATUS Status;
+
+ if (ExplicitDescriptor != NULL)
+ {
+ Length = RtlLengthSecurityDescriptor(ExplicitDescriptor);
+ }
+ else
+ {
+ DPRINT("No explicit security descriptor\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Descriptor = ExAllocatePool(NonPagedPool,
+ Length);
+ if (Descriptor == NULL)
+ {
+ DPRINT1("ExAlloctePool() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = RtlMakeSelfRelativeSD(ExplicitDescriptor,
+ Descriptor,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlMakeSelfRelativeSD() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ *NewDescriptor = Descriptor;
+
+ return STATUS_SUCCESS;
+
#if 0
- PSECURITY_DESCRIPTOR Descriptor;
PSID Owner;
PSID PrimaryGroup;
PACL DefaultDacl;
PSID ProcessOwner;
PSID ProcessPrimaryGroup;
PACL Sacl;
-
+
if (ExplicitDescriptor == NULL)
{
RtlCreateSecurityDescriptor(&Descriptor, 1);
{
Descriptor = ExplicitDescriptor;
}
+
SeLockSubjectContext(SubjectContext);
+
SepGetDefaultsSubjectContext(SubjectContext,
&Owner,
&PrimaryGroup,
&DefaultDacl,
&ProcessOwner,
&ProcessPrimaryGroup);
+
if (Descriptor->Control & SE_SACL_PRESENT ||
Descriptor->Control & SE_SACL_DEFAULTED)
{
if (ParentDescriptor == NULL)
{
}
+
if (Descriptor->Control & SE_SACL_PRESENT ||
Descriptor->Sacl == NULL ||)
{
Sacl = Descriptor->Sacl;
if (Descriptor->Control & SE_SELF_RELATIVE)
{
- Sacl = (PACL)(((PVOID)Sacl) + (PVOID)Descriptor);
+ Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)Descriptor);
}
}
+
SepInheritAcl(Sacl,
IsDirectoryObject,
Owner,
ProcessOwner,
GenericMapping);
}
-#else
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
#endif
}
-BOOLEAN SepSidInToken(PACCESS_TOKEN Token,
- PSID Sid)
+
+static BOOLEAN
+SepSidInToken(PACCESS_TOKEN Token,
+ PSID Sid)
{
- ULONG i;
-
- if (Token->UserAndGroupCount == 0)
- {
- return(FALSE);
- }
-
- for (i=0; i<Token->UserAndGroupCount; i++)
- {
- if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
- {
- if (i == 0 ||
- (!(Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)))
- {
- return(TRUE);
- }
- return(FALSE);
- }
- }
- return(FALSE);
+ ULONG i;
+
+ if (Token->UserAndGroupCount == 0)
+ {
+ return FALSE;
+ }
+
+ for (i=0; i<Token->UserAndGroupCount; i++)
+ {
+ if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
+ {
+ if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+ }
+
+ return FALSE;
}
-/*
- * @implemented
- */
-BOOLEAN STDCALL
-SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
- IN BOOLEAN SubjectContextLocked,
- IN ACCESS_MASK DesiredAccess,
- IN ACCESS_MASK PreviouslyGrantedAccess,
- OUT PPRIVILEGE_SET* Privileges,
- IN PGENERIC_MAPPING GenericMapping,
- IN KPROCESSOR_MODE AccessMode,
- OUT PACCESS_MODE GrantedAccess,
- OUT PNTSTATUS AccessStatus)
/*
* FUNCTION: Determines whether the requested access rights can be granted
* to an object protected by a security descriptor and an object owner
* GrantedAccess (OUT) = On return specifies the access granted
* AccessStatus (OUT) = Status indicating why access was denied
* RETURNS: If access was granted, returns TRUE
+ *
+ * @implemented
*/
+BOOLEAN STDCALL
+SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
+ IN BOOLEAN SubjectContextLocked,
+ IN ACCESS_MASK DesiredAccess,
+ IN ACCESS_MASK PreviouslyGrantedAccess,
+ OUT PPRIVILEGE_SET* Privileges,
+ IN PGENERIC_MAPPING GenericMapping,
+ IN KPROCESSOR_MODE AccessMode,
+ OUT PACCESS_MASK GrantedAccess,
+ OUT PNTSTATUS AccessStatus)
{
- ULONG i;
- PACL Dacl;
- BOOLEAN Present;
- BOOLEAN Defaulted;
- NTSTATUS Status;
- PACE CurrentAce;
- PSID Sid;
- ACCESS_MASK CurrentAccess;
-
- CurrentAccess = PreviouslyGrantedAccess;
-
- /*
- * Ignore the SACL for now
- */
-
- /*
- * Check the DACL
- */
- Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
- &Present,
- &Dacl,
+ LUID_AND_ATTRIBUTES Privilege;
+ ACCESS_MASK CurrentAccess;
+ PACCESS_TOKEN Token;
+ ULONG i;
+ PACL Dacl;
+ BOOLEAN Present;
+ BOOLEAN Defaulted;
+ PACE CurrentAce;
+ PSID Sid;
+ NTSTATUS Status;
+
+ CurrentAccess = PreviouslyGrantedAccess;
+
+ Token = SubjectSecurityContext->ClientToken ?
+ SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+
+ /* Get the DACL */
+ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+ &Present,
+ &Dacl,
+ &Defaulted);
+ if (!NT_SUCCESS(Status))
+ {
+ *AccessStatus = Status;
+ return FALSE;
+ }
+
+ /* RULE 1: Grant desired access if the object is unprotected */
+ if (Dacl == NULL)
+ {
+ *GrantedAccess = DesiredAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+
+ CurrentAccess = PreviouslyGrantedAccess;
+
+ /* RULE 2: Check token for 'take ownership' privilege */
+ Privilege.Luid = SeTakeOwnershipPrivilege;
+ Privilege.Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (SepPrivilegeCheck(Token,
+ &Privilege,
+ 1,
+ PRIVILEGE_SET_ALL_NECESSARY,
+ AccessMode))
+ {
+ CurrentAccess |= WRITE_OWNER;
+ if (DesiredAccess == CurrentAccess)
+ {
+ *GrantedAccess = CurrentAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ }
+
+ /* RULE 3: Check whether the token is the owner */
+ Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
+ &Sid,
&Defaulted);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
+ *AccessStatus = Status;
+ return FALSE;
+ }
- CurrentAce = (PACE)(Dacl + 1);
- for (i = 0; i < Dacl->AceCount; i++)
- {
- Sid = (PSID)(CurrentAce + 1);
- if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
- {
- if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid))
- {
- *AccessStatus = STATUS_ACCESS_DENIED;
- *GrantedAccess = 0;
- return(STATUS_SUCCESS);
- }
- }
- if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
- {
- if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid))
- {
- CurrentAccess = CurrentAccess |
- CurrentAce->AccessMask;
- }
- }
- }
- if (!(CurrentAccess & DesiredAccess) &&
- !((~CurrentAccess) & DesiredAccess))
- {
- *AccessStatus = STATUS_ACCESS_DENIED;
- }
- else
- {
- *AccessStatus = STATUS_SUCCESS;
- }
- *GrantedAccess = CurrentAccess;
+ if (SepSidInToken(Token, Sid))
+ {
+ CurrentAccess |= (READ_CONTROL | WRITE_DAC);
+ if (DesiredAccess == CurrentAccess)
+ {
+ *GrantedAccess = CurrentAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ }
+
+ /* RULE 4: Grant rights according to the DACL */
+ CurrentAce = (PACE)(Dacl + 1);
+ for (i = 0; i < Dacl->AceCount; i++)
+ {
+ Sid = (PSID)(CurrentAce + 1);
+ if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return TRUE;
+ }
+ }
+
+ if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+ CurrentAccess |= CurrentAce->AccessMask;
+ }
+ }
+ }
+
+ DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
+ CurrentAccess, DesiredAccess);
+
+ *GrantedAccess = CurrentAccess & DesiredAccess;
+
+ *AccessStatus =
+ (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
+
+ return TRUE;
+}
+
+
+NTSTATUS STDCALL
+NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN HANDLE TokenHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN PGENERIC_MAPPING GenericMapping,
+ OUT PPRIVILEGE_SET PrivilegeSet,
+ OUT PULONG ReturnLength,
+ OUT PACCESS_MASK GrantedAccess,
+ OUT PNTSTATUS AccessStatus)
+{
+ SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
+ KPROCESSOR_MODE PreviousMode;
+ PACCESS_TOKEN Token;
+ NTSTATUS Status;
+
+ DPRINT("NtAccessCheck() called\n");
+
+ PreviousMode = KeGetPreviousMode();
+ if (PreviousMode == KernelMode)
+ {
+ *GrantedAccess = DesiredAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return STATUS_SUCCESS;
+ }
+
+ Status = ObReferenceObjectByHandle(TokenHandle,
+ TOKEN_QUERY,
+ SepTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference token (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Check token type */
+ if (Token->TokenType != TokenImpersonation)
+ {
+ DPRINT1("No impersonation token\n");
+ ObDereferenceObject(Token);
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ /* Check impersonation level */
+ if (Token->ImpersonationLevel < SecurityAnonymous)
+ {
+ DPRINT1("Invalid impersonation level\n");
+ ObDereferenceObject(Token);
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ RtlZeroMemory(&SubjectSecurityContext,
+ sizeof(SECURITY_SUBJECT_CONTEXT));
+ SubjectSecurityContext.ClientToken = Token;
+ SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
+
+ /* FIXME: Lock subject context */
+
+ if (!SeAccessCheck(SecurityDescriptor,
+ &SubjectSecurityContext,
+ TRUE,
+ DesiredAccess,
+ 0,
+ &PrivilegeSet,
+ GenericMapping,
+ PreviousMode,
+ GrantedAccess,
+ AccessStatus))
+ {
+ Status = *AccessStatus;
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* FIXME: Unlock subject context */
+
+ ObDereferenceObject(Token);
+
+ DPRINT("NtAccessCheck() done\n");
- return(STATUS_SUCCESS);
+ return Status;
}
/* EOF */