[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / se / access.c
index 2d5f721..b4ebe9f 100644 (file)
  *                               Based on patch by Javier M. Mellid
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
-/* FUNCTIONS ***************************************************************/
+/* GLOBALS ********************************************************************/
 
+ERESOURCE SepSubjectContextLock;
+
+/* FUNCTIONS ******************************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeCaptureSubjectContextEx(IN PETHREAD Thread,
+                          IN PEPROCESS Process,
+                          OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+    BOOLEAN CopyOnOpen, EffectiveOnly;
+
+    PAGED_CODE();
+
+    /* Save the unique ID */
+    SubjectContext->ProcessAuditId = Process->UniqueProcessId;
+
+    /* Check if we have a thread */
+    if (!Thread)
+    {
+        /* We don't, so no token */
+        SubjectContext->ClientToken = NULL;
+    }
+    else
+    {
+        /* Get the impersonation token */
+        SubjectContext->ClientToken = PsReferenceImpersonationToken(Thread,
+                                                                    &CopyOnOpen,
+                                                                    &EffectiveOnly,
+                                                                    &SubjectContext->ImpersonationLevel);
+    }
+
+    /* Get the primary token */
+    SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+    /* Call the extended API */
+    SeCaptureSubjectContextEx(PsGetCurrentThread(),
+                              PsGetCurrentProcess(),
+                              SubjectContext);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+    PAGED_CODE();
+
+    KeEnterCriticalRegion();
+    ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+    PAGED_CODE();
+
+    ExReleaseResourceLite(&SepSubjectContextLock);
+    KeLeaveCriticalRegion();
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+    PAGED_CODE();
+
+    if (SubjectContext->PrimaryToken != NULL)
+    {
+        ObFastDereferenceObject(&PsGetCurrentProcess()->Token, SubjectContext->PrimaryToken);
+    }
+
+    if (SubjectContext->ClientToken != NULL)
+    {
+        ObDereferenceObject(SubjectContext->ClientToken);
+    }
+}
+
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 SeCreateAccessStateEx(IN PETHREAD Thread,
                       IN PEPROCESS Process,
                       IN OUT PACCESS_STATE AccessState,
-                      IN PAUX_DATA AuxData,
+                      IN PAUX_ACCESS_DATA AuxData,
                       IN ACCESS_MASK Access,
                       IN PGENERIC_MAPPING GenericMapping)
 {
     ACCESS_MASK AccessMask = Access;
     PTOKEN Token;
+
     PAGED_CODE();
 
     /* Map the Generic Acess to Specific Access if we have a Mapping */
@@ -50,9 +152,9 @@ SeCreateAccessStateEx(IN PETHREAD Thread,
     ExpAllocateLocallyUniqueId(&AccessState->OperationID);
 
     /* Get the Token to use */
-    Token =  AccessState->SubjectSecurityContext.ClientToken ?
-             (PTOKEN)&AccessState->SubjectSecurityContext.ClientToken :
-             (PTOKEN)&AccessState->SubjectSecurityContext.PrimaryToken;
+    Token = AccessState->SubjectSecurityContext.ClientToken ?
+            (PTOKEN)&AccessState->SubjectSecurityContext.ClientToken :
+            (PTOKEN)&AccessState->SubjectSecurityContext.PrimaryToken;
 
     /* Check for Travers Privilege */
     if (Token->TokenFlags & TOKEN_HAS_TRAVERSE_PRIVILEGE)
@@ -75,15 +177,15 @@ SeCreateAccessStateEx(IN PETHREAD Thread,
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 SeCreateAccessState(IN OUT PACCESS_STATE AccessState,
-                    IN PAUX_DATA AuxData,
+                    IN PAUX_ACCESS_DATA AuxData,
                     IN ACCESS_MASK Access,
                     IN PGENERIC_MAPPING GenericMapping)
 {
     PAGED_CODE();
 
-    /* Call the internal API */
+    /* Call the extended API */
     return SeCreateAccessStateEx(PsGetCurrentThread(),
                                  PsGetCurrentProcess(),
                                  AccessState,
@@ -96,10 +198,11 @@ SeCreateAccessState(IN OUT PACCESS_STATE AccessState,
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 SeDeleteAccessState(IN PACCESS_STATE AccessState)
 {
-    PAUX_DATA AuxData;
+    PAUX_ACCESS_DATA AuxData;
+
     PAGED_CODE();
 
     /* Get the Auxiliary Data */
@@ -113,7 +216,8 @@ SeDeleteAccessState(IN PACCESS_STATE AccessState)
     {
         ExFreePool(AccessState->ObjectName.Buffer);
     }
-    if (AccessState->ObjectTypeName.Buffer) 
+
+    if (AccessState->ObjectTypeName.Buffer)
     {
         ExFreePool(AccessState->ObjectTypeName.Buffer);
     }
@@ -126,14 +230,151 @@ SeDeleteAccessState(IN PACCESS_STATE AccessState)
  * @implemented
  */
 VOID
-STDCALL
-SeSetAccessStateGenericMapping(PACCESS_STATE AccessState,
-                               PGENERIC_MAPPING GenericMapping)
+NTAPI
+SeSetAccessStateGenericMapping(IN PACCESS_STATE AccessState,
+                               IN PGENERIC_MAPPING GenericMapping)
 {
     PAGED_CODE();
 
     /* Set the Generic Mapping */
-    ((PAUX_DATA)AccessState->AuxData)->GenericMapping = *GenericMapping;
+    ((PAUX_ACCESS_DATA)AccessState->AuxData)->GenericMapping = *GenericMapping;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+SeCreateClientSecurity(IN PETHREAD Thread,
+                       IN PSECURITY_QUALITY_OF_SERVICE Qos,
+                       IN BOOLEAN RemoteClient,
+                       OUT PSECURITY_CLIENT_CONTEXT ClientContext)
+{
+    TOKEN_TYPE TokenType;
+    BOOLEAN ThreadEffectiveOnly;
+    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+    PACCESS_TOKEN Token;
+    NTSTATUS Status;
+    PACCESS_TOKEN NewToken;
+
+    PAGED_CODE();
+
+    Token = PsReferenceEffectiveToken(Thread,
+                                      &TokenType,
+                                      &ThreadEffectiveOnly,
+                                      &ImpersonationLevel);
+    if (TokenType != TokenImpersonation)
+    {
+        ClientContext->DirectAccessEffectiveOnly = Qos->EffectiveOnly;
+    }
+    else
+    {
+        if (Qos->ImpersonationLevel > ImpersonationLevel)
+        {
+            if (Token) ObDereferenceObject(Token);
+            return STATUS_BAD_IMPERSONATION_LEVEL;
+        }
+
+        if ((ImpersonationLevel == SecurityAnonymous) ||
+            (ImpersonationLevel == SecurityIdentification) ||
+            ((RemoteClient) && (ImpersonationLevel != SecurityDelegation)))
+        {
+            if (Token) ObDereferenceObject(Token);
+            return STATUS_BAD_IMPERSONATION_LEVEL;
+        }
+
+        ClientContext->DirectAccessEffectiveOnly = ((ThreadEffectiveOnly) ||
+                                                    (Qos->EffectiveOnly)) ? TRUE : FALSE;
+    }
+
+    if (Qos->ContextTrackingMode == SECURITY_STATIC_TRACKING)
+    {
+        ClientContext->DirectlyAccessClientToken = FALSE;
+        Status = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken);
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+    else
+    {
+        ClientContext->DirectlyAccessClientToken = TRUE;
+        if (RemoteClient != FALSE)
+        {
+#if 0
+            SeGetTokenControlInformation(Token,
+                                         &ClientContext->ClientTokenControl);
+#endif
+        }
+
+        NewToken = Token;
+    }
+
+    ClientContext->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+    ClientContext->SecurityQos.ImpersonationLevel = Qos->ImpersonationLevel;
+    ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode;
+    ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly;
+    ClientContext->ServerIsRemote = RemoteClient;
+    ClientContext->ClientToken = NewToken;
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+SeCreateClientSecurityFromSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
+                                         IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos,
+                                         IN BOOLEAN ServerIsRemote,
+                                         OUT PSECURITY_CLIENT_CONTEXT ClientContext)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+SeImpersonateClientEx(IN PSECURITY_CLIENT_CONTEXT ClientContext,
+                      IN PETHREAD ServerThread OPTIONAL)
+{
+    BOOLEAN EffectiveOnly;
+
+    PAGED_CODE();
+
+    if (ClientContext->DirectlyAccessClientToken == FALSE)
+    {
+        EffectiveOnly = ClientContext->SecurityQos.EffectiveOnly;
+    }
+    else
+    {
+        EffectiveOnly = ClientContext->DirectAccessEffectiveOnly;
+    }
+
+    if (ServerThread == NULL)
+    {
+        ServerThread = PsGetCurrentThread();
+    }
+
+    return PsImpersonateClient(ServerThread,
+                               ClientContext->ClientToken,
+                               TRUE,
+                               EffectiveOnly,
+                               ClientContext->SecurityQos.ImpersonationLevel);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
+                    IN PETHREAD ServerThread OPTIONAL)
+{
+    PAGED_CODE();
+
+    SeImpersonateClientEx(ClientContext,
+                          ServerThread);
 }
 
 /* EOF */