549 lines
11 KiB
C
549 lines
11 KiB
C
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
|
||
|
GENERIC_MAPPING GenericMapping[SPD_OBJECT_COUNT] = {
|
||
|
{
|
||
|
SERVER_READ,
|
||
|
SERVER_WRITE,
|
||
|
SERVER_EXECUTE,
|
||
|
SERVER_ALL_ACCESS
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
InitializeSPDSecurity(
|
||
|
PSECURITY_DESCRIPTOR * ppSPDSD
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
BOOL bOK = FALSE;
|
||
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||
|
PSID pAdminAliasSid = NULL;
|
||
|
DWORD dwAceCount = 0;
|
||
|
UCHAR AceType[MAX_ACE];
|
||
|
PSID AceSid[MAX_ACE];
|
||
|
ACCESS_MASK AceMask[MAX_ACE];
|
||
|
BYTE InheritFlags[MAX_ACE];
|
||
|
DWORD dwObjectType = SPD_OBJECT_SERVER;
|
||
|
PSECURITY_DESCRIPTOR pSPDSD = NULL;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Administrator Alias SID.
|
||
|
//
|
||
|
|
||
|
bOK = AllocateAndInitializeSid(
|
||
|
&NtAuthority,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||
|
0, 0, 0, 0, 0, 0,
|
||
|
&pAdminAliasSid
|
||
|
);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
AceType[dwAceCount] = ACCESS_ALLOWED_ACE_TYPE;
|
||
|
AceSid[dwAceCount] = pAdminAliasSid;
|
||
|
AceMask[dwAceCount] = SERVER_ALL_ACCESS;
|
||
|
InheritFlags[dwAceCount] = 0;
|
||
|
dwAceCount++;
|
||
|
|
||
|
AceType[dwAceCount] = ACCESS_ALLOWED_ACE_TYPE;
|
||
|
AceSid[dwAceCount] = pAdminAliasSid;
|
||
|
AceMask[dwAceCount] = GENERIC_ALL;
|
||
|
InheritFlags[dwAceCount] = INHERIT_ONLY_ACE |
|
||
|
CONTAINER_INHERIT_ACE |
|
||
|
OBJECT_INHERIT_ACE;
|
||
|
dwAceCount++;
|
||
|
|
||
|
if (dwAceCount > MAX_ACE) {
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
dwError = BuildSPDObjectProtection(
|
||
|
dwAceCount,
|
||
|
AceType,
|
||
|
AceSid,
|
||
|
AceMask,
|
||
|
InheritFlags,
|
||
|
pAdminAliasSid,
|
||
|
pAdminAliasSid,
|
||
|
&GenericMapping[dwObjectType],
|
||
|
&pSPDSD
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
*ppSPDSD = pSPDSD;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (pAdminAliasSid) {
|
||
|
FreeSid(pAdminAliasSid);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
*ppSPDSD = NULL;
|
||
|
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
BuildSPDObjectProtection(
|
||
|
DWORD dwAceCount,
|
||
|
PUCHAR pAceType,
|
||
|
PSID * ppAceSid,
|
||
|
PACCESS_MASK pAceMask,
|
||
|
PBYTE pInheritFlags,
|
||
|
PSID pOwnerSid,
|
||
|
PSID pGroupSid,
|
||
|
PGENERIC_MAPPING pGenericMap,
|
||
|
PSECURITY_DESCRIPTOR * ppSecurityDescriptor
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
BOOL bOK = FALSE;
|
||
|
SECURITY_DESCRIPTOR Absolute;
|
||
|
DWORD dwDaclLength = 0;
|
||
|
DWORD i = 0;
|
||
|
PACL pTmpAcl= NULL;
|
||
|
PACCESS_ALLOWED_ACE pTmpAce = NULL;
|
||
|
DWORD dwSDLength = 0;
|
||
|
PSECURITY_DESCRIPTOR pRelative = NULL;
|
||
|
|
||
|
|
||
|
bOK = InitializeSecurityDescriptor(
|
||
|
&Absolute,
|
||
|
SECURITY_DESCRIPTOR_REVISION1
|
||
|
);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
bOK = SetSecurityDescriptorOwner(
|
||
|
&Absolute,
|
||
|
pOwnerSid,
|
||
|
FALSE
|
||
|
);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
bOK = SetSecurityDescriptorGroup(
|
||
|
&Absolute,
|
||
|
pGroupSid,
|
||
|
FALSE
|
||
|
);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Build the Discretionary ACL:
|
||
|
// Calculate its length.
|
||
|
// Allocate it.
|
||
|
// Initialize it.
|
||
|
// Add each ACE.
|
||
|
// Set ACE as InheritOnly if necessary.
|
||
|
// Add it to the security descriptor.
|
||
|
//
|
||
|
|
||
|
dwDaclLength = (DWORD) sizeof(ACL);
|
||
|
|
||
|
for (i = 0; i < dwAceCount; i++) {
|
||
|
|
||
|
dwDaclLength += GetLengthSid(ppAceSid[i]) +
|
||
|
(DWORD) sizeof(ACCESS_ALLOWED_ACE) -
|
||
|
(DWORD) sizeof(DWORD);
|
||
|
|
||
|
//
|
||
|
// Subtract out SidStart field length.
|
||
|
//
|
||
|
|
||
|
}
|
||
|
|
||
|
pTmpAcl = (PACL) AllocSPDMem(dwDaclLength);
|
||
|
|
||
|
if (!pTmpAcl) {
|
||
|
dwError = ERROR_OUTOFMEMORY;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
bOK = InitializeAcl(
|
||
|
pTmpAcl,
|
||
|
dwDaclLength,
|
||
|
ACL_REVISION2
|
||
|
);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < dwAceCount; i++) {
|
||
|
|
||
|
if (pAceType[i] == ACCESS_ALLOWED_ACE_TYPE) {
|
||
|
bOK = AddAccessAllowedAce(
|
||
|
pTmpAcl,
|
||
|
ACL_REVISION2,
|
||
|
pAceMask[i],
|
||
|
ppAceSid[i]
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
bOK = AddAccessDeniedAce(
|
||
|
pTmpAcl,
|
||
|
ACL_REVISION2,
|
||
|
pAceMask[i],
|
||
|
ppAceSid[i]
|
||
|
);
|
||
|
}
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
if (pInheritFlags[i] != 0) {
|
||
|
|
||
|
bOK = GetAce(pTmpAcl, i, (LPVOID *) &pTmpAce);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pTmpAce->Header.AceFlags = pInheritFlags[i];
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
bOK = SetSecurityDescriptorDacl(
|
||
|
&Absolute,
|
||
|
TRUE,
|
||
|
pTmpAcl,
|
||
|
FALSE
|
||
|
);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert the security descriptor from absolute to self-relative:
|
||
|
// Get the length needed.
|
||
|
// Allocate that much memory.
|
||
|
// Copy it.
|
||
|
// Free the generated absolute ACLs.
|
||
|
//
|
||
|
|
||
|
dwSDLength = GetSecurityDescriptorLength(&Absolute);
|
||
|
|
||
|
//
|
||
|
// Must allocate the relative SD from heap.
|
||
|
//
|
||
|
|
||
|
pRelative = LocalAlloc(0, dwSDLength);
|
||
|
if (!pRelative) {
|
||
|
dwError = ERROR_OUTOFMEMORY;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
bOK = MakeSelfRelativeSD(&Absolute, pRelative, &dwSDLength);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
*ppSecurityDescriptor = pRelative;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (pTmpAcl){
|
||
|
FreeSPDMem(pTmpAcl);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
*ppSecurityDescriptor = NULL;
|
||
|
|
||
|
if (pRelative) {
|
||
|
LocalFree(pRelative);
|
||
|
}
|
||
|
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ValidateSecurity(
|
||
|
DWORD dwObjectType,
|
||
|
ACCESS_MASK DesiredAccess,
|
||
|
LPVOID pObjectHandle,
|
||
|
PACCESS_MASK pGrantedAccess
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
|
||
|
ACCESS_MASK MappedDesiredAccess = 0;
|
||
|
BOOL bOK = FALSE;
|
||
|
HANDLE hClientToken = NULL;
|
||
|
BYTE PrivilegeSetBuffer[256];
|
||
|
DWORD dwPrivilegeSetBufferLen = 256;
|
||
|
PPRIVILEGE_SET pPrivilegeSet = NULL;
|
||
|
BOOL bAccessCheckOK = FALSE;
|
||
|
ACCESS_MASK GrantedAccess = 0;
|
||
|
BOOL bAccessStatus = FALSE;
|
||
|
|
||
|
|
||
|
memset(PrivilegeSetBuffer, 0, dwPrivilegeSetBufferLen);
|
||
|
|
||
|
switch (dwObjectType) {
|
||
|
|
||
|
case SPD_OBJECT_SERVER:
|
||
|
pSecurityDescriptor = gpSPDSD;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
dwError = ERROR_ACCESS_DENIED;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
MapGenericToSpecificAccess(
|
||
|
dwObjectType,
|
||
|
DesiredAccess,
|
||
|
&MappedDesiredAccess
|
||
|
);
|
||
|
|
||
|
bOK = GetTokenHandle(&hClientToken);
|
||
|
if (!bOK) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pPrivilegeSet = (PPRIVILEGE_SET) PrivilegeSetBuffer;
|
||
|
|
||
|
bAccessCheckOK = AccessCheck(
|
||
|
pSecurityDescriptor,
|
||
|
hClientToken,
|
||
|
MappedDesiredAccess,
|
||
|
&GenericMapping[dwObjectType],
|
||
|
pPrivilegeSet,
|
||
|
&dwPrivilegeSetBufferLen,
|
||
|
&GrantedAccess,
|
||
|
&bAccessStatus
|
||
|
);
|
||
|
if (!bAccessCheckOK) {
|
||
|
if (GetLastError() == ERROR_NO_IMPERSONATION_TOKEN) {
|
||
|
dwError = ERROR_SUCCESS;
|
||
|
GrantedAccess = MappedDesiredAccess;
|
||
|
}
|
||
|
else {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!bAccessStatus) {
|
||
|
dwError = GetLastError();
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = GrantedAccess;
|
||
|
}
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (hClientToken) {
|
||
|
CloseHandle(hClientToken);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = 0;
|
||
|
}
|
||
|
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
MapGenericToSpecificAccess(
|
||
|
DWORD dwObjectType,
|
||
|
ACCESS_MASK GenericAccess,
|
||
|
PACCESS_MASK pSpecificAccess
|
||
|
)
|
||
|
{
|
||
|
*pSpecificAccess = GenericAccess;
|
||
|
|
||
|
MapGenericMask(
|
||
|
pSpecificAccess,
|
||
|
&GenericMapping[dwObjectType]
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
GetTokenHandle(
|
||
|
PHANDLE phToken
|
||
|
)
|
||
|
{
|
||
|
if (!OpenThreadToken(
|
||
|
GetCurrentThread(),
|
||
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
|
TRUE,
|
||
|
phToken)) {
|
||
|
|
||
|
if (GetLastError() == ERROR_NO_TOKEN) {
|
||
|
|
||
|
//
|
||
|
// This means that there's no impersonation.
|
||
|
// Get the token out of the process.
|
||
|
//
|
||
|
|
||
|
if (!OpenProcessToken(
|
||
|
GetCurrentProcess(),
|
||
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
|
phToken)) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ValidateMMSecurity(
|
||
|
DWORD dwObjectType,
|
||
|
ACCESS_MASK DesiredAccess,
|
||
|
LPVOID pObjectHandle,
|
||
|
PACCESS_MASK pGrantedAccess
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
ACCESS_MASK GrantedAccess = 0;
|
||
|
|
||
|
|
||
|
dwError = ValidateSecurity(
|
||
|
dwObjectType,
|
||
|
DesiredAccess,
|
||
|
pObjectHandle,
|
||
|
&GrantedAccess
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = GrantedAccess;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = 0;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ValidateTxSecurity(
|
||
|
DWORD dwObjectType,
|
||
|
ACCESS_MASK DesiredAccess,
|
||
|
LPVOID pObjectHandle,
|
||
|
PACCESS_MASK pGrantedAccess
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
ACCESS_MASK GrantedAccess = 0;
|
||
|
|
||
|
|
||
|
dwError = ValidateSecurity(
|
||
|
dwObjectType,
|
||
|
DesiredAccess,
|
||
|
pObjectHandle,
|
||
|
&GrantedAccess
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = GrantedAccess;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = 0;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ValidateTnSecurity(
|
||
|
DWORD dwObjectType,
|
||
|
ACCESS_MASK DesiredAccess,
|
||
|
LPVOID pObjectHandle,
|
||
|
PACCESS_MASK pGrantedAccess
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
ACCESS_MASK GrantedAccess = 0;
|
||
|
|
||
|
|
||
|
dwError = ValidateSecurity(
|
||
|
dwObjectType,
|
||
|
DesiredAccess,
|
||
|
pObjectHandle,
|
||
|
&GrantedAccess
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = GrantedAccess;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pGrantedAccess) {
|
||
|
*pGrantedAccess = 0;
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|