[SAMSRV]
authorEric Kohl <eric.kohl@reactos.org>
Sat, 26 Oct 2013 09:09:31 +0000 (09:09 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sat, 26 Oct 2013 09:09:31 +0000 (09:09 +0000)
Create and set a security descriptor for new user account objects.

svn path=/trunk/; revision=60750

reactos/dll/win32/samsrv/domain.c
reactos/dll/win32/samsrv/samrpc.c
reactos/dll/win32/samsrv/samsrv.h
reactos/dll/win32/samsrv/security.c
reactos/dll/win32/samsrv/setup.c

index 956c418..bb9c7fc 100644 (file)
@@ -303,4 +303,55 @@ SampRemoveMemberFromAllAliases(IN PSAM_DB_OBJECT DomainObject,
     return Status;
 }
 
+
+NTSTATUS
+SampCreateAccountSid(IN PSAM_DB_OBJECT DomainObject,
+                     IN ULONG ulRelativeId,
+                     IN OUT PSID *AccountSid)
+{
+    PSID DomainSid = NULL;
+    ULONG Length = 0;
+    NTSTATUS Status;
+
+    Status = SampGetObjectAttribute(DomainObject,
+                                    L"SID",
+                                    NULL,
+                                    NULL,
+                                    &Length);
+    if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
+    {
+        TRACE("Status 0x%08lx\n", Status);
+        goto done;
+    }
+
+    TRACE("Length: %lu\n", Length);
+
+    DomainSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
+    if (DomainSid == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
+
+    Status = SampGetObjectAttribute(DomainObject,
+                                    L"SID",
+                                    NULL,
+                                    DomainSid,
+                                    &Length);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("Status 0x%08lx\n", Status);
+        goto done;
+    }
+
+    *AccountSid = AppendRidToSid(DomainSid,
+                                 ulRelativeId);
+
+done:
+    if (DomainSid != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
+
+    return Status;
+}
+
 /* EOF */
index 3b42f57..65420f9 100644 (file)
@@ -2174,6 +2174,9 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     ULONG ulSize;
     ULONG ulRid;
     WCHAR szRid[9];
+    PSECURITY_DESCRIPTOR Sd = NULL;
+    ULONG SdSize = 0;
+    PSID UserSid = NULL;
     NTSTATUS Status;
 
     TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
@@ -2239,6 +2242,28 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     ulRid = FixedDomainData.NextRid;
     FixedDomainData.NextRid++;
 
+    TRACE("RID: %lx\n", ulRid);
+
+    /* Create the user SID */
+    Status = SampCreateAccountSid(DomainObject,
+                                  ulRid,
+                                  &UserSid);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Create the security descriptor */
+    Status = SampCreateUserSD(UserSid,
+                              &Sd,
+                              &SdSize);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
     /* Store the fixed domain attributes */
     Status = SampSetObjectAttribute(DomainObject,
                            L"F",
@@ -2251,8 +2276,6 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
         goto done;
     }
 
-    TRACE("RID: %lx\n", ulRid);
-
     /* Convert the RID into a string (hex) */
     swprintf(szRid, L"%08lX", ulRid);
 
@@ -2505,7 +2528,17 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
         goto done;
     }
 
-    /* FIXME: Set SecDesc attribute*/
+    /* Set the SecDesc attribute*/
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"SecDesc",
+                                    REG_BINARY,
+                                    Sd,
+                                    SdSize);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        goto done;
+    }
 
     if (NT_SUCCESS(Status))
     {
@@ -2514,6 +2547,12 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     }
 
 done:
