diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index dc12d216c31..3b42f573f4d 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -1770,6 +1770,8 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle, SAM_GROUP_FIXED_DATA FixedGroupData; PSAM_DB_OBJECT DomainObject; PSAM_DB_OBJECT GroupObject; + PSECURITY_DESCRIPTOR Sd = NULL; + ULONG SdSize = 0; ULONG ulSize; ULONG ulRid; WCHAR szRid[9]; @@ -1814,6 +1816,15 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle, goto done; } + /* Create the security descriptor */ + Status = SampCreateGroupSD(&Sd, + &SdSize); + if (!NT_SUCCESS(Status)) + { + TRACE("SampCreateGroupSD failed (Status 0x%08lx)\n", Status); + goto done; + } + /* Get the fixed domain attributes */ ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); Status = SampGetObjectAttribute(DomainObject, @@ -1910,6 +1921,18 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle, goto done; } + /* Set the SecDesc attribute*/ + Status = SampSetObjectAttribute(GroupObject, + L"SecDesc", + REG_BINARY, + Sd, + SdSize); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + goto done; + } + if (NT_SUCCESS(Status)) { *GroupHandle = (SAMPR_HANDLE)GroupObject; @@ -1917,6 +1940,9 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle, } done: + if (Sd != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); + RtlReleaseResource(&SampResource); TRACE("returns with status 0x%08lx\n", Status); @@ -2848,7 +2874,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle, goto done; } - /* Set SecDesc attribute*/ + /* Set the SecDesc attribute*/ Status = SampSetObjectAttribute(AliasObject, L"SecDesc", REG_BINARY, diff --git a/reactos/dll/win32/samsrv/samsrv.h b/reactos/dll/win32/samsrv/samsrv.h index fcc5c62a1da..91427a0d523 100644 --- a/reactos/dll/win32/samsrv/samsrv.h +++ b/reactos/dll/win32/samsrv/samsrv.h @@ -332,6 +332,10 @@ NTSTATUS SampCreateAliasSD(OUT PSECURITY_DESCRIPTOR *AliasSd, OUT PULONG Size); +NTSTATUS +SampCreateGroupSD(OUT PSECURITY_DESCRIPTOR *GroupSd, + OUT PULONG Size); + /* setup.c */ diff --git a/reactos/dll/win32/samsrv/security.c b/reactos/dll/win32/samsrv/security.c index f18fdf3beee..dab82ad12b9 100644 --- a/reactos/dll/win32/samsrv/security.c +++ b/reactos/dll/win32/samsrv/security.c @@ -1147,4 +1147,290 @@ done: } +NTSTATUS +SampCreateGroupSD(OUT PSECURITY_DESCRIPTOR *GroupSd, + OUT PULONG Size) +{ + PSECURITY_DESCRIPTOR AbsSD = NULL; + PSECURITY_DESCRIPTOR RelSD = NULL; + PSID EveryoneSid = NULL; + PSID AnonymousSid = NULL; + PSID AdministratorsSid = NULL; + PSID AccountOperatorsSid = 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; + + /* Create the Account Operators SID */ + Status = RtlAllocateAndInitializeSid(&NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ACCOUNT_OPS, + 0, + 0, + 0, + 0, + 0, + 0, + &AccountOperatorsSid); + 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(AccountOperatorsSid); + + 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 | GROUP_LIST_MEMBERS | GROUP_READ_INFORMATION, + EveryoneSid); + ASSERT(NT_SUCCESS(Status)); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + GROUP_ALL_ACCESS, + AdministratorsSid); + ASSERT(Status == STATUS_SUCCESS); + if (!NT_SUCCESS(Status)) + goto done; + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + GROUP_ALL_ACCESS, + AccountOperatorsSid); + 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 | + GROUP_REMOVE_MEMBER | GROUP_ADD_MEMBER | + GROUP_WRITE_ACCOUNT, + 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; + } + + *GroupSd = 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 1f1b531809c..ad758cadca7 100644 --- a/reactos/dll/win32/samsrv/setup.c +++ b/reactos/dll/win32/samsrv/setup.c @@ -264,6 +264,8 @@ SampSetupCreateGroupAccount(HANDLE hDomainKey, WCHAR szAccountKeyName[32]; HANDLE hAccountKey = NULL; HANDLE hNamesKey = NULL; + PSECURITY_DESCRIPTOR Sd = NULL; + ULONG SdSize = 0; NTSTATUS Status; /* Initialize fixed group data */ @@ -305,6 +307,21 @@ SampSetupCreateGroupAccount(HANDLE hDomainKey, if (!NT_SUCCESS(Status)) goto done; + /* Create the security descriptor */ + Status = SampCreateGroupSD(&Sd, + &SdSize); + if (!NT_SUCCESS(Status)) + goto done; + + /* Set the SecDesc attribute*/ + Status = SampRegSetValue(hAccountKey, + L"SecDesc", + REG_BINARY, + Sd, + SdSize); + if (!NT_SUCCESS(Status)) + goto done; + Status = SampRegOpenKey(hDomainKey, L"Groups\\Names", KEY_ALL_ACCESS, @@ -321,6 +338,9 @@ SampSetupCreateGroupAccount(HANDLE hDomainKey, done: SampRegCloseKey(&hNamesKey); + if (Sd != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); + if (hAccountKey != NULL) { SampRegCloseKey(&hAccountKey);