From 44cc31028bf8dcad0289ac73d0dd23638c6cf162 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 23 Jun 2012 10:23:08 +0000 Subject: [PATCH] [SAMLIB] - Implement SamGetAliasMembership, SamQueryInformationAlias and SamSetInformationAlias. - Add stub SamLookupNamesInDomain. [SAMSRV] - Implement SamrGetAliasMembership and SamrSetInformationAlias. - Add stub for SamrQueryInformationAlias. - SamrCreateAliasInDomain and SAM setup code: Set the description attribute for aliases. svn path=/trunk/; revision=56785 --- reactos/dll/win32/samlib/samlib.c | 120 ++++++++++++- reactos/dll/win32/samlib/samlib.spec | 8 +- reactos/dll/win32/samsrv/samrpc.c | 257 ++++++++++++++++++++++++++- reactos/dll/win32/samsrv/setup.c | 126 +++++++++++++ reactos/include/ddk/ntsam.h | 53 ++++++ 5 files changed, 552 insertions(+), 12 deletions(-) diff --git a/reactos/dll/win32/samlib/samlib.c b/reactos/dll/win32/samlib/samlib.c index 401c8a49aaf..7cb6c553316 100644 --- a/reactos/dll/win32/samlib/samlib.c +++ b/reactos/dll/win32/samlib/samlib.c @@ -351,6 +351,57 @@ SamFreeMemory(IN PVOID Buffer) } +NTSTATUS +NTAPI +SamGetAliasMembership(IN SAM_HANDLE DomainHandle, + IN ULONG PassedCount, + IN PSID *Sids, + OUT PULONG MembershipCount, + OUT PULONG *Aliases) +{ + SAMPR_PSID_ARRAY SidArray; + SAMPR_ULONG_ARRAY Membership; + NTSTATUS Status; + + TRACE("SamAliasMembership(%p %ul %p %p %p)\n", + DomainHandle, PassedCount, Sids, MembershipCount, Aliases); + + if (Sids == NULL || + MembershipCount == NULL || + Aliases == NULL) + return STATUS_INVALID_PARAMETER; + + Membership.Element = NULL; + + RpcTryExcept + { + SidArray.Count = PassedCount; + SidArray.Sids = (PSAMPR_SID_INFORMATION)Sids; + + Status = SamrGetAliasMembership((SAMPR_HANDLE)DomainHandle, + &SidArray, + &Membership); + if (NT_SUCCESS(Status)) + { + *MembershipCount = Membership.Count; + *Aliases = Membership.Element; + } + else + { + if (Membership.Element != NULL) + midl_user_free(Membership.Element); + } + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamGetMembersInAlias(IN SAM_HANDLE AliasHandle, @@ -379,7 +430,7 @@ SamGetMembersInAlias(IN SAM_HANDLE AliasHandle, if (NT_SUCCESS(Status)) { *MemberCount = SidArray.Count; - *MemberIds = (PSID *)(SidArray.Sids); + *MemberIds = (PSID *)SidArray.Sids; } } @@ -420,6 +471,19 @@ SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle, } +NTSTATUS +NTAPI +SamLookupNamesInDomain(IN SAM_HANDLE DomainHandle, + IN ULONG Count, + IN PUNICODE_STRING Names, + OUT PULONG *RelativeIds, + OUT PSID_NAME_USE *Use) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + + NTSTATUS NTAPI SamOpenAlias(IN SAM_HANDLE DomainHandle, @@ -507,6 +571,33 @@ SamOpenUser(IN SAM_HANDLE DomainHandle, } +NTSTATUS +NTAPI +SamQueryInformationAlias(IN SAM_HANDLE AliasHandle, + IN ALIAS_INFORMATION_CLASS AliasInformationClass, + OUT PVOID *Buffer) +{ + NTSTATUS Status; + + TRACE("SamQueryInformationAlias(%p %lu %p)\n", + AliasHandle, AliasInformationClass, Buffer); + + RpcTryExcept + { + Status = SamrQueryInformationAlias((SAMPR_HANDLE)AliasHandle, + AliasInformationClass, + (PSAMPR_ALIAS_INFO_BUFFER *)Buffer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamQueryInformationDomain(IN SAM_HANDLE DomainHandle, @@ -561,6 +652,33 @@ SamQueryInformationUser(IN SAM_HANDLE UserHandle, } +NTSTATUS +NTAPI +SamSetInformationAlias(IN SAM_HANDLE AliasHandle, + IN ALIAS_INFORMATION_CLASS AliasInformationClass, + IN PVOID Buffer) +{ + NTSTATUS Status; + + TRACE("SamSetInformationAlias(%p %lu %p)\n", + AliasHandle, AliasInformationClass, Buffer); + + RpcTryExcept + { + Status = SamrSetInformationAlias((SAMPR_HANDLE)AliasHandle, + AliasInformationClass, + Buffer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamSetInformationDomain(IN SAM_HANDLE DomainHandle, diff --git a/reactos/dll/win32/samlib/samlib.spec b/reactos/dll/win32/samlib/samlib.spec index ee96c0b6a74..4810b439fd0 100644 --- a/reactos/dll/win32/samlib/samlib.spec +++ b/reactos/dll/win32/samlib/samlib.spec @@ -19,7 +19,7 @@ @ stub SamEnumerateGroupsInDomain @ stub SamEnumerateUsersInDomain @ stdcall SamFreeMemory(ptr) -@ stub SamGetAliasMembership +@ stdcall SamGetAliasMembership(ptr long ptr ptr ptr) @ stub SamGetCompatibilityMode @ stub SamGetDisplayEnumerationIndex @ stub SamGetGroupsForUser @@ -27,13 +27,13 @@ @ stub SamGetMembersInGroup @ stdcall SamLookupDomainInSamServer(ptr ptr ptr) @ stub SamLookupIdsInDomain -@ stub SamLookupNamesInDomain +@ stdcall SamLookupNamesInDomain(ptr long ptr ptr ptr) @ stdcall SamOpenAlias(ptr long long ptr) @ stdcall SamOpenDomain(ptr long ptr ptr) @ stub SamOpenGroup @ stdcall SamOpenUser(ptr long long ptr) @ stub SamQueryDisplayInformation -@ stub SamQueryInformationAlias +@ stdcall SamQueryInformationAlias(ptr long ptr) @ stdcall SamQueryInformationDomain(ptr long ptr) @ stub SamQueryInformationGroup @ stdcall SamQueryInformationUser(ptr long ptr) @@ -43,7 +43,7 @@ @ stub SamRemoveMemberFromGroup @ stub SamRemoveMultipleMembersFromAlias @ stub SamRidToSid -@ stub SamSetInformationAlias +@ stdcall SamSetInformationAlias(ptr long ptr) @ stdcall SamSetInformationDomain(ptr long ptr) @ stub SamSetInformationGroup @ stdcall SamSetInformationUser(ptr long ptr) diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index 661e6849449..2e2822cebbf 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -853,6 +853,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle, { PSAM_DB_OBJECT DomainObject; PSAM_DB_OBJECT AliasObject; + UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L""); ULONG ulSize; ULONG ulRid; WCHAR szRid[9]; @@ -941,7 +942,17 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle, return Status; } - /* FIXME: Set default alias attributes */ + /* Set the Description attribute */ + Status = SampSetObjectAttribute(AliasObject, + L"Description", + REG_SZ, + EmptyString.Buffer, + EmptyString.MaximumLength); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } if (NT_SUCCESS(Status)) { @@ -1198,8 +1209,142 @@ SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle, IN PSAMPR_PSID_ARRAY SidArray, OUT PSAMPR_ULONG_ARRAY Membership) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT DomainObject; + HANDLE AliasesKeyHandle = NULL; + HANDLE MembersKeyHandle = NULL; + HANDLE MemberKeyHandle = NULL; + LPWSTR MemberSidString = NULL; + PULONG RidArray = NULL; + ULONG MaxSidCount = 0; + ULONG ValueCount; + ULONG DataLength; + ULONG i, j; + NTSTATUS Status; + + TRACE("SamrGetAliasMembership(%p %p %p)\n", + DomainHandle, SidArray, Membership); + + /* Validate the domain handle */ + Status = SampValidateDbObject(DomainHandle, + SamDbDomainObject, + DOMAIN_LOOKUP, + &DomainObject); + if (!NT_SUCCESS(Status)) + return Status; + + Status = SampRegOpenKey(DomainObject->KeyHandle, + L"Aliases", + KEY_READ, + &AliasesKeyHandle); + TRACE("SampRegOpenKey returned %08lX\n", Status); + if (!NT_SUCCESS(Status)) + goto done; + + Status = SampRegOpenKey(AliasesKeyHandle, + L"Members", + KEY_READ, + &MembersKeyHandle); + TRACE("SampRegOpenKey returned %08lX\n", Status); + if (!NT_SUCCESS(Status)) + goto done; + + for (i = 0; i < SidArray->Count; i++) + { + ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString); +TRACE("Open %S\n", MemberSidString); + + Status = SampRegOpenKey(MembersKeyHandle, + MemberSidString, + KEY_READ, + &MemberKeyHandle); + TRACE("SampRegOpenKey returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + Status = SampRegQueryKeyInfo(MemberKeyHandle, + NULL, + &ValueCount); + if (NT_SUCCESS(Status)) + { + TRACE("Found %lu values\n", ValueCount); + MaxSidCount += ValueCount; + } + + + NtClose(MemberKeyHandle); + } + + LocalFree(MemberSidString); + } + + TRACE("Maximum sid count: %lu\n", MaxSidCount); + RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG)); + if (RidArray == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + for (i = 0; i < SidArray->Count; i++) + { + ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString); +TRACE("Open %S\n", MemberSidString); + + Status = SampRegOpenKey(MembersKeyHandle, + MemberSidString, + KEY_READ, + &MemberKeyHandle); + TRACE("SampRegOpenKey returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + Status = SampRegQueryKeyInfo(MemberKeyHandle, + NULL, + &ValueCount); + if (NT_SUCCESS(Status)) + { + TRACE("Found %lu values\n", ValueCount); + + for (j = 0; j < ValueCount; j++) + { + DataLength = sizeof(ULONG); + Status = SampRegEnumerateValue(MemberKeyHandle, + j, + NULL, + NULL, + NULL, + (PVOID)&RidArray[j], + &DataLength); + } + } + + NtClose(MemberKeyHandle); + } + + LocalFree(MemberSidString); + } + + +done: + if (NT_SUCCESS(Status)) + { + Membership->Count = MaxSidCount; + Membership->Element = RidArray; + } + else + { + if (RidArray != NULL) + midl_user_free(RidArray); + } + + if (MembersKeyHandle != NULL) + NtClose(MembersKeyHandle); + + if (MembersKeyHandle != NULL) + NtClose(MembersKeyHandle); + + if (AliasesKeyHandle != NULL) + NtClose(AliasesKeyHandle); + + return Status; } /* Function 17 */ @@ -1368,8 +1513,76 @@ SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle, IN ALIAS_INFORMATION_CLASS AliasInformationClass, OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT AliasObject; + NTSTATUS Status; + + TRACE("SamrQueryInformationAlias(%p %lu %p)\n", + AliasHandle, AliasInformationClass, Buffer); + + /* Validate the alias handle */ + Status = SampValidateDbObject(AliasHandle, + SamDbAliasObject, + ALIAS_READ_INFORMATION, + &AliasObject); + if (!NT_SUCCESS(Status)) + return Status; + + switch (AliasInformationClass) + { +#if 0 + case AliasGeneralInformation: + Status = SampQueryAliasGeneral(AliasObject, + &Buffer->General); + break; + + case AliasNameInformation: + Status = SampQueryAliasName(AliasObject, + &Buffer->Name); + break; + + case AliasAdminCommentInformation: + Status = SampQueryAliasAdminComment(AliasObject, + &Buffer->AdminComment); + break; +#endif + + default: + Status = STATUS_INVALID_INFO_CLASS; + break; + } + + return Status; +} + + +static NTSTATUS +SampSetAliasName(PSAM_DB_OBJECT AliasObject, + PSAMPR_ALIAS_NAME_INFORMATION AliasNameInfo) +{ + NTSTATUS Status; + + Status = SampSetObjectAttribute(AliasObject, + L"Name", + REG_SZ, + AliasNameInfo->Name.Buffer, + AliasNameInfo->Name.Length + sizeof(WCHAR)); + + return Status; +} + +static NTSTATUS +SampSetAliasAdminComment(PSAM_DB_OBJECT AliasObject, + PSAMPR_ALIAS_ADM_COMMENT_INFORMATION AliasAdminCommentInfo) +{ + NTSTATUS Status; + + Status = SampSetObjectAttribute(AliasObject, + L"Description", + REG_SZ, + AliasAdminCommentInfo->AdminComment.Buffer, + AliasAdminCommentInfo->AdminComment.Length + sizeof(WCHAR)); + + return Status; } /* Function 29 */ @@ -1379,8 +1592,38 @@ SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle, IN ALIAS_INFORMATION_CLASS AliasInformationClass, IN PSAMPR_ALIAS_INFO_BUFFER Buffer) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT AliasObject; + NTSTATUS Status; + + TRACE("SamrSetInformationAlias(%p %lu %p)\n", + AliasHandle, AliasInformationClass, Buffer); + + /* Validate the alias handle */ + Status = SampValidateDbObject(AliasHandle, + SamDbAliasObject, + ALIAS_WRITE_ACCOUNT, + &AliasObject); + if (!NT_SUCCESS(Status)) + return Status; + + switch (AliasInformationClass) + { + case AliasNameInformation: + Status = SampSetAliasName(AliasObject, + &Buffer->Name); + break; + + case AliasAdminCommentInformation: + Status = SampSetAliasAdminComment(AliasObject, + &Buffer->AdminComment); + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + break; + } + + return Status; } /* Function 30 */ diff --git a/reactos/dll/win32/samsrv/setup.c b/reactos/dll/win32/samsrv/setup.c index cf9ec290683..635fc9ceefc 100644 --- a/reactos/dll/win32/samsrv/setup.c +++ b/reactos/dll/win32/samsrv/setup.c @@ -58,9 +58,110 @@ SampIsSetupRunning(VOID) } +static PSID +AppendRidToSid(PSID SrcSid, + ULONG Rid) +{ + ULONG Rids[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + UCHAR RidCount; + PSID DstSid; + ULONG i; + + RidCount = *RtlSubAuthorityCountSid(SrcSid); + if (RidCount >= 8) + return NULL; + + for (i = 0; i < RidCount; i++) + Rids[i] = *RtlSubAuthoritySid(SrcSid, i); + + Rids[RidCount] = Rid; + RidCount++; + + RtlAllocateAndInitializeSid(RtlIdentifierAuthoritySid(SrcSid), + RidCount, + Rids[0], + Rids[1], + Rids[2], + Rids[3], + Rids[4], + Rids[5], + Rids[6], + Rids[7], + &DstSid); + + return DstSid; +} + + +static BOOL +SampAddMemberToAlias(HKEY hDomainKey, + ULONG AliasId, + PSID MemberSid) +{ + DWORD dwDisposition; + LPWSTR MemberSidString = NULL; + WCHAR szKeyName[256]; + HKEY hMembersKey; + + ConvertSidToStringSidW(MemberSid, &MemberSidString); + + swprintf(szKeyName, L"Aliases\\%08lX\\Members", AliasId); + + if (!RegCreateKeyExW(hDomainKey, + szKeyName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hMembersKey, + &dwDisposition)) + { + RegSetValueEx(hMembersKey, + MemberSidString, + 0, + REG_BINARY, + (LPVOID)MemberSid, + RtlLengthSid(MemberSid)); + + RegCloseKey(hMembersKey); + } + + swprintf(szKeyName, L"Aliases\\Members\\%s", MemberSidString); + + if (!RegCreateKeyExW(hDomainKey, + szKeyName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hMembersKey, + &dwDisposition)) + { + swprintf(szKeyName, L"%08lX", AliasId); + + RegSetValueEx(hMembersKey, + szKeyName, + 0, + REG_BINARY, + (LPVOID)MemberSid, + RtlLengthSid(MemberSid)); + + RegCloseKey(hMembersKey); + } + + if (MemberSidString != NULL) + LocalFree(MemberSidString); + + return TRUE; +} + + static BOOL SampCreateAliasAccount(HKEY hDomainKey, LPCWSTR lpAccountName, + LPCWSTR lpDescription, ULONG ulRelativeId) { DWORD dwDisposition; @@ -87,6 +188,13 @@ SampCreateAliasAccount(HKEY hDomainKey, (LPVOID)lpAccountName, (wcslen(lpAccountName) + 1) * sizeof(WCHAR)); + RegSetValueEx(hAccountKey, + L"Description", + 0, + REG_SZ, + (LPVOID)lpDescription, + (wcslen(lpDescription) + 1) * sizeof(WCHAR)); + RegCloseKey(hAccountKey); } @@ -332,6 +440,7 @@ SampInitializeSAM(VOID) HKEY hDomainKey = NULL; PSID pBuiltinSid = NULL; BOOL bResult = TRUE; + PSID pSid; NTSTATUS Status; TRACE("SampInitializeSAM() called\n"); @@ -398,20 +507,37 @@ SampInitializeSAM(VOID) { SampCreateAliasAccount(hDomainKey, L"Administrators", + L"", DOMAIN_ALIAS_RID_ADMINS); SampCreateAliasAccount(hDomainKey, L"Users", + L"", DOMAIN_ALIAS_RID_USERS); SampCreateAliasAccount(hDomainKey, L"Guests", + L"", DOMAIN_ALIAS_RID_GUESTS); SampCreateAliasAccount(hDomainKey, L"Power Users", + L"", DOMAIN_ALIAS_RID_POWER_USERS); + + pSid = AppendRidToSid(AccountDomainInfo->DomainSid, + DOMAIN_USER_RID_ADMIN); + if (pSid != NULL) + { + SampAddMemberToAlias(hDomainKey, + DOMAIN_ALIAS_RID_ADMINS, + pSid); + + RtlFreeHeap(RtlGetProcessHeap(), 0, pSid); + } + + RegCloseKey(hDomainKey); } diff --git a/reactos/include/ddk/ntsam.h b/reactos/include/ddk/ntsam.h index 83b537b23f5..2bb363e9360 100644 --- a/reactos/include/ddk/ntsam.h +++ b/reactos/include/ddk/ntsam.h @@ -58,6 +58,31 @@ typedef struct _SAM_SID_ENUMERATION UNICODE_STRING Name; } SAM_SID_ENUMERATION, *PSAM_SID_ENUMERATION; +typedef enum _ALIAS_INFORMATION_CLASS +{ + AliasGeneralInformation = 1, + AliasNameInformation, + AliasAdminCommentInformation +} ALIAS_INFORMATION_CLASS, *PALIAS_INFORMATION_CLASS; + +typedef struct _SAMPR_ALIAS_GENERAL_INFORMATION +{ + UNICODE_STRING Name; + ULONG MemberCount; + UNICODE_STRING AdminComment; +} SAMPR_ALIAS_GENERAL_INFORMATION, *PSAMPR_ALIAS_GENERAL_INFORMATION; + +typedef struct _SAMPR_ALIAS_NAME_INFORMATION +{ + UNICODE_STRING Name; +} SAMPR_ALIAS_NAME_INFORMATION, *PSAMPR_ALIAS_NAME_INFORMATION; + +typedef struct _SAMPR_ALIAS_ADM_COMMENT_INFORMATION +{ + UNICODE_STRING AdminComment; +} SAMPR_ALIAS_ADM_COMMENT_INFORMATION, *PSAMPR_ALIAS_ADM_COMMENT_INFORMATION; + + typedef enum _DOMAIN_INFORMATION_CLASS { DomainPasswordInformation = 1, @@ -172,6 +197,14 @@ NTSTATUS NTAPI SamFreeMemory(IN PVOID Buffer); +NTSTATUS +NTAPI +SamGetAliasMembership(IN SAM_HANDLE DomainHandle, + IN ULONG PassedCount, + IN PSID *Sids, + OUT PULONG MembershipCount, + OUT PULONG *Aliases); + NTSTATUS NTAPI SamGetMembersInAlias(IN SAM_HANDLE AliasHandle, @@ -184,6 +217,14 @@ SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle, IN PUNICODE_STRING Name, OUT PSID *DomainId); +NTSTATUS +NTAPI +SamLookupNamesInDomain(IN SAM_HANDLE DomainHandle, + IN ULONG Count, + IN PUNICODE_STRING Names, + OUT PULONG *RelativeIds, + OUT PSID_NAME_USE *Use); + NTSTATUS NTAPI SamOpenAlias(IN SAM_HANDLE DomainHandle, @@ -205,6 +246,12 @@ SamOpenUser(IN SAM_HANDLE DomainHandle, IN ULONG UserId, OUT PSAM_HANDLE UserHandle); +NTSTATUS +NTAPI +SamQueryInformationAlias(IN SAM_HANDLE AliasHandle, + IN ALIAS_INFORMATION_CLASS AliasInformationClass, + OUT PVOID *Buffer); + NTSTATUS NTAPI SamQueryInformationDomain(IN SAM_HANDLE DomainHandle, @@ -217,6 +264,12 @@ SamQueryInformationUser(IN SAM_HANDLE UserHandle, IN USER_INFORMATION_CLASS UserInformationClass, OUT PVOID *Buffer); +NTSTATUS +NTAPI +SamSetInformationAlias(IN SAM_HANDLE AliasHandle, + IN ALIAS_INFORMATION_CLASS AliasInformationClass, + IN PVOID Buffer); + NTSTATUS NTAPI SamSetInformationDomain(IN SAM_HANDLE DomainHandle,