mirror of
https://github.com/reactos/reactos.git
synced 2024-08-21 10:53:15 +00:00
398 lines
14 KiB
C
398 lines
14 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: Local Security Authority (LSA) Server
|
|
* FILE: reactos/dll/win32/lsasrv/privileges.c
|
|
* PURPOSE: Privilege lookup functions
|
|
*
|
|
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
|
*/
|
|
|
|
#include "lsasrv.h"
|
|
#include "resources.h"
|
|
|
|
typedef struct
|
|
{
|
|
LUID Luid;
|
|
LPCWSTR Name;
|
|
INT DisplayNameId;
|
|
} PRIVILEGE_DATA;
|
|
|
|
typedef struct
|
|
{
|
|
ULONG Flag;
|
|
LPCWSTR Name;
|
|
} RIGHT_DATA;
|
|
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
static const PRIVILEGE_DATA WellKnownPrivileges[] =
|
|
{
|
|
{{SE_CREATE_TOKEN_PRIVILEGE, 0}, SE_CREATE_TOKEN_NAME, IDS_CREATE_TOKEN_PRIVILEGE},
|
|
{{SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0}, SE_ASSIGNPRIMARYTOKEN_NAME, IDS_ASSIGNPRIMARYTOKEN_PRIVILEGE},
|
|
{{SE_LOCK_MEMORY_PRIVILEGE, 0}, SE_LOCK_MEMORY_NAME, IDS_LOCK_MEMORY_PRIVILEGE},
|
|
{{SE_INCREASE_QUOTA_PRIVILEGE, 0}, SE_INCREASE_QUOTA_NAME, IDS_INCREASE_QUOTA_PRIVILEGE},
|
|
{{SE_MACHINE_ACCOUNT_PRIVILEGE, 0}, SE_MACHINE_ACCOUNT_NAME, IDS_MACHINE_ACCOUNT_PRIVILEGE},
|
|
{{SE_TCB_PRIVILEGE, 0}, SE_TCB_NAME, IDS_TCB_PRIVILEGE},
|
|
{{SE_SECURITY_PRIVILEGE, 0}, SE_SECURITY_NAME, IDS_SECURITY_PRIVILEGE},
|
|
{{SE_TAKE_OWNERSHIP_PRIVILEGE, 0}, SE_TAKE_OWNERSHIP_NAME, IDS_TAKE_OWNERSHIP_PRIVILEGE},
|
|
{{SE_LOAD_DRIVER_PRIVILEGE, 0}, SE_LOAD_DRIVER_NAME, IDS_LOAD_DRIVER_PRIVILEGE},
|
|
{{SE_SYSTEM_PROFILE_PRIVILEGE, 0}, SE_SYSTEM_PROFILE_NAME, IDS_SYSTEM_PROFILE_PRIVILEGE},
|
|
{{SE_SYSTEMTIME_PRIVILEGE, 0}, SE_SYSTEMTIME_NAME, IDS_SYSTEMTIME_PRIVILEGE},
|
|
{{SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0}, SE_PROF_SINGLE_PROCESS_NAME, IDS_PROF_SINGLE_PROCESS_PRIVILEGE},
|
|
{{SE_INC_BASE_PRIORITY_PRIVILEGE, 0}, SE_INC_BASE_PRIORITY_NAME, IDS_INC_BASE_PRIORITY_PRIVILEGE},
|
|
{{SE_CREATE_PAGEFILE_PRIVILEGE, 0}, SE_CREATE_PAGEFILE_NAME, IDS_CREATE_PAGEFILE_PRIVILEGE},
|
|
{{SE_CREATE_PERMANENT_PRIVILEGE, 0}, SE_CREATE_PERMANENT_NAME, IDS_CREATE_PERMANENT_PRIVILEGE},
|
|
{{SE_BACKUP_PRIVILEGE, 0}, SE_BACKUP_NAME, IDS_BACKUP_PRIVILEGE},
|
|
{{SE_RESTORE_PRIVILEGE, 0}, SE_RESTORE_NAME, IDS_RESTORE_PRIVILEGE},
|
|
{{SE_SHUTDOWN_PRIVILEGE, 0}, SE_SHUTDOWN_NAME, IDS_SHUTDOWN_PRIVILEGE},
|
|
{{SE_DEBUG_PRIVILEGE, 0}, SE_DEBUG_NAME, IDS_DEBUG_PRIVILEGE},
|
|
{{SE_AUDIT_PRIVILEGE, 0}, SE_AUDIT_NAME, IDS_AUDIT_PRIVILEGE},
|
|
{{SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0}, SE_SYSTEM_ENVIRONMENT_NAME, IDS_SYSTEM_ENVIRONMENT_PRIVILEGE},
|
|
{{SE_CHANGE_NOTIFY_PRIVILEGE, 0}, SE_CHANGE_NOTIFY_NAME, IDS_CHANGE_NOTIFY_PRIVILEGE},
|
|
{{SE_REMOTE_SHUTDOWN_PRIVILEGE, 0}, SE_REMOTE_SHUTDOWN_NAME, IDS_REMOTE_SHUTDOWN_PRIVILEGE},
|
|
{{SE_UNDOCK_PRIVILEGE, 0}, SE_UNDOCK_NAME, IDS_UNDOCK_PRIVILEGE},
|
|
{{SE_SYNC_AGENT_PRIVILEGE, 0}, SE_SYNC_AGENT_NAME, IDS_SYNC_AGENT_PRIVILEGE},
|
|
{{SE_ENABLE_DELEGATION_PRIVILEGE, 0}, SE_ENABLE_DELEGATION_NAME, IDS_ENABLE_DELEGATION_PRIVILEGE},
|
|
{{SE_MANAGE_VOLUME_PRIVILEGE, 0}, SE_MANAGE_VOLUME_NAME, IDS_MANAGE_VOLUME_PRIVILEGE},
|
|
{{SE_IMPERSONATE_PRIVILEGE, 0}, SE_IMPERSONATE_NAME, IDS_IMPERSONATE_PRIVILEGE},
|
|
{{SE_CREATE_GLOBAL_PRIVILEGE, 0}, SE_CREATE_GLOBAL_NAME, IDS_CREATE_GLOBAL_PRIVILEGE}
|
|
};
|
|
|
|
static const RIGHT_DATA WellKnownRights[] =
|
|
{
|
|
{SECURITY_ACCESS_INTERACTIVE_LOGON, SE_INTERACTIVE_LOGON_NAME},
|
|
{SECURITY_ACCESS_NETWORK_LOGON, SE_NETWORK_LOGON_NAME},
|
|
{SECURITY_ACCESS_BATCH_LOGON, SE_BATCH_LOGON_NAME},
|
|
{SECURITY_ACCESS_SERVICE_LOGON, SE_SERVICE_LOGON_NAME},
|
|
{SECURITY_ACCESS_DENY_INTERACTIVE_LOGON, SE_DENY_INTERACTIVE_LOGON_NAME},
|
|
{SECURITY_ACCESS_DENY_NETWORK_LOGON, SE_DENY_NETWORK_LOGON_NAME},
|
|
{SECURITY_ACCESS_DENY_BATCH_LOGON, SE_DENY_BATCH_LOGON_NAME},
|
|
{SECURITY_ACCESS_DENY_SERVICE_LOGON, SE_DENY_SERVICE_LOGON_NAME},
|
|
{SECURITY_ACCESS_REMOTE_INTERACTIVE_LOGON, SE_REMOTE_INTERACTIVE_LOGON_NAME},
|
|
{SECURITY_ACCESS_DENY_REMOTE_INTERACTIVE_LOGON, SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME}
|
|
};
|
|
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
NTSTATUS
|
|
LsarpLookupPrivilegeName(PLUID Value,
|
|
PRPC_UNICODE_STRING *Name)
|
|
{
|
|
PRPC_UNICODE_STRING NameBuffer;
|
|
ULONG Priv;
|
|
|
|
if (Value->HighPart != 0 ||
|
|
(Value->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
|
|
Value->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
|
|
{
|
|
return STATUS_NO_SUCH_PRIVILEGE;
|
|
}
|
|
|
|
for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++)
|
|
{
|
|
if (Value->LowPart == WellKnownPrivileges[Priv].Luid.LowPart &&
|
|
Value->HighPart == WellKnownPrivileges[Priv].Luid.HighPart)
|
|
{
|
|
NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
|
|
if (NameBuffer == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
NameBuffer->Length = wcslen(WellKnownPrivileges[Priv].Name) * sizeof(WCHAR);
|
|
NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
|
|
|
|
NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
|
|
if (NameBuffer->Buffer == NULL)
|
|
{
|
|
MIDL_user_free(NameBuffer);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
wcscpy(NameBuffer->Buffer, WellKnownPrivileges[Priv].Name);
|
|
|
|
*Name = NameBuffer;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return STATUS_NO_SUCH_PRIVILEGE;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsarpLookupPrivilegeDisplayName(PRPC_UNICODE_STRING Name,
|
|
USHORT ClientLanguage,
|
|
USHORT ClientSystemDefaultLanguage,
|
|
PRPC_UNICODE_STRING *DisplayName,
|
|
USHORT *LanguageReturned)
|
|
{
|
|
PRPC_UNICODE_STRING DisplayNameBuffer;
|
|
HINSTANCE hInstance;
|
|
ULONG Index;
|
|
UINT nLength;
|
|
|
|
TRACE("LsarpLookupPrivilegeDisplayName(%p 0x%04hu 0x%04hu %p %p)",
|
|
Name, ClientLanguage, ClientSystemDefaultLanguage, DisplayName, LanguageReturned);
|
|
|
|
if (Name->Length == 0 || Name->Buffer == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
hInstance = GetModuleHandleW(L"lsasrv.dll");
|
|
|
|
for (Index = 0; Index < ARRAYSIZE(WellKnownPrivileges); Index++)
|
|
{
|
|
if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Index].Name) == 0)
|
|
{
|
|
TRACE("Index: %u\n", Index);
|
|
nLength = LsapGetResourceStringLengthEx(hInstance,
|
|
IDS_CREATE_TOKEN_PRIVILEGE + Index,
|
|
ClientLanguage);
|
|
if (nLength != 0)
|
|
{
|
|
DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
|
|
if (DisplayNameBuffer == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
DisplayNameBuffer->Length = nLength * sizeof(WCHAR);
|
|
DisplayNameBuffer->MaximumLength = DisplayNameBuffer->Length + sizeof(WCHAR);
|
|
|
|
DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength);
|
|
if (DisplayNameBuffer->Buffer == NULL)
|
|
{
|
|
MIDL_user_free(DisplayNameBuffer);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
LsapLoadStringEx(hInstance,
|
|
IDS_CREATE_TOKEN_PRIVILEGE + Index,
|
|
ClientLanguage,
|
|
DisplayNameBuffer->Buffer,
|
|
nLength);
|
|
|
|
*DisplayName = DisplayNameBuffer;
|
|
*LanguageReturned = ClientLanguage;
|
|
}
|
|
else
|
|
{
|
|
nLength = LsapGetResourceStringLengthEx(hInstance,
|
|
IDS_CREATE_TOKEN_PRIVILEGE + Index,
|
|
ClientSystemDefaultLanguage);
|
|
if (nLength != 0)
|
|
{
|
|
DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
|
|
if (DisplayNameBuffer == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
DisplayNameBuffer->Length = nLength * sizeof(WCHAR);
|
|
DisplayNameBuffer->MaximumLength = DisplayNameBuffer->Length + sizeof(WCHAR);
|
|
|
|
DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength);
|
|
if (DisplayNameBuffer->Buffer == NULL)
|
|
{
|
|
MIDL_user_free(DisplayNameBuffer);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
LsapLoadStringEx(hInstance,
|
|
IDS_CREATE_TOKEN_PRIVILEGE + Index,
|
|
ClientSystemDefaultLanguage,
|
|
DisplayNameBuffer->Buffer,
|
|
nLength);
|
|
|
|
*DisplayName = DisplayNameBuffer;
|
|
*LanguageReturned = ClientSystemDefaultLanguage;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
#if 0
|
|
nLength = LsapGetResourceStringLengthEx(hInstance,
|
|
IDS_CREATE_TOKEN_PRIVILEGE + Index,
|
|
0x409);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return STATUS_NO_SUCH_PRIVILEGE;
|
|
}
|
|
|
|
|
|
PLUID
|
|
LsarpLookupPrivilegeValue(
|
|
IN PRPC_UNICODE_STRING Name)
|
|
{
|
|
ULONG Priv;
|
|
|
|
if (Name->Length == 0 || Name->Buffer == NULL)
|
|
return NULL;
|
|
|
|
for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++)
|
|
{
|
|
if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0)
|
|
return (PLUID)&(WellKnownPrivileges[Priv].Luid);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsarpEnumeratePrivileges(DWORD *EnumerationContext,
|
|
PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
|
|
DWORD PreferedMaximumLength)
|
|
{
|
|
PLSAPR_POLICY_PRIVILEGE_DEF Privileges = NULL;
|
|
ULONG EnumIndex;
|
|
ULONG EnumCount = 0;
|
|
ULONG RequiredLength = 0;
|
|
ULONG i;
|
|
BOOLEAN MoreEntries = FALSE;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
EnumIndex = *EnumerationContext;
|
|
|
|
for (; EnumIndex < ARRAYSIZE(WellKnownPrivileges); EnumIndex++)
|
|
{
|
|
TRACE("EnumIndex: %lu\n", EnumIndex);
|
|
TRACE("Privilege Name: %S\n", WellKnownPrivileges[EnumIndex].Name);
|
|
TRACE("Name Length: %lu\n", wcslen(WellKnownPrivileges[EnumIndex].Name));
|
|
|
|
if ((RequiredLength +
|
|
wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
|
|
sizeof(UNICODE_NULL) +
|
|
sizeof(LSAPR_POLICY_PRIVILEGE_DEF)) > PreferedMaximumLength)
|
|
{
|
|
MoreEntries = TRUE;
|
|
break;
|
|
}
|
|
|
|
RequiredLength += (wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
|
|
sizeof(UNICODE_NULL) + sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
|
|
EnumCount++;
|
|
}
|
|
|
|
TRACE("EnumCount: %lu\n", EnumCount);
|
|
TRACE("RequiredLength: %lu\n", RequiredLength);
|
|
|
|
if (EnumCount == 0)
|
|
goto done;
|
|
|
|
Privileges = MIDL_user_allocate(EnumCount * sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
|
|
if (Privileges == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
EnumIndex = *EnumerationContext;
|
|
|
|
for (i = 0; i < EnumCount; i++, EnumIndex++)
|
|
{
|
|
Privileges[i].LocalValue = WellKnownPrivileges[EnumIndex].Luid;
|
|
|
|
Privileges[i].Name.Length = (USHORT)wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR);
|
|
Privileges[i].Name.MaximumLength = (USHORT)Privileges[i].Name.Length + sizeof(UNICODE_NULL);
|
|
|
|
Privileges[i].Name.Buffer = MIDL_user_allocate(Privileges[i].Name.MaximumLength);
|
|
if (Privileges[i].Name.Buffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
memcpy(Privileges[i].Name.Buffer,
|
|
WellKnownPrivileges[EnumIndex].Name,
|
|
Privileges[i].Name.Length);
|
|
}
|
|
|
|
done:
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
EnumerationBuffer->Entries = EnumCount;
|
|
EnumerationBuffer->Privileges = Privileges;
|
|
*EnumerationContext += EnumCount;
|
|
}
|
|
else
|
|
{
|
|
if (Privileges != NULL)
|
|
{
|
|
for (i = 0; i < EnumCount; i++)
|
|
{
|
|
if (Privileges[i].Name.Buffer != NULL)
|
|
MIDL_user_free(Privileges[i].Name.Buffer);
|
|
}
|
|
|
|
MIDL_user_free(Privileges);
|
|
}
|
|
}
|
|
|
|
if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE))
|
|
Status = STATUS_MORE_ENTRIES;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapLookupAccountRightName(ULONG RightValue,
|
|
PRPC_UNICODE_STRING *Name)
|
|
{
|
|
PRPC_UNICODE_STRING NameBuffer;
|
|
ULONG i;
|
|
|
|
for (i = 0; i < ARRAYSIZE(WellKnownRights); i++)
|
|
{
|
|
if (WellKnownRights[i].Flag == RightValue)
|
|
{
|
|
NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
|
|
if (NameBuffer == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
|
|
NameBuffer->Length = wcslen(WellKnownRights[i].Name) * sizeof(WCHAR);
|
|
NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
|
|
|
|
NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
|
|
if (NameBuffer->Buffer == NULL)
|
|
{
|
|
MIDL_user_free(NameBuffer);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
wcscpy(NameBuffer->Buffer, WellKnownRights[i].Name);
|
|
|
|
*Name = NameBuffer;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return STATUS_NO_SUCH_PRIVILEGE;
|
|
}
|
|
|
|
|
|
ACCESS_MASK
|
|
LsapLookupAccountRightValue(
|
|
IN PRPC_UNICODE_STRING Name)
|
|
{
|
|
ULONG i;
|
|
|
|
if (Name->Length == 0 || Name->Buffer == NULL)
|
|
return 0;
|
|
|
|
for (i = 0; i < ARRAYSIZE(WellKnownRights); i++)
|
|
{
|
|
if (_wcsicmp(Name->Buffer, WellKnownRights[i].Name) == 0)
|
|
return WellKnownRights[i].Flag;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* EOF */
|