+    if (Sd != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
+
+    if (UserSid != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
+
     RtlReleaseResource(&SampResource);
 
     TRACE("returns with status 0x%08lx\n", Status);
@@ -6871,7 +6910,6 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
 
     if (InfoBuffer->All.WhichFields & USER_ALL_SECURITYDESCRIPTOR)
     {
-#if 0
         Length = 0;
         SampGetObjectAttribute(UserObject,
                                L"SecDesc",
@@ -6898,7 +6936,6 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             if (!NT_SUCCESS(Status))
                 goto done;
         }
-#endif
     }
 
     *Buffer = InfoBuffer;
@@ -7670,13 +7707,11 @@ SampSetUserAll(PSAM_DB_OBJECT UserObject,
 
     if (WhichFields & USER_ALL_SECURITYDESCRIPTOR)
     {
-#if 0
         Status = SampSetObjectAttribute(UserObject,
                                         L"SecDesc",
                                         REG_BINARY,
                                         Buffer->All.SecurityDescriptor.SecurityDescriptor,
                                         Buffer->All.SecurityDescriptor.Length);
-#endif
     }
 
     if (WriteFixedData == TRUE)
@@ -8523,6 +8558,9 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     ULONG ulSize;
     ULONG ulRid;
     WCHAR szRid[9];
+    PSECURITY_DESCRIPTOR Sd = NULL;
+    ULONG SdSize = 0;
+    PSID UserSid = NULL;
     NTSTATUS Status;
 
     TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
@@ -8596,6 +8634,28 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     ulRid = FixedDomainData.NextRid;
     FixedDomainData.NextRid++;
 
+    TRACE("RID: %lx\n", ulRid);
+
+    /* Create the user SID */
+    Status = SampCreateAccountSid(DomainObject,
+                                  ulRid,
+                                  &UserSid);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Create the security descriptor */
+    Status = SampCreateUserSD(UserSid,
+                              &Sd,
+                              &SdSize);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
     /* Store the fixed domain attributes */
     Status = SampSetObjectAttribute(DomainObject,
                                     L"F",
@@ -8608,8 +8668,6 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
         goto done;
     }
 
-    TRACE("RID: %lx\n", ulRid);
-
     /* Convert the RID into a string (hex) */
     swprintf(szRid, L"%08lX", ulRid);
 
@@ -8861,7 +8919,17 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
         goto done;
     }
 
-    /* FIXME: Set SecDesc attribute*/
+    /* Set the SecDesc attribute*/
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"SecDesc",
+                                    REG_BINARY,
+                                    Sd,
+                                    SdSize);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        goto done;
+    }
 
     if (NT_SUCCESS(Status))
     {
@@ -8871,6 +8939,12 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     }
 
 done:
