Author: ekohl Date: Sat Aug 6 15:07:41 2016 New Revision: 72139
URL: http://svn.reactos.org/svn/reactos?rev=72139&view=rev Log: [LSASRV] Implement LsarAddAccountRigths and fix some bugs along the way: - LsarGetSystemAccessAccount: Fix an uninitialized varable. - LsarOpenAccount, LsarCreateAccount: Make these functions wrappers around the real implementation in LsarpCreateAccount and LsarpOpenAccount. - LsarEnumerateAccountRights: Fix the use of the wrong array index. - LsarAddAccountRights: Implement it. - LsarpLookupPrivilegeValue: Return a pointer to an LUID instead of an NTSTATUS. It is much earier to use it this way. - LsapLookupAccountRightValue: Implement it.
Modified: trunk/reactos/dll/win32/lsasrv/lsarpc.c trunk/reactos/dll/win32/lsasrv/lsasrv.h trunk/reactos/dll/win32/lsasrv/privileges.c
Modified: trunk/reactos/dll/win32/lsasrv/lsarpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/lsasrv/lsarpc.c?r... ============================================================================== --- trunk/reactos/dll/win32/lsasrv/lsarpc.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/lsasrv/lsarpc.c [iso-8859-1] Sat Aug 6 15:07:41 2016 @@ -537,42 +537,24 @@ }
-/* Function 10 */ -NTSTATUS WINAPI LsarCreateAccount( - LSAPR_HANDLE PolicyHandle, +NTSTATUS +LsarpCreateAccount( + PLSA_DB_OBJECT PolicyObject, PRPC_SID AccountSid, ACCESS_MASK DesiredAccess, - LSAPR_HANDLE *AccountHandle) -{ - PLSA_DB_OBJECT PolicyObject; - PLSA_DB_OBJECT AccountObject = NULL; + PLSA_DB_OBJECT *AccountObject) +{ LPWSTR SidString = NULL; PSECURITY_DESCRIPTOR AccountSd = NULL; ULONG AccountSdSize; NTSTATUS Status = STATUS_SUCCESS;
- /* Validate the AccountSid */ - if (!RtlValidSid(AccountSid)) - return STATUS_INVALID_PARAMETER; - - /* Validate the PolicyHandle */ - Status = LsapValidateDbObject(PolicyHandle, - LsaDbPolicyObject, - POLICY_CREATE_ACCOUNT, - &PolicyObject); - if (!NT_SUCCESS(Status)) - { - ERR("LsapValidateDbObject returned 0x%08lx\n", Status); - return Status; - } - /* Create SID string */ if (!ConvertSidToStringSid((PSID)AccountSid, &SidString)) { ERR("ConvertSidToStringSid failed\n"); - Status = STATUS_INVALID_PARAMETER; - goto done; + return STATUS_INVALID_PARAMETER; }
/* Create a security descriptor for the account */ @@ -581,7 +563,7 @@ if (!NT_SUCCESS(Status)) { ERR("LsapCreateAccountSd returned 0x%08lx\n", Status); - return Status; + goto done; }
/* Create the Account object */ @@ -591,7 +573,7 @@ LsaDbAccountObject, DesiredAccess, PolicyObject->Trusted, - &AccountObject); + AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapCreateDbObject failed (Status 0x%08lx)\n", Status); @@ -599,7 +581,7 @@ }
/* Set the Sid attribute */ - Status = LsapSetObjectAttribute(AccountObject, + Status = LsapSetObjectAttribute(*AccountObject, L"Sid", (PVOID)AccountSid, GetLengthSid(AccountSid)); @@ -607,7 +589,7 @@ goto done;
/* Set the SecDesc attribute */ - Status = LsapSetObjectAttribute(AccountObject, + Status = LsapSetObjectAttribute(*AccountObject, L"SecDesc", AccountSd, AccountSdSize); @@ -619,17 +601,47 @@ if (AccountSd != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AccountSd);
- if (!NT_SUCCESS(Status)) - { - if (AccountObject != NULL) - LsapCloseDbObject(AccountObject); - } - else + return Status; +} + + +/* Function 10 */ +NTSTATUS WINAPI LsarCreateAccount( + LSAPR_HANDLE PolicyHandle, + PRPC_SID AccountSid, + ACCESS_MASK DesiredAccess, + LSAPR_HANDLE *AccountHandle) +{ + PLSA_DB_OBJECT PolicyObject; + PLSA_DB_OBJECT AccountObject = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + /* Validate the AccountSid */ + if (!RtlValidSid(AccountSid)) + return STATUS_INVALID_PARAMETER; + + /* Validate the PolicyHandle */ + Status = LsapValidateDbObject(PolicyHandle, + LsaDbPolicyObject, + POLICY_CREATE_ACCOUNT, + &PolicyObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapValidateDbObject returned 0x%08lx\n", Status); + return Status; + } + + + Status = LsarpCreateAccount(PolicyObject, + AccountSid, + DesiredAccess, + &AccountObject); + if (NT_SUCCESS(Status)) { *AccountHandle = (LSAPR_HANDLE)AccountObject; }
- return STATUS_SUCCESS; + return Status; }
@@ -1089,40 +1101,23 @@ }
-/* Function 17 */ -NTSTATUS WINAPI LsarOpenAccount( - LSAPR_HANDLE PolicyHandle, - PRPC_SID AccountSid, - ACCESS_MASK DesiredAccess, - LSAPR_HANDLE *AccountHandle) -{ - PLSA_DB_OBJECT PolicyObject; - PLSA_DB_OBJECT AccountObject = NULL; +static +NTSTATUS +LsarpOpenAccount( + IN PLSA_DB_OBJECT PolicyObject, + IN PRPC_SID AccountSid, + IN ACCESS_MASK DesiredAccess, + OUT PLSA_DB_OBJECT *AccountObject) +{ LPWSTR SidString = NULL; NTSTATUS Status = STATUS_SUCCESS; - - /* Validate the AccountSid */ - if (!RtlValidSid(AccountSid)) - return STATUS_INVALID_PARAMETER; - - /* Validate the PolicyHandle */ - Status = LsapValidateDbObject(PolicyHandle, - LsaDbPolicyObject, - 0, - &PolicyObject); - if (!NT_SUCCESS(Status)) - { - ERR("LsapValidateDbObject returned 0x%08lx\n", Status); - return Status; - }
/* Create SID string */ if (!ConvertSidToStringSid((PSID)AccountSid, &SidString)) { ERR("ConvertSidToStringSid failed\n"); - Status = STATUS_INVALID_PARAMETER; - goto done; + return STATUS_INVALID_PARAMETER; }
/* Create the Account object */ @@ -1132,34 +1127,50 @@ LsaDbAccountObject, DesiredAccess, PolicyObject->Trusted, - &AccountObject); + AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapOpenDbObject failed (Status 0x%08lx)\n", Status); - goto done; - } - - /* Set the Sid attribute */ - Status = LsapSetObjectAttribute(AccountObject, - L"Sid", - (PVOID)AccountSid, - GetLengthSid(AccountSid)); - -done: + } + if (SidString != NULL) LocalFree(SidString);
- if (!NT_SUCCESS(Status)) - { - if (AccountObject != NULL) - LsapCloseDbObject(AccountObject); - } - else - { - *AccountHandle = (LSAPR_HANDLE)AccountObject; - } - return Status; +} + + +/* Function 17 */ +NTSTATUS WINAPI LsarOpenAccount( + LSAPR_HANDLE PolicyHandle, + PRPC_SID AccountSid, + ACCESS_MASK DesiredAccess, + LSAPR_HANDLE *AccountHandle) +{ + PLSA_DB_OBJECT PolicyObject; + NTSTATUS Status; + + /* Validate the AccountSid */ + if (!RtlValidSid(AccountSid)) + return STATUS_INVALID_PARAMETER; + + /* Validate the PolicyHandle */ + Status = LsapValidateDbObject(PolicyHandle, + LsaDbPolicyObject, + 0, + &PolicyObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapValidateDbObject returned 0x%08lx\n", Status); + return Status; + } + + + /* Open the Account object */ + return LsarpOpenAccount(PolicyObject, + AccountSid, + DesiredAccess, + (PLSA_DB_OBJECT *)AccountHandle); }
@@ -1281,7 +1292,7 @@ PrivilegeCount = CurrentPrivileges->PrivilegeCount; TRACE("Current privilege count: %lu\n", PrivilegeCount);
- /* Calculate the number privileges in the combined privilege set */ + /* Calculate the number of privileges in the combined privilege set */ for (i = 0; i < Privileges->PrivilegeCount; i++) { bFound = FALSE; @@ -1623,7 +1634,7 @@ ACCESS_MASK *SystemAccess) { PLSA_DB_OBJECT AccountObject; - ULONG Size; + ULONG Size = sizeof(ACCESS_MASK); NTSTATUS Status;
/* Validate the account handle */ @@ -2045,6 +2056,7 @@ PRPC_UNICODE_STRING Name, PLUID Value) { + PLUID pValue; NTSTATUS Status;
TRACE("LsarLookupPrivilegeValue(%p, %wZ, %p)\n", @@ -2062,10 +2074,13 @@
TRACE("Privilege: %wZ\n", Name);
- Status = LsarpLookupPrivilegeValue(Name, - Value); - - return Status; + pValue = LsarpLookupPrivilegeValue(Name); + if (pValue == NULL) + return STATUS_NO_SUCH_PRIVILEGE; + + RtlCopyLuid(Value, pValue); + + return STATUS_SUCCESS; }
@@ -2194,9 +2209,9 @@ PLSAPR_PRIVILEGE_SET PrivilegeSet = NULL; PRPC_UNICODE_STRING RightsBuffer = NULL; PRPC_UNICODE_STRING PrivilegeString; - ACCESS_MASK SystemAccess; + ACCESS_MASK SystemAccess = 0; ULONG RightsCount = 0; - ULONG RightsIndex; + ULONG Index; ULONG i; NTSTATUS Status;
@@ -2210,25 +2225,25 @@ &AccountHandle); if (!NT_SUCCESS(Status)) { - ERR("LsarOpenAccount returned 0x%08lx\n", Status); + WARN("LsarOpenAccount returned 0x%08lx\n", Status); return Status; }
/* Enumerate the privileges */ Status = LsarEnumeratePrivilegesAccount(AccountHandle, &PrivilegeSet); - if (!NT_SUCCESS(Status)) - { - ERR("LsarEnumeratePrivilegesAccount returned 0x%08lx\n", Status); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + WARN("LsarEnumeratePrivilegesAccount returned 0x%08lx\n", Status); goto done; }
/* Get account rights */ Status = LsarGetSystemAccessAccount(AccountHandle, &SystemAccess); - if (!NT_SUCCESS(Status)) - { - ERR("LsarGetSystemAccessAccount returned 0x%08lx\n", Status); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + WARN("LsarGetSystemAccessAccount returned 0x%08lx\n", Status); goto done; }
@@ -2259,22 +2274,28 @@ }
/* Copy the privileges into the buffer */ - RightsIndex = 0; - for (i = 0; i < PrivilegeSet->PrivilegeCount; i++) - { - PrivilegeString = NULL; - Status = LsarLookupPrivilegeName(PolicyHandle, - (PLUID)&PrivilegeSet->Privilege[i].Luid, - &PrivilegeString); - if (!NT_SUCCESS(Status)) - goto done; - - RightsBuffer[i].Length = PrivilegeString->Length; - RightsBuffer[i].MaximumLength = PrivilegeString->MaximumLength; - RightsBuffer[i].Buffer = PrivilegeString->Buffer; - - MIDL_user_free(PrivilegeString); - RightsIndex++; + Index = 0; + if (PrivilegeSet) + { + for (i = 0; i < PrivilegeSet->PrivilegeCount; i++) + { + PrivilegeString = NULL; + Status = LsarLookupPrivilegeName(PolicyHandle, + (PLUID)&PrivilegeSet->Privilege[i].Luid, + &PrivilegeString); + if (!NT_SUCCESS(Status)) + { + WARN("LsarLookupPrivilegeName returned 0x%08lx\n", Status); + goto done; + } + + RightsBuffer[Index].Length = PrivilegeString->Length; + RightsBuffer[Index].MaximumLength = PrivilegeString->MaximumLength; + RightsBuffer[Index].Buffer = PrivilegeString->Buffer; + + MIDL_user_free(PrivilegeString); + Index++; + } }
/* Copy account rights into the buffer */ @@ -2285,14 +2306,17 @@ Status = LsapLookupAccountRightName(1 << i, &PrivilegeString); if (!NT_SUCCESS(Status)) + { + WARN("LsarLookupAccountRightName returned 0x%08lx\n", Status); goto done; - - RightsBuffer[i].Length = PrivilegeString->Length; - RightsBuffer[i].MaximumLength = PrivilegeString->MaximumLength; - RightsBuffer[i].Buffer = PrivilegeString->Buffer; + } + + RightsBuffer[Index].Length = PrivilegeString->Length; + RightsBuffer[Index].MaximumLength = PrivilegeString->MaximumLength; + RightsBuffer[Index].Buffer = PrivilegeString->Buffer;
MIDL_user_free(PrivilegeString); - RightsIndex++; + Index++; } }
@@ -2304,10 +2328,10 @@ { if (RightsBuffer != NULL) { - for (RightsIndex = 0; RightsIndex < RightsCount; RightsIndex++) + for (Index = 0; Index < RightsCount; Index++) { - if (RightsBuffer[RightsIndex].Buffer != NULL) - MIDL_user_free(RightsBuffer[RightsIndex].Buffer); + if (RightsBuffer[Index].Buffer != NULL) + MIDL_user_free(RightsBuffer[Index].Buffer); }
MIDL_user_free(RightsBuffer); @@ -2329,8 +2353,215 @@ PRPC_SID AccountSid, PLSAPR_USER_RIGHT_SET UserRights) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PLSA_DB_OBJECT PolicyObject; + PLSA_DB_OBJECT AccountObject = NULL; + ULONG ulNewPrivileges = 0, ulNewRights = 0; + ACCESS_MASK SystemAccess = 0; + ULONG Size, Value, i, j; + PPRIVILEGE_SET PrivilegeSet = NULL; + ULONG PrivilegeSetBufferSize = 0; + ULONG PrivilegeCount; + BOOLEAN bFound; + PLUID pLuid; + NTSTATUS Status; + + TRACE("LsarAddAccountRights(%p %p %p)\n", + PolicyHandle, AccountSid, UserRights); + + /* Validate the PolicyHandle */ + Status = LsapValidateDbObject(PolicyHandle, + LsaDbPolicyObject, + POLICY_LOOKUP_NAMES, + &PolicyObject); + if (!NT_SUCCESS(Status)) + { + WARN("LsapValidateDbObject returned 0x%08lx\n", Status); + return Status; + } + + /* Validate the AccountSid */ + if (!RtlValidSid(AccountSid)) + { + Status = STATUS_INVALID_PARAMETER; + goto done; + } + + /* Validate the UserRights */ + if (UserRights == NULL) + { + Status = STATUS_INVALID_PARAMETER; + goto done; + } + + /* Validate the privilege and account right names */ + for (i = 0; i < UserRights->Entries; i++) + { + pLuid = LsarpLookupPrivilegeValue(&UserRights->UserRights[i]); + if (pLuid != NULL) + { + ulNewPrivileges++; + } + else + { + Status = LsapLookupAccountRightValue(&UserRights->UserRights[i], NULL); + if (Status == STATUS_SUCCESS) + ulNewRights++; + else + goto done; + } + } + + TRACE("ulNewPrivileges: %lu\n", ulNewPrivileges); + TRACE("ulNewRights: %lu\n", ulNewRights); + + /* Open the account */ + Status = LsarpOpenAccount(PolicyObject, + AccountSid, + 0, + &AccountObject); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + WARN("LsarpOpenAccount returned 0x%08lx\n", Status); + goto done; + } + else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + /* Create a new account if it does not yet exist */ + Status = LsarpCreateAccount(PolicyObject, + AccountSid, + 0, + &AccountObject); + if (!NT_SUCCESS(Status)) + { + WARN("LsarpCreateAccount returned 0x%08lx\n", Status); + goto done; + } + } + + if (ulNewPrivileges > 0) + { + Size = 0; + + /* Get the size of the Privilgs attribute */ + Status = LsapGetObjectAttribute(AccountObject, + L"Privilgs", + NULL, + &Size); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + goto done; + + /* Calculate the required privilege set buffer size */ + if (Size == 0) + PrivilegeSetBufferSize = sizeof(PRIVILEGE_SET) + + (ulNewPrivileges - 1) * sizeof(LUID_AND_ATTRIBUTES); + else + PrivilegeSetBufferSize = Size + + ulNewPrivileges * sizeof(LUID_AND_ATTRIBUTES); + + /* Allocate the privilege set buffer */ + PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + PrivilegeSetBufferSize); + if (PrivilegeSet == NULL) + return STATUS_NO_MEMORY; + + /* Get the privilege set */ + if (Size != 0) + { + Status = LsapGetObjectAttribute(AccountObject, + L"Privilgs", + PrivilegeSet, + &Size); + if (!NT_SUCCESS(Status)) + { + WARN("LsapGetObjectAttribute() failed (Status 0x%08lx)\n", Status); + goto done; + } + } + + PrivilegeCount = PrivilegeSet->PrivilegeCount; + TRACE("Privilege count: %lu\n", PrivilegeCount); + + for (i = 0; i < UserRights->Entries; i++) + { + pLuid = LsarpLookupPrivilegeValue(&UserRights->UserRights[i]); + if (pLuid == NULL) + continue; + + bFound = FALSE; + for (j = 0; j < PrivilegeSet->PrivilegeCount; j++) + { + if (RtlEqualLuid(&(PrivilegeSet->Privilege[j].Luid), pLuid)) + { + bFound = TRUE; + break; + } + } + + if (bFound == FALSE) + { + /* Copy the new privilege */ + RtlCopyMemory(&(PrivilegeSet->Privilege[PrivilegeSet->PrivilegeCount]), + pLuid, + sizeof(LUID)); + PrivilegeSet->PrivilegeCount++; + } + } + + /* Store the extended privilege set */ + if (PrivilegeCount != PrivilegeSet->PrivilegeCount) + { + Size = sizeof(PRIVILEGE_SET) + + (PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES); + + Status = LsapSetObjectAttribute(AccountObject, + L"Privilgs", + PrivilegeSet, + Size); + if (!NT_SUCCESS(Status)) + { + WARN("LsapSetObjectAttribute() failed (Status 0x%08lx)\n", Status); + goto done; + } + } + } + + if (ulNewRights > 0) + { + Size = 0; + + /* Get the system access flags, if the attribute exists */ + Status = LsapGetObjectAttribute(AccountObject, + L"ActSysAc", + &SystemAccess, + &Size); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + goto done; + + /* Set the new access rights */ + for (i = 0; i < UserRights->Entries; i++) + { + Status = LsapLookupAccountRightValue(&UserRights->UserRights[i], + &Value); + if (Status == STATUS_SUCCESS) + SystemAccess |= Value; + } + + /* Set the system access flags */ + Status = LsapSetObjectAttribute(AccountObject, + L"ActSysAc", + &SystemAccess, + sizeof(ACCESS_MASK)); + } + +done: + if (PrivilegeSet != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet); + + if (AccountObject != NULL) + LsapCloseDbObject(AccountObject); + + return Status; }
Modified: trunk/reactos/dll/win32/lsasrv/lsasrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/lsasrv/lsasrv.h?r... ============================================================================== --- trunk/reactos/dll/win32/lsasrv/lsasrv.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/lsasrv/lsasrv.h [iso-8859-1] Sat Aug 6 15:07:41 2016 @@ -315,9 +315,9 @@ PRPC_UNICODE_STRING *DisplayName, USHORT *LanguageReturned);
-NTSTATUS -LsarpLookupPrivilegeValue(PRPC_UNICODE_STRING Name, - PLUID Value); +PLUID +LsarpLookupPrivilegeValue( + IN PRPC_UNICODE_STRING Name);
NTSTATUS LsarpEnumeratePrivileges(DWORD *EnumerationContext, @@ -327,6 +327,11 @@ NTSTATUS LsapLookupAccountRightName(ULONG RightValue, PRPC_UNICODE_STRING *Name); + +NTSTATUS +LsapLookupAccountRightValue( + IN PRPC_UNICODE_STRING Name, + OUT PULONG Value OPTIONAL);
/* registry.h */ NTSTATUS
Modified: trunk/reactos/dll/win32/lsasrv/privileges.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/lsasrv/privileges... ============================================================================== --- trunk/reactos/dll/win32/lsasrv/privileges.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/lsasrv/privileges.c [iso-8859-1] Sat Aug 6 15:07:41 2016 @@ -152,25 +152,23 @@ return STATUS_SUCCESS; }
-NTSTATUS -LsarpLookupPrivilegeValue(PRPC_UNICODE_STRING Name, - PLUID Value) + +PLUID +LsarpLookupPrivilegeValue( + IN PRPC_UNICODE_STRING Name) { ULONG Priv;
if (Name->Length == 0 || Name->Buffer == NULL) - return STATUS_NO_SUCH_PRIVILEGE; + return NULL;
for (Priv = 0; Priv < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); Priv++) { if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0) - { - *Value = WellKnownPrivileges[Priv].Luid; - return STATUS_SUCCESS; - } - } - - return STATUS_NO_SUCH_PRIVILEGE; + return (PLUID)&(WellKnownPrivileges[Priv].Luid); + } + + return NULL; }
@@ -307,4 +305,28 @@ return STATUS_NO_SUCH_PRIVILEGE; }
+ +NTSTATUS +LsapLookupAccountRightValue( + IN PRPC_UNICODE_STRING Name, + OUT PULONG Value OPTIONAL) +{ + ULONG i; + + if (Name->Length == 0 || Name->Buffer == NULL) + return STATUS_NO_SUCH_PRIVILEGE; + + for (i = 0; i < sizeof(WellKnownRights) / sizeof(WellKnownRights[0]); i++) + { + if (_wcsicmp(Name->Buffer, WellKnownRights[i].Name) == 0) + { + if (Value != NULL) + *Value = WellKnownRights[i].Flag; + return STATUS_SUCCESS; + } + } + + return STATUS_NO_SUCH_PRIVILEGE; +} + /* EOF */