|
|
#include "precomp.h"
VOID InitializePolicyStateBlock( PIPSEC_POLICY_STATE pIpsecPolicyState ) { memset(pIpsecPolicyState, 0, sizeof(IPSEC_POLICY_STATE)); pIpsecPolicyState->DefaultPollingInterval = gDefaultPollingInterval; }
DWORD StartStatePollingManager( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0;
dwError = PlumbDirectoryPolicy( pIpsecPolicyState );
if (dwError) {
dwError = PlumbCachePolicy( pIpsecPolicyState );
if (dwError) {
dwError = PlumbRegistryPolicy( pIpsecPolicyState ); BAIL_ON_WIN32_ERROR(dwError);
}
}
//
// The new polling interval has been set by either the
// registry code or the DS code.
//
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
return (dwError);
error:
//
// On error, set the state to INITIAL.
//
pIpsecPolicyState->dwCurrentState = POLL_STATE_INITIAL;
gCurrentPollingInterval = pIpsecPolicyState->DefaultPollingInterval;
return (dwError); }
DWORD PlumbDirectoryPolicy( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszDirectoryPolicyDN = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL; PIPSEC_POLICY_DATA pIpsecPolicyData = NULL; DWORD dwStoreType = IPSEC_DIRECTORY_PROVIDER; DWORD dwSlientErrorCode = 0; BOOL bIsActivePolicy = FALSE;
dwError = GetDirectoryPolicyDN( &pszDirectoryPolicyDN ); BAIL_ON_WIN32_ERROR(dwError); bIsActivePolicy = TRUE;
dwError = LoadDirectoryPolicy( pszDirectoryPolicyDN, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ProcessNFAs( pIpsecPolicyObject, dwStoreType, &dwSlientErrorCode, &pIpsecPolicyData ); BAIL_ON_WIN32_ERROR(dwError);
//
// Plumb the DS policy.
//
dwError = AddPolicyInformation( pIpsecPolicyData );
if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyState->pIpsecPolicyObject); }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyState->pIpsecPolicyData); }
if (pIpsecPolicyState->pszDirectoryPolicyDN) { FreeSPDStr(pIpsecPolicyState->pszDirectoryPolicyDN); }
//
// Delete the old cache and write the new one in.
//
DeleteRegistryCache();
CacheDirectorytoRegistry(pIpsecPolicyObject);
pIpsecPolicyState->pIpsecPolicyObject = pIpsecPolicyObject;
pIpsecPolicyState->pIpsecPolicyData = pIpsecPolicyData;
pIpsecPolicyState->pszDirectoryPolicyDN = pszDirectoryPolicyDN;
//
// Set the state to DS_DOWNLOADED.
//
pIpsecPolicyState->dwCurrentState = POLL_STATE_DS_DOWNLOADED;
//
// Compute the new polling interval.
//
pIpsecPolicyState->CurrentPollingInterval = pIpsecPolicyData->dwPollingInterval;
pIpsecPolicyState->DSIncarnationNumber = pIpsecPolicyData->dwWhenChanged;
pIpsecPolicyState->RegIncarnationNumber = 0;
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
dwError = ERROR_SUCCESS; if (dwSlientErrorCode) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_SOME_NFA_APPLICATION, pIpsecPolicyData->pszIpsecName, dwSlientErrorCode, FALSE, TRUE ); } AuditIPSecPolicyEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_APPLIED_DS_POLICY, pIpsecPolicyData->pszIpsecName, TRUE, TRUE ); return (dwError);
error:
//
// Check pszDirectoryPolicyDN for non-NULL.
//
if (bIsActivePolicy && pszDirectoryPolicyDN) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_DS_POLICY_APPLICATION, pszDirectoryPolicyDN, dwError, FALSE, TRUE ); }
if (pszDirectoryPolicyDN) { FreeSPDStr(pszDirectoryPolicyDN); }
if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); }
if (pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyData); }
return (dwError); }
DWORD GetDirectoryPolicyDN( LPWSTR * ppszDirectoryPolicyDN ) { DWORD dwError = 0; HKEY hPolicyKey = NULL; LPWSTR pszIpsecPolicyName = NULL; DWORD dwSize = 0; LPWSTR pszPolicyDN = NULL; LPWSTR pszDirectoryPolicyDN = NULL;
*ppszDirectoryPolicyDN = NULL;
dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE, gpszIpsecDSPolicyKey, 0, KEY_ALL_ACCESS, &hPolicyKey ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegstoreQueryValue( hPolicyKey, L"DSIPSECPolicyPath", REG_SZ, (LPBYTE *)&pszIpsecPolicyName, &dwSize ); BAIL_ON_WIN32_ERROR(dwError);
//
// Move by LDAP:// to get the real DN and allocate
// this string.
// Fix this by fixing the gpo extension.
//
pszPolicyDN = pszIpsecPolicyName + wcslen(L"LDAP://");
pszDirectoryPolicyDN = AllocSPDStr(pszPolicyDN);
if (!pszDirectoryPolicyDN) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
*ppszDirectoryPolicyDN = pszDirectoryPolicyDN;
error:
if (pszIpsecPolicyName) { FreeSPDStr(pszIpsecPolicyName); }
if (hPolicyKey) { CloseHandle(hPolicyKey); }
return (dwError); }
DWORD LoadDirectoryPolicy( LPWSTR pszDirectoryPolicyDN, PIPSEC_POLICY_OBJECT * ppIpsecPolicyObject ) { DWORD dwError = 0; LPWSTR pszDefaultDirectory = NULL; HLDAP hLdapBindHandle = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL;
dwError = ComputeDefaultDirectory( &pszDefaultDirectory ); BAIL_ON_WIN32_ERROR(dwError);
dwError = OpenDirectoryServerHandle( pszDefaultDirectory, 389, &hLdapBindHandle ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ReadPolicyObjectFromDirectory( hLdapBindHandle, pszDirectoryPolicyDN, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
*ppIpsecPolicyObject = pIpsecPolicyObject;
cleanup:
if (pszDefaultDirectory) { FreeSPDStr(pszDefaultDirectory); }
if (hLdapBindHandle) { CloseDirectoryServerHandle(hLdapBindHandle); }
return (dwError);
error:
*ppIpsecPolicyObject = NULL;
goto cleanup; }
DWORD PlumbCachePolicy( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszCachePolicyDN = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL; PIPSEC_POLICY_DATA pIpsecPolicyData = NULL; DWORD dwStoreType = IPSEC_REGISTRY_PROVIDER; DWORD dwSlientErrorCode = 0; BOOL bIsActivePolicy = FALSE;
dwError = GetCachePolicyDN( &pszCachePolicyDN ); BAIL_ON_WIN32_ERROR(dwError); bIsActivePolicy = TRUE;
dwError = LoadCachePolicy( pszCachePolicyDN, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ProcessNFAs( pIpsecPolicyObject, dwStoreType, &dwSlientErrorCode, &pIpsecPolicyData ); BAIL_ON_WIN32_ERROR(dwError);
dwError = AddPolicyInformation( pIpsecPolicyData );
if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyState->pIpsecPolicyObject); }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyState->pIpsecPolicyData); }
if (pIpsecPolicyState->pszCachePolicyDN) { FreeSPDStr(pIpsecPolicyState->pszCachePolicyDN); }
pIpsecPolicyState->pIpsecPolicyObject = pIpsecPolicyObject;
pIpsecPolicyState->pIpsecPolicyData = pIpsecPolicyData;
pIpsecPolicyState->pszCachePolicyDN = pszCachePolicyDN;
//
// Set the state to CACHE_DOWNLOADED.
//
//
pIpsecPolicyState->dwCurrentState = POLL_STATE_CACHE_DOWNLOADED;
//
// Compute the new polling interval.
//
pIpsecPolicyState->CurrentPollingInterval = pIpsecPolicyData->dwPollingInterval;
pIpsecPolicyState->DSIncarnationNumber = 0;
pIpsecPolicyState->RegIncarnationNumber = pIpsecPolicyData->dwWhenChanged;
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
dwError = ERROR_SUCCESS; if (dwSlientErrorCode) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_SOME_NFA_APPLICATION, pIpsecPolicyData->pszIpsecName, dwSlientErrorCode, FALSE, TRUE ); } AuditIPSecPolicyEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_APPLIED_CACHED_POLICY, pIpsecPolicyData->pszIpsecName, TRUE, TRUE ); return (dwError);
error:
//
// Check pszCachePolicyDN for non-NULL.
//
if (bIsActivePolicy && pszCachePolicyDN) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_CACHED_POLICY_APPLICATION, pszCachePolicyDN, dwError, FALSE, TRUE ); }
if (pszCachePolicyDN) { FreeSPDStr(pszCachePolicyDN); }
if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); }
if (pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyData); }
return (dwError); }
DWORD GetCachePolicyDN( LPWSTR * ppszCachePolicyDN ) { DWORD dwError = 0; LPWSTR pszDirectoryPolicyDN = NULL; LPWSTR pszCachePolicyDN = NULL;
*ppszCachePolicyDN = NULL;
dwError = GetDirectoryPolicyDN( &pszDirectoryPolicyDN ); BAIL_ON_WIN32_ERROR(dwError);
dwError = CopyPolicyDSToFQRegString( pszDirectoryPolicyDN, &pszCachePolicyDN ); BAIL_ON_WIN32_ERROR(dwError);
*ppszCachePolicyDN = pszCachePolicyDN;
error:
if (pszDirectoryPolicyDN) { FreeSPDStr(pszDirectoryPolicyDN); }
return (dwError); }
DWORD LoadCachePolicy( LPWSTR pszCachePolicyDN, PIPSEC_POLICY_OBJECT * ppIpsecPolicyObject ) { DWORD dwError = 0; HKEY hRegistryKey = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL;
dwError = OpenRegistryIPSECRootKey( NULL, gpszIpsecCachePolicyKey, &hRegistryKey ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ReadPolicyObjectFromRegistry( hRegistryKey, pszCachePolicyDN, gpszIpsecCachePolicyKey, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
*ppIpsecPolicyObject = pIpsecPolicyObject;
cleanup:
if (hRegistryKey) { CloseHandle(hRegistryKey); }
return (dwError);
error:
*ppIpsecPolicyObject = NULL;
goto cleanup; }
DWORD PlumbRegistryPolicy( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszRegistryPolicyDN = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL; PIPSEC_POLICY_DATA pIpsecPolicyData = NULL; DWORD dwStoreType = IPSEC_REGISTRY_PROVIDER; DWORD dwSlientErrorCode = 0; BOOL bIsActivePolicy = FALSE;
dwError = GetRegistryPolicyDN( &pszRegistryPolicyDN ); BAIL_ON_WIN32_ERROR(dwError); bIsActivePolicy = TRUE;
dwError = LoadRegistryPolicy( pszRegistryPolicyDN, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ProcessNFAs( pIpsecPolicyObject, dwStoreType, &dwSlientErrorCode, &pIpsecPolicyData ); BAIL_ON_WIN32_ERROR(dwError);
dwError = AddPolicyInformation( pIpsecPolicyData );
if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyState->pIpsecPolicyObject); }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyState->pIpsecPolicyData); }
if (pIpsecPolicyState->pszRegistryPolicyDN) { FreeSPDStr(pIpsecPolicyState->pszRegistryPolicyDN); }
pIpsecPolicyState->pIpsecPolicyObject = pIpsecPolicyObject;
pIpsecPolicyState->pIpsecPolicyData = pIpsecPolicyData;
pIpsecPolicyState->pszRegistryPolicyDN = pszRegistryPolicyDN;
//
// Set the state to LOCAL_DOWNLOADED.
//
pIpsecPolicyState->dwCurrentState = POLL_STATE_LOCAL_DOWNLOADED;
//
// Compute the new polling interval.
//
pIpsecPolicyState->CurrentPollingInterval = pIpsecPolicyData->dwPollingInterval;
pIpsecPolicyState->DSIncarnationNumber = 0;
pIpsecPolicyState->RegIncarnationNumber = pIpsecPolicyData->dwWhenChanged;
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
dwError = ERROR_SUCCESS; if (dwSlientErrorCode) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_SOME_NFA_APPLICATION, pIpsecPolicyData->pszIpsecName, dwSlientErrorCode, FALSE, TRUE ); } AuditIPSecPolicyEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_APPLIED_LOCAL_POLICY, pIpsecPolicyData->pszIpsecName, TRUE, TRUE ); return (dwError);
error:
//
// Check pszRegistryPolicyDN for non-NULL.
//
if (bIsActivePolicy && pszRegistryPolicyDN) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_LOCAL_POLICY_APPLICATION, pszRegistryPolicyDN, dwError, FALSE, TRUE ); }
if (pszRegistryPolicyDN) { FreeSPDStr(pszRegistryPolicyDN); }
if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); }
if (pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyData); }
return (dwError); }
DWORD GetRegistryPolicyDN( LPWSTR * ppszRegistryPolicyDN ) { DWORD dwError = 0; HKEY hPolicyKey = NULL; LPWSTR pszIpsecPolicyName = NULL; DWORD dwSize = 0;
dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE, gpszIpsecLocalPolicyKey, 0, KEY_ALL_ACCESS, &hPolicyKey ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegstoreQueryValue( hPolicyKey, L"ActivePolicy", REG_SZ, (LPBYTE *)&pszIpsecPolicyName, &dwSize ); BAIL_ON_WIN32_ERROR(dwError);
if (!pszIpsecPolicyName || !*pszIpsecPolicyName) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
*ppszRegistryPolicyDN = pszIpsecPolicyName;
cleanup:
if (hPolicyKey) { CloseHandle(hPolicyKey); }
return (dwError);
error:
if (pszIpsecPolicyName) { FreeSPDStr(pszIpsecPolicyName); }
*ppszRegistryPolicyDN = NULL;
goto cleanup; }
DWORD LoadRegistryPolicy( LPWSTR pszRegistryPolicyDN, PIPSEC_POLICY_OBJECT * ppIpsecPolicyObject ) { DWORD dwError = 0; HKEY hRegistryKey = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL;
dwError = OpenRegistryIPSECRootKey( NULL, gpszIpsecLocalPolicyKey, &hRegistryKey ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ReadPolicyObjectFromRegistry( hRegistryKey, pszRegistryPolicyDN, gpszIpsecLocalPolicyKey, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
*ppIpsecPolicyObject = pIpsecPolicyObject;
cleanup:
if (hRegistryKey) { CloseHandle(hRegistryKey); }
return (dwError);
error:
*ppIpsecPolicyObject = NULL;
goto cleanup; }
DWORD AddPolicyInformation( PIPSEC_POLICY_DATA pIpsecPolicyData ) { DWORD dwError = 0;
dwError = AddMMPolicyInformation(pIpsecPolicyData);
dwError = AddQMPolicyInformation(pIpsecPolicyData);
dwError = ERROR_SUCCESS;
return (dwError); }
DWORD AddMMPolicyInformation( PIPSEC_POLICY_DATA pIpsecPolicyData ) { DWORD dwError = 0;
dwError = PAAddMMPolicies( &(pIpsecPolicyData->pIpsecISAKMPData), 1 );
dwError = PAAddMMAuthMethods( pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount );
dwError = PAAddMMFilters( pIpsecPolicyData->pIpsecISAKMPData, pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount ); BAIL_ON_WIN32_ERROR(dwError);
error:
return (dwError); }
DWORD AddQMPolicyInformation( PIPSEC_POLICY_DATA pIpsecPolicyData ) { DWORD dwError = 0;
dwError = PAAddQMPolicies( pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount );
dwError = PAAddQMFilters( pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount ); BAIL_ON_WIN32_ERROR(dwError);
error:
return (dwError); }
DWORD OnPolicyChanged( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0;
//
// Remove all the old policy that was plumbed.
//
dwError = DeletePolicyInformation( pIpsecPolicyState->pIpsecPolicyData );
ClearPolicyStateBlock( pIpsecPolicyState );
//
// Calling the Initializer again.
//
dwError = StartStatePollingManager( pIpsecPolicyState );
return (dwError); }
DWORD DeletePolicyInformation( PIPSEC_POLICY_DATA pIpsecPolicyData ) { DWORD dwError = 0;
if (!pIpsecPolicyData) { dwError = ERROR_SUCCESS; return (dwError); }
dwError = DeleteMMPolicyInformation(pIpsecPolicyData);
dwError = DeleteQMPolicyInformation(pIpsecPolicyData);
dwError = ERROR_SUCCESS;
return (dwError); }
DWORD DeleteMMPolicyInformation( PIPSEC_POLICY_DATA pIpsecPolicyData ) { DWORD dwError = 0;
dwError = PADeleteMMFilters( pIpsecPolicyData->pIpsecISAKMPData, pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount );
dwError = PADeleteMMAuthMethods( pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount );
dwError = PADeleteMMPolicies( &(pIpsecPolicyData->pIpsecISAKMPData), 1 );
return (dwError); }
DWORD DeleteQMPolicyInformation( PIPSEC_POLICY_DATA pIpsecPolicyData ) { DWORD dwError = 0;
dwError = PADeleteQMFilters( pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount );
dwError = PADeleteQMPolicies( pIpsecPolicyData->ppIpsecNFAData, pIpsecPolicyData->dwNumNFACount );
return (dwError); }
DWORD DeleteAllPolicyInformation( ) { DWORD dwError = 0;
dwError = DeleteAllMMPolicyInformation();
dwError = DeleteAllQMPolicyInformation();
dwError = ERROR_SUCCESS;
return (dwError); }
DWORD DeleteAllMMPolicyInformation( ) { DWORD dwError = 0;
dwError = PADeleteAllMMFilters();
dwError = PADeleteAllMMAuthMethods();
dwError = PADeleteAllMMPolicies();
return (dwError); }
DWORD DeleteAllQMPolicyInformation( ) { DWORD dwError = 0;
dwError = PADeleteAllTxFilters();
dwError = PADeleteAllTnFilters();
dwError = PADeleteAllQMPolicies();
return (dwError); }
VOID ClearPolicyStateBlock( PIPSEC_POLICY_STATE pIpsecPolicyState ) { if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject( pIpsecPolicyState->pIpsecPolicyObject ); pIpsecPolicyState->pIpsecPolicyObject = NULL; }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData( pIpsecPolicyState->pIpsecPolicyData ); pIpsecPolicyState->pIpsecPolicyData = NULL; }
if (pIpsecPolicyState->pszDirectoryPolicyDN) { FreeSPDStr(pIpsecPolicyState->pszDirectoryPolicyDN); pIpsecPolicyState->pszDirectoryPolicyDN = NULL; }
pIpsecPolicyState->CurrentPollingInterval = gDefaultPollingInterval; pIpsecPolicyState->DefaultPollingInterval = gDefaultPollingInterval; pIpsecPolicyState->DSIncarnationNumber = 0; pIpsecPolicyState->RegIncarnationNumber = 0; pIpsecPolicyState->dwCurrentState = POLL_STATE_INITIAL; }
DWORD OnPolicyPoll( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0;
switch (pIpsecPolicyState->dwCurrentState) {
case POLL_STATE_DS_DOWNLOADED: dwError = ProcessDirectoryPolicyPollState(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); break;
case POLL_STATE_CACHE_DOWNLOADED: dwError = ProcessCachePolicyPollState(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); break;
case POLL_STATE_LOCAL_DOWNLOADED: dwError = ProcessLocalPolicyPollState(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); break;
case POLL_STATE_INITIAL: dwError = OnPolicyChanged(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); break;
}
//
// Set the new polling interval.
//
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
return (dwError);
error:
//
// If in any of the three states other than the initial state,
// then there was an error in pulling down the incarnation number
// or the IPSec Policy from either the directory or the registry
// or there might not no longer be any IPSec policy assigned to
// this machine. So the polling state must reset back to the
// start state through a forced policy change. This is also
// necessary if the polling state is already in the initial state.
//
dwError = OnPolicyChanged( pIpsecPolicyState );
return (dwError); }
DWORD ProcessDirectoryPolicyPollState( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; DWORD dwIncarnationNumber = 0; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL; PIPSEC_POLICY_DATA pIpsecPolicyData = NULL; DWORD dwStoreType = IPSEC_DIRECTORY_PROVIDER; DWORD dwSlientErrorCode = 0;
//
// The directory policy DN has to be the same, otherwise the
// IPSec extension in Winlogon would have already notified
// PA Store of the DS policy change.
//
dwError = GetDirectoryIncarnationNumber( pIpsecPolicyState->pszDirectoryPolicyDN, &dwIncarnationNumber ); if (dwError) { dwError = MigrateFromDSToCache(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); return (ERROR_SUCCESS); }
if (dwIncarnationNumber == pIpsecPolicyState->DSIncarnationNumber) {
//
// The policy has not changed at all.
//
AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_POLLING_NO_CHANGES, NULL, TRUE, TRUE ); return (ERROR_SUCCESS); }
//
// The incarnation number is different, so there's a need to
// update the policy.
//
dwError = LoadDirectoryPolicy( pIpsecPolicyState->pszDirectoryPolicyDN, &pIpsecPolicyObject ); if (dwError) { dwError = MigrateFromDSToCache(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); return (ERROR_SUCCESS); }
dwError = ProcessNFAs( pIpsecPolicyObject, dwStoreType, &dwSlientErrorCode, &pIpsecPolicyData ); if (dwError) { dwError = MigrateFromDSToCache(pIpsecPolicyState); BAIL_ON_WIN32_ERROR(dwError); if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); } return (ERROR_SUCCESS); }
dwError = UpdatePolicyInformation( pIpsecPolicyState->pIpsecPolicyData, pIpsecPolicyData );
if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyState->pIpsecPolicyObject); }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyState->pIpsecPolicyData); }
//
// Now delete the old cache and write the new one in.
//
DeleteRegistryCache();
CacheDirectorytoRegistry(pIpsecPolicyObject);
pIpsecPolicyState->pIpsecPolicyObject = pIpsecPolicyObject;
pIpsecPolicyState->pIpsecPolicyData = pIpsecPolicyData;
pIpsecPolicyState->CurrentPollingInterval = pIpsecPolicyData->dwPollingInterval;
pIpsecPolicyState->DSIncarnationNumber = dwIncarnationNumber;
NotifyIpsecPolicyChange();
dwError = ERROR_SUCCESS; if (dwSlientErrorCode) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_SOME_NFA_APPLICATION, pIpsecPolicyData->pszIpsecName, dwSlientErrorCode, FALSE, TRUE ); } AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_POLLING_APPLIED_CHANGES, NULL, TRUE, TRUE ); return (dwError);
error:
if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); }
if (pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyData); }
return (dwError); }
DWORD GetDirectoryIncarnationNumber( LPWSTR pszIpsecPolicyDN, DWORD * pdwIncarnationNumber ) { DWORD dwError = 0; LPWSTR pszDefaultDirectory = NULL; HLDAP hLdapBindHandle = NULL; LPWSTR Attributes[] = {L"whenChanged", NULL}; LDAPMessage *res = NULL; LDAPMessage *e = NULL; WCHAR **strvalues = NULL; DWORD dwCount = 0; DWORD dwWhenChanged = 0;
*pdwIncarnationNumber = 0;
//
// Open the directory store.
//
dwError = ComputeDefaultDirectory( &pszDefaultDirectory ); BAIL_ON_WIN32_ERROR(dwError);
dwError = OpenDirectoryServerHandle( pszDefaultDirectory, 389, &hLdapBindHandle ); BAIL_ON_WIN32_ERROR(dwError);
dwError = LdapSearchST( hLdapBindHandle, pszIpsecPolicyDN, LDAP_SCOPE_BASE, L"(objectClass=*)", Attributes, 0, NULL, &res ); BAIL_ON_WIN32_ERROR(dwError);
dwError = LdapFirstEntry( hLdapBindHandle, res, &e ); BAIL_ON_WIN32_ERROR(dwError);
dwError = LdapGetValues( hLdapBindHandle, e, L"whenChanged", (WCHAR ***)&strvalues, (int *)&dwCount ); BAIL_ON_WIN32_ERROR(dwError);
dwWhenChanged = _wtol(LDAPOBJECT_STRING((PLDAPOBJECT)strvalues));
*pdwIncarnationNumber = dwWhenChanged;
error:
if (pszDefaultDirectory) { FreeSPDStr(pszDefaultDirectory); }
if (hLdapBindHandle) { CloseDirectoryServerHandle(hLdapBindHandle); }
if (res) { LdapMsgFree(res); }
if (strvalues) { LdapValueFree(strvalues); }
return (dwError); }
DWORD MigrateFromDSToCache( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszCachePolicyDN = NULL;
dwError = GetCachePolicyDN( &pszCachePolicyDN ); BAIL_ON_WIN32_ERROR(dwError);
if (pIpsecPolicyState->pszDirectoryPolicyDN) { FreeSPDStr(pIpsecPolicyState->pszDirectoryPolicyDN); pIpsecPolicyState->pszDirectoryPolicyDN = NULL; }
pIpsecPolicyState->pszCachePolicyDN = pszCachePolicyDN;
//
// Keep pIpsecPolicyState->pIpsecPolicyData.
// Keep pIpsecPolicyState->pIpsecPolicyObject.
// Change the incarnation numbers.
//
pIpsecPolicyState->RegIncarnationNumber = pIpsecPolicyState->DSIncarnationNumber;
pIpsecPolicyState->DSIncarnationNumber = 0;
pIpsecPolicyState->dwCurrentState = POLL_STATE_CACHE_DOWNLOADED;
//
// Keep pIpsecPolicyState->CurrentPollingInterval.
// Keep pIpsecPolicyState->DefaultPollingInterval.
//
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_MIGRATE_DS_TO_CACHE, NULL, TRUE, TRUE );
error:
return (dwError); }
DWORD ProcessCachePolicyPollState( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszDirectoryPolicyDN = NULL; DWORD dwIncarnationNumber = 0; LPWSTR pszCachePolicyDN = NULL;
dwError = GetDirectoryPolicyDN( &pszDirectoryPolicyDN );
if (!dwError) {
dwError = GetDirectoryIncarnationNumber( pszDirectoryPolicyDN, &dwIncarnationNumber );
if (!dwError) {
dwError = CopyPolicyDSToFQRegString( pszDirectoryPolicyDN, &pszCachePolicyDN );
if (!dwError) {
if (!_wcsicmp(pIpsecPolicyState->pszCachePolicyDN, pszCachePolicyDN)) {
if (pIpsecPolicyState->RegIncarnationNumber == dwIncarnationNumber) { dwError = MigrateFromCacheToDS(pIpsecPolicyState); } else { dwError = UpdateFromCacheToDS(pIpsecPolicyState); }
if (dwError) { dwError = OnPolicyChanged(pIpsecPolicyState); }
} else {
dwError = OnPolicyChanged(pIpsecPolicyState);
}
}
}
}
if (pszDirectoryPolicyDN) { FreeSPDStr(pszDirectoryPolicyDN); }
if (pszCachePolicyDN) { FreeSPDStr(pszCachePolicyDN); }
return (ERROR_SUCCESS); }
DWORD MigrateFromCacheToDS( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszDirectoryPolicyDN = NULL;
dwError = GetDirectoryPolicyDN( &pszDirectoryPolicyDN ); BAIL_ON_WIN32_ERROR(dwError);
if (pIpsecPolicyState->pszCachePolicyDN) { FreeSPDStr(pIpsecPolicyState->pszCachePolicyDN); pIpsecPolicyState->pszCachePolicyDN = NULL; }
pIpsecPolicyState->pszDirectoryPolicyDN = pszDirectoryPolicyDN;
//
// Keep pIpsecPolicyState->pIpsecPolicyData.
// Keep pIpsecPolicyState->pIpsecPolicyObject.
// Change the incarnation numbers.
//
pIpsecPolicyState->DSIncarnationNumber = pIpsecPolicyState->RegIncarnationNumber;
pIpsecPolicyState->RegIncarnationNumber = 0;
pIpsecPolicyState->dwCurrentState = POLL_STATE_DS_DOWNLOADED;
//
// Keep pIpsecPolicyState->CurrentPollingInterval.
// Keep pIpsecPolicyState->DefaultPollingInterval.
//
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_MIGRATE_CACHE_TO_DS, NULL, TRUE, TRUE );
error:
return (dwError); }
DWORD UpdateFromCacheToDS( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwError = 0; LPWSTR pszDirectoryPolicyDN = NULL; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL; PIPSEC_POLICY_DATA pIpsecPolicyData = NULL; DWORD dwStoreType = IPSEC_DIRECTORY_PROVIDER; DWORD dwSlientErrorCode = 0;
dwError = GetDirectoryPolicyDN( &pszDirectoryPolicyDN ); BAIL_ON_WIN32_ERROR(dwError);
dwError = LoadDirectoryPolicy( pszDirectoryPolicyDN, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ProcessNFAs( pIpsecPolicyObject, dwStoreType, &dwSlientErrorCode, &pIpsecPolicyData ); BAIL_ON_WIN32_ERROR(dwError);
dwError = UpdatePolicyInformation( pIpsecPolicyState->pIpsecPolicyData, pIpsecPolicyData );
if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyState->pIpsecPolicyObject); }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyState->pIpsecPolicyData); }
if (pIpsecPolicyState->pszCachePolicyDN) { FreeSPDStr(pIpsecPolicyState->pszCachePolicyDN); }
//
// Now delete the old cache and write the new one in.
//
DeleteRegistryCache();
CacheDirectorytoRegistry(pIpsecPolicyObject);
pIpsecPolicyState->pIpsecPolicyObject = pIpsecPolicyObject;
pIpsecPolicyState->pIpsecPolicyData = pIpsecPolicyData;
pIpsecPolicyState->pszDirectoryPolicyDN = pszDirectoryPolicyDN;
//
// Set the state to DS-DOWNLOADED.
//
pIpsecPolicyState->dwCurrentState = POLL_STATE_DS_DOWNLOADED;
//
// Compute the new polling interval.
//
pIpsecPolicyState->CurrentPollingInterval = pIpsecPolicyData->dwPollingInterval;
pIpsecPolicyState->DSIncarnationNumber = pIpsecPolicyData->dwWhenChanged;
pIpsecPolicyState->RegIncarnationNumber = 0;
gCurrentPollingInterval = pIpsecPolicyState->CurrentPollingInterval;
NotifyIpsecPolicyChange();
dwError = ERROR_SUCCESS; if (dwSlientErrorCode) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_SOME_NFA_APPLICATION, pIpsecPolicyData->pszIpsecName, dwSlientErrorCode, FALSE, TRUE ); } AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_UPDATE_CACHE_TO_DS, NULL, TRUE, TRUE ); return (dwError);
error:
if (pszDirectoryPolicyDN) { FreeSPDStr(pszDirectoryPolicyDN); }
if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); }
if (pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyData); }
return (dwError); }
DWORD ProcessLocalPolicyPollState( PIPSEC_POLICY_STATE pIpsecPolicyState ) { DWORD dwStatus = 0; LPWSTR pszDirectoryPolicyDN = NULL; DWORD dwDSIncarnationNumber = 0; DWORD dwError = 0; BOOL bChanged = FALSE; DWORD dwIncarnationNumber = 0; PIPSEC_POLICY_OBJECT pIpsecPolicyObject = NULL; PIPSEC_POLICY_DATA pIpsecPolicyData = NULL; DWORD dwStoreType = IPSEC_REGISTRY_PROVIDER; DWORD dwSlientErrorCode = 0;
dwStatus = GetDirectoryPolicyDN( &pszDirectoryPolicyDN ); if (!dwStatus) {
dwStatus = GetDirectoryIncarnationNumber( pszDirectoryPolicyDN, &dwDSIncarnationNumber ); if (pszDirectoryPolicyDN) { FreeSPDStr(pszDirectoryPolicyDN); } if (!dwStatus) { dwStatus = OnPolicyChanged(pIpsecPolicyState); return (dwStatus); }
}
dwError = HasRegistryPolicyChanged( pIpsecPolicyState->pszRegistryPolicyDN, &bChanged ); BAIL_ON_WIN32_ERROR(dwError);
if (bChanged) {
dwError = OnPolicyChanged(pIpsecPolicyState); return (dwError);
}
if (pIpsecPolicyState->dwCurrentState == POLL_STATE_INITIAL) { return (ERROR_SUCCESS); }
dwError = GetRegistryIncarnationNumber( pIpsecPolicyState->pszRegistryPolicyDN, &dwIncarnationNumber ); BAIL_ON_WIN32_ERROR(dwError);
if (dwIncarnationNumber == pIpsecPolicyState->RegIncarnationNumber) {
//
// The policy has not changed at all.
//
AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_POLLING_NO_CHANGES, NULL, TRUE, TRUE ); return (ERROR_SUCCESS); }
dwError = LoadRegistryPolicy( pIpsecPolicyState->pszRegistryPolicyDN, &pIpsecPolicyObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = ProcessNFAs( pIpsecPolicyObject, dwStoreType, &dwSlientErrorCode, &pIpsecPolicyData ); BAIL_ON_WIN32_ERROR(dwError);
dwError = UpdatePolicyInformation( pIpsecPolicyState->pIpsecPolicyData, pIpsecPolicyData );
if (pIpsecPolicyState->pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyState->pIpsecPolicyObject); }
if (pIpsecPolicyState->pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyState->pIpsecPolicyData); }
pIpsecPolicyState->pIpsecPolicyObject = pIpsecPolicyObject;
pIpsecPolicyState->pIpsecPolicyData = pIpsecPolicyData;
pIpsecPolicyState->CurrentPollingInterval = pIpsecPolicyData->dwPollingInterval;
pIpsecPolicyState->RegIncarnationNumber = dwIncarnationNumber;
NotifyIpsecPolicyChange();
dwError = ERROR_SUCCESS; if (dwSlientErrorCode) { AuditIPSecPolicyErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_FAILED_SOME_NFA_APPLICATION, pIpsecPolicyData->pszIpsecName, dwSlientErrorCode, FALSE, TRUE ); } AuditEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, PASTORE_POLLING_APPLIED_CHANGES, NULL, TRUE, TRUE ); return (dwError);
error:
if (pIpsecPolicyObject) { FreeIpsecPolicyObject(pIpsecPolicyObject); }
if (pIpsecPolicyData) { FreeIpsecPolicyData(pIpsecPolicyData); }
return (dwError); }
DWORD HasRegistryPolicyChanged( LPWSTR pszCurrentPolicyDN, PBOOL pbChanged ) { DWORD dwError = 0; HKEY hRegKey = NULL; LPWSTR pszIpsecPolicyName = NULL; DWORD dwSize = 0; BOOL bChanged = FALSE;
dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE, gpszIpsecLocalPolicyKey, 0, KEY_ALL_ACCESS, &hRegKey ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegstoreQueryValue( hRegKey, L"ActivePolicy", REG_SZ, (LPBYTE *)&pszIpsecPolicyName, &dwSize ); //
// Must not bail from here, as there can be no
// active local policy.
//
if (pszIpsecPolicyName && *pszIpsecPolicyName) {
if (!pszCurrentPolicyDN || !*pszCurrentPolicyDN) { bChanged = TRUE; } else {
if (!_wcsicmp(pszIpsecPolicyName, pszCurrentPolicyDN)) { bChanged = FALSE; } else { bChanged = TRUE; }
}
} else { if (!pszCurrentPolicyDN || !*pszCurrentPolicyDN) { bChanged = FALSE; } else { bChanged = TRUE; } }
*pbChanged = bChanged; dwError = ERROR_SUCCESS;
cleanup:
if (hRegKey) { CloseHandle(hRegKey); }
if (pszIpsecPolicyName) { FreeSPDStr(pszIpsecPolicyName); }
return (dwError);
error:
*pbChanged = FALSE;
goto cleanup; }
DWORD GetRegistryIncarnationNumber( LPWSTR pszIpsecPolicyDN, DWORD * pdwIncarnationNumber ) { DWORD dwError = 0; HKEY hRegKey = NULL; DWORD dwType = REG_DWORD; DWORD dwWhenChanged = 0; DWORD dwSize = sizeof(DWORD);
*pdwIncarnationNumber = 0;
dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE, pszIpsecPolicyDN, 0, KEY_ALL_ACCESS, &hRegKey ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegQueryValueExW( hRegKey, L"whenChanged", NULL, &dwType, (LPBYTE)&dwWhenChanged, &dwSize ); BAIL_ON_WIN32_ERROR(dwError);
*pdwIncarnationNumber = dwWhenChanged;
error:
if (hRegKey) { CloseHandle(hRegKey); }
return(dwError); }
DWORD UpdatePolicyInformation( PIPSEC_POLICY_DATA pOldIpsecPolicyData, PIPSEC_POLICY_DATA pNewIpsecPolicyData ) { DWORD dwError = 0; PIPSEC_ISAKMP_DATA pOldIpsecISAKMPData = NULL; PIPSEC_NFA_DATA * ppOldIpsecNFAData = NULL; DWORD dwNumOldNFACount = 0; PIPSEC_ISAKMP_DATA pNewIpsecISAKMPData = NULL; PIPSEC_NFA_DATA * ppNewIpsecNFAData = NULL; DWORD dwNumNewNFACount = 0;
pOldIpsecISAKMPData = pOldIpsecPolicyData->pIpsecISAKMPData; ppOldIpsecNFAData = pOldIpsecPolicyData->ppIpsecNFAData; dwNumOldNFACount = pOldIpsecPolicyData->dwNumNFACount;
pNewIpsecISAKMPData = pNewIpsecPolicyData->pIpsecISAKMPData; ppNewIpsecNFAData = pNewIpsecPolicyData->ppIpsecNFAData; dwNumNewNFACount = pNewIpsecPolicyData->dwNumNFACount;
dwError = PADeleteObseleteISAKMPData( &pOldIpsecISAKMPData, 1, ppOldIpsecNFAData, dwNumOldNFACount, &pNewIpsecISAKMPData, 1 );
dwError = PAUpdateISAKMPData( &pNewIpsecISAKMPData, 1, ppOldIpsecNFAData, dwNumOldNFACount, &pOldIpsecISAKMPData, 1 );
dwError = PADeleteObseleteNFAData( pNewIpsecISAKMPData, ppOldIpsecNFAData, dwNumOldNFACount, ppNewIpsecNFAData, dwNumNewNFACount );
dwError = PAUpdateNFAData( pNewIpsecISAKMPData, ppNewIpsecNFAData, dwNumNewNFACount, ppOldIpsecNFAData, dwNumOldNFACount );
return (dwError); }
DWORD LoadDefaultISAKMPInformation( LPWSTR pszDefaultISAKMPDN ) { DWORD dwError = 0;
gbLoadedISAKMPDefaults = TRUE;
return (dwError); }
VOID UnLoadDefaultISAKMPInformation( LPWSTR pszDefaultISAKMPDN ) { return; }
|