|
|
#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); }
|