From c2691edfa191d0c2ea6172f1b8817f1f3354b5d2 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 26 Oct 2013 09:09:31 +0000 Subject: [PATCH] [SAMSRV] Create and set a security descriptor for new user account objects. svn path=/trunk/; revision=60750 --- reactos/dll/win32/samsrv/domain.c | 51 ++++++ reactos/dll/win32/samsrv/samrpc.c | 94 +++++++++- reactos/dll/win32/samsrv/samsrv.h | 8 + reactos/dll/win32/samsrv/security.c | 272 ++++++++++++++++++++++++++++ reactos/dll/win32/samsrv/setup.c | 33 +++- 5 files changed, 445 insertions(+), 13 deletions(-) diff --git a/reactos/dll/win32/samsrv/domain.c b/reactos/dll/win32/samsrv/domain.c index 956c4181f49..bb9c7fc544a 100644 --- a/reactos/dll/win32/samsrv/domain.c +++ b/reactos/dll/win32/samsrv/domain.c @@ -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 */ diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index 3b42f573f4d..65420f9623c 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -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); diff --git a/reactos/dll/win32/samsrv/samsrv.h b/reactos/dll/win32/samsrv/samsrv.h index 91427a0d523..c7767d7f261 100644 --- a/reactos/dll/win32/samsrv/samsrv.h +++ b/reactos/dll/win32/samsrv/samsrv.h @@ -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 */ diff --git a/reactos/dll/win32/samsrv/security.c b/reactos/dll/win32/samsrv/security.c index dab82ad12b9..e1410a8ba2c 100644 --- a/reactos/dll/win32/samsrv/security.c +++ b/reactos/dll/win32/samsrv/security.c @@ -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 */ diff --git a/reactos/dll/win32/samsrv/setup.c b/reactos/dll/win32/samsrv/setup.c index ad758cadca7..10cef65b466 100644 --- a/reactos/dll/win32/samsrv/setup.c +++ b/reactos/dll/win32/samsrv/setup.c @@ -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);