[CMAKE]
[reactos.git] / ntoskrnl / se / priv.c
index d7d3bf9..6031942 100644 (file)
@@ -51,7 +51,7 @@ LUID SeEnableDelegationPrivilege;
 VOID
 INIT_FUNCTION
 NTAPI
-SepInitPrivileges (VOID)
+SepInitPrivileges(VOID)
 {
     SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
     SeCreateTokenPrivilege.HighPart = 0;
@@ -110,25 +110,25 @@ SepInitPrivileges (VOID)
 
 BOOLEAN
 NTAPI
-SepPrivilegeCheck (PTOKEN Token,
-                   PLUID_AND_ATTRIBUTES Privileges,
-                   ULONG PrivilegeCount,
-                   ULONG PrivilegeControl,
-                   KPROCESSOR_MODE PreviousMode)
+SepPrivilegeCheck(PTOKEN Token,
+                  PLUID_AND_ATTRIBUTES Privileges,
+                  ULONG PrivilegeCount,
+                  ULONG PrivilegeControl,
+                  KPROCESSOR_MODE PreviousMode)
 {
     ULONG i;
     ULONG j;
     ULONG k;
-    
-    DPRINT ("SepPrivilegeCheck() called\n");
-    
+
+    DPRINT("SepPrivilegeCheck() called\n");
+
     PAGED_CODE();
-    
+
     if (PreviousMode == KernelMode)
     {
         return TRUE;
     }
-    
+
     k = 0;
     if (PrivilegeCount > 0)
     {
@@ -139,10 +139,10 @@ SepPrivilegeCheck (PTOKEN Token,
                 if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
                     Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
                 {
-                    DPRINT ("Found privilege\n");
-                    DPRINT ("Privilege attributes %lx\n",
-                            Token->Privileges[i].Attributes);
-                    
+                    DPRINT("Found privilege\n");
+                    DPRINT("Privilege attributes %lx\n",
+                           Token->Privileges[i].Attributes);
+
                     if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
                     {
                         Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
@@ -152,58 +152,58 @@ SepPrivilegeCheck (PTOKEN Token,
             }
         }
     }
-    
+
     if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
         PrivilegeCount == k)
     {
         return TRUE;
     }
-    
+
     if (k > 0 &&
         !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
     {
         return TRUE;
     }
-    
+
     return FALSE;
 }
 
 NTSTATUS
 NTAPI
-SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
-                                 ULONG PrivilegeCount,
-                                 KPROCESSOR_MODE PreviousMode,
-                                 PLUID_AND_ATTRIBUTES AllocatedMem,
-                                 ULONG AllocatedLength,
-                                 POOL_TYPE PoolType,
-                                 BOOLEAN CaptureIfKernel,
-                                 PLUID_AND_ATTRIBUTES* Dest,
-                                 PULONG Length)
+SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
+                                ULONG PrivilegeCount,
+                                KPROCESSOR_MODE PreviousMode,
+                                PLUID_AND_ATTRIBUTES AllocatedMem,
+                                ULONG AllocatedLength,
+                                POOL_TYPE PoolType,
+                                BOOLEAN CaptureIfKernel,
+                                PLUID_AND_ATTRIBUTES *Dest,
+                                PULONG Length)
 {
     ULONG BufferSize;
     NTSTATUS Status = STATUS_SUCCESS;
-    
+
     PAGED_CODE();
-    
+
     if (PrivilegeCount == 0)
     {
         *Dest = 0;
         *Length = 0;
         return STATUS_SUCCESS;
     }
-    
+
     if (PreviousMode == KernelMode && !CaptureIfKernel)
     {
         *Dest = Src;
         return STATUS_SUCCESS;
     }
-    
+
     /* FIXME - check PrivilegeCount for a valid number so we don't
      cause an integer overflow or exhaust system resources! */
-    
+
     BufferSize = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
     *Length = ROUND_UP(BufferSize, 4); /* round up to a 4 byte alignment */
-    
+
     /* probe the buffer */
     if (PreviousMode != KernelMode)
     {
@@ -220,7 +220,7 @@ SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
         }
         _SEH2_END;
     }
-    
+
     /* allocate enough memory or check if the provided buffer is
      large enough to hold the array */
     if (AllocatedMem != NULL)
@@ -229,14 +229,13 @@ SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
         {
             return STATUS_BUFFER_TOO_SMALL;
         }
-        
+
         *Dest = AllocatedMem;
     }
     else
     {
         *Dest = ExAllocatePool(PoolType,
                                BufferSize);
-        
         if (*Dest == NULL)
         {
             return STATUS_INSUFFICIENT_RESOURCES;
@@ -255,23 +254,23 @@ SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
         Status = _SEH2_GetExceptionCode();
     }
     _SEH2_END;
-    
+
     if (!NT_SUCCESS(Status) && AllocatedMem == NULL)
     {
         ExFreePool(*Dest);
     }
-    
+
     return Status;
 }
 
 VOID
 NTAPI
-SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
-                                 KPROCESSOR_MODE PreviousMode,
-                                 BOOLEAN CaptureIfKernel)
+SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege,
+                                KPROCESSOR_MODE PreviousMode,
+                                BOOLEAN CaptureIfKernel)
 {
     PAGED_CODE();
-    
+
     if (Privilege != NULL &&
         (PreviousMode != KernelMode || CaptureIfKernel))
     {
@@ -282,39 +281,100 @@ SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS
 NTAPI
-SeAppendPrivileges(PACCESS_STATE AccessState,
-                   PPRIVILEGE_SET Privileges)
+SeAppendPrivileges(IN OUT PACCESS_STATE AccessState,
+                   IN PPRIVILEGE_SET Privileges)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PAUX_ACCESS_DATA AuxData;
+    ULONG OldPrivilegeSetSize;
+    ULONG NewPrivilegeSetSize;
+    PPRIVILEGE_SET PrivilegeSet;
+
+    PAGED_CODE();
+
+    /* Get the Auxiliary Data */
+    AuxData = AccessState->AuxData;
+
+    /* Calculate the size of the old privilege set */
+    OldPrivilegeSetSize = sizeof(PRIVILEGE_SET) +
+                          (AuxData->PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES);
+
+    if (AuxData->PrivilegeSet->PrivilegeCount +
+        Privileges->PrivilegeCount > INITIAL_PRIVILEGE_COUNT)
+    {
+        /* Calculate the size of the new privilege set */
+        NewPrivilegeSetSize = OldPrivilegeSetSize +
+                              Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+
+        /* Allocate a new privilege set */
+        PrivilegeSet = ExAllocatePool(PagedPool, NewPrivilegeSetSize);
+        if (PrivilegeSet == NULL)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        /* Copy original privileges from the acess state */
+        RtlCopyMemory(PrivilegeSet,
+                      AuxData->PrivilegeSet,
+                      OldPrivilegeSetSize);
+
+        /* Append privileges from the privilege set*/
+        RtlCopyMemory((PVOID)((ULONG_PTR)PrivilegeSet + OldPrivilegeSetSize),
+                      (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)),
+                      Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
+
+        /* Adjust the number of privileges in the new privilege set */
+        PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount;
+
+        /* Free the old privilege set if it was allocated */
+        if (AccessState->PrivilegesAllocated == TRUE)
+            ExFreePool(AuxData->PrivilegeSet);
+
+        /* Now we are using an allocated privilege set */
+        AccessState->PrivilegesAllocated = TRUE;
+
+        /* Assign the new privileges to the access state */
+        AuxData->PrivilegeSet = PrivilegeSet;
+    }
+    else
+    {
+        /* Append privileges */
+        RtlCopyMemory((PVOID)((ULONG_PTR)AuxData->PrivilegeSet + OldPrivilegeSetSize),
+                      (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)),
+                      Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
+
+        /* Adjust the number of privileges in the target privilege set */
+        AuxData->PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount;
+    }
+
+    return STATUS_SUCCESS;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
 SeFreePrivileges(IN PPRIVILEGE_SET Privileges)
 {
-    UNIMPLEMENTED;
+    PAGED_CODE();
+    ExFreePool(Privileges);
 }
 
 /*
  * @implemented
  */
-BOOLEAN NTAPI
-SePrivilegeCheck (PPRIVILEGE_SET Privileges,
-                  PSECURITY_SUBJECT_CONTEXT SubjectContext,
-                  KPROCESSOR_MODE PreviousMode)
+BOOLEAN
+NTAPI
+SePrivilegeCheck(PPRIVILEGE_SET Privileges,
+                 PSECURITY_SUBJECT_CONTEXT SubjectContext,
+                 KPROCESSOR_MODE PreviousMode)
 {
     PACCESS_TOKEN Token = NULL;
-    
+
     PAGED_CODE();
-    
+
     if (SubjectContext->ClientToken == NULL)
     {
         Token = SubjectContext->PrimaryToken;
@@ -327,58 +387,60 @@ SePrivilegeCheck (PPRIVILEGE_SET Privileges,
             return FALSE;
         }
     }
-    
-    return SepPrivilegeCheck (Token,
-                              Privileges->Privilege,
-                              Privileges->PrivilegeCount,
-                              Privileges->Control,
-                              PreviousMode);
+
+    return SepPrivilegeCheck(Token,
+                             Privileges->Privilege,
+                             Privileges->PrivilegeCount,
+                             Privileges->Control,
+                             PreviousMode);
 }
 
 /*
  * @implemented
  */
-BOOLEAN NTAPI
-SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
-                        IN KPROCESSOR_MODE PreviousMode)
+BOOLEAN
+NTAPI
+SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
+                       IN KPROCESSOR_MODE PreviousMode)
 {
     SECURITY_SUBJECT_CONTEXT SubjectContext;
     PRIVILEGE_SET Priv;
     BOOLEAN Result;
-    
+
     PAGED_CODE();
-    
-    SeCaptureSubjectContext (&SubjectContext);
-    
+
+    SeCaptureSubjectContext(&SubjectContext);
+
     Priv.PrivilegeCount = 1;
     Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
     Priv.Privilege[0].Luid = PrivilegeValue;
     Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
-    
-    Result = SePrivilegeCheck (&Priv,
-                               &SubjectContext,
-                               PreviousMode);
-    
+
+    Result = SePrivilegeCheck(&Priv,
+                              &SubjectContext,
+                              PreviousMode);
+
     if (PreviousMode != KernelMode)
     {
 #if 0
-        SePrivilegedServiceAuditAlarm (0,
-                                       &SubjectContext,
-                                       &PrivilegeValue);
+        SePrivilegedServiceAuditAlarm(0,
+                                      &SubjectContext,
+                                      &PrivilegeValue);
 #endif
     }
-    
-    SeReleaseSubjectContext (&SubjectContext);
-    
+
+    SeReleaseSubjectContext(&SubjectContext);
+
     return Result;
 }
 
 /* SYSTEM CALLS ***************************************************************/
 
