mirror of https://github.com/tongzx/nt5src
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.
1980 lines
44 KiB
1980 lines
44 KiB
|
|
|
|
#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;
|
|
}
|
|
|