Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1395 lines
43 KiB

/////////////////////////////////////////////////////////////////////////////
//
// 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 <clusudef.h>
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