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

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. loopmgr.c
  5. Abstract:
  6. This module contains all of the code to drive the
  7. Loop Manager of IPSecSPD Service.
  8. Author:
  9. abhisheV 30-September-1999
  10. Environment
  11. User Level: Win32
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #ifdef TRACE_ON
  16. #include "loopmgr.tmh"
  17. #endif
  18. enum {
  19. SERVICE_STOP_EVENT = 0,
  20. INTERFACE_CHANGE_EVENT,
  21. NEW_LOCAL_POLICY_EVENT,
  22. NEW_DS_POLICY_EVENT,
  23. FORCED_POLICY_RELOAD_EVENT,
  24. GPUPDATE_REFRESH_EVENT,
  25. WAIT_EVENT_COUNT,
  26. };
  27. DWORD
  28. ServiceWait(
  29. )
  30. {
  31. // ASSERT: All the following are true at this point:
  32. // . Persistent policy has not been defined or if persistent policy has been
  33. // defined, then it has been applied successfully.
  34. // . IKE is up.
  35. // . Driver is up.
  36. // If persistent policy application failed, IKE init failed, or driver op failed,
  37. // then service would have shutdown with driver in block mode if possible.
  38. DWORD dwError = 0;
  39. HANDLE hWaitForEvents[WAIT_EVENT_COUNT];
  40. BOOL bDoneWaiting = FALSE;
  41. DWORD dwWaitMilliseconds = 0;
  42. DWORD dwStatus = 0;
  43. time_t LastTimeOutTime = 0;
  44. AuditEvent(
  45. SE_CATEGID_POLICY_CHANGE,
  46. SE_AUDITID_IPSEC_POLICY_CHANGED,
  47. IPSECSVC_SUCCESSFUL_START,
  48. NULL,
  49. TRUE,
  50. TRUE
  51. );
  52. hWaitForEvents[SERVICE_STOP_EVENT] = ghServiceStopEvent;
  53. hWaitForEvents[INTERFACE_CHANGE_EVENT] = GetInterfaceChangeEvent();
  54. hWaitForEvents[NEW_LOCAL_POLICY_EVENT] = ghNewLocalPolicyEvent;
  55. hWaitForEvents[NEW_DS_POLICY_EVENT] = ghNewDSPolicyEvent;
  56. hWaitForEvents[FORCED_POLICY_RELOAD_EVENT] = ghForcedPolicyReloadEvent;
  57. hWaitForEvents[GPUPDATE_REFRESH_EVENT] = ghGpupdateRefreshEvent;
  58. //
  59. // First load the default main mode policy.
  60. //
  61. (VOID) LoadDefaultISAKMPInformation(
  62. gpszDefaultISAKMPPolicyDN
  63. );
  64. //
  65. // Call the Polling Manager for the first time.
  66. //
  67. (VOID) StartStatePollingManager(
  68. gpIpsecPolicyState
  69. );
  70. NotifyIpsecPolicyChange();
  71. ComputeRelativePollingTime(
  72. LastTimeOutTime,
  73. TRUE,
  74. gdwRetryCount,
  75. &dwWaitMilliseconds
  76. );
  77. time(&LastTimeOutTime);
  78. TRACE(TRC_INFORMATION, (L"Completed startup routines. Entering service wait loop."));
  79. while (!bDoneWaiting) {
  80. dwStatus = WaitForMultipleObjects(
  81. WAIT_EVENT_COUNT,
  82. hWaitForEvents,
  83. FALSE,
  84. dwWaitMilliseconds
  85. );
  86. PADeleteInUsePolicies();
  87. switch (dwStatus) {
  88. case SERVICE_STOP_EVENT:
  89. TRACE(TRC_INFORMATION, (L"Service stop event signaled"));
  90. dwError = ERROR_SUCCESS;
  91. bDoneWaiting = TRUE;
  92. break;
  93. case INTERFACE_CHANGE_EVENT:
  94. TRACE(TRC_INFORMATION, (L"Interface changed event signaled"));
  95. (VOID) OnInterfaceChangeEvent(
  96. );
  97. (VOID) IKEInterfaceChange();
  98. break;
  99. case NEW_LOCAL_POLICY_EVENT:
  100. TRACE(TRC_INFORMATION, (L"New local policy event signaled"));
  101. ResetEvent(ghNewLocalPolicyEvent);
  102. if ((gpIpsecPolicyState->CurrentState != SPD_STATE_DS_APPLY_SUCCESS) &&
  103. (gpIpsecPolicyState->CurrentState != SPD_STATE_CACHE_APPLY_SUCCESS)) {
  104. (VOID) ProcessLocalPolicyPollState(
  105. gpIpsecPolicyState
  106. );
  107. NotifyIpsecPolicyChange();
  108. }
  109. break;
  110. case NEW_DS_POLICY_EVENT:
  111. TRACE(TRC_INFORMATION, (L"New DS policy event signaled"));
  112. ResetEvent(ghNewDSPolicyEvent);
  113. (VOID) OnPolicyChanged(
  114. gpIpsecPolicyState
  115. );
  116. NotifyIpsecPolicyChange();
  117. break;
  118. case GPUPDATE_REFRESH_EVENT:
  119. TRACE(TRC_INFORMATION, (L"Group policy refresh event signaled"));
  120. ResetEvent(ghGpupdateRefreshEvent);
  121. dwError = ProcessDirectoryPolicyPollState(
  122. gpIpsecPolicyState
  123. );
  124. break;
  125. case FORCED_POLICY_RELOAD_EVENT:
  126. TRACE(TRC_INFORMATION, (L"Forced policy reload event signaled"));
  127. ResetEvent(ghForcedPolicyReloadEvent);
  128. (VOID) OnPolicyChanged(
  129. gpIpsecPolicyState
  130. );
  131. NotifyIpsecPolicyChange();
  132. AuditEvent(
  133. SE_CATEGID_POLICY_CHANGE,
  134. SE_AUDITID_IPSEC_POLICY_CHANGED,
  135. PASTORE_FORCED_POLICY_RELOAD,
  136. NULL,
  137. TRUE,
  138. TRUE
  139. );
  140. break;
  141. case WAIT_TIMEOUT:
  142. TRACE(TRC_INFORMATION, (L"Polling event signaled"));
  143. time(&LastTimeOutTime);
  144. (VOID) OnPolicyPoll(
  145. gpIpsecPolicyState
  146. );
  147. (VOID) OnSpecialAddrsChange();
  148. break;
  149. case WAIT_FAILED:
  150. dwError = GetLastError();
  151. TRACE(TRC_ERROR, (L"Failed service wait WaitForMultipleObjects %!winerr!: ", dwError));
  152. bDoneWaiting = TRUE;
  153. break;
  154. default:
  155. dwError = ERROR_INVALID_EVENT_COUNT;
  156. bDoneWaiting = TRUE;
  157. break;
  158. }
  159. ComputeRelativePollingTime(
  160. LastTimeOutTime,
  161. FALSE,
  162. gdwRetryCount,
  163. &dwWaitMilliseconds
  164. );
  165. if (InAcceptableState(gpIpsecPolicyState->CurrentState)) {
  166. // Polling is not going to retry anymore since we've reached an
  167. // acceptable state. So reset gdwRetryCount for NEXT time
  168. // in case we reach an unacceptable state.
  169. gdwRetryCount = 0;
  170. TRACE(
  171. TRC_INFORMATION,
  172. ("Policy Agent now in state %d",
  173. (DWORD) gpIpsecPolicyState->CurrentState)
  174. );
  175. }
  176. #ifdef TRACE_ON
  177. else {
  178. TRACE(
  179. TRC_INFORMATION,
  180. ("Policy Agent in error state %d, retry count is %d ",
  181. (DWORD) gpIpsecPolicyState->CurrentState,
  182. gdwRetryCount)
  183. );
  184. }
  185. #endif
  186. }
  187. if (!dwError) {
  188. AuditEvent(
  189. SE_CATEGID_POLICY_CHANGE,
  190. SE_AUDITID_IPSEC_POLICY_CHANGED,
  191. IPSECSVC_SUCCESSFUL_SHUTDOWN,
  192. NULL,
  193. TRUE,
  194. TRUE
  195. );
  196. }
  197. else {
  198. AuditOneArgErrorEvent(
  199. SE_CATEGID_POLICY_CHANGE,
  200. SE_AUDITID_IPSEC_POLICY_CHANGED,
  201. IPSECSVC_ERROR_SHUTDOWN,
  202. dwError,
  203. FALSE,
  204. TRUE
  205. );
  206. TRACE(TRC_ERROR, (L"Failed and exiting service wait %!winerr!: ", dwError));
  207. }
  208. return (dwError);
  209. }
  210. VOID
  211. ComputeRelativePollingTime(
  212. IN time_t LastTimeOutTime,
  213. IN BOOL bInitialLoad,
  214. IN DWORD dwRetryCount,
  215. IN PDWORD pWaitMilliseconds
  216. )
  217. {
  218. DWORD WaitMilliseconds = 0;
  219. DWORD DSReconnectMilliseconds = 0;
  220. time_t NextTimeOutTime = 0;
  221. time_t PresentTime = 0;
  222. long WaitSeconds = gDefaultPollingInterval;
  223. DWORD64 NewPollingIntervalSeconds = 0;
  224. if (!InAcceptableState(gpIpsecPolicyState->CurrentState)) {
  225. // Exponentially back-off polling interval until
  226. // we hit default polling interval.
  227. // Polling interval increases as (dwRetryCount+1)^2
  228. NewPollingIntervalSeconds = (dwRetryCount+1) * (dwRetryCount+1) * 60;
  229. if (NewPollingIntervalSeconds < gDefaultPollingInterval) {
  230. gCurrentPollingInterval = (DWORD) NewPollingIntervalSeconds;
  231. } else {
  232. gCurrentPollingInterval = gDefaultPollingInterval;
  233. }
  234. }
  235. WaitMilliseconds = gCurrentPollingInterval * 1000;
  236. if (!WaitMilliseconds) {
  237. WaitMilliseconds = INFINITE;
  238. }
  239. if (!bInitialLoad && WaitMilliseconds != INFINITE) {
  240. //
  241. // LastTimeOutTime is the snapshot time value in the past when
  242. // we timed out waiting for multiple events.
  243. // Ideally, the time for the next time out, NextTimeOutTime, is
  244. // the time value in future which is sum of the last time when
  245. // we timed out + the current waiting time value.
  246. //
  247. NextTimeOutTime = LastTimeOutTime + (WaitMilliseconds/1000);
  248. //
  249. // However, the last time we may not have timed out waiting
  250. // for multiple events but rather came out because one of the
  251. // events other than WAIT_TIMEOUT happened.
  252. // However, on that event we may not have done a policy
  253. // poll to figure out whether there was a policy change or
  254. // not. If we again wait for WaitMilliseconds, then we are
  255. // un-knowingly making our net time for policy poll greater
  256. // than the alloted time interval value = WaitMilliseconds.
  257. // So, we need to adjust the WaitMilliseconds to such a value
  258. // that no matter what happens, we always do a policy poll
  259. // atmost every WaitMilliseconds time interval value.
  260. // The current time is PresentTime.
  261. //
  262. time(&PresentTime);
  263. WaitSeconds = (long) (NextTimeOutTime - PresentTime);
  264. if (WaitSeconds < 0) {
  265. WaitMilliseconds = 0;
  266. }
  267. else {
  268. WaitMilliseconds = WaitSeconds * 1000;
  269. }
  270. }
  271. *pWaitMilliseconds = WaitMilliseconds;
  272. }
  273. VOID
  274. NotifyIpsecPolicyChange(
  275. )
  276. {
  277. PulseEvent(ghPolicyChangeNotifyEvent);
  278. SendPschedIoctl();
  279. ResetEvent(ghPolicyChangeNotifyEvent);
  280. return;
  281. }
  282. VOID
  283. SendPschedIoctl(
  284. )
  285. {
  286. HANDLE hPschedDriverHandle = NULL;
  287. ULONG uBytesReturned = 0;
  288. BOOL bIOStatus = FALSE;
  289. #define DriverName TEXT("\\\\.\\PSCHED")
  290. #define IOCTL_PSCHED_ZAW_EVENT CTL_CODE( \
  291. FILE_DEVICE_NETWORK, \
  292. 20, \
  293. METHOD_BUFFERED, \
  294. FILE_ANY_ACCESS \
  295. )
  296. hPschedDriverHandle = CreateFile(
  297. DriverName,
  298. GENERIC_READ | GENERIC_WRITE,
  299. FILE_SHARE_READ | FILE_SHARE_WRITE,
  300. NULL,
  301. OPEN_EXISTING,
  302. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  303. NULL
  304. );
  305. if (hPschedDriverHandle != INVALID_HANDLE_VALUE) {
  306. bIOStatus = DeviceIoControl(
  307. hPschedDriverHandle,
  308. IOCTL_PSCHED_ZAW_EVENT,
  309. NULL,
  310. 0,
  311. NULL,
  312. 0,
  313. &uBytesReturned,
  314. NULL
  315. );
  316. CloseHandle(hPschedDriverHandle);
  317. }
  318. }
  319. VOID
  320. PADeleteInUsePolicies(
  321. )
  322. {
  323. DWORD dwError = 0;
  324. TRACE(TRC_INFORMATION, (L"Deleting policy components no longer in use"));
  325. dwError = PADeleteInUseMMPolicies();
  326. dwError = PADeleteInUseMMAuthMethods();
  327. dwError = PADeleteInUseQMPolicies();
  328. return;
  329. }