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