[LSASRV][MSV1_0]
[reactos.git] / reactos / dll / win32 / lsasrv / authpackage.c
index 9922031..4e5f2ad 100644 (file)
@@ -6,12 +6,8 @@
  * COPYRIGHT:   Copyright 2013 Eric Kohl
  */
 
-/* INCLUDES ****************************************************************/
-
 #include "lsasrv.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(lsasrv);
-
 typedef enum _LSA_TOKEN_INFORMATION_TYPE
 {
     LsaTokenInformationNull,
@@ -551,9 +547,9 @@ LsapCopyLocalGroups(
     PTOKEN_GROUPS LocalGroups = NULL;
     ULONG SidHeaderLength = 0;
     PSID SidHeader = NULL;
-    PSID Sid;
+    PSID SrcSid, DstSid;
     ULONG SidLength;
-    ULONG CopiedSids = 0;
+    ULONG AllocatedSids = 0;
     ULONG i;
     NTSTATUS Status;
 
@@ -589,8 +585,10 @@ LsapCopyLocalGroups(
 
     for (i = 0; i < ClientGroupsCount; i++)
     {
+        SrcSid = LocalGroups->Groups[i].Sid;
+
         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
-                                     LocalGroups->Groups[i].Sid,
+                                     SrcSid,
                                      SidHeader,
                                      SidHeaderLength,
                                      NULL);
@@ -600,28 +598,28 @@ LsapCopyLocalGroups(
         SidLength = RtlLengthSid(SidHeader);
         TRACE("Sid %lu: Length %lu\n", i, SidLength);
 
-        Sid = RtlAllocateHeap(RtlGetProcessHeap(),
-                              HEAP_ZERO_MEMORY,
-                              SidLength);
-        if (SidHeader == NULL)
+        DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
+                                 HEAP_ZERO_MEMORY,
+                                 SidLength);
+        if (DstSid == NULL)
         {
             Status = STATUS_INSUFFICIENT_RESOURCES;
             goto done;
         }
 
         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
-                                     LocalGroups->Groups[i].Sid,
-                                     Sid,
+                                     SrcSid,
+                                     DstSid,
                                      SidLength,
                                      NULL);
         if (!NT_SUCCESS(Status))
         {
-            RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, DstSid);
             goto done;
         }
 
-        LocalGroups->Groups[i].Sid = Sid;
-        CopiedSids++;
+        LocalGroups->Groups[i].Sid = DstSid;
+        AllocatedSids++;
     }
 
     *TokenGroups = LocalGroups;
