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.
 
 
 
 
 
 

429 lines
12 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
loopmgr.c
Abstract:
This module contains all of the code to drive the
Loop Manager of IPSecSPD Service.
Author:
abhisheV 30-September-1999
Environment
User Level: Win32
Revision History:
--*/
#include "precomp.h"
#ifdef TRACE_ON
#include "loopmgr.tmh"
#endif
enum {
SERVICE_STOP_EVENT = 0,
INTERFACE_CHANGE_EVENT,
NEW_LOCAL_POLICY_EVENT,
NEW_DS_POLICY_EVENT,
FORCED_POLICY_RELOAD_EVENT,
GPUPDATE_REFRESH_EVENT,
WAIT_EVENT_COUNT,
};
DWORD
ServiceWait(
)
{
// ASSERT: All the following are true at this point:
// . Persistent policy has not been defined or if persistent policy has been
// defined, then it has been applied successfully.
// . IKE is up.
// . Driver is up.
// If persistent policy application failed, IKE init failed, or driver op failed,
// then service would have shutdown with driver in block mode if possible.
DWORD dwError = 0;
HANDLE hWaitForEvents[WAIT_EVENT_COUNT];
BOOL bDoneWaiting = FALSE;
DWORD dwWaitMilliseconds = 0;
DWORD dwStatus = 0;
time_t LastTimeOutTime = 0;
AuditEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
IPSECSVC_SUCCESSFUL_START,
NULL,
TRUE,
TRUE
);
hWaitForEvents[SERVICE_STOP_EVENT] = ghServiceStopEvent;
hWaitForEvents[INTERFACE_CHANGE_EVENT] = GetInterfaceChangeEvent();
hWaitForEvents[NEW_LOCAL_POLICY_EVENT] = ghNewLocalPolicyEvent;
hWaitForEvents[NEW_DS_POLICY_EVENT] = ghNewDSPolicyEvent;
hWaitForEvents[FORCED_POLICY_RELOAD_EVENT] = ghForcedPolicyReloadEvent;
hWaitForEvents[GPUPDATE_REFRESH_EVENT] = ghGpupdateRefreshEvent;
//
// First load the default main mode policy.
//
(VOID) LoadDefaultISAKMPInformation(
gpszDefaultISAKMPPolicyDN
);
//
// Call the Polling Manager for the first time.
//
(VOID) StartStatePollingManager(
gpIpsecPolicyState
);
NotifyIpsecPolicyChange();
ComputeRelativePollingTime(
LastTimeOutTime,
TRUE,
gdwRetryCount,
&dwWaitMilliseconds
);
time(&LastTimeOutTime);
TRACE(TRC_INFORMATION, (L"Completed startup routines. Entering service wait loop."));
while (!bDoneWaiting) {
dwStatus = WaitForMultipleObjects(
WAIT_EVENT_COUNT,
hWaitForEvents,
FALSE,
dwWaitMilliseconds
);
PADeleteInUsePolicies();
switch (dwStatus) {
case SERVICE_STOP_EVENT:
TRACE(TRC_INFORMATION, (L"Service stop event signaled"));
dwError = ERROR_SUCCESS;
bDoneWaiting = TRUE;
break;
case INTERFACE_CHANGE_EVENT:
TRACE(TRC_INFORMATION, (L"Interface changed event signaled"));
(VOID) OnInterfaceChangeEvent(
);
(VOID) IKEInterfaceChange();
break;
case NEW_LOCAL_POLICY_EVENT:
TRACE(TRC_INFORMATION, (L"New local policy event signaled"));
ResetEvent(ghNewLocalPolicyEvent);
if ((gpIpsecPolicyState->CurrentState != SPD_STATE_DS_APPLY_SUCCESS) &&
(gpIpsecPolicyState->CurrentState != SPD_STATE_CACHE_APPLY_SUCCESS)) {
(VOID) ProcessLocalPolicyPollState(
gpIpsecPolicyState
);
NotifyIpsecPolicyChange();
}
break;
case NEW_DS_POLICY_EVENT:
TRACE(TRC_INFORMATION, (L"New DS policy event signaled"));
ResetEvent(ghNewDSPolicyEvent);
(VOID) OnPolicyChanged(
gpIpsecPolicyState
);
NotifyIpsecPolicyChange();
break;
case GPUPDATE_REFRESH_EVENT:
TRACE(TRC_INFORMATION, (L"Group policy refresh event signaled"));
ResetEvent(ghGpupdateRefreshEvent);
dwError = ProcessDirectoryPolicyPollState(
gpIpsecPolicyState
);
break;
case FORCED_POLICY_RELOAD_EVENT:
TRACE(TRC_INFORMATION, (L"Forced policy reload event signaled"));
ResetEvent(ghForcedPolicyReloadEvent);
(VOID) OnPolicyChanged(
gpIpsecPolicyState
);
NotifyIpsecPolicyChange();
AuditEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
PASTORE_FORCED_POLICY_RELOAD,
NULL,
TRUE,
TRUE
);
break;
case WAIT_TIMEOUT:
TRACE(TRC_INFORMATION, (L"Polling event signaled"));
time(&LastTimeOutTime);
(VOID) OnPolicyPoll(
gpIpsecPolicyState
);
(VOID) OnSpecialAddrsChange();
break;
case WAIT_FAILED:
dwError = GetLastError();
TRACE(TRC_ERROR, (L"Failed service wait WaitForMultipleObjects %!winerr!: ", dwError));
bDoneWaiting = TRUE;
break;
default:
dwError = ERROR_INVALID_EVENT_COUNT;
bDoneWaiting = TRUE;
break;
}
ComputeRelativePollingTime(
LastTimeOutTime,
FALSE,
gdwRetryCount,
&dwWaitMilliseconds
);
if (InAcceptableState(gpIpsecPolicyState->CurrentState)) {
// Polling is not going to retry anymore since we've reached an
// acceptable state. So reset gdwRetryCount for NEXT time
// in case we reach an unacceptable state.
gdwRetryCount = 0;
TRACE(
TRC_INFORMATION,
("Policy Agent now in state %d",
(DWORD) gpIpsecPolicyState->CurrentState)
);
}
#ifdef TRACE_ON
else {
TRACE(
TRC_INFORMATION,
("Policy Agent in error state %d, retry count is %d ",
(DWORD) gpIpsecPolicyState->CurrentState,
gdwRetryCount)
);
}
#endif
}
if (!dwError) {
AuditEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
IPSECSVC_SUCCESSFUL_SHUTDOWN,
NULL,
TRUE,
TRUE
);
}
else {
AuditOneArgErrorEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
IPSECSVC_ERROR_SHUTDOWN,
dwError,
FALSE,
TRUE
);
TRACE(TRC_ERROR, (L"Failed and exiting service wait %!winerr!: ", dwError));
}
return (dwError);
}
VOID
ComputeRelativePollingTime(
IN time_t LastTimeOutTime,
IN BOOL bInitialLoad,
IN DWORD dwRetryCount,
IN PDWORD pWaitMilliseconds
)
{
DWORD WaitMilliseconds = 0;
DWORD DSReconnectMilliseconds = 0;
time_t NextTimeOutTime = 0;
time_t PresentTime = 0;
long WaitSeconds = gDefaultPollingInterval;
DWORD64 NewPollingIntervalSeconds = 0;
if (!InAcceptableState(gpIpsecPolicyState->CurrentState)) {
// Exponentially back-off polling interval until
// we hit default polling interval.
// Polling interval increases as (dwRetryCount+1)^2
NewPollingIntervalSeconds = (dwRetryCount+1) * (dwRetryCount+1) * 60;
if (NewPollingIntervalSeconds < gDefaultPollingInterval) {
gCurrentPollingInterval = (DWORD) NewPollingIntervalSeconds;
} else {
gCurrentPollingInterval = gDefaultPollingInterval;
}
}
WaitMilliseconds = gCurrentPollingInterval * 1000;
if (!WaitMilliseconds) {
WaitMilliseconds = INFINITE;
}
if (!bInitialLoad && WaitMilliseconds != INFINITE) {
//
// LastTimeOutTime is the snapshot time value in the past when
// we timed out waiting for multiple events.
// Ideally, the time for the next time out, NextTimeOutTime, is
// the time value in future which is sum of the last time when
// we timed out + the current waiting time value.
//
NextTimeOutTime = LastTimeOutTime + (WaitMilliseconds/1000);
//
// However, the last time we may not have timed out waiting
// for multiple events but rather came out because one of the
// events other than WAIT_TIMEOUT happened.
// However, on that event we may not have done a policy
// poll to figure out whether there was a policy change or
// not. If we again wait for WaitMilliseconds, then we are
// un-knowingly making our net time for policy poll greater
// than the alloted time interval value = WaitMilliseconds.
// So, we need to adjust the WaitMilliseconds to such a value
// that no matter what happens, we always do a policy poll
// atmost every WaitMilliseconds time interval value.
// The current time is PresentTime.
//
time(&PresentTime);
WaitSeconds = (long) (NextTimeOutTime - PresentTime);
if (WaitSeconds < 0) {
WaitMilliseconds = 0;
}
else {
WaitMilliseconds = WaitSeconds * 1000;
}
}
*pWaitMilliseconds = WaitMilliseconds;
}
VOID
NotifyIpsecPolicyChange(
)
{
PulseEvent(ghPolicyChangeNotifyEvent);
SendPschedIoctl();
ResetEvent(ghPolicyChangeNotifyEvent);
return;
}
VOID
SendPschedIoctl(
)
{
HANDLE hPschedDriverHandle = NULL;
ULONG uBytesReturned = 0;
BOOL bIOStatus = FALSE;
#define DriverName TEXT("\\\\.\\PSCHED")
#define IOCTL_PSCHED_ZAW_EVENT CTL_CODE( \
FILE_DEVICE_NETWORK, \
20, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS \
)
hPschedDriverHandle = CreateFile(
DriverName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL
);
if (hPschedDriverHandle != INVALID_HANDLE_VALUE) {
bIOStatus = DeviceIoControl(
hPschedDriverHandle,
IOCTL_PSCHED_ZAW_EVENT,
NULL,
0,
NULL,
0,
&uBytesReturned,
NULL
);
CloseHandle(hPschedDriverHandle);
}
}
VOID
PADeleteInUsePolicies(
)
{
DWORD dwError = 0;
TRACE(TRC_INFORMATION, (L"Deleting policy components no longer in use"));
dwError = PADeleteInUseMMPolicies();
dwError = PADeleteInUseMMAuthMethods();
dwError = PADeleteInUseQMPolicies();
return;
}