+    if (Sd != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
+
+    if (UserSid != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
+
     RtlReleaseResource(&SampResource);
 
     TRACE("returns with status 0x%08lx\n", Status);
index 91427a0..c7767d7 100644 (file)
@@ -230,6 +230,10 @@ NTSTATUS
 SampRemoveMemberFromAllAliases(IN PSAM_DB_OBJECT DomainObject,
                                IN PRPC_SID MemberSid);
 
+NTSTATUS
+SampCreateAccountSid(IN PSAM_DB_OBJECT DomainObject,
+                     IN ULONG ulRelativeId,
+                     IN OUT PSID *AccountSid);
 
 /* group.h */
 
@@ -336,6 +340,10 @@ NTSTATUS
 SampCreateGroupSD(OUT PSECURITY_DESCRIPTOR *GroupSd,
                   OUT PULONG Size);
 
+NTSTATUS
+SampCreateUserSD(IN PSID UserSid,
+                 OUT PSECURITY_DESCRIPTOR *UserSd,
+                 OUT PULONG Size);
 
 /* setup.c */
 
index dab82ad..e1410a8 100644 (file)
@@ -1433,4 +1433,276 @@ done:
     return Status;
 }
 
+
+NTSTATUS
+SampCreateUserSD(IN PSID UserSid,
+                 OUT PSECURITY_DESCRIPTOR *UserSd,
+                 OUT PULONG Size)
+{
+    PSECURITY_DESCRIPTOR AbsSD = NULL;
+    PSECURITY_DESCRIPTOR RelSD = NULL;
+    PSID EveryoneSid = NULL;
+    PSID AnonymousSid = NULL;
+    PSID AdministratorsSid = NULL;
+    PACL Dacl = NULL;
+    PACL Sacl = NULL;
+    ULONG DaclSize;
+    ULONG SaclSize;
+    ULONG RelSDSize = 0;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+
+    /* Create the Everyone SID */
+    Status = RtlAllocateAndInitializeSid(&WorldAuthority,
+                                         1,
+                                         SECURITY_WORLD_RID,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         &EveryoneSid);
+    ASSERT(NT_SUCCESS(Status));
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Create the Anonymous SID */
+    Status = RtlAllocateAndInitializeSid(&NtAuthority,
+                                         1,
+                                         SECURITY_ANONYMOUS_LOGON_RID,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         &AnonymousSid);
+    ASSERT(NT_SUCCESS(Status));
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Create the Administrators SID */
+    Status = RtlAllocateAndInitializeSid(&NtAuthority,
+                                         2,
+                                         SECURITY_BUILTIN_DOMAIN_RID,
+                                         DOMAIN_ALIAS_RID_ADMINS,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         0,
+                                         &AdministratorsSid);
+    ASSERT(NT_SUCCESS(Status));
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Allocate a buffer for the absolute SD */
+    AbsSD = RtlAllocateHeap(RtlGetProcessHeap(),
+                            HEAP_ZERO_MEMORY,
+                            sizeof(SECURITY_DESCRIPTOR));
+    if (AbsSD == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    ASSERT(Status == STATUS_SUCCESS);
+        goto done;
+    }
+
+    /* Create the absolute SD */
+    Status = RtlCreateSecurityDescriptor(AbsSD,
+                                         SECURITY_DESCRIPTOR_REVISION);
+    ASSERT(NT_SUCCESS(Status));
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* allocate and create the DACL */
+    DaclSize = sizeof(ACL) + 
+               3 * sizeof(ACE) +
+               RtlLengthSid(EveryoneSid) +
+               RtlLengthSid(AdministratorsSid) +
+               RtlLengthSid(UserSid);
+
+    Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
+                           HEAP_ZERO_MEMORY,
+                           DaclSize);
+    if (Dacl == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    ASSERT(Status == STATUS_SUCCESS);
+        goto done;
+    }
+
+    Status = RtlCreateAcl(Dacl,
+                          DaclSize,
+                          ACL_REVISION);
+    ASSERT(NT_SUCCESS(Status));
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    Status = RtlAddAccessAllowedAce(Dacl,
+                                    ACL_REVISION,
+                                    READ_CONTROL | USER_READ_GROUP_INFORMATION | USER_LIST_GROUPS |
+                                    USER_CHANGE_PASSWORD | USER_READ_ACCOUNT | USER_READ_LOGON |
+                                    USER_READ_PREFERENCES | USER_READ_GENERAL,
+                                    EveryoneSid);
+    ASSERT(NT_SUCCESS(Status));
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    Status = RtlAddAccessAllowedAce(Dacl,
+                                    ACL_REVISION,
+                                    USER_ALL_ACCESS,
+                                    AdministratorsSid);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    Status = RtlAddAccessAllowedAce(Dacl,
+                                    ACL_REVISION,
+                                    READ_CONTROL | USER_CHANGE_PASSWORD | USER_WRITE_PREFERENCES,
+                                    UserSid);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Set the DACL */
+    Status = RtlSetDaclSecurityDescriptor(AbsSD,
+                                          TRUE,
+                                          Dacl,
+                                          FALSE);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* allocate and create the SACL */
+    SaclSize = sizeof(ACL) + 
+               2 * sizeof(ACE) +
+               RtlLengthSid(EveryoneSid) +
+               RtlLengthSid(AnonymousSid);
+
+    Sacl = RtlAllocateHeap(RtlGetProcessHeap(),
+                           HEAP_ZERO_MEMORY,
+                           DaclSize);
+    if (Sacl == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    ASSERT(Status == STATUS_SUCCESS);
+        goto done;
+    }
+
+    Status = RtlCreateAcl(Sacl,
+                          SaclSize,
+                          ACL_REVISION);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    Status = RtlAddAuditAccessAce(Sacl,
+                                  ACL_REVISION,
+                                  ACCESS_SYSTEM_SECURITY | WRITE_DAC | DELETE |
+                                  USER_CHANGE_PASSWORD | USER_WRITE_PREFERENCES,
+                                  EveryoneSid,
+                                  TRUE,
+                                  TRUE);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    Status = RtlAddAuditAccessAce(Sacl,
+                                  ACL_REVISION,
+                                  STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+                                  AnonymousSid,
+                                  TRUE,
+                                  TRUE);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Set the SACL */
+    Status = RtlSetSaclSecurityDescriptor(AbsSD,
+                                          TRUE,
+                                          Sacl,
+                                          FALSE);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Set the owner SID */
+    Status = RtlSetOwnerSecurityDescriptor(AbsSD,
+                                           AdministratorsSid,
+                                           FALSE);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Set the group SID */
+    Status = RtlSetGroupSecurityDescriptor(AbsSD,
+                                           AdministratorsSid,
+                                           FALSE);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Get the reqired buffer size for the self-relative SD */
+    Status = RtlAbsoluteToSelfRelativeSD(AbsSD,
+                                         NULL,
+                                         &RelSDSize);
+    if (Status != STATUS_BUFFER_TOO_SMALL)
+        goto done;
+
+    /* Allocate a buffer for the self-relative SD */
+    RelSD = RtlAllocateHeap(RtlGetProcessHeap(),
+                            HEAP_ZERO_MEMORY,
+                            RelSDSize);
+    if (RelSD == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    ASSERT(Status == STATUS_SUCCESS);
+        goto done;
+    }
+
+    /* Convert the absolute SD to self-relative format */
+    Status = RtlAbsoluteToSelfRelativeSD(AbsSD,
+                                         RelSD,
+                                         &RelSDSize);
+    if (Status == STATUS_BUFFER_TOO_SMALL)
+    {
+    ASSERT(Status == STATUS_SUCCESS);
+        goto done;
+    }
+
+    *UserSd = RelSD;
+    *Size = RelSDSize;
+
+done:
+    if (!NT_SUCCESS(Status))
+    {
+        if (RelSD != NULL)
+            RtlFreeHeap(RtlGetProcessHeap(), 0, RelSD);
+    }
+
+    if (EveryoneSid != NULL)
+        RtlFreeSid(EveryoneSid);
+
+    if (AnonymousSid != NULL)
+        RtlFreeSid(AnonymousSid);
+
+    if (AdministratorsSid != NULL)
+        RtlFreeSid(AdministratorsSid);
+
+    if (Dacl != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
+
+    if (Sacl != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Sacl);
+
+    if (AbsSD != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, AbsSD);
+
+    return Status;
+}
+
 /* EOF */
index ad758ca..10cef65 100644 (file)
@@ -359,6 +359,7 @@ NTSTATUS
 SampSetupCreateUserAccount(HANDLE hDomainKey,
                            LPCWSTR lpAccountName,
                            LPCWSTR lpComment,
+                           PSID lpDomainSid,
                            ULONG ulRelativeId,
                            ULONG UserAccountControl)
 {
@@ -369,8 +370,21 @@ SampSetupCreateUserAccount(HANDLE hDomainKey,
     WCHAR szAccountKeyName[32];
     HANDLE hAccountKey = NULL;
     HANDLE hNamesKey = NULL;
+    PSECURITY_DESCRIPTOR Sd = NULL;
+    ULONG SdSize = 0;
+    PSID UserSid = NULL;
     NTSTATUS Status;
 
+    UserSid = AppendRidToSid(lpDomainSid,
+                             ulRelativeId);
+
+    /* Create the security descriptor */
+    Status = SampCreateUserSD(UserSid,
+                              &Sd,
+                              &SdSize);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
     /* Initialize fixed user data */
     FixedUserData.Version = 1;
     FixedUserData.Reserved = 0;
@@ -558,9 +572,14 @@ SampSetupCreateUserAccount(HANDLE hDomainKey,
     if (!NT_SUCCESS(Status))
         goto done;
 
-
-    /* FIXME: Set SecDesc attribute*/
-
+    /* Set the SecDesc attribute*/
+    Status = SampRegSetValue(hAccountKey,
+                             L"SecDesc",
+                             REG_BINARY,
+                             Sd,
+                             SdSize);
+    if (!NT_SUCCESS(Status))
+        goto done;
 
     Status = SampRegOpenKey(hDomainKey,
                             L"Users\\Names",
@@ -578,6 +597,12 @@ SampSetupCreateUserAccount(HANDLE hDomainKey,
 done:
     SampRegCloseKey(&hNamesKey);
 
+    if (Sd != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
+
+    if (UserSid != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
+
     if (hAccountKey != NULL)
     {
         SampRegCloseKey(&hAccountKey);
@@ -1057,6 +1082,7 @@ SampInitializeSAM(VOID)
         SampSetupCreateUserAccount(hAccountDomainKey,
                                    szName,
                                    szComment,
+                                   AccountDomainInfo->DomainSid,
                                    DOMAIN_USER_RID_ADMIN,
                                    USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
 
@@ -1070,6 +1096,7 @@ SampInitializeSAM(VOID)
         SampSetupCreateUserAccount(hAccountDomainKey,
                                    szName,
                                    szComment,
+                                   AccountDomainInfo->DomainSid,
                                    DOMAIN_USER_RID_GUEST,
                                    USER_ACCOUNT_DISABLED | USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);