@@ -634,7 +632,7 @@ done:
     {
         if (LocalGroups != NULL)
         {
-            for (i = 0; i < CopiedSids; i++)
+            for (i = 0; i < AllocatedSids; i++)
                 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
 
             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
@@ -645,6 +643,177 @@ done:
 }
 
 
+static
+NTSTATUS
+LsapAddLocalGroups(
+    IN PVOID TokenInformation,
+    IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
+    IN PTOKEN_GROUPS LocalGroups)
+{
+    PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
+    PTOKEN_GROUPS Groups;
+    ULONG Length;
+    ULONG i;
+    ULONG j;
+
+    if (LocalGroups == NULL || LocalGroups->GroupCount == 0)
+        return STATUS_SUCCESS;
+
+    if (TokenInformationType == LsaTokenInformationV1)
+    {
+        TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
+
+        if (TokenInfo1->Groups != NULL)
+        {
+            Length = sizeof(TOKEN_GROUPS) +
+                     (LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
+
+            Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
+            if (Groups == NULL)
+            {
+                ERR("Group buffer allocation failed!\n");
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            Groups->GroupCount = LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount;
+
+            for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
+            {
+                Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
+                Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
+            }
+
+            for (j = 0; j < LocalGroups->GroupCount; i++, j++)
+            {
+                Groups->Groups[i].Sid = LocalGroups->Groups[j].Sid;
+                Groups->Groups[i].Attributes = LocalGroups->Groups[j].Attributes;
+                LocalGroups->Groups[j].Sid = NULL;
+            }
+
+            RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
+
+            TokenInfo1->Groups = Groups;
+        }
+        else
+        {
+            Length = sizeof(TOKEN_GROUPS) +
+                     (LocalGroups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
+
+            Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
+            if (Groups == NULL)
+            {
+                ERR("Group buffer allocation failed!\n");
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            Groups->GroupCount = LocalGroups->GroupCount;
+
+            for (i = 0; i < LocalGroups->GroupCount; i++)
+            {
+                Groups->Groups[i].Sid = LocalGroups->Groups[i].Sid;
+                Groups->Groups[i].Attributes = LocalGroups->Groups[i].Attributes;
+            }
+
+            TokenInfo1->Groups = Groups;
+        }
+    }
+    else
+    {
+        FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+LsapSetTokenOwner(
+    IN PVOID TokenInformation,
+    IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
+{
+    PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
+    PSID OwnerSid = NULL;
+    ULONG i, Length;
+
+    if (TokenInformationType == LsaTokenInformationV1)
+    {
+        TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
+
+        if (TokenInfo1->Owner.Owner != NULL)
+            return STATUS_SUCCESS;
+
+        OwnerSid = TokenInfo1->User.User.Sid;
+        for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
+        {
+            if (EqualSid(TokenInfo1->Groups->Groups[i].Sid, LsapAdministratorsSid))
+            {
+                OwnerSid = LsapAdministratorsSid;
+                break;
+            }
+        }
+
+        Length = RtlLengthSid(OwnerSid);
+        TokenInfo1->Owner.Owner = DispatchTable.AllocateLsaHeap(Length);
+        if (TokenInfo1->Owner.Owner == NULL)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        RtlCopyMemory(TokenInfo1->Owner.Owner,
+                      OwnerSid,
+                      Length);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+LsapAddTokenDefaultDacl(
+    IN PVOID TokenInformation,
+    IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
+{
+    PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
+    PACL Dacl = NULL;
+    ULONG Length;
+
+    if (TokenInformationType == LsaTokenInformationV1)
+    {
+        TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
+
+        if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
+            return STATUS_SUCCESS;
+
+        Length = sizeof(ACL) +
+                 (2 * sizeof(ACCESS_ALLOWED_ACE)) +
+                 RtlLengthSid(TokenInfo1->Owner.Owner) +
+                 RtlLengthSid(LsapLocalSystemSid);
+
+        Dacl = DispatchTable.AllocateLsaHeap(Length);
+        if (Dacl == NULL)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        RtlCreateAcl(Dacl, Length, ACL_REVISION);
+
+        RtlAddAccessAllowedAce(Dacl,
+                               ACL_REVISION,
+                               GENERIC_ALL,
+                               TokenInfo1->Owner.Owner);
+
+        /* SID: S-1-5-18 */
+        RtlAddAccessAllowedAce(Dacl,
+                               ACL_REVISION,
+                               GENERIC_ALL,
+                               LsapLocalSystemSid);
+
+        TokenInfo1->DefaultDacl.DefaultDacl = Dacl;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 LsapLogonUser(PLSA_API_MSG RequestMsg,
               PLSAP_LOGON_CONTEXT LogonContext)
@@ -673,7 +842,7 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
     Package = LsapGetAuthenticationPackage(PackageId);
     if (Package == NULL)
     {
-        TRACE("LsapGetAuthenticationPackage() failed to find a package\n");
+        ERR("LsapGetAuthenticationPackage() failed to find a package\n");
         return STATUS_NO_SUCH_PACKAGE;
     }
 
@@ -685,7 +854,7 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
                                         RequestMsg->LogonUser.Request.AuthenticationInformationLength);
         if (LocalAuthInfo == NULL)
         {
-            TRACE("RtlAllocateHeap() failed\n");
+            ERR("RtlAllocateHeap() failed\n");
             return STATUS_INSUFFICIENT_RESOURCES;
         }
 
@@ -697,7 +866,7 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
                                      NULL);
         if (!NT_SUCCESS(Status))
         {
-            TRACE("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
+            ERR("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
             return Status;
         }
@@ -710,7 +879,10 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
                                      RequestMsg->LogonUser.Request.LocalGroupsCount,
                                      &LocalGroups);
         if (!NT_SUCCESS(Status))
+        {
+            ERR("LsapCopyLocalGroups failed (Status 0x%08lx)\n", Status);
             goto done;
+        }
 
         TRACE("GroupCount: %lu\n", LocalGroups->GroupCount);
     }
@@ -770,7 +942,36 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
 
     if (!NT_SUCCESS(Status))
     {
-        TRACE("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
+        ERR("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    if (LocalGroups->GroupCount > 0)
+    {
+        /* Add local groups to the token information */
+        Status = LsapAddLocalGroups(TokenInformation,
+                                    TokenInformationType,
+                                    LocalGroups);
+        if (!NT_SUCCESS(Status))
+        {
+            ERR("LsapAddLocalGroupsToTokenInfo() failed (Status 0x%08lx)\n", Status);
+            goto done;
+        }
+    }
+
+    Status = LsapSetTokenOwner(TokenInformation,
+                               TokenInformationType);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapSetTokenOwner() failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    Status = LsapAddTokenDefaultDacl(TokenInformation,
+                                     TokenInformationType);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapAddTokenDefaultDacl() failed (Status 0x%08lx)\n", Status);
         goto done;
     }
 
@@ -806,7 +1007,7 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
                                &RequestMsg->LogonUser.Request.SourceContext);
         if (!NT_SUCCESS(Status))
         {
-            TRACE("NtCreateToken failed (Status 0x%08lx)\n", Status);
+            ERR("NtCreateToken failed (Status 0x%08lx)\n", Status);
             goto done;
         }
     }
@@ -827,20 +1028,18 @@ LsapLogonUser(PLSA_API_MSG RequestMsg,
                                DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE);
     if (!NT_SUCCESS(Status))
     {
-        TRACE("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
+        ERR("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
         goto done;
     }
 
     TokenHandle = NULL;
 
-#if 0
     Status = LsapSetLogonSessionData(&RequestMsg->LogonUser.Reply.LogonId);
     if (!NT_SUCCESS(Status))
     {
-        TRACE("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
+        ERR("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
         goto done;
     }
-#endif
 
 done:
     if (!NT_SUCCESS(Status))
@@ -853,7 +1052,10 @@ done:
     if (LocalGroups != NULL)
     {
         for (i = 0; i < LocalGroups->GroupCount; i++)
-            RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
+        {
+            if (LocalGroups->Groups[i].Sid != NULL)
+                RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
+        }
 
         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
     }