/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: Local Security Authority (LSA) Server * FILE: reactos/dll/win32/lsasrv/lsarpc.h * PURPOSE: RPC interface functions * * PROGRAMMERS: Eric Kohl */ #include "lsasrv.h" /* GLOBALS *****************************************************************/ static RTL_CRITICAL_SECTION PolicyHandleTableLock; static GENERIC_MAPPING LsapPolicyMapping = {POLICY_READ, POLICY_WRITE, POLICY_EXECUTE, POLICY_ALL_ACCESS}; static GENERIC_MAPPING LsapAccountMapping = {ACCOUNT_READ, ACCOUNT_WRITE, ACCOUNT_EXECUTE, ACCOUNT_ALL_ACCESS}; static GENERIC_MAPPING LsapSecretMapping = {SECRET_READ, SECRET_WRITE, SECRET_EXECUTE, SECRET_ALL_ACCESS}; /* FUNCTIONS ***************************************************************/ NTSTATUS LsarStartRpcServer(VOID) { RPC_STATUS Status; DWORD dwError; HANDLE hEvent; RtlInitializeCriticalSection(&PolicyHandleTableLock); TRACE("LsarStartRpcServer() called\n"); Status = RpcServerUseProtseqEpW(L"ncacn_np", RPC_C_PROTSEQ_MAX_REQS_DEFAULT, L"\\pipe\\lsarpc", NULL); if (Status != RPC_S_OK) { WARN("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); return I_RpcMapWin32Status(Status); } Status = RpcServerRegisterIf(lsarpc_v0_0_s_ifspec, NULL, NULL); if (Status != RPC_S_OK) { WARN("RpcServerRegisterIf() failed (Status %lx)\n", Status); return I_RpcMapWin32Status(Status); } DsSetupInit(); Status = RpcServerListen(1, 20, TRUE); if (Status != RPC_S_OK) { WARN("RpcServerListen() failed (Status %lx)\n", Status); return I_RpcMapWin32Status(Status); } /* Notify the service manager */ TRACE("Creating notification event!\n"); hEvent = CreateEventW(NULL, TRUE, FALSE, L"LSA_RPC_SERVER_ACTIVE"); if (hEvent == NULL) { dwError = GetLastError(); TRACE("Failed to create or open the notification event (Error %lu)\n", dwError); #if 0 if (dwError == ERROR_ALREADY_EXISTS) { hEvent = OpenEventW(GENERIC_WRITE, FALSE, L"LSA_RPC_SERVER_ACTIVE"); if (hEvent == NULL) { ERR("Could not open the notification event (Error %lu)\n", GetLastError()); return STATUS_UNSUCCESSFUL; } } #endif return STATUS_UNSUCCESSFUL; } TRACE("Set notification event!\n"); SetEvent(hEvent); /* NOTE: Do not close the event handle, as it must remain alive! */ TRACE("LsarStartRpcServer() done\n"); return STATUS_SUCCESS; } void __RPC_USER LSAPR_HANDLE_rundown(LSAPR_HANDLE hHandle) { } /* Function 0 */ NTSTATUS WINAPI LsarClose( LSAPR_HANDLE *ObjectHandle) { PLSA_DB_OBJECT DbObject; NTSTATUS Status = STATUS_SUCCESS; TRACE("LsarClose(%p)\n", ObjectHandle); // RtlEnterCriticalSection(&PolicyHandleTableLock); Status = LsapValidateDbObject(*ObjectHandle, LsaDbIgnoreObject, 0, &DbObject); if (Status == STATUS_SUCCESS) { Status = LsapCloseDbObject(DbObject); *ObjectHandle = NULL; } // RtlLeaveCriticalSection(&PolicyHandleTableLock); return Status; } /* Function 1 */ NTSTATUS WINAPI LsarDelete( LSAPR_HANDLE ObjectHandle) { TRACE("LsarDelete(%p)\n", ObjectHandle); return LsarDeleteObject(&ObjectHandle); } /* Function 2 */ NTSTATUS WINAPI LsarEnumeratePrivileges( LSAPR_HANDLE PolicyHandle, DWORD *EnumerationContext, PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer, DWORD PreferedMaximumLength) { PLSA_DB_OBJECT PolicyObject; NTSTATUS Status; TRACE("LsarEnumeratePrivileges(%p %p %p %lu)\n", PolicyHandle, EnumerationContext, EnumerationBuffer, PreferedMaximumLength); Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_VIEW_LOCAL_INFORMATION, &PolicyObject); if (!NT_SUCCESS(Status)) return Status; if (EnumerationContext == NULL) return STATUS_INVALID_PARAMETER; return LsarpEnumeratePrivileges(EnumerationContext, EnumerationBuffer, PreferedMaximumLength); } /* Function 3 */ NTSTATUS WINAPI LsarQuerySecurityObject( LSAPR_HANDLE ObjectHandle, SECURITY_INFORMATION SecurityInformation, PLSAPR_SR_SECURITY_DESCRIPTOR *SecurityDescriptor) { PLSA_DB_OBJECT DbObject = NULL; PSECURITY_DESCRIPTOR RelativeSd = NULL; PSECURITY_DESCRIPTOR ResultSd = NULL; PLSAPR_SR_SECURITY_DESCRIPTOR SdData = NULL; ACCESS_MASK DesiredAccess = 0; ULONG RelativeSdSize = 0; ULONG ResultSdSize = 0; NTSTATUS Status; TRACE("LsarQuerySecurityObject(%p %lx %p)\n", ObjectHandle, SecurityInformation, SecurityDescriptor); if (SecurityDescriptor == NULL) return STATUS_INVALID_PARAMETER; *SecurityDescriptor = NULL; if ((SecurityInformation & OWNER_SECURITY_INFORMATION) || (SecurityInformation & GROUP_SECURITY_INFORMATION) || (SecurityInformation & DACL_SECURITY_INFORMATION)) DesiredAccess |= READ_CONTROL; if (SecurityInformation & SACL_SECURITY_INFORMATION) DesiredAccess |= ACCESS_SYSTEM_SECURITY; /* Validate the ObjectHandle */ Status = LsapValidateDbObject(ObjectHandle, LsaDbIgnoreObject, DesiredAccess, &DbObject); if (!NT_SUCCESS(Status)) return Status; /* Get the size of the SD */ Status = LsapGetObjectAttribute(DbObject, L"SecDesc", NULL, &RelativeSdSize); if (!NT_SUCCESS(Status)) return Status; /* Allocate a buffer for the SD */ RelativeSd = MIDL_user_allocate(RelativeSdSize); if (RelativeSd == NULL) return STATUS_INSUFFICIENT_RESOURCES; /* Get the SD */ Status = LsapGetObjectAttribute(DbObject, L"SecDesc", RelativeSd, &RelativeSdSize); if (!NT_SUCCESS(Status)) goto done; /* Invalidate the SD information that was not requested */ if (!(SecurityInformation & OWNER_SECURITY_INFORMATION)) ((PISECURITY_DESCRIPTOR)RelativeSd)->Owner = NULL; if (!(SecurityInformation & GROUP_SECURITY_INFORMATION)) ((PISECURITY_DESCRIPTOR)RelativeSd)->Group = NULL; if (!(SecurityInformation & DACL_SECURITY_INFORMATION)) ((PISECURITY_DESCRIPTOR)RelativeSd)->Control &= ~SE_DACL_PRESENT; if (!(SecurityInformation & SACL_SECURITY_INFORMATION)) ((PISECURITY_DESCRIPTOR)RelativeSd)->Control &= ~SE_SACL_PRESENT; /* Calculate the required SD size */ Status = RtlMakeSelfRelativeSD(RelativeSd, NULL, &ResultSdSize); if (Status != STATUS_BUFFER_TOO_SMALL) goto done; /* Allocate a buffer for the new SD */ ResultSd = MIDL_user_allocate(ResultSdSize); if (ResultSd == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } /* Build the new SD */ Status = RtlMakeSelfRelativeSD(RelativeSd, ResultSd, &ResultSdSize); if (!NT_SUCCESS(Status)) goto done; /* Allocate the SD data buffer */ SdData = MIDL_user_allocate(sizeof(LSAPR_SR_SECURITY_DESCRIPTOR)); if (SdData == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } /* Fill the SD data buffer and return it to the caller */ SdData->Length = RelativeSdSize; SdData->SecurityDescriptor = (PBYTE)ResultSd; *SecurityDescriptor = SdData; done: if (!NT_SUCCESS(Status)) { if (ResultSd != NULL) MIDL_user_free(ResultSd); } if (RelativeSd != NULL) MIDL_user_free(RelativeSd); return Status; } /* Function 4 */ NTSTATUS WINAPI LsarSetSecurityObject( LSAPR_HANDLE ObjectHandle, SECURITY_INFORMATION SecurityInformation, PLSAPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor) { PLSA_DB_OBJECT DbObject = NULL; ACCESS_MASK DesiredAccess = 0; PSECURITY_DESCRIPTOR RelativeSd = NULL; ULONG RelativeSdSize = 0; HANDLE TokenHandle = NULL; PGENERIC_MAPPING Mapping; NTSTATUS Status; TRACE("LsarSetSecurityObject(%p %lx %p)\n", ObjectHandle, SecurityInformation, SecurityDescriptor); if ((SecurityDescriptor == NULL) || (SecurityDescriptor->SecurityDescriptor == NULL) || !RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)SecurityDescriptor->SecurityDescriptor)) return ERROR_INVALID_PARAMETER; if (SecurityInformation == 0 || SecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)) return ERROR_INVALID_PARAMETER; if (SecurityInformation & SACL_SECURITY_INFORMATION) DesiredAccess |= ACCESS_SYSTEM_SECURITY; if (SecurityInformation & DACL_SECURITY_INFORMATION) DesiredAccess |= WRITE_DAC; if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) DesiredAccess |= WRITE_OWNER; if ((SecurityInformation & OWNER_SECURITY_INFORMATION) && (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Owner == NULL)) return ERROR_INVALID_PARAMETER; if ((SecurityInformation & GROUP_SECURITY_INFORMATION) && (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Group == NULL)) return ERROR_INVALID_PARAMETER; /* Validate the ObjectHandle */ Status = LsapValidateDbObject(ObjectHandle, LsaDbIgnoreObject, DesiredAccess, &DbObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject failed (Status 0x%08lx)\n", Status); return Status; } /* Get the mapping for the object type */ switch (DbObject->ObjectType) { case LsaDbPolicyObject: Mapping = &LsapPolicyMapping; break; case LsaDbAccountObject: Mapping = &LsapAccountMapping; break; // case LsaDbDomainObject: // Mapping = &LsapDomainMapping; // break; case LsaDbSecretObject: Mapping = &LsapSecretMapping; break; default: return STATUS_INVALID_HANDLE; } /* Get the size of the SD */ Status = LsapGetObjectAttribute(DbObject, L"SecDesc", NULL, &RelativeSdSize); if (!NT_SUCCESS(Status)) return Status; /* Allocate a buffer for the SD */ RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), 0, RelativeSdSize); if (RelativeSd == NULL) return STATUS_INSUFFICIENT_RESOURCES; /* Get the SD */ Status = LsapGetObjectAttribute(DbObject, L"SecDesc", RelativeSd, &RelativeSdSize); if (!NT_SUCCESS(Status)) goto done; /* Get the clients token if we try to set the owner */ if (SecurityInformation & OWNER_SECURITY_INFORMATION) { Status = I_RpcMapWin32Status(RpcImpersonateClient(NULL)); if (!NT_SUCCESS(Status)) { ERR("RpcImpersonateClient returns 0x%08lx\n", Status); goto done; } Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, TRUE, &TokenHandle); RpcRevertToSelf(); if (!NT_SUCCESS(Status)) { ERR("NtOpenThreadToken returns 0x%08lx\n", Status); goto done; } } /* Build the new security descriptor */ Status = RtlSetSecurityObject(SecurityInformation, (PSECURITY_DESCRIPTOR)SecurityDescriptor->SecurityDescriptor, &RelativeSd, Mapping, TokenHandle); if (!NT_SUCCESS(Status)) { ERR("RtlSetSecurityObject failed (Status 0x%08lx)\n", Status); goto done; } /* Set the modified SD */ Status = LsapSetObjectAttribute(DbObject, L"SecDesc", RelativeSd, RtlLengthSecurityDescriptor(RelativeSd)); if (!NT_SUCCESS(Status)) { ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status); } done: if (TokenHandle != NULL) NtClose(TokenHandle); if (RelativeSd != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); return Status; } /* Function 5 */ NTSTATUS WINAPI LsarChangePassword( handle_t IDL_handle, PRPC_UNICODE_STRING String1, PRPC_UNICODE_STRING String2, PRPC_UNICODE_STRING String3, PRPC_UNICODE_STRING String4, PRPC_UNICODE_STRING String5) { /* Deprecated */ return STATUS_NOT_IMPLEMENTED; } /* Function 6 */ NTSTATUS WINAPI LsarOpenPolicy( LPWSTR SystemName, PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *PolicyHandle) { PLSA_DB_OBJECT PolicyObject; NTSTATUS Status; TRACE("LsarOpenPolicy(%S %p %lx %p)\n", SystemName, ObjectAttributes, DesiredAccess, PolicyHandle); RtlEnterCriticalSection(&PolicyHandleTableLock); Status = LsapOpenDbObject(NULL, NULL, L"Policy", LsaDbPolicyObject, DesiredAccess, FALSE, &PolicyObject); RtlLeaveCriticalSection(&PolicyHandleTableLock); if (NT_SUCCESS(Status)) *PolicyHandle = (LSAPR_HANDLE)PolicyObject; TRACE("LsarOpenPolicy done!\n"); return Status; } /* Function 7 */ NTSTATUS WINAPI LsarQueryInformationPolicy( LSAPR_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_POLICY_INFORMATION *PolicyInformation) { PLSA_DB_OBJECT PolicyObject; ACCESS_MASK DesiredAccess = 0; NTSTATUS Status; TRACE("LsarQueryInformationPolicy(%p,0x%08x,%p)\n", PolicyHandle, InformationClass, PolicyInformation); if (PolicyInformation) { TRACE("*PolicyInformation %p\n", *PolicyInformation); } switch (InformationClass) { case PolicyAuditLogInformation: case PolicyAuditEventsInformation: case PolicyAuditFullQueryInformation: DesiredAccess = POLICY_VIEW_AUDIT_INFORMATION; break; case PolicyPrimaryDomainInformation: case PolicyAccountDomainInformation: case PolicyLsaServerRoleInformation: case PolicyReplicaSourceInformation: case PolicyDefaultQuotaInformation: case PolicyModificationInformation: case PolicyDnsDomainInformation: case PolicyDnsDomainInformationInt: case PolicyLocalAccountDomainInformation: DesiredAccess = POLICY_VIEW_LOCAL_INFORMATION; break; case PolicyPdAccountInformation: DesiredAccess = POLICY_GET_PRIVATE_INFORMATION; break; default: ERR("Invalid InformationClass!\n"); return STATUS_INVALID_PARAMETER; } Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, DesiredAccess, &PolicyObject); if (!NT_SUCCESS(Status)) return Status; switch (InformationClass) { case PolicyAuditLogInformation: /* 1 */ Status = LsarQueryAuditLog(PolicyObject, PolicyInformation); break; case PolicyAuditEventsInformation: /* 2 */ Status = LsarQueryAuditEvents(PolicyObject, PolicyInformation); break; case PolicyPrimaryDomainInformation: /* 3 */ Status = LsarQueryPrimaryDomain(PolicyObject, PolicyInformation); break; case PolicyPdAccountInformation: /* 4 */ Status = LsarQueryPdAccount(PolicyObject, PolicyInformation); break; case PolicyAccountDomainInformation: /* 5 */ Status = LsarQueryAccountDomain(PolicyObject, PolicyInformation); break; case PolicyLsaServerRoleInformation: /* 6 */ Status = LsarQueryServerRole(PolicyObject, PolicyInformation); break; case PolicyReplicaSourceInformation: /* 7 */ Status = LsarQueryReplicaSource(PolicyObject, PolicyInformation); break; case PolicyDefaultQuotaInformation: /* 8 */ Status = LsarQueryDefaultQuota(PolicyObject, PolicyInformation); break; case PolicyModificationInformation: /* 9 */ Status = LsarQueryModification(PolicyObject, PolicyInformation); break; case PolicyAuditFullQueryInformation: /* 11 (0xB) */ Status = LsarQueryAuditFull(PolicyObject, PolicyInformation); break; case PolicyDnsDomainInformation: /* 12 (0xC) */ Status = LsarQueryDnsDomain(PolicyObject, PolicyInformation); break; case PolicyDnsDomainInformationInt: /* 13 (0xD) */ Status = LsarQueryDnsDomainInt(PolicyObject, PolicyInformation); break; case PolicyLocalAccountDomainInformation: /* 14 (0xE) */ Status = LsarQueryLocalAccountDomain(PolicyObject, PolicyInformation); break; default: ERR("Invalid InformationClass!\n"); Status = STATUS_INVALID_PARAMETER; } return Status; } /* Function 8 */ NTSTATUS WINAPI LsarSetInformationPolicy( LSAPR_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_POLICY_INFORMATION PolicyInformation) { PLSA_DB_OBJECT PolicyObject; ACCESS_MASK DesiredAccess = 0; NTSTATUS Status; TRACE("LsarSetInformationPolicy(%p,0x%08x,%p)\n", PolicyHandle, InformationClass, PolicyInformation); if (PolicyInformation) { TRACE("*PolicyInformation %p\n", *PolicyInformation); } switch (InformationClass) { case PolicyAuditLogInformation: case PolicyAuditFullSetInformation: DesiredAccess = POLICY_AUDIT_LOG_ADMIN; break; case PolicyAuditEventsInformation: DesiredAccess = POLICY_SET_AUDIT_REQUIREMENTS; break; case PolicyPrimaryDomainInformation: case PolicyAccountDomainInformation: case PolicyDnsDomainInformation: case PolicyDnsDomainInformationInt: case PolicyLocalAccountDomainInformation: DesiredAccess = POLICY_TRUST_ADMIN; break; case PolicyLsaServerRoleInformation: case PolicyReplicaSourceInformation: DesiredAccess = POLICY_SERVER_ADMIN; break; case PolicyDefaultQuotaInformation: DesiredAccess = POLICY_SET_DEFAULT_QUOTA_LIMITS; break; default: ERR("Invalid InformationClass!\n"); return STATUS_INVALID_PARAMETER; } Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, DesiredAccess, &PolicyObject); if (!NT_SUCCESS(Status)) return Status; switch (InformationClass) { case PolicyAuditLogInformation: /* 1 */ Status = LsarSetAuditLog(PolicyObject, (PPOLICY_AUDIT_LOG_INFO)PolicyInformation); break; case PolicyAuditEventsInformation: /* 2 */ Status = LsarSetAuditEvents(PolicyObject, (PLSAPR_POLICY_AUDIT_EVENTS_INFO)PolicyInformation); if (NT_SUCCESS(Status)) LsapNotifyPolicyChange(PolicyNotifyAuditEventsInformation); break; case PolicyPrimaryDomainInformation: /* 3 */ Status = LsarSetPrimaryDomain(PolicyObject, (PLSAPR_POLICY_PRIMARY_DOM_INFO)PolicyInformation); if (NT_SUCCESS(Status)) LsapNotifyPolicyChange(PolicyNotifyDnsDomainInformation); break; case PolicyAccountDomainInformation: /* 5 */ Status = LsarSetAccountDomain(PolicyObject, (PLSAPR_POLICY_ACCOUNT_DOM_INFO)PolicyInformation); if (NT_SUCCESS(Status)) LsapNotifyPolicyChange(PolicyNotifyAccountDomainInformation); break; case PolicyLsaServerRoleInformation: /* 6 */ Status = LsarSetServerRole(PolicyObject, (PPOLICY_LSA_SERVER_ROLE_INFO)PolicyInformation); if (NT_SUCCESS(Status)) LsapNotifyPolicyChange(PolicyNotifyServerRoleInformation); break; case PolicyReplicaSourceInformation: /* 7 */ Status = LsarSetReplicaSource(PolicyObject, (PPOLICY_LSA_REPLICA_SRCE_INFO)PolicyInformation); break; case PolicyDefaultQuotaInformation: /* 8 */ Status = LsarSetDefaultQuota(PolicyObject, (PPOLICY_DEFAULT_QUOTA_INFO)PolicyInformation); break; case PolicyModificationInformation: /* 9 */ Status = LsarSetModification(PolicyObject, (PPOLICY_MODIFICATION_INFO)PolicyInformation); break; case PolicyAuditFullSetInformation: /* 10 (0xA) */ Status = LsarSetAuditFull(PolicyObject, (PPOLICY_AUDIT_FULL_QUERY_INFO)PolicyInformation); break; case PolicyDnsDomainInformation: /* 12 (0xC) */ Status = LsarSetDnsDomain(PolicyObject, (PLSAPR_POLICY_DNS_DOMAIN_INFO)PolicyInformation); if (NT_SUCCESS(Status)) LsapNotifyPolicyChange(PolicyNotifyDnsDomainInformation); break; case PolicyDnsDomainInformationInt: /* 13 (0xD) */ Status = LsarSetDnsDomainInt(PolicyObject, (PLSAPR_POLICY_DNS_DOMAIN_INFO)PolicyInformation); break; case PolicyLocalAccountDomainInformation: /* 14 (0xE) */ Status = LsarSetLocalAccountDomain(PolicyObject, (PLSAPR_POLICY_ACCOUNT_DOM_INFO)PolicyInformation); break; default: Status = STATUS_INVALID_PARAMETER; break; } return Status; } /* Function 9 */ NTSTATUS WINAPI LsarClearAuditLog( LSAPR_HANDLE ObjectHandle) { /* Deprecated */ return STATUS_NOT_IMPLEMENTED; } NTSTATUS LsarpCreateAccount( PLSA_DB_OBJECT PolicyObject, PRPC_SID AccountSid, ACCESS_MASK DesiredAccess, PLSA_DB_OBJECT *AccountObject) { LPWSTR SidString = NULL; PSECURITY_DESCRIPTOR AccountSd = NULL; ULONG AccountSdSize; NTSTATUS Status = STATUS_SUCCESS; /* Create SID string */ if (!ConvertSidToStringSid((PSID)AccountSid, &SidString)) { ERR("ConvertSidToStringSid failed\n"); return STATUS_INVALID_PARAMETER; } /* Create a security descriptor for the account */ Status = LsapCreateAccountSd(&AccountSd, &AccountSdSize); if (!NT_SUCCESS(Status)) { ERR("LsapCreateAccountSd returned 0x%08lx\n", Status); goto done; } /* Create the Account object */ Status = LsapCreateDbObject(PolicyObject, L"Accounts", SidString, LsaDbAccountObject, DesiredAccess, PolicyObject->Trusted, AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapCreateDbObject failed (Status 0x%08lx)\n", Status); goto done; } /* Set the Sid attribute */ Status = LsapSetObjectAttribute(*AccountObject, L"Sid", (PVOID)AccountSid, GetLengthSid(AccountSid)); if (!NT_SUCCESS(Status)) goto done; /* Set the SecDesc attribute */ Status = LsapSetObjectAttribute(*AccountObject, L"SecDesc", AccountSd, AccountSdSize); done: if (SidString != NULL) LocalFree(SidString); if (AccountSd != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AccountSd); 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; TRACE("LsarCreateAccount(%p %p %lx %p)\n", PolicyHandle, AccountSid, DesiredAccess, AccountHandle); /* 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; } /* Function 11 */ NTSTATUS WINAPI LsarEnumerateAccounts( LSAPR_HANDLE PolicyHandle, DWORD *EnumerationContext, PLSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer, DWORD PreferedMaximumLength) { LSAPR_ACCOUNT_ENUM_BUFFER EnumBuffer = {0, NULL}; PLSA_DB_OBJECT PolicyObject = NULL; PWSTR AccountKeyBuffer = NULL; HANDLE AccountsKeyHandle = NULL; HANDLE AccountKeyHandle; HANDLE SidKeyHandle; ULONG AccountKeyBufferSize; ULONG EnumIndex; ULONG EnumCount; ULONG RequiredLength; ULONG DataLength; ULONG i; NTSTATUS Status = STATUS_SUCCESS; TRACE("LsarEnumerateAccount(%p %p %p %lu)\n", PolicyHandle, EnumerationContext, EnumerationBuffer, PreferedMaximumLength); if (EnumerationContext == NULL || EnumerationBuffer == NULL) return STATUS_INVALID_PARAMETER; EnumerationBuffer->EntriesRead = 0; EnumerationBuffer->Information = NULL; /* Validate the PolicyHandle */ Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_VIEW_LOCAL_INFORMATION, &PolicyObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } Status = LsapRegOpenKey(PolicyObject->KeyHandle, L"Accounts", KEY_READ, &AccountsKeyHandle); if (!NT_SUCCESS(Status)) return Status; Status = LsapRegQueryKeyInfo(AccountsKeyHandle, NULL, &AccountKeyBufferSize, NULL); if (!NT_SUCCESS(Status)) { ERR("LsapRegQueryKeyInfo returned 0x%08lx\n", Status); return Status; } AccountKeyBufferSize += sizeof(WCHAR); AccountKeyBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, AccountKeyBufferSize); if (AccountKeyBuffer == NULL) { return STATUS_NO_MEMORY; } EnumIndex = *EnumerationContext; EnumCount = 0; RequiredLength = 0; while (TRUE) { Status = LsapRegEnumerateSubKey(AccountsKeyHandle, EnumIndex, AccountKeyBufferSize, AccountKeyBuffer); if (!NT_SUCCESS(Status)) break; TRACE("EnumIndex: %lu\n", EnumIndex); TRACE("Account key name: %S\n", AccountKeyBuffer); Status = LsapRegOpenKey(AccountsKeyHandle, AccountKeyBuffer, KEY_READ, &AccountKeyHandle); TRACE("LsapRegOpenKey returned %08lX\n", Status); if (NT_SUCCESS(Status)) { Status = LsapRegOpenKey(AccountKeyHandle, L"Sid", KEY_READ, &SidKeyHandle); TRACE("LsapRegOpenKey returned %08lX\n", Status); if (NT_SUCCESS(Status)) { DataLength = 0; Status = LsapRegQueryValue(SidKeyHandle, NULL, NULL, NULL, &DataLength); TRACE("LsapRegQueryValue returned %08lX\n", Status); if (NT_SUCCESS(Status)) { TRACE("Data length: %lu\n", DataLength); if ((RequiredLength + DataLength + sizeof(LSAPR_ACCOUNT_INFORMATION)) > PreferedMaximumLength) break; RequiredLength += (DataLength + sizeof(LSAPR_ACCOUNT_INFORMATION)); EnumCount++; } LsapRegCloseKey(SidKeyHandle); } LsapRegCloseKey(AccountKeyHandle); } EnumIndex++; } TRACE("EnumCount: %lu\n", EnumCount); TRACE("RequiredLength: %lu\n", RequiredLength); EnumBuffer.EntriesRead = EnumCount; EnumBuffer.Information = midl_user_allocate(EnumCount * sizeof(LSAPR_ACCOUNT_INFORMATION)); if (EnumBuffer.Information == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } EnumIndex = *EnumerationContext; for (i = 0; i < EnumCount; i++, EnumIndex++) { Status = LsapRegEnumerateSubKey(AccountsKeyHandle, EnumIndex, AccountKeyBufferSize, AccountKeyBuffer); if (!NT_SUCCESS(Status)) break; TRACE("EnumIndex: %lu\n", EnumIndex); TRACE("Account key name: %S\n", AccountKeyBuffer); Status = LsapRegOpenKey(AccountsKeyHandle, AccountKeyBuffer, KEY_READ, &AccountKeyHandle); TRACE("LsapRegOpenKey returned %08lX\n", Status); if (NT_SUCCESS(Status)) { Status = LsapRegOpenKey(AccountKeyHandle, L"Sid", KEY_READ, &SidKeyHandle); TRACE("LsapRegOpenKey returned %08lX\n", Status); if (NT_SUCCESS(Status)) { DataLength = 0; Status = LsapRegQueryValue(SidKeyHandle, NULL, NULL, NULL, &DataLength); TRACE("LsapRegQueryValue returned %08lX\n", Status); if (NT_SUCCESS(Status)) { EnumBuffer.Information[i].Sid = midl_user_allocate(DataLength); if (EnumBuffer.Information[i].Sid == NULL) { LsapRegCloseKey(AccountKeyHandle); Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } Status = LsapRegQueryValue(SidKeyHandle, NULL, NULL, EnumBuffer.Information[i].Sid, &DataLength); TRACE("SampRegQueryValue returned %08lX\n", Status); } LsapRegCloseKey(SidKeyHandle); } LsapRegCloseKey(AccountKeyHandle); if (!NT_SUCCESS(Status)) goto done; } } if (NT_SUCCESS(Status)) { *EnumerationContext += EnumCount; EnumerationBuffer->EntriesRead = EnumBuffer.EntriesRead; EnumerationBuffer->Information = EnumBuffer.Information; } done: if (!NT_SUCCESS(Status)) { if (EnumBuffer.Information) { for (i = 0; i < EnumBuffer.EntriesRead; i++) { if (EnumBuffer.Information[i].Sid != NULL) midl_user_free(EnumBuffer.Information[i].Sid); } midl_user_free(EnumBuffer.Information); } } if (AccountKeyBuffer != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AccountKeyBuffer); if (AccountsKeyHandle != NULL) LsapRegCloseKey(AccountsKeyHandle); return Status; } /* Function 12 */ NTSTATUS WINAPI LsarCreateTrustedDomain( LSAPR_HANDLE PolicyHandle, PLSAPR_TRUST_INFORMATION TrustedDomainInformation, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *TrustedDomainHandle) { /* FIXME: We are not running an AD yet */ return STATUS_DIRECTORY_SERVICE_REQUIRED; } /* Function 13 */ NTSTATUS WINAPI LsarEnumerateTrustedDomains( LSAPR_HANDLE PolicyHandle, DWORD *EnumerationContext, PLSAPR_TRUSTED_ENUM_BUFFER EnumerationBuffer, DWORD PreferedMaximumLength) { /* FIXME: We are not running an AD yet */ EnumerationBuffer->EntriesRead = 0; EnumerationBuffer->Information = NULL; return STATUS_NO_MORE_ENTRIES; } /* Function 14 */ NTSTATUS WINAPI LsarLookupNames( LSAPR_HANDLE PolicyHandle, DWORD Count, PRPC_UNICODE_STRING Names, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_SIDS TranslatedSids, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount) { LSAPR_TRANSLATED_SIDS_EX2 TranslatedSidsEx2; ULONG i; NTSTATUS Status; TRACE("LsarLookupNames(%p %lu %p %p %p %d %p)\n", PolicyHandle, Count, Names, ReferencedDomains, TranslatedSids, LookupLevel, MappedCount); TranslatedSids->Entries = 0; TranslatedSids->Sids = NULL; *ReferencedDomains = NULL; if (Count == 0) return STATUS_NONE_MAPPED; TranslatedSidsEx2.Entries = 0; TranslatedSidsEx2.Sids = NULL; Status = LsapLookupNames(Count, Names, ReferencedDomains, &TranslatedSidsEx2, LookupLevel, MappedCount, 0, 0); if (!NT_SUCCESS(Status)) return Status; TranslatedSids->Entries = TranslatedSidsEx2.Entries; TranslatedSids->Sids = MIDL_user_allocate(TranslatedSids->Entries * sizeof(LSA_TRANSLATED_SID)); if (TranslatedSids->Sids == NULL) { MIDL_user_free(TranslatedSidsEx2.Sids); MIDL_user_free(*ReferencedDomains); *ReferencedDomains = NULL; return STATUS_INSUFFICIENT_RESOURCES; } for (i = 0; i < TranslatedSidsEx2.Entries; i++) { TranslatedSids->Sids[i].Use = TranslatedSidsEx2.Sids[i].Use; TranslatedSids->Sids[i].RelativeId = LsapGetRelativeIdFromSid(TranslatedSidsEx2.Sids[i].Sid); TranslatedSids->Sids[i].DomainIndex = TranslatedSidsEx2.Sids[i].DomainIndex; } MIDL_user_free(TranslatedSidsEx2.Sids); return STATUS_SUCCESS; } /* Function 15 */ NTSTATUS WINAPI LsarLookupSids( LSAPR_HANDLE PolicyHandle, PLSAPR_SID_ENUM_BUFFER SidEnumBuffer, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_NAMES TranslatedNames, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount) { LSAPR_TRANSLATED_NAMES_EX TranslatedNamesEx; ULONG i; NTSTATUS Status; TRACE("LsarLookupSids(%p %p %p %p %d %p)\n", PolicyHandle, SidEnumBuffer, ReferencedDomains, TranslatedNames, LookupLevel, MappedCount); /* FIXME: Fail, if there is an invalid SID in the SidEnumBuffer */ TranslatedNames->Entries = SidEnumBuffer->Entries; TranslatedNames->Names = NULL; *ReferencedDomains = NULL; TranslatedNamesEx.Entries = SidEnumBuffer->Entries; TranslatedNamesEx.Names = NULL; Status = LsapLookupSids(SidEnumBuffer, ReferencedDomains, &TranslatedNamesEx, LookupLevel, MappedCount, 0, 0); if (!NT_SUCCESS(Status)) return Status; TranslatedNames->Entries = SidEnumBuffer->Entries; TranslatedNames->Names = MIDL_user_allocate(SidEnumBuffer->Entries * sizeof(LSAPR_TRANSLATED_NAME)); if (TranslatedNames->Names == NULL) { MIDL_user_free(TranslatedNamesEx.Names); MIDL_user_free(*ReferencedDomains); *ReferencedDomains = NULL; return STATUS_INSUFFICIENT_RESOURCES; } for (i = 0; i < TranslatedNamesEx.Entries; i++) { TranslatedNames->Names[i].Use = TranslatedNamesEx.Names[i].Use; TranslatedNames->Names[i].Name.Length = TranslatedNamesEx.Names[i].Name.Length; TranslatedNames->Names[i].Name.MaximumLength = TranslatedNamesEx.Names[i].Name.MaximumLength; TranslatedNames->Names[i].Name.Buffer = TranslatedNamesEx.Names[i].Name.Buffer; TranslatedNames->Names[i].DomainIndex = TranslatedNamesEx.Names[i].DomainIndex; } MIDL_user_free(TranslatedNamesEx.Names); return Status; } /* Function 16 */ NTSTATUS WINAPI LsarCreateSecret( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING SecretName, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *SecretHandle) { PLSA_DB_OBJECT PolicyObject; PLSA_DB_OBJECT SecretObject = NULL; LARGE_INTEGER Time; PSECURITY_DESCRIPTOR SecretSd = NULL; ULONG SecretSdSize; NTSTATUS Status = STATUS_SUCCESS; TRACE("LsarCreateSecret(%p %wZ %lx %p)\n", PolicyHandle, SecretName, DesiredAccess, SecretHandle); /* Validate the PolicyHandle */ Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_CREATE_SECRET, &PolicyObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* Get the current time */ Status = NtQuerySystemTime(&Time); if (!NT_SUCCESS(Status)) { ERR("NtQuerySystemTime failed (Status 0x%08lx)\n", Status); goto done; } /* Create a security descriptor for the secret */ Status = LsapCreateSecretSd(&SecretSd, &SecretSdSize); if (!NT_SUCCESS(Status)) { ERR("LsapCreateAccountSd returned 0x%08lx\n", Status); return Status; } /* Create the Secret object */ Status = LsapCreateDbObject(PolicyObject, L"Secrets", SecretName->Buffer, LsaDbSecretObject, DesiredAccess, PolicyObject->Trusted, &SecretObject); if (!NT_SUCCESS(Status)) { ERR("LsapCreateDbObject failed (Status 0x%08lx)\n", Status); goto done; } /* Set the CurrentTime attribute */ Status = LsapSetObjectAttribute(SecretObject, L"CurrentTime", (PVOID)&Time, sizeof(LARGE_INTEGER)); if (!NT_SUCCESS(Status)) { ERR("LsapSetObjectAttribute (CurrentTime) failed (Status 0x%08lx)\n", Status); goto done; } /* Set the OldTime attribute */ Status = LsapSetObjectAttribute(SecretObject, L"OldTime", (PVOID)&Time, sizeof(LARGE_INTEGER)); if (!NT_SUCCESS(Status)) { ERR("LsapSetObjectAttribute (OldTime) failed (Status 0x%08lx)\n", Status); goto done; } /* Set the SecDesc attribute */ Status = LsapSetObjectAttribute(SecretObject, L"SecDesc", SecretSd, SecretSdSize); done: if (SecretSd != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, SecretSd); if (!NT_SUCCESS(Status)) { if (SecretObject != NULL) LsapCloseDbObject(SecretObject); } else { *SecretHandle = (LSAPR_HANDLE)SecretObject; } return STATUS_SUCCESS; } 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; /* Create SID string */ if (!ConvertSidToStringSid((PSID)AccountSid, &SidString)) { ERR("ConvertSidToStringSid failed\n"); return STATUS_INVALID_PARAMETER; } /* Create the Account object */ Status = LsapOpenDbObject(PolicyObject, L"Accounts", SidString, LsaDbAccountObject, DesiredAccess, PolicyObject->Trusted, AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapOpenDbObject(Accounts/%S) failed (Status 0x%08lx)\n", SidString, Status); } if (SidString != NULL) LocalFree(SidString); 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; TRACE("LsarOpenAccount(%p %p %lx %p)\n", PolicyHandle, AccountSid, DesiredAccess, AccountHandle); /* 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); } /* Function 18 */ NTSTATUS WINAPI LsarEnumeratePrivilegesAccount( LSAPR_HANDLE AccountHandle, PLSAPR_PRIVILEGE_SET *Privileges) { PLSA_DB_OBJECT AccountObject; ULONG PrivilegeSetSize = 0; PLSAPR_PRIVILEGE_SET PrivilegeSet = NULL; NTSTATUS Status; TRACE("LsarEnumeratePrivilegesAccount(%p %p)\n", AccountHandle, Privileges); *Privileges = NULL; /* Validate the AccountHandle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_VIEW, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* Get the size of the privilege set */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", NULL, &PrivilegeSetSize); if (!NT_SUCCESS(Status)) return Status; /* Allocate a buffer for the privilege set */ PrivilegeSet = MIDL_user_allocate(PrivilegeSetSize); if (PrivilegeSet == NULL) return STATUS_NO_MEMORY; /* Get the privilege set */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", PrivilegeSet, &PrivilegeSetSize); if (!NT_SUCCESS(Status)) { MIDL_user_free(PrivilegeSet); return Status; } /* Return a pointer to the privilege set */ *Privileges = PrivilegeSet; return STATUS_SUCCESS; } /* Function 19 */ NTSTATUS WINAPI LsarAddPrivilegesToAccount( LSAPR_HANDLE AccountHandle, PLSAPR_PRIVILEGE_SET Privileges) { PLSA_DB_OBJECT AccountObject; PPRIVILEGE_SET CurrentPrivileges = NULL; PPRIVILEGE_SET NewPrivileges = NULL; ULONG PrivilegeSetSize = 0; ULONG PrivilegeCount; ULONG i, j; BOOL bFound; NTSTATUS Status; TRACE("LsarAddPrivilegesToAccount(%p %p)\n", AccountHandle, Privileges); /* Validate the AccountHandle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_ADJUST_PRIVILEGES, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* Get the size of the Privilgs attribute */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", NULL, &PrivilegeSetSize); if (!NT_SUCCESS(Status) || PrivilegeSetSize == 0) { /* The Privilgs attribute does not exist */ PrivilegeSetSize = sizeof(PRIVILEGE_SET) + (Privileges->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES); Status = LsapSetObjectAttribute(AccountObject, L"Privilgs", Privileges, PrivilegeSetSize); } else { /* The Privilgs attribute exists */ /* Allocate memory for the stored privilege set */ CurrentPrivileges = MIDL_user_allocate(PrivilegeSetSize); if (CurrentPrivileges == NULL) return STATUS_NO_MEMORY; /* Get the current privilege set */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", CurrentPrivileges, &PrivilegeSetSize); if (!NT_SUCCESS(Status)) { TRACE("LsapGetObjectAttribute() failed (Status 0x%08lx)\n", Status); goto done; } PrivilegeCount = CurrentPrivileges->PrivilegeCount; TRACE("Current privilege count: %lu\n", PrivilegeCount); /* Calculate the number of privileges in the combined privilege set */ for (i = 0; i < Privileges->PrivilegeCount; i++) { bFound = FALSE; for (j = 0; j < CurrentPrivileges->PrivilegeCount; j++) { if (RtlEqualLuid(&(Privileges->Privilege[i].Luid), &(CurrentPrivileges->Privilege[i].Luid))) { bFound = TRUE; break; } } if (bFound == FALSE) { TRACE("Found new privilege\n"); PrivilegeCount++; } } TRACE("New privilege count: %lu\n", PrivilegeCount); /* Calculate the size of the new privilege set and allocate it */ PrivilegeSetSize = sizeof(PRIVILEGE_SET) + (PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES); NewPrivileges = MIDL_user_allocate(PrivilegeSetSize); if (NewPrivileges == NULL) { Status = STATUS_NO_MEMORY; goto done; } /* Initialize the new privilege set */ NewPrivileges->PrivilegeCount = PrivilegeCount; NewPrivileges->Control = 0; /* Copy all privileges from the current privilege set */ RtlCopyLuidAndAttributesArray(CurrentPrivileges->PrivilegeCount, &(CurrentPrivileges->Privilege[0]), &(NewPrivileges->Privilege[0])); /* Add new privileges to the new privilege set */ PrivilegeCount = CurrentPrivileges->PrivilegeCount; for (i = 0; i < Privileges->PrivilegeCount; i++) { bFound = FALSE; for (j = 0; j < CurrentPrivileges->PrivilegeCount; j++) { if (RtlEqualLuid(&(Privileges->Privilege[i].Luid), &(CurrentPrivileges->Privilege[i].Luid))) { /* Overwrite attributes if a matching privilege was found */ NewPrivileges->Privilege[j].Attributes = Privileges->Privilege[i].Attributes; bFound = TRUE; break; } } if (bFound == FALSE) { /* Copy the new privilege */ RtlCopyLuidAndAttributesArray(1, (PLUID_AND_ATTRIBUTES)&(Privileges->Privilege[i]), &(NewPrivileges->Privilege[PrivilegeCount])); PrivilegeCount++; } } /* Set the new privilege set */ Status = LsapSetObjectAttribute(AccountObject, L"Privilgs", NewPrivileges, PrivilegeSetSize); } done: if (CurrentPrivileges != NULL) MIDL_user_free(CurrentPrivileges); if (NewPrivileges != NULL) MIDL_user_free(NewPrivileges); return Status; } /* Function 20 */ NTSTATUS WINAPI LsarRemovePrivilegesFromAccount( LSAPR_HANDLE AccountHandle, BOOLEAN AllPrivileges, PLSAPR_PRIVILEGE_SET Privileges) { PLSA_DB_OBJECT AccountObject; PPRIVILEGE_SET CurrentPrivileges = NULL; PPRIVILEGE_SET NewPrivileges = NULL; ULONG PrivilegeSetSize = 0; ULONG PrivilegeCount; ULONG i, j, k; BOOL bFound; NTSTATUS Status; TRACE("LsarRemovePrivilegesFromAccount(%p %u %p)\n", AccountHandle, AllPrivileges, Privileges); /* */ if (((AllPrivileges == FALSE) && (Privileges == NULL)) || ((AllPrivileges != FALSE) && (Privileges != NULL))) return STATUS_INVALID_PARAMETER; /* Validate the AccountHandle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_ADJUST_PRIVILEGES, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } if (AllPrivileges != FALSE) { /* Delete the Privilgs attribute */ Status = LsapDeleteObjectAttribute(AccountObject, L"Privilgs"); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) Status = STATUS_SUCCESS; } else { /* Get the size of the Privilgs attribute */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", NULL, &PrivilegeSetSize); if (!NT_SUCCESS(Status)) goto done; /* Succeed, if there is no privilege set to remove privileges from */ if (PrivilegeSetSize == 0) { Status = STATUS_SUCCESS; goto done; } /* Allocate memory for the stored privilege set */ CurrentPrivileges = MIDL_user_allocate(PrivilegeSetSize); if (CurrentPrivileges == NULL) return STATUS_NO_MEMORY; /* Get the current privilege set */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", CurrentPrivileges, &PrivilegeSetSize); if (!NT_SUCCESS(Status)) { TRACE("LsapGetObjectAttribute() failed (Status 0x%08lx)\n", Status); goto done; } PrivilegeCount = CurrentPrivileges->PrivilegeCount; TRACE("Current privilege count: %lu\n", PrivilegeCount); /* Calculate the number of privileges in the new privilege set */ for (i = 0; i < CurrentPrivileges->PrivilegeCount; i++) { for (j = 0; j < Privileges->PrivilegeCount; j++) { if (RtlEqualLuid(&(CurrentPrivileges->Privilege[i].Luid), &(Privileges->Privilege[j].Luid))) { if (PrivilegeCount > 0) PrivilegeCount--; } } } TRACE("New privilege count: %lu\n", PrivilegeCount); if (PrivilegeCount == 0) { /* Delete the Privilgs attribute */ Status = LsapDeleteObjectAttribute(AccountObject, L"Privilgs"); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) Status = STATUS_SUCCESS; } else { /* Calculate the size of the new privilege set and allocate it */ PrivilegeSetSize = sizeof(PRIVILEGE_SET) + (PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES); NewPrivileges = MIDL_user_allocate(PrivilegeSetSize); if (NewPrivileges == NULL) { Status = STATUS_NO_MEMORY; goto done; } /* Initialize the new privilege set */ NewPrivileges->PrivilegeCount = PrivilegeCount; NewPrivileges->Control = 0; /* Copy the privileges which are not to be removed */ for (i = 0, k = 0; i < CurrentPrivileges->PrivilegeCount; i++) { bFound = FALSE; for (j = 0; j < Privileges->PrivilegeCount; j++) { if (RtlEqualLuid(&(CurrentPrivileges->Privilege[i].Luid), &(Privileges->Privilege[j].Luid))) bFound = TRUE; } if (bFound == FALSE) { /* Copy the privilege */ RtlCopyLuidAndAttributesArray(1, &(CurrentPrivileges->Privilege[i]), &(NewPrivileges->Privilege[k])); k++; } } /* Set the new privilege set */ Status = LsapSetObjectAttribute(AccountObject, L"Privilgs", NewPrivileges, PrivilegeSetSize); } } done: if (CurrentPrivileges != NULL) MIDL_user_free(CurrentPrivileges); if (NewPrivileges != NULL) MIDL_user_free(NewPrivileges); return Status; } /* Function 21 */ NTSTATUS WINAPI LsarGetQuotasForAccount( LSAPR_HANDLE AccountHandle, PQUOTA_LIMITS QuotaLimits) { PLSA_DB_OBJECT AccountObject; ULONG Size; NTSTATUS Status; TRACE("LsarGetQuotasForAccount(%p %p)\n", AccountHandle, QuotaLimits); /* Validate the account handle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_VIEW, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("Invalid handle (Status %lx)\n", Status); return Status; } /* Get the quota attribute */ Status = LsapGetObjectAttribute(AccountObject, L"DefQuota", QuotaLimits, &Size); return Status; } /* Function 22 */ NTSTATUS WINAPI LsarSetQuotasForAccount( LSAPR_HANDLE AccountHandle, PQUOTA_LIMITS QuotaLimits) { PLSA_DB_OBJECT AccountObject; QUOTA_LIMITS InternalQuotaLimits; ULONG Size; NTSTATUS Status; TRACE("LsarSetQuotasForAccount(%p %p)\n", AccountHandle, QuotaLimits); /* Validate the account handle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_ADJUST_QUOTAS, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("Invalid handle (Status %lx)\n", Status); return Status; } /* Get the quota limits attribute */ Size = sizeof(QUOTA_LIMITS); Status = LsapGetObjectAttribute(AccountObject, L"DefQuota", &InternalQuotaLimits, &Size); if (!NT_SUCCESS(Status)) { TRACE("LsapGetObjectAttribute() failed (Status 0x%08lx)\n", Status); return Status; } /* Update the quota limits */ if (QuotaLimits->PagedPoolLimit != 0) InternalQuotaLimits.PagedPoolLimit = QuotaLimits->PagedPoolLimit; if (QuotaLimits->NonPagedPoolLimit != 0) InternalQuotaLimits.NonPagedPoolLimit = QuotaLimits->NonPagedPoolLimit; if (QuotaLimits->MinimumWorkingSetSize != 0) InternalQuotaLimits.MinimumWorkingSetSize = QuotaLimits->MinimumWorkingSetSize; if (QuotaLimits->MaximumWorkingSetSize != 0) InternalQuotaLimits.MaximumWorkingSetSize = QuotaLimits->MaximumWorkingSetSize; if (QuotaLimits->PagefileLimit != 0) InternalQuotaLimits.PagefileLimit = QuotaLimits->PagefileLimit; /* Set the quota limits attribute */ Status = LsapSetObjectAttribute(AccountObject, L"DefQuota", &InternalQuotaLimits, sizeof(QUOTA_LIMITS)); return Status; } /* Function 23 */ NTSTATUS WINAPI LsarGetSystemAccessAccount( LSAPR_HANDLE AccountHandle, ACCESS_MASK *SystemAccess) { PLSA_DB_OBJECT AccountObject; ULONG Size = sizeof(ACCESS_MASK); NTSTATUS Status; TRACE("LsarGetSystemAccessAccount(%p %p)\n", AccountHandle, SystemAccess); /* Validate the account handle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_VIEW, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("Invalid handle (Status %lx)\n", Status); return Status; } /* Get the system access flags */ Status = LsapGetObjectAttribute(AccountObject, L"ActSysAc", SystemAccess, &Size); return Status; } /* Function 24 */ NTSTATUS WINAPI LsarSetSystemAccessAccount( LSAPR_HANDLE AccountHandle, ACCESS_MASK SystemAccess) { PLSA_DB_OBJECT AccountObject; NTSTATUS Status; TRACE("LsarSetSystemAccessAccount(%p %lx)\n", AccountHandle, SystemAccess); /* Validate the account handle */ Status = LsapValidateDbObject(AccountHandle, LsaDbAccountObject, ACCOUNT_ADJUST_SYSTEM_ACCESS, &AccountObject); if (!NT_SUCCESS(Status)) { ERR("Invalid handle (Status %lx)\n", Status); return Status; } /* Set the system access flags */ Status = LsapSetObjectAttribute(AccountObject, L"ActSysAc", &SystemAccess, sizeof(ACCESS_MASK)); return Status; } /* Function 25 */ NTSTATUS WINAPI LsarOpenTrustedDomain( LSAPR_HANDLE PolicyHandle, PRPC_SID TrustedDomainSid, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *TrustedDomainHandle) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 26 */ NTSTATUS WINAPI LsarQueryInfoTrustedDomain( LSAPR_HANDLE TrustedDomainHandle, TRUSTED_INFORMATION_CLASS InformationClass, PLSAPR_TRUSTED_DOMAIN_INFO *TrustedDomainInformation) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 27 */ NTSTATUS WINAPI LsarSetInformationTrustedDomain( LSAPR_HANDLE TrustedDomainHandle, TRUSTED_INFORMATION_CLASS InformationClass, PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 28 */ NTSTATUS WINAPI LsarOpenSecret( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING SecretName, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *SecretHandle) { PLSA_DB_OBJECT PolicyObject; PLSA_DB_OBJECT SecretObject = NULL; NTSTATUS Status = STATUS_SUCCESS; TRACE("LsarOpenSecret(%p %wZ %lx %p)\n", PolicyHandle, SecretName, DesiredAccess, SecretHandle); /* Validate the PolicyHandle */ Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, 0, &PolicyObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* Create the secret object */ Status = LsapOpenDbObject(PolicyObject, L"Secrets", SecretName->Buffer, LsaDbSecretObject, DesiredAccess, PolicyObject->Trusted, &SecretObject); if (!NT_SUCCESS(Status)) { ERR("LsapOpenDbObject failed (Status 0x%08lx)\n", Status); goto done; } done: if (!NT_SUCCESS(Status)) { if (SecretObject != NULL) LsapCloseDbObject(SecretObject); } else { *SecretHandle = (LSAPR_HANDLE)SecretObject; } return Status; } /* Function 29 */ NTSTATUS WINAPI LsarSetSecret( LSAPR_HANDLE SecretHandle, PLSAPR_CR_CIPHER_VALUE EncryptedCurrentValue, PLSAPR_CR_CIPHER_VALUE EncryptedOldValue) { PLSA_DB_OBJECT SecretObject; PBYTE CurrentValue = NULL; PBYTE OldValue = NULL; ULONG CurrentValueLength = 0; ULONG OldValueLength = 0; LARGE_INTEGER Time; NTSTATUS Status; TRACE("LsarSetSecret(%p %p %p)\n", SecretHandle, EncryptedCurrentValue, EncryptedOldValue); /* Validate the SecretHandle */ Status = LsapValidateDbObject(SecretHandle, LsaDbSecretObject, SECRET_SET_VALUE, &SecretObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } if (EncryptedCurrentValue != NULL) { /* FIXME: Decrypt the current value */ CurrentValue = EncryptedCurrentValue->Buffer; CurrentValueLength = EncryptedCurrentValue->MaximumLength; } /* Set the current value */ Status = LsapSetObjectAttribute(SecretObject, L"CurrentValue", CurrentValue, CurrentValueLength); 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 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; } if (EncryptedOldValue != NULL) { /* FIXME: Decrypt the old value */ OldValue = EncryptedOldValue->Buffer; OldValueLength = EncryptedOldValue->MaximumLength; } /* Set the old value */ Status = LsapSetObjectAttribute(SecretObject, L"OldValue", OldValue, OldValueLength); 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: return Status; } /* Function 30 */ NTSTATUS WINAPI LsarQuerySecret( LSAPR_HANDLE SecretHandle, PLSAPR_CR_CIPHER_VALUE *EncryptedCurrentValue, PLARGE_INTEGER CurrentValueSetTime, PLSAPR_CR_CIPHER_VALUE *EncryptedOldValue, PLARGE_INTEGER OldValueSetTime) { PLSA_DB_OBJECT SecretObject; PLSAPR_CR_CIPHER_VALUE EncCurrentValue = NULL; PLSAPR_CR_CIPHER_VALUE EncOldValue = NULL; PBYTE CurrentValue = NULL; PBYTE OldValue = NULL; ULONG CurrentValueLength = 0; ULONG OldValueLength = 0; ULONG BufferSize; NTSTATUS Status; TRACE("LsarQuerySecret(%p %p %p %p %p)\n", SecretHandle, EncryptedCurrentValue, CurrentValueSetTime, EncryptedOldValue, OldValueSetTime); /* Validate the SecretHandle */ Status = LsapValidateDbObject(SecretHandle, LsaDbSecretObject, SECRET_QUERY_VALUE, &SecretObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } if (EncryptedCurrentValue != NULL) { CurrentValueLength = 0; /* 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)); 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)CurrentValue; } if (CurrentValueSetTime != NULL) { BufferSize = sizeof(LARGE_INTEGER); /* Get the current value time */ Status = LsapGetObjectAttribute(SecretObject, L"CurrentTime", (PBYTE)CurrentValueSetTime, &BufferSize); if (!NT_SUCCESS(Status)) goto done; } if (EncryptedOldValue != NULL) { OldValueLength = 0; /* Get the size of the old value */ Status = LsapGetObjectAttribute(SecretObject, L"OldValue", NULL, &OldValueLength); if (!NT_SUCCESS(Status)) goto done; /* Allocate a buffer for the old value */ OldValue = midl_user_allocate(OldValueLength); if (OldValue == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } /* Get the old value */ Status = LsapGetObjectAttribute(SecretObject, L"OldValue", OldValue, &OldValueLength); if (!NT_SUCCESS(Status)) goto done; /* Allocate a buffer for the encrypted old value */ EncOldValue = midl_user_allocate(sizeof(LSAPR_CR_CIPHER_VALUE) + OldValueLength); if (EncOldValue == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } /* FIXME: Encrypt the old value */ EncOldValue->Length = (USHORT)(OldValueLength - sizeof(WCHAR)); EncOldValue->MaximumLength = (USHORT)OldValueLength; EncOldValue->Buffer = (PBYTE)OldValue; } if (OldValueSetTime != NULL) { BufferSize = sizeof(LARGE_INTEGER); /* Get the old value time */ Status = LsapGetObjectAttribute(SecretObject, L"OldTime", (PBYTE)OldValueSetTime, &BufferSize); if (!NT_SUCCESS(Status)) goto done; } done: if (NT_SUCCESS(Status)) { if (EncryptedCurrentValue != NULL) *EncryptedCurrentValue = EncCurrentValue; if (EncryptedOldValue != NULL) *EncryptedOldValue = EncOldValue; } else { if (EncryptedCurrentValue != NULL) *EncryptedCurrentValue = NULL; if (EncryptedOldValue != NULL) *EncryptedOldValue = NULL; if (EncCurrentValue != NULL) midl_user_free(EncCurrentValue); if (EncOldValue != NULL) midl_user_free(EncOldValue); if (CurrentValue != NULL) midl_user_free(CurrentValue); if (OldValue != NULL) midl_user_free(OldValue); } TRACE("LsarQuerySecret done (Status 0x%08lx)\n", Status); return Status; } /* Function 31 */ NTSTATUS WINAPI LsarLookupPrivilegeValue( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING Name, PLUID Value) { PLUID pValue; NTSTATUS Status; TRACE("LsarLookupPrivilegeValue(%p, %wZ, %p)\n", PolicyHandle, Name, Value); Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_LOOKUP_NAMES, NULL); if (!NT_SUCCESS(Status)) { ERR("Invalid handle (Status %lx)\n", Status); return Status; } TRACE("Privilege: %wZ\n", Name); pValue = LsarpLookupPrivilegeValue(Name); if (pValue == NULL) return STATUS_NO_SUCH_PRIVILEGE; RtlCopyLuid(Value, pValue); return STATUS_SUCCESS; } /* Function 32 */ NTSTATUS WINAPI LsarLookupPrivilegeName( LSAPR_HANDLE PolicyHandle, PLUID Value, PRPC_UNICODE_STRING *Name) { NTSTATUS Status; TRACE("LsarLookupPrivilegeName(%p, %p, %p)\n", PolicyHandle, Value, Name); Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_LOOKUP_NAMES, NULL); if (!NT_SUCCESS(Status)) { ERR("Invalid handle\n"); return Status; } Status = LsarpLookupPrivilegeName(Value, Name); return Status; } /* Function 33 */ NTSTATUS WINAPI LsarLookupPrivilegeDisplayName( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING Name, USHORT ClientLanguage, USHORT ClientSystemDefaultLanguage, PRPC_UNICODE_STRING *DisplayName, USHORT *LanguageReturned) { NTSTATUS Status; TRACE("LsarLookupPrivilegeDisplayName(%p, %p, %u, %u, %p, %p)\n", PolicyHandle, Name, ClientLanguage, ClientSystemDefaultLanguage, DisplayName, LanguageReturned); Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_LOOKUP_NAMES, NULL); if (!NT_SUCCESS(Status)) { ERR("Invalid handle\n"); return Status; } Status = LsarpLookupPrivilegeDisplayName(Name, ClientLanguage, ClientSystemDefaultLanguage, DisplayName, LanguageReturned); return Status; } /* Function 34 */ NTSTATUS WINAPI LsarDeleteObject( LSAPR_HANDLE *ObjectHandle) { PLSA_DB_OBJECT DbObject; NTSTATUS Status; TRACE("LsarDeleteObject(%p)\n", ObjectHandle); if (ObjectHandle == NULL) return STATUS_INVALID_PARAMETER; /* Validate the ObjectHandle */ Status = LsapValidateDbObject(*ObjectHandle, LsaDbIgnoreObject, DELETE, &DbObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* You cannot delete the policy object */ if (DbObject->ObjectType == LsaDbPolicyObject) return STATUS_INVALID_PARAMETER; /* Delete the database object */ Status = LsapDeleteDbObject(DbObject); if (!NT_SUCCESS(Status)) { ERR("LsapDeleteDbObject returned 0x%08lx\n", Status); return Status; } /* Invalidate the object handle */ *ObjectHandle = NULL; return STATUS_SUCCESS; } /* Function 35 */ NTSTATUS WINAPI LsarEnumerateAccountsWithUserRight( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING UserRight, PLSAPR_ACCOUNT_ENUM_BUFFER EnumerationBuffer) { PLSA_DB_OBJECT PolicyObject; ACCESS_MASK AccountRight = 0; PLUID Luid = NULL; ULONG AccountKeyBufferSize; PWSTR AccountKeyBuffer = NULL; HKEY AccountsKeyHandle = NULL; HKEY AccountKeyHandle = NULL; HKEY AttributeKeyHandle; ACCESS_MASK SystemAccess; PPRIVILEGE_SET PrivilegeSet; PLSAPR_ACCOUNT_INFORMATION EnumBuffer = NULL, ReturnBuffer; ULONG SubKeyCount = 0; ULONG EnumIndex, EnumCount; ULONG Size, i; BOOL Found; NTSTATUS Status; TRACE("LsarEnumerateAccountsWithUserRights(%p %wZ %p)\n", PolicyHandle, UserRight, EnumerationBuffer); /* Validate the privilege and account right names */ if (UserRight != NULL) { Luid = LsarpLookupPrivilegeValue(UserRight); if (Luid == NULL) { AccountRight = LsapLookupAccountRightValue(UserRight); if (AccountRight == 0) return STATUS_NO_SUCH_PRIVILEGE; } } if (EnumerationBuffer == NULL) return STATUS_INVALID_PARAMETER; EnumerationBuffer->EntriesRead = 0; EnumerationBuffer->Information = NULL; /* Validate the PolicyHandle */ Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &PolicyObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } Status = LsapRegOpenKey(PolicyObject->KeyHandle, L"Accounts", KEY_READ, &AccountsKeyHandle); if (!NT_SUCCESS(Status)) { ERR("LsapRegOpenKey returned 0x%08lx\n", Status); return Status; } Status = LsapRegQueryKeyInfo(AccountsKeyHandle, &SubKeyCount, &AccountKeyBufferSize, NULL); if (!NT_SUCCESS(Status)) { ERR("LsapRegOpenKey returned 0x%08lx\n", Status); return Status; } AccountKeyBufferSize += sizeof(WCHAR); AccountKeyBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, AccountKeyBufferSize); if (AccountKeyBuffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } EnumBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, SubKeyCount * sizeof(LSAPR_ACCOUNT_INFORMATION)); if (EnumBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } EnumCount = 0; EnumIndex = 0; while (TRUE) { Found = FALSE; Status = LsapRegEnumerateSubKey(AccountsKeyHandle, EnumIndex, AccountKeyBufferSize, AccountKeyBuffer); if (!NT_SUCCESS(Status)) { if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS; break; } TRACE("EnumIndex: %lu\n", EnumIndex); TRACE("Account key name: %S\n", AccountKeyBuffer); Status = LsapRegOpenKey(AccountsKeyHandle, AccountKeyBuffer, KEY_READ, &AccountKeyHandle); if (NT_SUCCESS(Status)) { if (Luid != NULL || AccountRight != 0) { Status = LsapRegOpenKey(AccountKeyHandle, (Luid != NULL) ? L"Privilgs" : L"ActSysAc", KEY_READ, &AttributeKeyHandle); if (NT_SUCCESS(Status)) { if (Luid != NULL) { Size = 0; LsapRegQueryValue(AttributeKeyHandle, NULL, NULL, NULL, &Size); if (Size != 0) { PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); if (PrivilegeSet) { if (LsapRegQueryValue(AttributeKeyHandle, NULL, NULL, PrivilegeSet, &Size) == STATUS_SUCCESS) { for (i = 0; i < PrivilegeSet->PrivilegeCount; i++) { if (RtlEqualLuid(&(PrivilegeSet->Privilege[i].Luid), Luid)) { TRACE("%S got the privilege!\n", AccountKeyBuffer); Found = TRUE; break; } } } RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet); } } } else if (AccountRight != 0) { SystemAccess = 0; Size = sizeof(ACCESS_MASK); LsapRegQueryValue(AttributeKeyHandle, NULL, NULL, &SystemAccess, &Size); if (SystemAccess & AccountRight) { TRACE("%S got the account right!\n", AccountKeyBuffer); Found = TRUE; } } LsapRegCloseKey(AttributeKeyHandle); } } else { /* enumerate all accounts */ Found = TRUE; } if (Found == TRUE) { TRACE("Add account: %S\n", AccountKeyBuffer); Status = LsapRegOpenKey(AccountKeyHandle, L"Sid", KEY_READ, &AttributeKeyHandle); if (NT_SUCCESS(Status)) { Size = 0; LsapRegQueryValue(AttributeKeyHandle, NULL, NULL, NULL, &Size); if (Size != 0) { EnumBuffer[EnumCount].Sid = midl_user_allocate(Size); if (EnumBuffer[EnumCount].Sid != NULL) { Status = LsapRegQueryValue(AttributeKeyHandle, NULL, NULL, EnumBuffer[EnumCount].Sid, &Size); if (NT_SUCCESS(Status)) { EnumCount++; } else { TRACE("SampRegQueryValue returned %08lX\n", Status); midl_user_free(EnumBuffer[EnumCount].Sid); EnumBuffer[EnumCount].Sid = NULL; } } } LsapRegCloseKey(AttributeKeyHandle); } } LsapRegCloseKey(AccountKeyHandle); } EnumIndex++; } TRACE("EnumCount: %lu\n", EnumCount); if (NT_SUCCESS(Status) && EnumCount != 0) { ReturnBuffer = midl_user_allocate(EnumCount * sizeof(LSAPR_ACCOUNT_INFORMATION)); if (ReturnBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } RtlCopyMemory(ReturnBuffer, EnumBuffer, EnumCount * sizeof(LSAPR_ACCOUNT_INFORMATION)); EnumerationBuffer->EntriesRead = EnumCount; EnumerationBuffer->Information = ReturnBuffer; } done: if (EnumBuffer != NULL) { if (Status != STATUS_SUCCESS) { for (i = 0; i < EnumCount; i++) { if (EnumBuffer[i].Sid != NULL) midl_user_free(EnumBuffer[i].Sid); } } RtlFreeHeap(RtlGetProcessHeap(), 0, EnumBuffer); } if (AccountKeyBuffer != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AccountKeyBuffer); if (Status == STATUS_SUCCESS && EnumCount == 0) Status = STATUS_NO_MORE_ENTRIES; return Status; } /* Function 36 */ NTSTATUS WINAPI LsarEnumerateAccountRights( LSAPR_HANDLE PolicyHandle, PRPC_SID AccountSid, PLSAPR_USER_RIGHT_SET UserRights) { LSAPR_HANDLE AccountHandle; PLSAPR_PRIVILEGE_SET PrivilegeSet = NULL; PRPC_UNICODE_STRING RightsBuffer = NULL; PRPC_UNICODE_STRING PrivilegeString; ACCESS_MASK SystemAccess = 0; ULONG RightsCount = 0; ULONG Index; ULONG i; NTSTATUS Status; TRACE("LsarEnumerateAccountRights(%p %p %p)\n", PolicyHandle, AccountSid, UserRights); /* Open the account */ Status = LsarOpenAccount(PolicyHandle, AccountSid, ACCOUNT_VIEW, &AccountHandle); if (!NT_SUCCESS(Status)) { WARN("LsarOpenAccount returned 0x%08lx\n", Status); return Status; } /* Enumerate the privileges */ Status = LsarEnumeratePrivilegesAccount(AccountHandle, &PrivilegeSet); 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) && Status != STATUS_OBJECT_NAME_NOT_FOUND) { WARN("LsarGetSystemAccessAccount returned 0x%08lx\n", Status); goto done; } RightsCount = PrivilegeSet->PrivilegeCount; /* Count account rights */ for (i = 0; i < sizeof(ACCESS_MASK) * 8; i++) { if (SystemAccess & (1 << i)) RightsCount++; } /* We are done if there are no rights to be enumerated */ if (RightsCount == 0) { UserRights->Entries = 0; UserRights->UserRights = NULL; Status = STATUS_SUCCESS; goto done; } /* Allocate a buffer for the account rights */ RightsBuffer = MIDL_user_allocate(RightsCount * sizeof(RPC_UNICODE_STRING)); if (RightsBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } /* Copy the privileges into the buffer */ 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 */ for (i = 0; i < sizeof(ACCESS_MASK) * 8; i++) { if (SystemAccess & (1 << i)) { Status = LsapLookupAccountRightName(1 << i, &PrivilegeString); if (!NT_SUCCESS(Status)) { WARN("LsarLookupAccountRightName 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++; } } UserRights->Entries = RightsCount; UserRights->UserRights = (PRPC_UNICODE_STRING)RightsBuffer; done: if (!NT_SUCCESS(Status)) { if (RightsBuffer != NULL) { for (Index = 0; Index < RightsCount; Index++) { if (RightsBuffer[Index].Buffer != NULL) MIDL_user_free(RightsBuffer[Index].Buffer); } MIDL_user_free(RightsBuffer); } } if (PrivilegeSet != NULL) MIDL_user_free(PrivilegeSet); LsarClose(&AccountHandle); return Status; } /* Function 37 */ NTSTATUS WINAPI LsarAddAccountRights( LSAPR_HANDLE PolicyHandle, PRPC_SID AccountSid, PLSAPR_USER_RIGHT_SET UserRights) { 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 AccountSid */ if (!RtlValidSid(AccountSid)) return STATUS_INVALID_PARAMETER; /* Validate the UserRights */ if (UserRights == NULL) return STATUS_INVALID_PARAMETER; /* Validate the privilege and account right names */ for (i = 0; i < UserRights->Entries; i++) { if (LsarpLookupPrivilegeValue(&UserRights->UserRights[i]) != NULL) { ulNewPrivileges++; } else { if (LsapLookupAccountRightValue(&UserRights->UserRights[i]) == 0) return STATUS_NO_SUCH_PRIVILEGE; ulNewRights++; } } TRACE("ulNewPrivileges: %lu\n", ulNewPrivileges); TRACE("ulNewRights: %lu\n", ulNewRights); /* Validate the PolicyHandle */ Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_LOOKUP_NAMES, &PolicyObject); if (!NT_SUCCESS(Status)) { WARN("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* 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 = sizeof(ACCESS_MASK); /* 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++) { Value = LsapLookupAccountRightValue(&UserRights->UserRights[i]); if (Value != 0) 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; } /* Function 38 */ NTSTATUS WINAPI LsarRemoveAccountRights( LSAPR_HANDLE PolicyHandle, PRPC_SID AccountSid, BOOLEAN AllRights, PLSAPR_USER_RIGHT_SET UserRights) { PLSA_DB_OBJECT PolicyObject; PLSA_DB_OBJECT AccountObject = NULL; ULONG PrivilegesToRemove = 0, RightsToRemove = 0; ACCESS_MASK SystemAccess = 0; ULONG Size, Value, i, j, Index; PPRIVILEGE_SET PrivilegeSet = NULL; ULONG PrivilegeCount; PLUID pLuid; NTSTATUS Status; TRACE("LsarRemoveAccountRights(%p %p %lu %p)\n", PolicyHandle, AccountSid, AllRights, UserRights); /* Validate the AccountSid */ if (!RtlValidSid(AccountSid)) return STATUS_INVALID_PARAMETER; /* Validate the UserRights */ if (UserRights == NULL) return STATUS_INVALID_PARAMETER; /* Validate the privilege and account right names */ for (i = 0; i < UserRights->Entries; i++) { if (LsarpLookupPrivilegeValue(&UserRights->UserRights[i]) != NULL) { PrivilegesToRemove++; } else { if (LsapLookupAccountRightValue(&UserRights->UserRights[i]) == 0) return STATUS_NO_SUCH_PRIVILEGE; RightsToRemove++; } } /* Validate the PolicyHandle */ Status = LsapValidateDbObject(PolicyHandle, LsaDbPolicyObject, POLICY_LOOKUP_NAMES, &PolicyObject); if (!NT_SUCCESS(Status)) { ERR("LsapValidateDbObject returned 0x%08lx\n", Status); return Status; } /* Open the account */ Status = LsarpOpenAccount(PolicyObject, AccountSid, 0, &AccountObject); if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) { ERR("LsarpOpenAccount returned 0x%08lx\n", Status); goto done; } if (AllRights == FALSE) { /* Get the size of the Privilgs attribute */ Size = 0; Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", NULL, &Size); if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) goto done; if ((Size != 0) && (PrivilegesToRemove != 0)) { /* Allocate the privilege set buffer */ PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Size); if (PrivilegeSet == NULL) return STATUS_NO_MEMORY; /* Get the privilege set */ Status = LsapGetObjectAttribute(AccountObject, L"Privilgs", PrivilegeSet, &Size); if (!NT_SUCCESS(Status)) { ERR("LsapGetObjectAttribute() failed (Status 0x%08lx)\n", Status); goto done; } PrivilegeCount = PrivilegeSet->PrivilegeCount; for (i = 0; i < UserRights->Entries; i++) { pLuid = LsarpLookupPrivilegeValue(&UserRights->UserRights[i]); if (pLuid == NULL) continue; Index = -1; for (j = 0; j < PrivilegeSet->PrivilegeCount; j++) { if (RtlEqualLuid(&(PrivilegeSet->Privilege[j].Luid), pLuid)) { Index = j; break; } } if (Index != -1) { /* Remove the privilege */ if ((PrivilegeSet->PrivilegeCount > 1) && (Index < PrivilegeSet->PrivilegeCount - 1)) RtlMoveMemory(&(PrivilegeSet->Privilege[Index]), &(PrivilegeSet->Privilege[Index + 1]), (Index - PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID)); /* Wipe the last entry */ RtlZeroMemory(&(PrivilegeSet->Privilege[PrivilegeSet->PrivilegeCount - 1]), 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)) { ERR("LsapSetObjectAttribute() failed (Status 0x%08lx)\n", Status); goto done; } } } /* Get the system access flags, if the attribute exists */ Size = 0; Status = LsapGetObjectAttribute(AccountObject, L"ActSysAc", &SystemAccess, &Size); if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) goto done; if ((Size != 0) && (RightsToRemove != 0)) { ERR("Rights: 0x%lx\n", SystemAccess); /* Set the new access rights */ for (i = 0; i < UserRights->Entries; i++) { Value = LsapLookupAccountRightValue(&UserRights->UserRights[i]); if (Value != 0) SystemAccess &= ~Value; } ERR("New Rights: 0x%lx\n", SystemAccess); /* Set the system access flags */ Status = LsapSetObjectAttribute(AccountObject, L"ActSysAc", &SystemAccess, sizeof(ACCESS_MASK)); } } else { } done: if (PrivilegeSet != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet); if (AccountObject != NULL) LsapCloseDbObject(AccountObject); return Status; } /* Function 39 */ NTSTATUS WINAPI LsarQueryTrustedDomainInfo( LSAPR_HANDLE PolicyHandle, PRPC_SID TrustedDomainSid, TRUSTED_INFORMATION_CLASS InformationClass, PLSAPR_TRUSTED_DOMAIN_INFO *TrustedDomainInformation) { /* FIXME: We are not running an AD yet */ return STATUS_DIRECTORY_SERVICE_REQUIRED; } /* Function 40 */ NTSTATUS WINAPI LsarSetTrustedDomainInfo( LSAPR_HANDLE PolicyHandle, PRPC_SID TrustedDomainSid, TRUSTED_INFORMATION_CLASS InformationClass, PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainInformation) { /* FIXME: We are not running an AD yet */ return STATUS_DIRECTORY_SERVICE_REQUIRED; } /* Function 41 */ NTSTATUS WINAPI LsarDeleteTrustedDomain( LSAPR_HANDLE PolicyHandle, PRPC_SID TrustedDomainSid) { /* FIXME: We are not running an AD yet */ return STATUS_DIRECTORY_SERVICE_REQUIRED; } /* Function 42 */ NTSTATUS WINAPI LsarStorePrivateData( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING KeyName, PLSAPR_CR_CIPHER_VALUE EncryptedData) { 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; } /* Function 43 */ NTSTATUS WINAPI LsarRetrievePrivateData( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING KeyName, PLSAPR_CR_CIPHER_VALUE *EncryptedData) { PLSA_DB_OBJECT PolicyObject = NULL; PLSA_DB_OBJECT SecretObject = NULL; PLSAPR_CR_CIPHER_VALUE EncCurrentValue = NULL; ULONG CurrentValueLength = 0; PBYTE CurrentValue = NULL; NTSTATUS Status; TRACE("LsarRetrievePrivateData(%p %wZ %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 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; } /* Function 44 */ NTSTATUS WINAPI LsarOpenPolicy2( LPWSTR SystemName, PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *PolicyHandle) { return LsarOpenPolicy(SystemName, ObjectAttributes, DesiredAccess, PolicyHandle); } /* Function 45 */ NTSTATUS WINAPI LsarGetUserName( LPWSTR SystemName, PRPC_UNICODE_STRING *UserName, PRPC_UNICODE_STRING *DomainName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 46 */ NTSTATUS WINAPI LsarQueryInformationPolicy2( LSAPR_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_POLICY_INFORMATION *PolicyInformation) { return LsarQueryInformationPolicy(PolicyHandle, InformationClass, PolicyInformation); } /* Function 47 */ NTSTATUS WINAPI LsarSetInformationPolicy2( LSAPR_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_POLICY_INFORMATION PolicyInformation) { return LsarSetInformationPolicy(PolicyHandle, InformationClass, PolicyInformation); } /* Function 48 */ NTSTATUS WINAPI LsarQueryTrustedDomainInfoByName( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING TrustedDomainName, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_TRUSTED_DOMAIN_INFO *PolicyInformation) { /* FIXME: We are not running an AD yet */ return STATUS_OBJECT_NAME_NOT_FOUND; } /* Function 49 */ NTSTATUS WINAPI LsarSetTrustedDomainInfoByName( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING TrustedDomainName, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_TRUSTED_DOMAIN_INFO PolicyInformation) { /* FIXME: We are not running an AD yet */ return STATUS_OBJECT_NAME_NOT_FOUND; } /* Function 50 */ NTSTATUS WINAPI LsarEnumerateTrustedDomainsEx( LSAPR_HANDLE PolicyHandle, DWORD *EnumerationContext, PLSAPR_TRUSTED_ENUM_BUFFER_EX EnumerationBuffer, DWORD PreferedMaximumLength) { /* FIXME: We are not running an AD yet */ EnumerationBuffer->EntriesRead = 0; EnumerationBuffer->EnumerationBuffer = NULL; return STATUS_NO_MORE_ENTRIES; } /* Function 51 */ NTSTATUS WINAPI LsarCreateTrustedDomainEx( LSAPR_HANDLE PolicyHandle, PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation, PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION AuthentificationInformation, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *TrustedDomainHandle) { /* FIXME: We are not running an AD yet */ return STATUS_DIRECTORY_SERVICE_REQUIRED; } /* Function 52 */ NTSTATUS WINAPI LsarSetPolicyReplicationHandle( PLSAPR_HANDLE PolicyHandle) { /* Deprecated */ return STATUS_NOT_IMPLEMENTED; } /* Function 53 */ NTSTATUS WINAPI LsarQueryDomainInformationPolicy( LSAPR_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_POLICY_DOMAIN_INFORMATION *PolicyInformation) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 54 */ NTSTATUS WINAPI LsarSetDomainInformationPolicy( LSAPR_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PLSAPR_POLICY_DOMAIN_INFORMATION PolicyInformation) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 55 */ NTSTATUS WINAPI LsarOpenTrustedDomainByName( LSAPR_HANDLE PolicyHandle, PRPC_UNICODE_STRING TrustedDomainName, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *TrustedDomainHandle) { /* FIXME: We are not running an AD yet */ return STATUS_OBJECT_NAME_NOT_FOUND; } /* Function 56 */ NTSTATUS WINAPI LsarTestCall( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 57 */ NTSTATUS WINAPI LsarLookupSids2( LSAPR_HANDLE PolicyHandle, PLSAPR_SID_ENUM_BUFFER SidEnumBuffer, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_NAMES_EX TranslatedNames, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount, DWORD LookupOptions, DWORD ClientRevision) { NTSTATUS Status; TRACE("LsarLookupSids2(%p %p %p %p %d %p %lu %lu)\n", PolicyHandle, SidEnumBuffer, ReferencedDomains, TranslatedNames, LookupLevel, MappedCount, LookupOptions, ClientRevision); TranslatedNames->Entries = SidEnumBuffer->Entries; TranslatedNames->Names = NULL; *ReferencedDomains = NULL; /* FIXME: Fail, if there is an invalid SID in the SidEnumBuffer */ Status = LsapLookupSids(SidEnumBuffer, ReferencedDomains, TranslatedNames, LookupLevel, MappedCount, LookupOptions, ClientRevision); return Status; } /* Function 58 */ NTSTATUS WINAPI LsarLookupNames2( LSAPR_HANDLE PolicyHandle, DWORD Count, PRPC_UNICODE_STRING Names, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_SIDS_EX TranslatedSids, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount, DWORD LookupOptions, DWORD ClientRevision) { LSAPR_TRANSLATED_SIDS_EX2 TranslatedSidsEx2; ULONG i; NTSTATUS Status; TRACE("LsarLookupNames2(%p %lu %p %p %p %d %p %lu %lu)\n", PolicyHandle, Count, Names, ReferencedDomains, TranslatedSids, LookupLevel, MappedCount, LookupOptions, ClientRevision); TranslatedSids->Entries = 0; TranslatedSids->Sids = NULL; *ReferencedDomains = NULL; if (Count == 0) return STATUS_NONE_MAPPED; TranslatedSidsEx2.Entries = 0; TranslatedSidsEx2.Sids = NULL; Status = LsapLookupNames(Count, Names, ReferencedDomains, &TranslatedSidsEx2, LookupLevel, MappedCount, LookupOptions, ClientRevision); if (!NT_SUCCESS(Status)) return Status; TranslatedSids->Entries = TranslatedSidsEx2.Entries; TranslatedSids->Sids = MIDL_user_allocate(TranslatedSids->Entries * sizeof(LSA_TRANSLATED_SID)); if (TranslatedSids->Sids == NULL) { MIDL_user_free(TranslatedSidsEx2.Sids); MIDL_user_free(*ReferencedDomains); *ReferencedDomains = NULL; return STATUS_INSUFFICIENT_RESOURCES; } for (i = 0; i < TranslatedSidsEx2.Entries; i++) { TranslatedSids->Sids[i].Use = TranslatedSidsEx2.Sids[i].Use; TranslatedSids->Sids[i].RelativeId = LsapGetRelativeIdFromSid(TranslatedSidsEx2.Sids[i].Sid); TranslatedSids->Sids[i].DomainIndex = TranslatedSidsEx2.Sids[i].DomainIndex; TranslatedSids->Sids[i].Flags = TranslatedSidsEx2.Sids[i].Flags; } MIDL_user_free(TranslatedSidsEx2.Sids); return STATUS_SUCCESS; } /* Function 59 */ NTSTATUS WINAPI LsarCreateTrustedDomainEx2( LSAPR_HANDLE PolicyHandle, PLSAPR_TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation, PLSAPR_TRUSTED_DOMAIN_AUTH_INFORMATION_INTERNAL AuthentificationInformation, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *TrustedDomainHandle) { /* FIXME: We are not running an AD yet */ return STATUS_DIRECTORY_SERVICE_REQUIRED; } /* Function 60 */ NTSTATUS WINAPI CredrWrite( PLSAPR_SERVER_NAME SystemName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 61 */ NTSTATUS WINAPI CredrRead( PLSAPR_SERVER_NAME SystemName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 62 */ NTSTATUS WINAPI CredrEnumerate( PLSAPR_SERVER_NAME SystemName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 63 */ NTSTATUS WINAPI CredrWriteDomainCredentials( PLSAPR_SERVER_NAME SystemName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 64 */ NTSTATUS WINAPI CredrReadDomainCredentials( PLSAPR_SERVER_NAME SystemName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 65 */ NTSTATUS WINAPI CredrDelete( PLSAPR_SERVER_NAME SystemName, LPWSTR TargetName, DWORD Type, DWORD Flags) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 66 */ NTSTATUS WINAPI CredrGetTargetInfo( PLSAPR_SERVER_NAME SystemName, LPWSTR TargetName, DWORD Flags, CREDPR_TARGET_INFORMATION *TargetInformation) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 67 */ NTSTATUS WINAPI CredrProfileLoaded( PLSAPR_SERVER_NAME SystemName) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 68 */ NTSTATUS WINAPI LsarLookupNames3( LSAPR_HANDLE PolicyHandle, DWORD Count, PRPC_UNICODE_STRING Names, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_SIDS_EX2 TranslatedSids, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount, DWORD LookupOptions, DWORD ClientRevision) { NTSTATUS Status; TRACE("LsarLookupNames3(%p %lu %p %p %p %d %p %lu %lu)\n", PolicyHandle, Count, Names, ReferencedDomains, TranslatedSids, LookupLevel, MappedCount, LookupOptions, ClientRevision); TranslatedSids->Entries = 0; TranslatedSids->Sids = NULL; *ReferencedDomains = NULL; if (Count == 0) return STATUS_NONE_MAPPED; Status = LsapLookupNames(Count, Names, ReferencedDomains, TranslatedSids, LookupLevel, MappedCount, LookupOptions, ClientRevision); return Status; } /* Function 69 */ NTSTATUS WINAPI CredrGetSessionTypes( PLSAPR_SERVER_NAME SystemName, DWORD MaximumPersistCount, DWORD *MaximumPersist) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 70 */ NTSTATUS WINAPI LsarRegisterAuditEvent( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 71 */ NTSTATUS WINAPI LsarGenAuditEvent( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 72 */ NTSTATUS WINAPI LsarUnregisterAuditEvent( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 73 */ NTSTATUS WINAPI LsarQueryForestTrustInformation( LSAPR_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, LSA_FOREST_TRUST_RECORD_TYPE HighestRecordType, PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 74 */ NTSTATUS WINAPI LsarSetForestTrustInformation( LSAPR_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, LSA_FOREST_TRUST_RECORD_TYPE HighestRecordType, PLSA_FOREST_TRUST_INFORMATION ForestTrustInfo, BOOLEAN CheckOnly, PLSA_FOREST_TRUST_COLLISION_INFORMATION *CollisionInfo) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 75 */ NTSTATUS WINAPI CredrRename( PLSAPR_SERVER_NAME SystemName, LPWSTR OldTargetName, LPWSTR NewTargetName, DWORD Type, DWORD Flags) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 76 */ NTSTATUS WINAPI LsarLookupSids3( LSAPR_HANDLE PolicyHandle, PLSAPR_SID_ENUM_BUFFER SidEnumBuffer, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_NAMES_EX TranslatedNames, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount, DWORD LookupOptions, DWORD ClientRevision) { NTSTATUS Status; TRACE("LsarLookupSids3(%p %p %p %p %d %p %lu %lu)\n", PolicyHandle, SidEnumBuffer, ReferencedDomains, TranslatedNames, LookupLevel, MappedCount, LookupOptions, ClientRevision); TranslatedNames->Entries = SidEnumBuffer->Entries; TranslatedNames->Names = NULL; *ReferencedDomains = NULL; /* FIXME: Fail, if there is an invalid SID in the SidEnumBuffer */ Status = LsapLookupSids(SidEnumBuffer, ReferencedDomains, TranslatedNames, LookupLevel, MappedCount, LookupOptions, ClientRevision); return Status; } /* Function 77 */ NTSTATUS WINAPI LsarLookupNames4( handle_t RpcHandle, DWORD Count, PRPC_UNICODE_STRING Names, PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSAPR_TRANSLATED_SIDS_EX2 TranslatedSids, LSAP_LOOKUP_LEVEL LookupLevel, DWORD *MappedCount, DWORD LookupOptions, DWORD ClientRevision) { NTSTATUS Status; TRACE("LsarLookupNames4(%p %lu %p %p %p %d %p %lu %lu)\n", RpcHandle, Count, Names, ReferencedDomains, TranslatedSids, LookupLevel, MappedCount, LookupOptions, ClientRevision); TranslatedSids->Entries = 0; TranslatedSids->Sids = NULL; *ReferencedDomains = NULL; if (Count == 0) return STATUS_NONE_MAPPED; Status = LsapLookupNames(Count, Names, ReferencedDomains, TranslatedSids, LookupLevel, MappedCount, LookupOptions, ClientRevision); return Status; } /* Function 78 */ NTSTATUS WINAPI LsarOpenPolicySce( LPWSTR SystemName, PLSAPR_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, LSAPR_HANDLE *PolicyHandle) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 79 */ NTSTATUS WINAPI LsarAdtRegisterSecurityEventSource( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 80 */ NTSTATUS WINAPI LsarAdtUnregisterSecurityEventSource( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* Function 81 */ NTSTATUS WINAPI LsarAdtReportSecurityEvent( handle_t hBinding) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } /* EOF */