-NTSTATUS NTAPI
-NtPrivilegeCheck (IN HANDLE ClientToken,
-                  IN PPRIVILEGE_SET RequiredPrivileges,
-                  OUT PBOOLEAN Result)
+NTSTATUS
+NTAPI
+NtPrivilegeCheck(IN HANDLE ClientToken,
+                 IN PPRIVILEGE_SET RequiredPrivileges,
+                 OUT PBOOLEAN Result)
 {
     PLUID_AND_ATTRIBUTES Privileges;
     PTOKEN Token;
@@ -388,11 +450,11 @@ NtPrivilegeCheck (IN HANDLE ClientToken,
     BOOLEAN CheckResult;
     KPROCESSOR_MODE PreviousMode;
     NTSTATUS Status;
-    
+
     PAGED_CODE();
-    
+
     PreviousMode = KeGetPreviousMode();
-    
+
     /* probe the buffers */
     if (PreviousMode != KernelMode)
     {
@@ -402,10 +464,10 @@ NtPrivilegeCheck (IN HANDLE ClientToken,
                           FIELD_OFFSET(PRIVILEGE_SET,
                                        Privilege),
                           sizeof(ULONG));
-            
+
             PrivilegeCount = RequiredPrivileges->PrivilegeCount;
             PrivilegeControl = RequiredPrivileges->Control;
-            
+
             /* Check PrivilegeCount to avoid an integer overflow! */
             if (FIELD_OFFSET(PRIVILEGE_SET,
                              Privilege[PrivilegeCount]) /
@@ -413,13 +475,13 @@ NtPrivilegeCheck (IN HANDLE ClientToken,
             {
                 _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
             }
-            
+
             /* probe all of the array */
             ProbeForWrite(RequiredPrivileges,
                           FIELD_OFFSET(PRIVILEGE_SET,
                                        Privilege[PrivilegeCount]),
                           sizeof(ULONG));
-            
+
             ProbeForWriteBoolean(Result);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -434,51 +496,51 @@ NtPrivilegeCheck (IN HANDLE ClientToken,
         PrivilegeCount = RequiredPrivileges->PrivilegeCount;
         PrivilegeControl = RequiredPrivileges->Control;
     }
-    
+
     /* reference the token and make sure we're
      not doing an anonymous impersonation */
-    Status = ObReferenceObjectByHandle (ClientToken,
-                                        TOKEN_QUERY,
-                                        SepTokenObjectType,
-                                        PreviousMode,
-                                        (PVOID*)&Token,
-                                        NULL);
+    Status = ObReferenceObjectByHandle(ClientToken,
+                                       TOKEN_QUERY,
+                                       SepTokenObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Token,
+                                       NULL);
     if (!NT_SUCCESS(Status))
     {
         return Status;
     }
-    
+
     if (Token->TokenType == TokenImpersonation &&
         Token->ImpersonationLevel < SecurityIdentification)
     {
-        ObDereferenceObject (Token);
+        ObDereferenceObject(Token);
         return STATUS_BAD_IMPERSONATION_LEVEL;
     }
-    
+
     /* capture the privileges */
-    Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
-                                              PrivilegeCount,
-                                              PreviousMode,
-                                              NULL,
-                                              0,
-                                              PagedPool,
-                                              TRUE,
-                                              &Privileges,
-                                              &Length);
+    Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege,
+                                             PrivilegeCount,
+                                             PreviousMode,
+                                             NULL,
+                                             0,
+                                             PagedPool,
+                                             TRUE,
+                                             &Privileges,
+                                             &Length);
     if (!NT_SUCCESS(Status))
     {
         ObDereferenceObject (Token);
         return Status;
     }
-    
-    CheckResult = SepPrivilegeCheck (Token,
-                                     Privileges,
-                                     PrivilegeCount,
-                                     PrivilegeControl,
-                                     PreviousMode);
-    
-    ObDereferenceObject (Token);
-    
+
+    CheckResult = SepPrivilegeCheck(Token,
+                                    Privileges,
+                                    PrivilegeCount,
+                                    PrivilegeControl,
+                                    PreviousMode);
+
+    ObDereferenceObject(Token);
+
     /* return the array */
     _SEH2_TRY
     {
@@ -493,13 +555,12 @@ NtPrivilegeCheck (IN HANDLE ClientToken,
         Status = _SEH2_GetExceptionCode();
     }
     _SEH2_END;
-    
-    SeReleaseLuidAndAttributesArray (Privileges,
-                                     PreviousMode,
-                                     TRUE);
-    
+
+    SeReleaseLuidAndAttributesArray(Privileges,
+                                    PreviousMode,
+                                    TRUE);
+
     return Status;
 }
 
-
 /* EOF */