/*++ Copyright (c) 1998 Microsoft Corporation Module Name: FixUp.c Abstract: This module contains common security routines for NT Clusters rolling upgrade and backward compatibility. Author: Galen Barbee (galenb) 31-Mar-1998 --*/ #include "clusrtlp.h" PSECURITY_DESCRIPTOR ClRtlConvertClusterSDToNT4Format( IN PSECURITY_DESCRIPTOR psd ) /*++ Routine Description: Convert the SD from nt 5 to nt 4 format. This means enforcing the following rules: 1. Convert denied ACE to allowed ACE. Convert "Full Control" access mask to CLUAPI_NO_ACCESS. Arguments: psd [IN] Security descriptor. Return Value: The new SD in self-Relative format --*/ { PACL pacl; BOOL bHasDACL; BOOL bDACLDefaulted; PSECURITY_DESCRIPTOR psec = NULL; if (NULL == psd) { return NULL; } psec = ClRtlCopySecurityDescriptor(psd); ASSERT(psec != NULL); if ( (GetSecurityDescriptorDacl(psec, (LPBOOL) &bHasDACL, (PACL *) &pacl, (LPBOOL) &bDACLDefaulted)) && ( bHasDACL != FALSE ) ) { ACL_SIZE_INFORMATION asiAclSize; DWORD dwBufLength; dwBufLength = sizeof(asiAclSize); if (GetAclInformation(pacl, &asiAclSize, dwBufLength, AclSizeInformation)) { ACCESS_DENIED_ACE * pAce; DWORD dwIndex; for (dwIndex = 0; dwIndex < asiAclSize.AceCount; dwIndex++) { if (GetAce(pacl, dwIndex, (LPVOID *) &pAce)) { if (pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { if (pAce->Mask & SPECIFIC_RIGHTS_ALL) { pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pAce->Mask = CLUSAPI_NO_ACCESS; } } // end if (pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) } // end if (GetAce()) } // end for } // end if (GetAclInformation()) } // end if (HrGetSecurityDescriptorDacl()) and DACL is present ASSERT(IsValidSecurityDescriptor(psec)); return psec; } //*** ClRtlConvertClusterSDToNT4Format() PSECURITY_DESCRIPTOR ClRtlConvertClusterSDToNT5Format( IN PSECURITY_DESCRIPTOR psd ) /*++ Routine Description: Convert the SD from nt 5 to nt 4 format. This means enforcing the following rules: 1. Convert allowed ACE with mask CLUAPI_NO_ACCESS to denied ACE mask full control. Arguments: psd [IN] Security descriptor. Return Value: The new SD in self-Relative format --*/ { PACL pacl; BOOL bHasDACL; BOOL bDACLDefaulted; PSECURITY_DESCRIPTOR psec = NULL; if (NULL == psd) { return NULL; } psec = ClRtlCopySecurityDescriptor(psd); ASSERT(psec != NULL); if ( (GetSecurityDescriptorDacl(psec, (LPBOOL) &bHasDACL, (PACL *) &pacl, (LPBOOL) &bDACLDefaulted)) && ( bHasDACL != FALSE ) ) { ACL_SIZE_INFORMATION asiAclSize; DWORD dwBufLength; dwBufLength = sizeof(asiAclSize); if (GetAclInformation(pacl, &asiAclSize, dwBufLength, AclSizeInformation)) { ACCESS_DENIED_ACE * pAce; DWORD dwIndex; for (dwIndex = 0; dwIndex < asiAclSize.AceCount; dwIndex++) { if (GetAce(pacl, dwIndex, (LPVOID *) &pAce)) { if (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { if (pAce->Mask & CLUSAPI_NO_ACCESS) { pAce->Header.AceType = ACCESS_DENIED_ACE_TYPE; pAce->Mask = SPECIFIC_RIGHTS_ALL; } } // end if (pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) } // end if (GetAce()) } // end for } // end if (GetAclInformation()) } // end if (HrGetSecurityDescriptorDacl()) and DACL is present ASSERT(IsValidSecurityDescriptor(psec)); return psec; } //*** ClRtlConvertClusterSDToNT5Format() static GENERIC_MAPPING gmFileShareMap = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }; #define SPECIFIC_CHANGE (DELETE | FILE_GENERIC_WRITE) #define SPECIFIC_READ (FILE_GENERIC_READ | FILE_LIST_DIRECTORY | FILE_EXECUTE) #define GENERIC_CHANGE (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE) PSECURITY_DESCRIPTOR ClRtlConvertFileShareSDToNT4Format( IN PSECURITY_DESCRIPTOR psd ) /*++ Routine Description: Convert the SD from nt 5 to nt 4 format. This means enforcing the following rules: Arguments: psd [IN] Security descriptor. Return Value: The new SD in self-Relative format --*/ { PACL pacl; BOOL bHasDACL; BOOL bDACLDefaulted; PSECURITY_DESCRIPTOR psec = NULL; if (NULL == psd) { return NULL; } psec = ClRtlCopySecurityDescriptor(psd); ASSERT(psec != NULL); if ( (GetSecurityDescriptorDacl(psec, (LPBOOL) &bHasDACL, (PACL *) &pacl, (LPBOOL) &bDACLDefaulted)) && ( bHasDACL != FALSE ) ) { ACL_SIZE_INFORMATION asiAclSize; DWORD dwBufLength; ACCESS_MASK amTemp1; ACCESS_MASK amTemp2; dwBufLength = sizeof(asiAclSize); if (GetAclInformation(pacl, &asiAclSize, dwBufLength, AclSizeInformation)) { ACCESS_DENIED_ACE * pAce; DWORD dwSid; DWORD dwIndex; for (dwIndex = 0; dwIndex < asiAclSize.AceCount; dwIndex++) { amTemp1 = 0; amTemp2 = 0; if (GetAce(pacl, dwIndex, (LPVOID *) &pAce)) { // delete deny read ACEs since they don't mean anything to AclEdit if ((pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) && (pAce->Mask == SPECIFIC_READ)) { dwSid = pAce->SidStart; if (DeleteAce(pacl, dwIndex)) { asiAclSize.AceCount -= 1; dwIndex -= 1; } else { ClRtlDbgPrint(LOG_UNUSUAL, "[ClRtl] DeteteAce failed removing ACE #%1!d! due to error %2!d!\n", dwIndex, GetLastError()); } continue; } // convert deny change deny read ACEs to deny all ACEs if ((pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) && (pAce->Mask == (SPECIFIC_CHANGE | SPECIFIC_READ))) { pAce->Mask = GENERIC_ALL; continue; } // convert deny change ACEs to allow read (read only) ACEs if ((pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) && (pAce->Mask == SPECIFIC_CHANGE)) { pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pAce->Mask = GENERIC_READ | GENERIC_EXECUTE; continue; } // convert specific allow change to generic allow change if ((pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) && (pAce->Mask == SPECIFIC_CHANGE)) { pAce->Mask = GENERIC_CHANGE; continue; } // convert specific all to generic all if ((pAce->Mask & gmFileShareMap.GenericAll) == gmFileShareMap.GenericAll) { amTemp1 |= GENERIC_ALL; amTemp2 |= gmFileShareMap.GenericAll; } else { // convert specific read to generic read if ((pAce->Mask & gmFileShareMap.GenericRead) == gmFileShareMap.GenericRead) { amTemp1 |= GENERIC_READ; amTemp2 |= gmFileShareMap.GenericRead; } // convert specific write to generic write which includes delete if ((pAce->Mask & gmFileShareMap.GenericWrite) == gmFileShareMap.GenericWrite) { amTemp1 |= (GENERIC_WRITE | DELETE); amTemp2 |= gmFileShareMap.GenericWrite; } // convert specific execute to generic execute if ((pAce->Mask & gmFileShareMap.GenericExecute) == gmFileShareMap.GenericExecute) { amTemp1 |= GENERIC_EXECUTE; amTemp2 |= gmFileShareMap.GenericExecute; } } pAce->Mask &= ~amTemp2; // turn off specific bits pAce->Mask |= amTemp1; // turn on generic bits } // end if (GetAce()) } // end for } // end if (GetAclInformation()) } // end if (HrGetSecurityDescriptorDacl()) and DACL is present ASSERT(IsValidSecurityDescriptor(psec)); return psec; } //*** ClRtlConvertFileShareSDToNT4Format()