From b9272a3090ff0b4e302348284409ea34a5705da5 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 12 Jan 2013 21:32:26 +0000 Subject: [PATCH] [SAMSRV] - SamrAddMemberToGroup: Add the group membership to the user object. - SamrRemoveMemberFromGroup: Remove the group membership from the user object. svn path=/trunk/; revision=58161 --- reactos/dll/win32/samsrv/CMakeLists.txt | 1 + reactos/dll/win32/samsrv/samrpc.c | 61 +++++++- reactos/dll/win32/samsrv/samsrv.h | 18 +++ reactos/dll/win32/samsrv/user.c | 188 ++++++++++++++++++++++++ 4 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 reactos/dll/win32/samsrv/user.c diff --git a/reactos/dll/win32/samsrv/CMakeLists.txt b/reactos/dll/win32/samsrv/CMakeLists.txt index 81969d98f72..f242a36a4a5 100644 --- a/reactos/dll/win32/samsrv/CMakeLists.txt +++ b/reactos/dll/win32/samsrv/CMakeLists.txt @@ -15,6 +15,7 @@ list(APPEND SOURCE samrpc.c samsrv.c setup.c + user.c samsrv.rc ${CMAKE_CURRENT_BINARY_DIR}/samsrv_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/samsrv.def diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index 6c522d6d4c2..33db795d9e3 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -3931,6 +3931,7 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle, IN unsigned long Attributes) { PSAM_DB_OBJECT GroupObject; + PSAM_DB_OBJECT UserObject = NULL; NTSTATUS Status; TRACE("(%p %lu %lx)\n", @@ -3944,10 +3945,38 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle, if (!NT_SUCCESS(Status)) return Status; - /* FIXME: Add group membership to the user object */ + /* Open the user object in the same domain */ + Status = SampOpenUserObject(GroupObject->ParentObject, + MemberId, + 0, + &UserObject); + if (!NT_SUCCESS(Status)) + { + ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); + goto done; + } + /* Add group membership to the user object */ + Status = SampAddGroupMembershipToUser(UserObject, + GroupObject->RelativeId, + Attributes); + if (!NT_SUCCESS(Status)) + { + ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Add the member to the group object */ Status = SampAddMemberToGroup(GroupObject, MemberId); + if (!NT_SUCCESS(Status)) + { + ERR("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status); + } + +done: + if (UserObject) + SampCloseDbObject(UserObject); return Status; } @@ -3970,6 +3999,7 @@ SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle, IN unsigned long MemberId) { PSAM_DB_OBJECT GroupObject; + PSAM_DB_OBJECT UserObject = NULL; NTSTATUS Status; TRACE("(%p %lu)\n", @@ -3983,10 +4013,37 @@ SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle, if (!NT_SUCCESS(Status)) return Status; - /* FIXME: Remove group membership from the user object */ + /* Open the user object in the same domain */ + Status = SampOpenUserObject(GroupObject->ParentObject, + MemberId, + 0, + &UserObject); + if (!NT_SUCCESS(Status)) + { + ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); + goto done; + } + /* Remove group membership from the user object */ + Status = SampRemoveGroupMembershipFromUser(UserObject, + GroupObject->RelativeId); + if (!NT_SUCCESS(Status)) + { + ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Remove the member from the group object */ Status = SampRemoveMemberFromGroup(GroupObject, MemberId); + if (!NT_SUCCESS(Status)) + { + ERR("SampRemoveMemberFromGroup() failed (Status 0x%08lx)\n", Status); + } + +done: + if (UserObject) + SampCloseDbObject(UserObject); return Status; } diff --git a/reactos/dll/win32/samsrv/samsrv.h b/reactos/dll/win32/samsrv/samsrv.h index b25f69d8462..eab66474d3e 100644 --- a/reactos/dll/win32/samsrv/samsrv.h +++ b/reactos/dll/win32/samsrv/samsrv.h @@ -261,4 +261,22 @@ VOID SampStartRpcServer(VOID); BOOL SampIsSetupRunning(VOID); BOOL SampInitializeSAM(VOID); + +/* user.c */ + +NTSTATUS +SampOpenUserObject(IN PSAM_DB_OBJECT DomainObject, + IN ULONG UserId, + IN ACCESS_MASK DesiredAccess, + OUT PSAM_DB_OBJECT *UserObject); + +NTSTATUS +SampAddGroupMembershipToUser(PSAM_DB_OBJECT UserObject, + ULONG GroupId, + ULONG Attributes); + +NTSTATUS +SampRemoveGroupMembershipFromUser(PSAM_DB_OBJECT UserObject, + ULONG GroupId); + /* EOF */ diff --git a/reactos/dll/win32/samsrv/user.c b/reactos/dll/win32/samsrv/user.c new file mode 100644 index 00000000000..be7042ee4bf --- /dev/null +++ b/reactos/dll/win32/samsrv/user.c @@ -0,0 +1,188 @@ +/* + * PROJECT: Local Security Authority Server DLL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/samsrv/user.c + * PURPOSE: User specific helper functions + * COPYRIGHT: Copyright 2013 Eric Kohl + */ + +/* INCLUDES ****************************************************************/ + +#include "samsrv.h" + +WINE_DEFAULT_DEBUG_CHANNEL(samsrv); + + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS +SampOpenUserObject(IN PSAM_DB_OBJECT DomainObject, + IN ULONG UserId, + IN ACCESS_MASK DesiredAccess, + OUT PSAM_DB_OBJECT *UserObject) +{ + WCHAR szRid[9]; + + TRACE("(%p %lu %lx %p)\n", + DomainObject, UserId, DesiredAccess, UserObject); + + /* Convert the RID into a string (hex) */ + swprintf(szRid, L"%08lX", UserId); + + /* Create the user object */ + return SampOpenDbObject(DomainObject, + L"Users", + szRid, + UserId, + SamDbUserObject, + DesiredAccess, + UserObject); +} + + +NTSTATUS +SampAddGroupMembershipToUser(IN PSAM_DB_OBJECT UserObject, + IN ULONG GroupId, + IN ULONG Attributes) +{ + PGROUP_MEMBERSHIP GroupsBuffer = NULL; + ULONG GroupsCount = 0; + ULONG Length = 0; + ULONG i; + NTSTATUS Status; + + TRACE("(%p %lu %lx)\n", + UserObject, GroupId, Attributes); + + Status = SampGetObjectAttribute(UserObject, + L"Groups", + NULL, + NULL, + &Length); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + goto done; + + GroupsBuffer = midl_user_allocate(Length + sizeof(GROUP_MEMBERSHIP)); + if (GroupsBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + Status = SampGetObjectAttribute(UserObject, + L"Groups", + NULL, + GroupsBuffer, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + GroupsCount = Length / sizeof(GROUP_MEMBERSHIP); + } + + for (i = 0; i < GroupsCount; i++) + { + if (GroupsBuffer[i].RelativeId == GroupId) + { + Status = STATUS_MEMBER_IN_GROUP; + goto done; + } + } + + GroupsBuffer[GroupsCount].RelativeId = GroupId; + GroupsBuffer[GroupsCount].Attributes = Attributes; + Length += sizeof(GROUP_MEMBERSHIP); + + Status = SampSetObjectAttribute(UserObject, + L"Groups", + REG_BINARY, + GroupsBuffer, + Length); + +done: + if (GroupsBuffer != NULL) + midl_user_free(GroupsBuffer); + + return Status; +} + + +NTSTATUS +SampRemoveGroupMembershipFromUser(IN PSAM_DB_OBJECT UserObject, + IN ULONG GroupId) +{ + PGROUP_MEMBERSHIP GroupsBuffer = NULL; + ULONG GroupsCount = 0; + ULONG Length = 0; + ULONG i; + NTSTATUS Status; + + TRACE("(%p %lu)\n", + UserObject, GroupId); + + Status = SampGetObjectAttribute(UserObject, + L"Groups", + NULL, + NULL, + &Length); + + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + return STATUS_MEMBER_NOT_IN_GROUP; + + if (!NT_SUCCESS(Status)) + return Status; + + GroupsBuffer = midl_user_allocate(Length); + if (GroupsBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = SampGetObjectAttribute(UserObject, + L"Groups", + NULL, + GroupsBuffer, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + Status = STATUS_MEMBER_NOT_IN_GROUP; + + GroupsCount = Length / sizeof(GROUP_MEMBERSHIP); + for (i = 0; i < GroupsCount; i++) + { + if (GroupsBuffer[i].RelativeId == GroupId) + { + Length -= sizeof(GROUP_MEMBERSHIP); + Status = STATUS_SUCCESS; + break; + } + + if (Status == STATUS_SUCCESS && i < GroupsCount - 1) + { + CopyMemory(&GroupsBuffer[i], + &GroupsBuffer[i + 1], + sizeof(GROUP_MEMBERSHIP)); + } + } + + if (!NT_SUCCESS(Status)) + goto done; + + Status = SampSetObjectAttribute(UserObject, + L"Groups", + REG_BINARY, + GroupsBuffer, + Length); + +done: + if (GroupsBuffer != NULL) + midl_user_free(GroupsBuffer); + + return Status; +} + +/* EOF */