reactos/dll/win32/lsasrv/security.c
George Bișoc bee9b2fcc6
[LSASRV] Set up a security descriptor for the token object
LSASS implements a default ACL inside the token structure field but it doesn't actually set a protective security descriptor for the token object itself. This happens so that the kernel gets whatever default ACLs it finds for the object which is incorrect.

SYSTEM has full and supreme control over tokens, administrators can only read the token as such. The logged in user of their own token has full access. Credits and courtesy goes to Thomas Faber for the patch.
2022-05-06 10:09:36 +02:00

779 lines
26 KiB
C

/*
* PROJECT: Local Security Authority Server DLL
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/win32/lsasrv/security.c
* PURPOSE: LSA object security functions
* COPYRIGHT: Copyright 2012 Eric Kohl
*/
#include "lsasrv.h"
/* FUNCTIONS ***************************************************************/
NTSTATUS
LsapCreatePolicySd(PSECURITY_DESCRIPTOR *PolicySd,
PULONG PolicySdSize)
{
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
ULONG RelativeSdSize = 0;
PSID AnonymousSid = NULL;
PSID AdministratorsSid = NULL;
PSID EveryoneSid = NULL;
PSID LocalServiceSid = NULL;
PSID NetworkServiceSid = NULL;
PSID LocalSystemSid = NULL;
PACL Dacl = NULL;
ULONG DaclSize;
NTSTATUS Status;
if (PolicySd == NULL || PolicySdSize == NULL)
return STATUS_INVALID_PARAMETER;
*PolicySd = NULL;
*PolicySdSize = 0;
/* Initialize the SD */
Status = RtlCreateSecurityDescriptor(&AbsoluteSd,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
return Status;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_ANONYMOUS_LOGON_RID,
0,
0,
0,
0,
0,
0,
0,
&AnonymousSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,
0,
0,
0,
0,
0,
&AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&WorldSidAuthority,
1,
SECURITY_WORLD_RID,
0,
0,
0,
0,
0,
0,
0,
&EveryoneSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_LOCAL_SERVICE_RID,
0,
0,
0,
0,
0,
0,
0,
&LocalServiceSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_NETWORK_SERVICE_RID,
0,
0,
0,
0,
0,
0,
0,
&NetworkServiceSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_LOCAL_SYSTEM_RID,
0,
0,
0,
0,
0,
0,
0,
&LocalSystemSid);
if (!NT_SUCCESS(Status))
goto done;
/* Allocate and initialize the DACL */
DaclSize = sizeof(ACL) +
sizeof(ACCESS_DENIED_ACE) - sizeof(ULONG) + RtlLengthSid(AnonymousSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(AdministratorsSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(EveryoneSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(AnonymousSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(LocalServiceSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(NetworkServiceSid);
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
DaclSize);
if (Dacl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlCreateAcl(Dacl,
DaclSize,
ACL_REVISION);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessDeniedAce(Dacl,
ACL_REVISION,
POLICY_LOOKUP_NAMES,
AnonymousSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
POLICY_ALL_ACCESS | POLICY_NOTIFICATION,
AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
POLICY_EXECUTE,
EveryoneSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
AnonymousSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
POLICY_NOTIFICATION,
LocalServiceSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
POLICY_NOTIFICATION,
NetworkServiceSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd,
TRUE,
Dacl,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetGroupSecurityDescriptor(&AbsoluteSd,
LocalSystemSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetOwnerSecurityDescriptor(&AbsoluteSd,
AdministratorsSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (Status != STATUS_BUFFER_TOO_SMALL)
goto done;
RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
RelativeSdSize);
if (RelativeSd == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (!NT_SUCCESS(Status))
goto done;
*PolicySd = RelativeSd;
*PolicySdSize = RelativeSdSize;
done:
if (Dacl != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
if (AnonymousSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AnonymousSid);
if (AdministratorsSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AdministratorsSid);
if (EveryoneSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, EveryoneSid);
if (LocalServiceSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalServiceSid);
if (NetworkServiceSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, NetworkServiceSid);
if (LocalSystemSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
if (!NT_SUCCESS(Status))
{
if (RelativeSd != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
}
return Status;
}
NTSTATUS
LsapCreateAccountSd(PSECURITY_DESCRIPTOR *AccountSd,
PULONG AccountSdSize)
{
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
ULONG RelativeSdSize = 0;
PSID AdministratorsSid = NULL;
PSID EveryoneSid = NULL;
PSID LocalSystemSid = NULL;
PACL Dacl = NULL;
ULONG DaclSize;
NTSTATUS Status;
if (AccountSd == NULL || AccountSdSize == NULL)
return STATUS_INVALID_PARAMETER;
*AccountSd = NULL;
*AccountSdSize = 0;
/* Initialize the SD */
Status = RtlCreateSecurityDescriptor(&AbsoluteSd,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
return Status;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,
0,
0,
0,
0,
0,
&AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&WorldSidAuthority,
1,
SECURITY_WORLD_RID,
0,
0,
0,
0,
0,
0,
0,
&EveryoneSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_LOCAL_SYSTEM_RID,
0,
0,
0,
0,
0,
0,
0,
&LocalSystemSid);
if (!NT_SUCCESS(Status))
goto done;
/* Allocate and initialize the DACL */
DaclSize = sizeof(ACL) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(AdministratorsSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(EveryoneSid);
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
DaclSize);
if (Dacl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlCreateAcl(Dacl,
DaclSize,
ACL_REVISION);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
ACCOUNT_ALL_ACCESS,
AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
ACCOUNT_EXECUTE,
EveryoneSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd,
TRUE,
Dacl,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetGroupSecurityDescriptor(&AbsoluteSd,
LocalSystemSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetOwnerSecurityDescriptor(&AbsoluteSd,
AdministratorsSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (Status != STATUS_BUFFER_TOO_SMALL)
goto done;
RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
RelativeSdSize);
if (RelativeSd == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (!NT_SUCCESS(Status))
goto done;
*AccountSd = RelativeSd;
*AccountSdSize = RelativeSdSize;
done:
if (Dacl != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
if (AdministratorsSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AdministratorsSid);
if (EveryoneSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, EveryoneSid);
if (LocalSystemSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
if (!NT_SUCCESS(Status))
{
if (RelativeSd != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
}
return Status;
}
NTSTATUS
LsapCreateSecretSd(PSECURITY_DESCRIPTOR *SecretSd,
PULONG SecretSdSize)
{
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
ULONG RelativeSdSize = 0;
PSID AdministratorsSid = NULL;
PSID EveryoneSid = NULL;
PSID LocalSystemSid = NULL;
PACL Dacl = NULL;
ULONG DaclSize;
NTSTATUS Status;
if (SecretSd == NULL || SecretSdSize == NULL)
return STATUS_INVALID_PARAMETER;
*SecretSd = NULL;
*SecretSdSize = 0;
/* Initialize the SD */
Status = RtlCreateSecurityDescriptor(&AbsoluteSd,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
return Status;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,
0,
0,
0,
0,
0,
&AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&WorldSidAuthority,
1,
SECURITY_WORLD_RID,
0,
0,
0,
0,
0,
0,
0,
&EveryoneSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_LOCAL_SYSTEM_RID,
0,
0,
0,
0,
0,
0,
0,
&LocalSystemSid);
if (!NT_SUCCESS(Status))
goto done;
/* Allocate and initialize the DACL */
DaclSize = sizeof(ACL) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(AdministratorsSid) +
sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(EveryoneSid);
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
DaclSize);
if (Dacl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlCreateAcl(Dacl,
DaclSize,
ACL_REVISION);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
SECRET_ALL_ACCESS,
AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
SECRET_EXECUTE,
EveryoneSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd,
TRUE,
Dacl,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetGroupSecurityDescriptor(&AbsoluteSd,
LocalSystemSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetOwnerSecurityDescriptor(&AbsoluteSd,
AdministratorsSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (Status != STATUS_BUFFER_TOO_SMALL)
goto done;
RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
RelativeSdSize);
if (RelativeSd == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (!NT_SUCCESS(Status))
goto done;
*SecretSd = RelativeSd;
*SecretSdSize = RelativeSdSize;
done:
if (Dacl != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
if (AdministratorsSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AdministratorsSid);
if (EveryoneSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, EveryoneSid);
if (LocalSystemSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
if (!NT_SUCCESS(Status))
{
if (RelativeSd != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
}
return Status;
}
/**
* @brief
* Creates a security descriptor for the token
* object.
*
* @param[in] User
* A primary user to be given to the function.
* This user represents the owner that is in
* charge of this object.
*
* @param[out] TokenSd
* A pointer to an allocated security descriptor
* for the token object.
*
* @param[out] TokenSdSize
* A pointer to a returned size of the descriptor.
*
* @return
* STATUS_SUCCESS is returned if the function has
* successfully created the security descriptor.
* STATUS_INVALID_PARAMETER is returned if one of the
* parameters are not valid. STATUS_INSUFFICIENT_RESOURCES
* is returned if memory heap allocation for specific
* security buffers couldn't be done. A NTSTATUS status
* code is returned otherwise.
*
* @remarks
* Bot the local system and user are given full access rights
* for the token (they can open it, read and write into it, etc.)
* whereas admins can only read from the token. This security
* descriptor is TO NOT BE confused with the default DACL of the
* token which is another thing that serves different purpose.
*/
NTSTATUS
LsapCreateTokenSd(
_In_ const TOKEN_USER *User,
_Outptr_ PSECURITY_DESCRIPTOR *TokenSd,
_Out_ PULONG TokenSdSize)
{
SECURITY_DESCRIPTOR AbsoluteSd;
PSECURITY_DESCRIPTOR RelativeSd = NULL;
ULONG RelativeSdSize = 0;
PSID AdministratorsSid = NULL;
PSID LocalSystemSid = NULL;
PACL Dacl = NULL;
ULONG DaclSize;
NTSTATUS Status;
if (TokenSd == NULL || TokenSdSize == NULL)
return STATUS_INVALID_PARAMETER;
*TokenSd = NULL;
*TokenSdSize = 0;
/* Initialize the SD */
Status = RtlCreateSecurityDescriptor(&AbsoluteSd,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
return Status;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0,
&LocalSystemSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAllocateAndInitializeSid(&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
/* Allocate and initialize the DACL */
DaclSize = sizeof(ACL) +
sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(LocalSystemSid) +
sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(AdministratorsSid) +
sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(User->User.Sid);
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
DaclSize);
if (Dacl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlCreateAcl(Dacl,
DaclSize,
ACL_REVISION);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
TOKEN_ALL_ACCESS,
LocalSystemSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
TOKEN_READ,
AdministratorsSid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
TOKEN_ALL_ACCESS,
User->User.Sid);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd,
TRUE,
Dacl,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlSetOwnerSecurityDescriptor(&AbsoluteSd,
AdministratorsSid,
FALSE);
if (!NT_SUCCESS(Status))
goto done;
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (Status != STATUS_BUFFER_TOO_SMALL)
goto done;
RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
RelativeSdSize);
if (RelativeSd == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
RelativeSd,
&RelativeSdSize);
if (!NT_SUCCESS(Status))
goto done;
*TokenSd = RelativeSd;
*TokenSdSize = RelativeSdSize;
done:
if (Dacl != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
if (AdministratorsSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AdministratorsSid);
if (LocalSystemSid != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
if (!NT_SUCCESS(Status))
{
if (RelativeSd != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
}
return Status;
}
/* EOF */