From 3c5e5eaf1b2a0228fb4030dfefc50b17e88ed55d Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 3 Jan 2016 09:22:14 +0000 Subject: [PATCH] [LSASRV] Implement LsarStorePrivateData and LsarRetrievePrivateData. [ADVAPI32] Implement LsaRetrievePrivateData and LsaStorePrivateData. Encryption of secrets (aka private data) is NOT implemented yet! svn path=/trunk/; revision=70479 --- reactos/dll/win32/advapi32/sec/lsa.c | 109 +++++++++++- reactos/dll/win32/lsasrv/lsarpc.c | 240 ++++++++++++++++++++++++++- 2 files changed, 338 insertions(+), 11 deletions(-) diff --git a/reactos/dll/win32/advapi32/sec/lsa.c b/reactos/dll/win32/advapi32/sec/lsa.c index c277dd9a110..da480b10e8a 100644 --- a/reactos/dll/win32/advapi32/sec/lsa.c +++ b/reactos/dll/win32/advapi32/sec/lsa.c @@ -1400,7 +1400,7 @@ LsaQueryInformationPolicy(IN LSA_HANDLE PolicyHandle, /* - * @unimplemented + * @implemented */ NTSTATUS WINAPI @@ -1683,7 +1683,7 @@ LsaRemovePrivilegesFromAccount(IN LSA_HANDLE AccountHandle, /* - * @unimplemented + * @implemented */ NTSTATUS WINAPI @@ -1691,9 +1691,64 @@ LsaRetrievePrivateData(IN LSA_HANDLE PolicyHandle, IN PLSA_UNICODE_STRING KeyName, OUT PLSA_UNICODE_STRING *PrivateData) { - FIXME("LsaRetrievePrivateData(%p %p %p) stub\n", + PLSAPR_CR_CIPHER_VALUE EncryptedData = NULL; + PLSA_UNICODE_STRING DecryptedData = NULL; + SIZE_T BufferSize; + NTSTATUS Status; + + TRACE("LsaRetrievePrivateData(%p %p %p)\n", PolicyHandle, KeyName, PrivateData); - return STATUS_OBJECT_NAME_NOT_FOUND; + + RpcTryExcept + { + Status = LsarRetrievePrivateData((LSAPR_HANDLE)PolicyHandle, + (PRPC_UNICODE_STRING)KeyName, + &EncryptedData); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + + if (EncryptedData == NULL) + { + *PrivateData = NULL; + } + else + { + BufferSize = sizeof(LSA_UNICODE_STRING) + EncryptedData->MaximumLength; + DecryptedData = midl_user_allocate(BufferSize); + if (DecryptedData == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + DecryptedData->Length = (USHORT)EncryptedData->Length; + DecryptedData->MaximumLength = (USHORT)EncryptedData->MaximumLength; + DecryptedData->Buffer = (PWSTR)(DecryptedData + 1); + RtlCopyMemory(DecryptedData->Buffer, + EncryptedData->Buffer, + EncryptedData->Length); + + *PrivateData = DecryptedData; + } + +done: + if (!NT_SUCCESS(Status)) + { + if (DecryptedData != NULL) + midl_user_free(DecryptedData); + + *PrivateData = NULL; + } + + if (EncryptedData != NULL) + midl_user_free(EncryptedData); + + return Status; } @@ -2024,7 +2079,7 @@ LsaSetTrustedDomainInformation(IN LSA_HANDLE PolicyHandle, /* - * @unimplemented + * @implemented */ NTSTATUS WINAPI @@ -2032,9 +2087,49 @@ LsaStorePrivateData(IN LSA_HANDLE PolicyHandle, IN PLSA_UNICODE_STRING KeyName, IN PLSA_UNICODE_STRING PrivateData OPTIONAL) { - FIXME("LsaStorePrivateData(%p %p %p) stub\n", + PLSAPR_CR_CIPHER_VALUE EncryptedData = NULL; + SIZE_T BufferSize; + NTSTATUS Status; + + TRACE("LsaStorePrivateData(%p %p %p)\n", PolicyHandle, KeyName, PrivateData); - return STATUS_OBJECT_NAME_NOT_FOUND; + + if (PrivateData != NULL) + { + BufferSize = sizeof(LSAPR_CR_CIPHER_VALUE) + PrivateData->MaximumLength; + EncryptedData = midl_user_allocate(BufferSize); + if (EncryptedData == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + EncryptedData->Length = PrivateData->Length; + EncryptedData->MaximumLength = PrivateData->MaximumLength; + EncryptedData->Buffer = (BYTE *)(EncryptedData + 1); + if (EncryptedData->Buffer != NULL) + RtlCopyMemory(EncryptedData->Buffer, + PrivateData->Buffer, + PrivateData->Length); + } + + RpcTryExcept + { + Status = LsarStorePrivateData((LSAPR_HANDLE)PolicyHandle, + (PRPC_UNICODE_STRING)KeyName, + EncryptedData); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + +done: + if (EncryptedData != NULL) + midl_user_free(EncryptedData); + + return Status; } /* EOF */ diff --git a/reactos/dll/win32/lsasrv/lsarpc.c b/reactos/dll/win32/lsasrv/lsarpc.c index 1f07a4318aa..7d90797d9c7 100644 --- a/reactos/dll/win32/lsasrv/lsarpc.c +++ b/reactos/dll/win32/lsasrv/lsarpc.c @@ -2386,8 +2386,151 @@ NTSTATUS WINAPI LsarStorePrivateData( PRPC_UNICODE_STRING KeyName, PLSAPR_CR_CIPHER_VALUE EncryptedData) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PLSA_DB_OBJECT PolicyObject = NULL; + PLSA_DB_OBJECT SecretsObject = NULL; + PLSA_DB_OBJECT SecretObject = NULL; + LARGE_INTEGER Time; + PBYTE Value = NULL; + ULONG ValueLength = 0; + NTSTATUS Status; + + TRACE("LsarStorePrivateData(%p %p %p)\n", + PolicyHandle, KeyName, EncryptedData); + + /* Validate the SecretHandle */ + Status = LsapValidateDbObject(PolicyHandle, + LsaDbPolicyObject, + POLICY_CREATE_SECRET, + &PolicyObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapValidateDbObject returned 0x%08lx\n", Status); + return Status; + } + + /* Open the 'Secrets' object */ + Status = LsapOpenDbObject(PolicyObject, + NULL, + L"Secrets", + LsaDbIgnoreObject, + 0, + PolicyObject->Trusted, + &SecretsObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapOpenDbObject failed (Status 0x%08lx)\n", Status); + goto done; + } + + if (EncryptedData == NULL) + { + /* Open the Secret object */ + Status = LsapOpenDbObject(SecretsObject, + NULL, + KeyName->Buffer, + LsaDbSecretObject, + 0, + PolicyObject->Trusted, + &SecretObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapOpenDbObject failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Delete the secret */ + Status = LsapDeleteDbObject(SecretObject); + if (NT_SUCCESS(Status)) + SecretObject = NULL; + } + else + { + /* Create the Secret object */ + Status = LsapCreateDbObject(SecretsObject, + NULL, + KeyName->Buffer, + LsaDbSecretObject, + 0, + PolicyObject->Trusted, + &SecretObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapCreateDbObject failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* FIXME: Decrypt data */ + Value = EncryptedData->Buffer; + ValueLength = EncryptedData->MaximumLength; + + /* Get the current time */ + Status = NtQuerySystemTime(&Time); + if (!NT_SUCCESS(Status)) + { + ERR("NtQuerySystemTime failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Set the current value */ + Status = LsapSetObjectAttribute(SecretObject, + L"CurrentValue", + Value, + ValueLength); + if (!NT_SUCCESS(Status)) + { + ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Set the current time */ + Status = LsapSetObjectAttribute(SecretObject, + L"CurrentTime", + &Time, + sizeof(LARGE_INTEGER)); + if (!NT_SUCCESS(Status)) + { + ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Get the current time */ + Status = NtQuerySystemTime(&Time); + if (!NT_SUCCESS(Status)) + { + ERR("NtQuerySystemTime failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Set the old value */ + Status = LsapSetObjectAttribute(SecretObject, + L"OldValue", + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Set the old time */ + Status = LsapSetObjectAttribute(SecretObject, + L"OldTime", + &Time, + sizeof(LARGE_INTEGER)); + if (!NT_SUCCESS(Status)) + { + ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status); + } + } + +done: + if (SecretObject != NULL) + LsapCloseDbObject(SecretObject); + + if (SecretsObject != NULL) + LsapCloseDbObject(SecretsObject); + + return Status; } @@ -2397,8 +2540,97 @@ NTSTATUS WINAPI LsarRetrievePrivateData( PRPC_UNICODE_STRING KeyName, PLSAPR_CR_CIPHER_VALUE *EncryptedData) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PLSA_DB_OBJECT PolicyObject = NULL; + PLSA_DB_OBJECT SecretObject = NULL; + PLSAPR_CR_CIPHER_VALUE EncCurrentValue = NULL; + ULONG CurrentValueLength = 0; + PBYTE CurrentValue = NULL; + NTSTATUS Status; + + /* Validate the SecretHandle */ + Status = LsapValidateDbObject(PolicyHandle, + LsaDbPolicyObject, + POLICY_CREATE_SECRET, + &PolicyObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapValidateDbObject returned 0x%08lx\n", Status); + return Status; + } + + /* Open the secret object */ + Status = LsapOpenDbObject(PolicyObject, + L"Secrets", + KeyName->Buffer, + LsaDbSecretObject, + 0, + PolicyObject->Trusted, + &SecretObject); + if (!NT_SUCCESS(Status)) + { + ERR("LsapOpenDbObject failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Get the size of the current value */ + Status = LsapGetObjectAttribute(SecretObject, + L"CurrentValue", + NULL, + &CurrentValueLength); + if (!NT_SUCCESS(Status)) + goto done; + + /* Allocate a buffer for the current value */ + CurrentValue = midl_user_allocate(CurrentValueLength); + if (CurrentValue == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + /* Get the current value */ + Status = LsapGetObjectAttribute(SecretObject, + L"CurrentValue", + CurrentValue, + &CurrentValueLength); + if (!NT_SUCCESS(Status)) + goto done; + + /* Allocate a buffer for the encrypted current value */ + EncCurrentValue = midl_user_allocate(sizeof(LSAPR_CR_CIPHER_VALUE) + CurrentValueLength); + if (EncCurrentValue == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + /* FIXME: Encrypt the current value */ + EncCurrentValue->Length = (USHORT)(CurrentValueLength - sizeof(WCHAR)); + EncCurrentValue->MaximumLength = (USHORT)CurrentValueLength; + EncCurrentValue->Buffer = (PBYTE)(EncCurrentValue + 1); + RtlCopyMemory(EncCurrentValue->Buffer, + CurrentValue, + CurrentValueLength); + +done: + if (NT_SUCCESS(Status)) + { + if (EncryptedData != NULL) + *EncryptedData = EncCurrentValue; + } + else + { + if (EncryptedData != NULL) + *EncryptedData = NULL; + + if (EncCurrentValue != NULL) + midl_user_free(EncCurrentValue); + + if (SecretObject != NULL) + LsapCloseDbObject(SecretObject); + } + + return Status; }