///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998-2000 Microsoft Corporation // // Module Name: // ClusPage.cpp // // Abstract: // CClusterSecurityPage class implementation. This class will encapsulate // the cluster security extension page. // // Author: // Galen Barbee (galenb) February 11, 1998 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "resource.h" #include "ClusPage.h" #include "AclUtils.h" #include static GENERIC_MAPPING ShareMap = { CLUSAPI_READ_ACCESS, CLUSAPI_CHANGE_ACCESS, CLUSAPI_NO_ACCESS, CLUSAPI_ALL_ACCESS }; static SI_ACCESS siClusterAccesses[] = { { &GUID_NULL, CLUSAPI_ALL_ACCESS, MAKEINTRESOURCE(IDS_ACLEDIT_PERM_GEN_ALL), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC /*| OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE*/ } }; ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::CClusterSecurityInformation // // Routine Description: // Default contructor // // Arguments: // none // // Return Value: // none // //-- ///////////////////////////////////////////////////////////////////////////// CClusterSecurityInformation::CClusterSecurityInformation( void ) : m_pcsp( NULL ) { m_pShareMap = &ShareMap; m_psiAccess = (SI_ACCESS *) &siClusterAccesses; m_nAccessElems = ARRAYSIZE( siClusterAccesses ); m_nDefAccess = 0; m_dwFlags = SI_EDIT_PERMS | SI_NO_ACL_PROTECT //| SI_UGOP_PROVIDED //| SI_NO_UGOP_ACCOUNT_GROUPS //| SI_NO_UGOP_USERS //| SI_NO_UGOP_LOCAL_GROUPS //| SI_NO_UGOP_WELLKNOWN //| SI_NO_UGOP_BUILTIN ; } //*** CClusterSecurityInformation::CClusterSecurityInformation() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::GetSecurity // // Routine Description: // Give our security descriptor to the ISecurityInfomation UI // so it can be displayed and edited. // // Arguments: // RequestedInformation [IN] // ppSecurityDescriptor [IN OUT] // fDefault [IN] // // Return Value: // E_FAIL for error and S_OK for success. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusterSecurityInformation::GetSecurity( IN SECURITY_INFORMATION RequestedInformation, IN OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor, IN BOOL fDefault ) { AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); HRESULT hr = E_FAIL; try { if ( ppSecurityDescriptor != NULL ) { PSECURITY_DESCRIPTOR pSD = NULL; pSD = ClRtlCopySecurityDescriptor( Pcsp()->Psec() ); if ( pSD != NULL ) { //hr = HrFixupSD( pSD ); //if ( SUCCEEDED( hr ) ) //{ *ppSecurityDescriptor = pSD; //} hr = S_OK; } // if: no errors copying the security descriptor else { hr = GetLastError(); TRACE( _T("CClusterSecurityInformation::GetSecurity() - Error %08.8x copying the security descriptor.\n"), hr ); hr = HRESULT_FROM_WIN32( hr ); } // else: error copying the security descriptor } else { hr = S_OK; } // else: no security descriptor pointer } catch ( ... ) { TRACE( _T("CClusterSecurityInformation::GetSecurity() - Unknown error occurred.\n") ); } return hr; } //*** CClusterSecurityInformation::GetSecurity() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::SetSecurity // // Routine Description: // ISecurityInformation is giving back the edited security descriptor. // // Arguments: // SecurityInformation [IN] // pSecurityDescriptor [IN OUT] // // Return Value: // E_FAIL for error and S_OK for success. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusterSecurityInformation::SetSecurity( IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR pSecurityDescriptor ) { AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); HRESULT hr = E_FAIL; PSID pSystemSid = NULL; PSID pAdminSid = NULL; PSID pNetServiceSid = NULL; try { SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; hr = CSecurityInformation::SetSecurity( SecurityInformation, pSecurityDescriptor ); if ( hr == S_OK ) { if ( AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSid ) ) { CString strMsg; if ( BSidInSD( pSecurityDescriptor, pSystemSid ) ) { // // allocate and init the Administrators group sid // if ( AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSid ) ) { if ( BSidInSD( pSecurityDescriptor, pAdminSid ) ) { // // allocate and init the Network Service sid // if ( AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pNetServiceSid ) ) { if ( BSidInSD( pSecurityDescriptor, pNetServiceSid ) ) { hr = Pcsp()->HrSetSecurityDescriptor( pSecurityDescriptor ); } // if: service SID in the SD else { strMsg.LoadString( IDS_NETSERVICE_ACCOUNT_NOT_SPECIFIED ); AfxMessageBox( strMsg, MB_OK | MB_ICONSTOP ); hr = S_FALSE; // if there are missing required accounts then return S_FALSE to keep AclUi alive. } // else } // if: allocate and init service SID } // if: admin SID in the SD else { strMsg.LoadString( IDS_ADMIN_ACCOUNT_NOT_SPECIFIED ); AfxMessageBox( strMsg, MB_OK | MB_ICONSTOP ); hr = S_FALSE; // if there are missing required accounts then return S_FALSE to keep AclUi alive. } // else } // if: allocate and init admin SID } // if: system SID in the SD else { strMsg.LoadString( IDS_SYS_ACCOUNT_NOT_SPECIFIED ); AfxMessageBox( strMsg, MB_OK | MB_ICONSTOP ); hr = S_FALSE; // if there are missing required accounts then return S_FALSE to keep AclUi alive. } // else } // if: allocate and init system SID } // if: CSecurityInformation::SetSecurity() worked } catch( ... ) { ; } if ( pSystemSid != NULL ) { FreeSid( pSystemSid ); } if ( pAdminSid != NULL ) { FreeSid( pAdminSid ); } if ( pNetServiceSid != NULL ) { FreeSid( pNetServiceSid ); } return hr; } //*** CClusterSecurityInformation::SetSecurity() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::HrInit // // Routine Description: // Initialize method. // // Arguments: // pcsp [IN] back pointer to parent property page wrapper // strServer [IN] cluster name // // Return Value: // S_OK for success. E_FAIL for failure. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityInformation::HrInit( IN CClusterSecurityPage * pcsp, IN CString const & strServer, IN CString const & strNode ) { ASSERT( pcsp != NULL ); ASSERT( strServer.GetLength() > 0 ); AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); m_pcsp = pcsp; m_strServer = strServer; m_strNode = strNode; m_nLocalSIDErrorMessageID = IDS_LOCAL_ACCOUNTS_SPECIFIED_CLUS; return S_OK; } //*** CClusterSecurityInformation::HrInit() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::BSidInSD // // Routine Description: // Determines if there is an ACEs for the passed in SID in the // Security Descriptor (pSD) after the ACL editor has been called // // Arguments: // pSD [IN] - Security Descriptor to be checked. // pSid [IN] - SID to look for // // Return Value: // TRUE if an ACE for the SID was found, False otherwise. // ///////////////////////////////////////////////////////////////////////////// BOOL CClusterSecurityInformation::BSidInSD( IN PSECURITY_DESCRIPTOR pSD, IN PSID pSid ) { BOOL bSIdInACL = FALSE; try { PACL pDACL = NULL; BOOL bHasDACL = FALSE; BOOL bDaclDefaulted = FALSE; if ( ::GetSecurityDescriptorDacl( pSD, &bHasDACL, &pDACL, &bDaclDefaulted ) ) { if ( bHasDACL && ( pDACL != NULL ) && ::IsValidAcl( pDACL ) ) { ACL_SIZE_INFORMATION asiAclSize; ACCESS_ALLOWED_ACE * paaAllowedAce; if ( ::GetAclInformation( pDACL, (LPVOID) &asiAclSize, sizeof( asiAclSize ), AclSizeInformation ) ) { // // Search the ACL for the SID // for ( DWORD dwCount = 0; dwCount < asiAclSize.AceCount; dwCount++ ) { if ( ::GetAce( pDACL, dwCount, (LPVOID *) &paaAllowedAce ) ) { if ( paaAllowedAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ) { if ( EqualSid( &paaAllowedAce->SidStart, pSid ) ) { bSIdInACL = TRUE; break; } // if: EqualSid } // if: is this an access allowed ace? } // if: can we get the ace from the DACL? } // for } // if: get ACL information } // if: is the ACL valid } // if: get the ACL from the SD } catch ( ... ) { TRACE( _T("CClusterSecurityInformation::BSidInSD() - Unknown error occurred.\n") ); } return bSIdInACL; } //*** CClusterSecurityInformation::BSidInSD() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::HrFixupSD // // Routine Description: // Performs any fixups to the SD that may be requrired. // // Arguments: // pSD [IN] - Security Descriptor to be checked. // // Return Value: // S_OK, or other Win32 error // ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityInformation::HrFixupSD( IN PSECURITY_DESCRIPTOR pSD ) { HRESULT hr = S_OK; PSID pSystemSid = NULL; PSID pAdminSid = NULL; PSID pNetServiceSid = NULL; try { SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; if ( AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSid ) ) { if ( ! BSidInSD( pSD, pSystemSid ) ) { HrAddSidToSD( &pSD, pSystemSid ); } // if: system SID found in SD } // if: allocate system SID // // allocate and init the Administrators group sid // if ( AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSid ) ) { if ( ! BSidInSD( pSD, pAdminSid ) ) { HrAddSidToSD( &pSD, pAdminSid ); } // if: admin SID found in SD } // if: allocate admin SID // // allocate and init the Network Service sid // if ( AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pNetServiceSid ) ) { if ( ! BSidInSD( pSD, pNetServiceSid ) ) { HrAddSidToSD( &pSD, pNetServiceSid ); } // if: Network Service SID found in SD } // if: allocate Network Service SID } catch ( ... ) { TRACE( _T("CClusterSecurityInformation::HrFixupSD() - Unknown error occurred.\n") ); } if ( pSystemSid != NULL ) { FreeSid( pSystemSid ); } if ( pAdminSid != NULL ) { FreeSid( pAdminSid ); } if ( pNetServiceSid != NULL ) { FreeSid( pNetServiceSid ); } return hr; } //*** CClusterSecurityInformation::HrFixupSD() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityInformation::HrAddSidToSD // // Routine Description: // Adds the passed in SID to the DACL of the passed in SD // // Arguments: // ppSD [IN, OUT] - Security Descriptor to be added to // PSid [IN] - SID to add // // Return Value: // S_OK, or other Win32 error // ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityInformation::HrAddSidToSD( IN OUT PSECURITY_DESCRIPTOR * ppSD, IN PSID pSid ) { HRESULT hr = S_OK; DWORD sc; SECURITY_DESCRIPTOR sd; DWORD dwSDLen = sizeof( SECURITY_DESCRIPTOR ); PACL pDacl = NULL; DWORD dwDaclLen = 0; PACL pSacl = NULL; DWORD dwSaclLen = 0; PSID pOwnerSid = NULL; DWORD dwOwnerSidLen = 0; PSID pGroupSid = NULL; DWORD dwGroupSidLen = NULL; PSECURITY_DESCRIPTOR pNewSD = NULL; DWORD dwNewSDLen = 0; try { BOOL bRet = FALSE; bRet = ::MakeAbsoluteSD( *ppSD, // address of self relative SD &sd, // address of absolute SD &dwSDLen, // address of size of absolute SD NULL, // address of discretionary ACL &dwDaclLen, // address of size of discretionary ACL NULL, // address of system ACL &dwSaclLen, // address of size of system ACL NULL, // address of owner SID &dwOwnerSidLen, // address of size of owner SID NULL, // address of primary-group SID &dwGroupSidLen // address of size of group SID ); if ( ! bRet ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); if ( hr != ERROR_INSUFFICIENT_BUFFER ) // Duh, we're trying to find out how big the buffer should be? { goto fnExit; } } // // increase the DACL length to hold one more ace and its sid. // dwDaclLen += ( sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( pSid ) +1024 ); pDacl = (PACL) ::LocalAlloc( LMEM_ZEROINIT, dwDaclLen ); if ( pDacl == NULL ) { hr = E_OUTOFMEMORY; goto fnExit; } InitializeAcl( pDacl, dwDaclLen, ACL_REVISION ); if ( dwSaclLen > 0 ) { pSacl = (PACL) ::LocalAlloc( LMEM_ZEROINIT, dwSaclLen ); if ( pSacl == NULL ) { hr = E_OUTOFMEMORY; goto fnExit; } } if ( dwOwnerSidLen > 0 ) { pOwnerSid = (PSID) ::LocalAlloc( LMEM_ZEROINIT, dwOwnerSidLen ); if ( pOwnerSid == NULL ) { hr = E_OUTOFMEMORY; goto fnExit; } } if ( dwGroupSidLen > 0 ) { pGroupSid = (PSID) ::LocalAlloc( LMEM_ZEROINIT, dwGroupSidLen ); if ( pGroupSid == NULL ) { hr = E_OUTOFMEMORY; goto fnExit; } } bRet = ::MakeAbsoluteSD( *ppSD, // address of self relative SD &sd, // address of absolute SD &dwSDLen, // address of size of absolute SD pDacl, // address of discretionary ACL &dwDaclLen, // address of size of discretionary ACL pSacl, // address of system ACL &dwSaclLen, // address of size of system ACL pOwnerSid, // address of owner SID &dwOwnerSidLen, // address of size of owner SID pGroupSid, // address of primary-group SID &dwGroupSidLen // address of size of group SID ); if ( !bRet ) { goto fnExit; } // // Add the ACE for the SID to the DACL // // if ( !AddAccessAllowedAceEx( pDacl, // ACL_REVISION, // CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, // CLUSAPI_ALL_ACCESS, // pSid ) ) if ( ! AddAccessAllowedAce( pDacl, ACL_REVISION, CLUSAPI_ALL_ACCESS, pSid ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); goto fnExit; } if ( ! ::SetSecurityDescriptorDacl( &sd, TRUE, pDacl, FALSE ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); goto fnExit; } if ( ! ::SetSecurityDescriptorOwner( &sd, pOwnerSid, FALSE ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); goto fnExit; } if ( ! ::SetSecurityDescriptorGroup( &sd, pGroupSid, FALSE ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); goto fnExit; } if ( ! ::SetSecurityDescriptorSacl( &sd, TRUE, pSacl, FALSE ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); goto fnExit; } dwNewSDLen = 0 ; if ( ! ::MakeSelfRelativeSD( &sd, NULL, &dwNewSDLen ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); if ( hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) ) // Duh, we're trying to find out how big the buffer should be? { goto fnExit; } } pNewSD = ::LocalAlloc( LPTR, dwNewSDLen ); if ( pNewSD != NULL ) { if ( ! ::MakeSelfRelativeSD( &sd, pNewSD, &dwNewSDLen ) ) { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); goto fnExit; } ::LocalFree( *ppSD ); *ppSD = pNewSD; hr = ERROR_SUCCESS; } else { hr = ERROR_NOT_ENOUGH_MEMORY; } } catch ( ... ) { TRACE( _T("CClusterSecurityInformation::HrAddSidToSD() - Unknown error occurred.\n") ); } fnExit: if ( pSacl != NULL ) { ::LocalFree( pSacl ); } if ( pOwnerSid != NULL ) { ::LocalFree( pOwnerSid ); } if ( pGroupSid != NULL ) { ::LocalFree( pGroupSid ); } return hr; } //*** CClusterSecurityInformation::HrAddSidToSD() //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::CClusterSecurityPage // // Routine Description: // Default contructor. // // Arguments: // none // // Return Value: // none // //-- ///////////////////////////////////////////////////////////////////////////// CClusterSecurityPage::CClusterSecurityPage( void ) : m_psec( NULL ) , m_psecPrev( NULL ) , m_hpage( 0 ) , m_hkey( 0 ) , m_psecinfo( NULL ) , m_pOwner( NULL ) , m_pGroup( NULL ) , m_fOwnerDef( FALSE ) , m_fGroupDef( FALSE ) { AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); m_bSecDescModified = FALSE; } //*** CClusterSecurityPage::CClusterSecurityPage() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::~CClusterSecurityPage // // Routine Description: // Destructor // // Arguments: // none // // Return Value: // none // //-- ///////////////////////////////////////////////////////////////////////////// CClusterSecurityPage::~CClusterSecurityPage( void ) { AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); ::LocalFree( m_psec ); m_psec = NULL; ::LocalFree( m_psecPrev ); m_psecPrev = NULL; ::LocalFree( m_pOwner ); m_pOwner = NULL; ::LocalFree( m_pGroup ); m_pGroup = NULL; m_psecinfo->Release(); } //*** CClusterSecurityPage::~CClusterSecurityPage() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrInit // // Routine Description: // Initialize method. // // Arguments: // peo [IN] back pointer to parent extension object. // // Return Value: // S_OK Page was initialized successfully. // hr Error initializing the page. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrInit( IN CExtObject * peo ) { ASSERT( peo != NULL ); AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); HRESULT _hr = S_OK; DWORD _sc; if ( peo != NULL ) { m_peo = peo; _hr = CComObject< CClusterSecurityInformation >::CreateInstance( &m_psecinfo ); if ( SUCCEEDED( _hr ) ) { m_psecinfo->AddRef(); m_hkey = GetClusterKey( Hcluster(), KEY_ALL_ACCESS ); if ( m_hkey != NULL ) { _hr = HrGetSecurityDescriptor(); if ( SUCCEEDED( _hr ) ) { CString strServer; CString strNode; strServer.Format( _T( "\\\\%s" ), StrClusterName() ); // Get the node on which the Cluster Name resource is online. if ( BGetClusterNetworkNameNode( strNode ) ) { _hr = m_psecinfo->HrInit( this, strServer, strNode ); if ( SUCCEEDED( _hr ) ) { m_hpage = CreateClusterSecurityPage( m_psecinfo ); if ( m_hpage == NULL ) { _sc = ::GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); } // if: error creating the page } // if: initialized security info successfully } // if: retrieved cluster network name node successfully else { } // else: error getting cluster network name node } // if: error getting SD } // if: retrieved cluster key else { _sc = ::GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); TRACE( _T( "CClusterSecurityPage::ScInit() - Failed to get the cluster key, 0x%08lx.\n" ), _sc ); } // else: error getting cluster key } // if: created security info object successfully else { TRACE( _T( "CClusterSecurityPage::ScInit() - Failed to create CClusterSecurityInformation object, %0x%08lx.\n" ), _hr ); } } // if: extension object is available return _hr; } //*** CClusterSecurityPage::HrInit() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrGetSecurityDescriptor // // Routine Description: // Get the security descriptor from the cluster database or create a // default one if it doesn't exist. // // Arguments: // none // // Return Value: // // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrGetSecurityDescriptor( void ) { AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); HRESULT hr = S_OK; PSECURITY_DESCRIPTOR psec = NULL; hr = HrGetSDFromClusterDB( &psec ); //uses localalloc if ( FAILED( hr ) || ( psec == NULL ) || ( IsValidSecurityDescriptor( psec ) == FALSE ) ) { DWORD sc; DWORD dwLen = 0; // // If the SD was not found or was not a valid SD then build a default // SD and save it into the cluster DB... // TRACE( _T( "Security Descriptor is NULL. Build default SD" ) ); sc = ::ClRtlBuildDefaultClusterSD( NULL, &psec, &dwLen ); //uses localalloc hr = HRESULT_FROM_WIN32( sc ); if ( FAILED( hr ) ) { TRACE( _T( "ClRtlBuildDefaultClusterSD failed, 0x%08x" ), hr ); } // if: error building the default SD else { SetPermissions( psec ); } // else: } // if: error getting SD from cluster database if ( SUCCEEDED( hr ) ) { delete m_psec; m_psec = ClRtlCopySecurityDescriptor( psec ); hr = GetLastError(); // Get the last error ::LocalFree( psec ); psec = NULL; if ( m_psec == NULL ) { hr = HRESULT_FROM_WIN32( hr ); // Convert to HRESULT goto Cleanup; } // if: error copying the security descriptor hr = HrGetSDOwner( m_psec ); if ( SUCCEEDED( hr ) ) { hr = HrGetSDGroup( m_psec ); if ( SUCCEEDED( hr ) ) { m_psecPrev = ClRtlCopySecurityDescriptor( m_psec ); if ( m_psecPrev == NULL ) { hr = GetLastError(); // Get the last error hr = HRESULT_FROM_WIN32( hr ); // Convert to HRESULT goto Cleanup; } // if: error copying the security descriptor } // if: got SD group successfully } // if: got SD owner successfully } // if: retrieved or built SD successfully #ifdef _DEBUG if ( m_psec != NULL ) { ASSERT( IsValidSecurityDescriptor( m_psec ) ); } #endif Cleanup: return hr; } //*** CClusterSecurityPage::HrGetSecurityDescriptor() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrSetSecurityDescriptor // // Routine Description: // Save the new security descriptor to the cluster database. // // Arguments: // psec [IN] the new security descriptor // // Return Value: // hr // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrSetSecurityDescriptor( IN PSECURITY_DESCRIPTOR psec ) { ASSERT( psec != NULL ); AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); HRESULT hr = S_OK; try { if ( psec != NULL ) { CWaitCursor wc; ASSERT( IsValidSecurityDescriptor( psec ) ); if ( IsValidSecurityDescriptor( psec ) ) { hr = HrSetSDOwner( psec ); if ( SUCCEEDED( hr ) ) { hr = HrSetSDGroup( psec ); if ( SUCCEEDED( hr ) ) { LocalFree( m_psecPrev ); m_psecPrev = NULL; if ( m_psec == NULL ) { m_psecPrev = NULL; } // if: no previous value else { m_psecPrev = ClRtlCopySecurityDescriptor( m_psec ); if ( m_psecPrev == NULL ) { hr = GetLastError(); // Get the last error TRACE( _T( "CClusterSecurityPage::HrSetSecurityDescriptor() - Error %08.8x copying the previous SD.\n" ), hr ); hr = HRESULT_FROM_WIN32( hr ); // Convert to HRESULT goto Cleanup; } // if: error copying the security descriptor } // else: previous value exists LocalFree( m_psec ); m_psec = NULL; m_psec = ClRtlCopySecurityDescriptor( psec ); if ( m_psec == NULL ) { hr = GetLastError(); // Get the last error TRACE( _T( "CClusterSecurityPage::HrSetSecurityDescriptor() - Error %08.8x copying the new SD.\n" ), hr ); hr = HRESULT_FROM_WIN32( hr ); // Convert to HRESULT goto Cleanup; } // if: error copying the security descriptor SetPermissions( m_psec ); } // if: SD group set successfully } // if: SD owner set successfully } // if: security descriptor is valid else { hr = HRESULT_FROM_WIN32( ERROR_INVALID_SECURITY_DESCR ); TRACE( _T( "CClusterSecurityPage::HrSetSecurityDescriptor() - Invalid security descriptor.\n" ) ); } // else: invalid security descriptor } // if: security descriptor specified else { hr = HRESULT_FROM_WIN32( ERROR_INVALID_SECURITY_DESCR ); } // else: no security descriptor specified } // try catch ( ... ) { hr = E_FAIL; TRACE( _T( "CClusterSecurityPage::HrSetSecurityDescriptor() - Unknown error occurred.\n" ) ); } Cleanup: return hr; } //*** CClusterSecurityPage::HrSetSecurityDescriptor() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::SetPermissions // // Routine Description: // Set the permissions for accessing the cluster. // // Arguments: // psec [IN] Security descriptor. // // Return Value: // None. // // Exceptions Thrown: // Any exceptions thrown by CClusterItem::WriteValue(). //-- ///////////////////////////////////////////////////////////////////////////// void CClusterSecurityPage::SetPermissions( IN const PSECURITY_DESCRIPTOR psec ) { ASSERT( psec != NULL ); ASSERT( IsValidSecurityDescriptor( psec ) ); DWORD cbNew; DWORD cbOld; LPBYTE psecPrev; // buffer for use by ScWriteValue. Prev SD is saved elsewhere now. // Get the length of the two security descriptors. if ( m_psecPrev == NULL ) { cbOld = 0; } else { cbOld = ::GetSecurityDescriptorLength( m_psecPrev ); } if ( psec == NULL ) { cbNew = 0; } else { cbNew = ::GetSecurityDescriptorLength( psec ); } // Allocate a new buffer for the previous data pointer. try { psecPrev = new BYTE [cbOld]; if ( psecPrev == NULL ) { return; } // if: error allocating previous data buffer } catch ( CMemoryException * ) { return; } // catch: CMemoryException ::CopyMemory( psecPrev, m_psecPrev, cbOld ); ScWriteValue( CLUSREG_NAME_CLUS_SD, (LPBYTE) psec, cbNew, (LPBYTE *) &psecPrev, cbOld, m_hkey ); // // Convert the NT5 SD to one that is compatible with the ACLEdit stuff on // NT4. If that conversion fails then don't write it to the cluster DB. // PSECURITY_DESCRIPTOR psd = NULL; psd = ClRtlConvertClusterSDToNT4Format( psec ); if ( psd != NULL ) { ScWriteValue( CLUSREG_NAME_CLUS_SECURITY, (LPBYTE) psd, cbNew, (LPBYTE *) &psecPrev, cbOld, m_hkey ); ::LocalFree( psd ); } // if: delete [] psecPrev; } //*** CClusterSecurityPage::SetPermissions() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrGetSDOwner // // Routine Description: // Get the owner sid and save it. // // Arguments: // psec [IN] Security descriptor. // // Return Value: // hr // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrGetSDOwner( IN const PSECURITY_DESCRIPTOR psec ) { HRESULT hr = S_OK; DWORD sc; PSID pOwner = NULL; if ( ::GetSecurityDescriptorOwner( psec, &pOwner, &m_fOwnerDef ) != 0 ) { // The security descriptor does not have an owner. if ( pOwner == NULL ) { ::LocalFree( m_pOwner ); m_pOwner = NULL; } else { DWORD dwLen = ::GetLengthSid( pOwner ); // copy the sid since AclUi will free the SD... hr = ::GetLastError(); if ( SUCCEEDED( hr ) ) { ::LocalFree( m_pOwner ); m_pOwner = ::LocalAlloc( LMEM_ZEROINIT, dwLen ); if ( m_pOwner != NULL ) { if ( ::CopySid( dwLen, m_pOwner, pOwner ) ) { hr = S_OK; } else { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } } else { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } } } } else { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } return( hr ); } //*** CClusterSecurityPage::HrGetSDOwner() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrGetSDGroup // // Routine Description: // Get the group sid and save it. // // Arguments: // psec [IN] Security descriptor. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrGetSDGroup( IN const PSECURITY_DESCRIPTOR psec ) { HRESULT hr = S_OK; DWORD sc; PSID pGroup = NULL; if ( ::GetSecurityDescriptorOwner( psec, &pGroup, &m_fOwnerDef ) != 0 ) { // This SID does not contain group information. if ( pGroup == NULL ) { ::LocalFree( m_pGroup ); m_pGroup = NULL; } else { DWORD dwLen = ::GetLengthSid( pGroup ); // copy the sid since AclUi will free the SD... hr = ::GetLastError(); if ( SUCCEEDED( hr ) ) { ::LocalFree( m_pGroup ); m_pGroup = ::LocalAlloc( LMEM_ZEROINIT, dwLen ); if ( m_pGroup != NULL ) { if ( ::CopySid( dwLen, m_pGroup, pGroup ) ) { hr = S_OK; } else { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } } else { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } } } } else { sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } return( hr ); } //*** CClusterSecurityPage::HrGetSDGroup() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrSetSDOwner // // Routine Description: // Set the owner sid. // // Arguments: // psec [IN] Security descriptor. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrSetSDOwner( IN PSECURITY_DESCRIPTOR psec ) { HRESULT hr = S_OK; if ( !::SetSecurityDescriptorOwner( psec, m_pOwner, m_fOwnerDef ) ) { DWORD sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } return( hr ); } //*** CClusterSecurityPage::HrSetSDOwner() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrSetSDGroup // // Routine Description: // Set the group sid. // // Arguments: // psec [IN] Security descriptor. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrSetSDGroup( IN PSECURITY_DESCRIPTOR psec ) { HRESULT hr = S_OK; if ( !::SetSecurityDescriptorGroup( psec, m_pGroup, m_fGroupDef ) ) { DWORD sc = ::GetLastError(); hr = HRESULT_FROM_WIN32( sc ); } return( hr ); } //*** CClusterSecurityPage::HrSetSDGroup() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterSecurityPage::HrGetSDFromClusterDB // // Routine Description: // Retrieve the SD from the cluster database. // // Arguments: // ppsec [OUT] Pointer to security descriptor. // // Return Value: // S_OK for success // Any error returned by ScReadValue // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusterSecurityPage::HrGetSDFromClusterDB( OUT PSECURITY_DESCRIPTOR * ppsec ) { AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ); ASSERT( ppsec != NULL ); HRESULT hr = E_FAIL; PSECURITY_DESCRIPTOR psd = NULL; if ( ppsec != NULL ) { DWORD sc; // Read the security descriptor. sc = ScReadValue( CLUSREG_NAME_CLUS_SD, (LPBYTE *) &psd, m_hkey ); //alloc using new hr = HRESULT_FROM_WIN32( sc ); if ( FAILED( hr ) || ( psd == NULL ) ) { // try getting the NT4 SD... sc = ScReadValue( CLUSREG_NAME_CLUS_SECURITY, (LPBYTE *) &psd, m_hkey ); //alloc using new hr = HRESULT_FROM_WIN32( sc ); if ( SUCCEEDED( hr ) ) { *ppsec = ::ClRtlConvertClusterSDToNT5Format( psd ); } } else { *ppsec = ClRtlCopySecurityDescriptor( psd ); if ( *ppsec == NULL ) { hr = GetLastError(); // Get the last error hr = HRESULT_FROM_WIN32( hr ); // Convert to HRESULT } // if: error copying the security descriptor } delete [] psd; if ( *ppsec != NULL ) { ::ClRtlExamineSD( *ppsec, "[ClusPage]" ); } // if: security descriptor is available to be examined } return hr; } //*** CClusterSecurityPage::HrGetSDFromClusterDB