/*++ Copyright (c) 1999 Microsoft Corporation Module Name: ipsecspd.c Abstract: This module contains all of the code to drive the IPSecSPD Service. Author: abhisheV 30-September-1999 Environment User Level: Win32 Revision History: --*/ #include "precomp.h" SERVICE_STATUS IPSecSPDStatus; SERVICE_STATUS_HANDLE IPSecSPDStatusHandle = NULL; #define IPSECSPD_SERVICE L"PolicyAgent" void WINAPI SPDServiceMain( IN DWORD dwArgc, IN LPTSTR * lpszArgv ) { DWORD dwError = 0; // Sleep(30000); dwError = InitSPDThruRegistry(); BAIL_ON_WIN32_ERROR(dwError); // Initialize all the status fields so that the subsequent calls // to SetServiceStatus need to only update fields that changed. IPSecSPDStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; IPSecSPDStatus.dwCurrentState = SERVICE_START_PENDING; IPSecSPDStatus.dwControlsAccepted = 0; IPSecSPDStatus.dwCheckPoint = 1; IPSecSPDStatus.dwWaitHint = 5000; IPSecSPDStatus.dwWin32ExitCode = NO_ERROR; IPSecSPDStatus.dwServiceSpecificExitCode = 0; // Initialize the workstation to receive service requests // by registering the service control handler. IPSecSPDStatusHandle = RegisterServiceCtrlHandlerW( IPSECSPD_SERVICE, IPSecSPDControlHandler ); if (IPSecSPDStatusHandle == (SERVICE_STATUS_HANDLE) NULL) { dwError = ERROR_INVALID_HANDLE; BAIL_ON_WIN32_ERROR(dwError); } (void) IPSecSPDUpdateStatus(); dwError = InitSPDGlobals(); BAIL_ON_WIN32_ERROR(dwError); IPSecSPDStatus.dwCurrentState = SERVICE_RUNNING; IPSecSPDStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; IPSecSPDStatus.dwCheckPoint = 0; IPSecSPDStatus.dwWaitHint = 0; IPSecSPDStatus.dwWin32ExitCode = NO_ERROR; IPSecSPDStatus.dwServiceSpecificExitCode = 0; (void) IPSecSPDUpdateStatus(); // // Get the current list of active interfaces on the machine. // (VOID) CreateInterfaceList( &gpInterfaceList ); // // Open the IPSec Driver. // dwError = SPDOpenIPSecDriver( &ghIPSecDriver ); if (dwError) { AuditOneArgErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_DRIVER_INIT_FAILURE, dwError, FALSE, TRUE ); } BAIL_ON_WIN32_ERROR(dwError); (VOID) LoadPersistedIPSecInformation(); dwError = SPDSetIPSecDriverOpMode( (DWORD) IPSEC_SECURE_MODE ); if (dwError) { AuditOneArgErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_DRIVER_INIT_FAILURE, dwError, FALSE, TRUE ); } BAIL_ON_WIN32_ERROR(dwError); dwError = SPDRegisterIPSecDriverProtocols( (DWORD) IPSEC_REGISTER_PROTOCOLS ); if (dwError) { AuditOneArgErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_DRIVER_INIT_FAILURE, dwError, FALSE, TRUE ); } BAIL_ON_WIN32_ERROR(dwError); // // Start IKE Service. // dwError = IKEInit(); if (dwError) { AuditOneArgErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_IKE_INIT_FAILURE, dwError, FALSE, TRUE ); } BAIL_ON_WIN32_ERROR(dwError); gbIsIKEUp = TRUE; gbIKENotify = TRUE; // // Start the RPC Server. // dwError = SPDStartRPCServer( ); if (dwError) { AuditOneArgErrorEvent( SE_CATEGID_POLICY_CHANGE, SE_AUDITID_IPSEC_POLICY_CHANGED, IPSECSVC_RPC_INIT_FAILURE, dwError, FALSE, TRUE ); } BAIL_ON_WIN32_ERROR(dwError); dwError = ServiceWait(); error: IPSecSPDShutdown(dwError); return; } DWORD IPSecSPDUpdateStatus( ) { DWORD dwError = 0; if (!SetServiceStatus(IPSecSPDStatusHandle, &IPSecSPDStatus)) { dwError = GetLastError(); } return (dwError); } VOID IPSecSPDControlHandler( IN DWORD dwOpCode ) { switch (dwOpCode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: if (IPSecSPDStatus.dwCurrentState != SERVICE_STOP_PENDING) { IPSecSPDStatus.dwCurrentState = SERVICE_STOP_PENDING; IPSecSPDStatus.dwCheckPoint = 1; IPSecSPDStatus.dwWaitHint = 60000; (void) IPSecSPDUpdateStatus(); SetEvent(ghServiceStopEvent); return; } break; case SERVICE_CONTROL_NEW_LOCAL_POLICY: SetEvent(ghNewLocalPolicyEvent); break; case SERVICE_CONTROL_FORCED_POLICY_RELOAD: SetEvent(ghForcedPolicyReloadEvent); break; case SERVICE_CONTROL_INTERROGATE: break; } (void) IPSecSPDUpdateStatus(); return; } VOID IPSecSPDShutdown( IN DWORD dwErrorCode ) { gbIKENotify = FALSE; (VOID) DeleteAllPolicyInformation(); ClearPolicyStateBlock( gpIpsecPolicyState ); if (gbLoadedISAKMPDefaults) { UnLoadDefaultISAKMPInformation(gpszDefaultISAKMPPolicyDN); } ClearPAStoreGlobals(); // // Service stop still pending. // Increment checkpoint counter and update // the status with the Service Control Manager. // (IPSecSPDStatus.dwCheckPoint)++; (void) IPSecSPDUpdateStatus(); if (gbSPDRPCServerUp) { gbSPDRPCServerUp = FALSE; SPDStopRPCServer(); } if (gbIsIKEUp) { gbIsIKEUp = FALSE; IKEShutdown(); } if (gpIniMMPolicy) { FreeIniMMPolicyList(gpIniMMPolicy); } if (gpIniMMAuthMethods) { FreeIniMMAuthMethodsList(gpIniMMAuthMethods); } if (gpIniQMPolicy) { FreeIniQMPolicyList(gpIniQMPolicy); } if (gpIniMMSFilter) { FreeIniMMSFilterList(gpIniMMSFilter); } if (gpMMFilterHandle) { FreeMMFilterHandleList(gpMMFilterHandle); } if (gpIniMMFilter) { FreeIniMMFilterList(gpIniMMFilter); } if (gpIniTxSFilter) { (VOID) DeleteTransportFiltersFromIPSec(gpIniTxSFilter); FreeIniTxSFilterList(gpIniTxSFilter); } if (gpTxFilterHandle) { FreeTxFilterHandleList(gpTxFilterHandle); } if (gpIniTxFilter) { FreeIniTxFilterList(gpIniTxFilter); } if (gpIniTnSFilter) { (VOID) DeleteTunnelFiltersFromIPSec(gpIniTnSFilter); FreeIniTnSFilterList(gpIniTnSFilter); } if (gpTnFilterHandle) { FreeTnFilterHandleList(gpTnFilterHandle); } if (gpIniTnFilter) { FreeIniTnFilterList(gpIniTnFilter); } (VOID) SPDRegisterIPSecDriverProtocols( (DWORD) IPSEC_DEREGISTER_PROTOCOLS ); if (ghIPSecDriver != INVALID_HANDLE_VALUE) { SPDCloseIPSecDriver(ghIPSecDriver); } if (gpInterfaceList) { DestroyInterfaceList( gpInterfaceList ); } ClearSPDGlobals(); IPSecSPDStatus.dwCurrentState = SERVICE_STOPPED; IPSecSPDStatus.dwControlsAccepted = 0; IPSecSPDStatus.dwCheckPoint = 0; IPSecSPDStatus.dwWaitHint = 0; IPSecSPDStatus.dwWin32ExitCode = dwErrorCode; IPSecSPDStatus.dwServiceSpecificExitCode = 0; (void) IPSecSPDUpdateStatus(); return; } VOID ClearSPDGlobals( ) { DestroyInterfaceChangeEvent(); if (gbSPDSection) { DeleteCriticalSection(&gcSPDSection); } if (gbServerListenSection == TRUE) { DeleteCriticalSection(&gcServerListenSection); } if (ghServiceStopEvent) { CloseHandle(ghServiceStopEvent); } if (ghNewDSPolicyEvent) { CloseHandle(ghNewDSPolicyEvent); } if (ghNewLocalPolicyEvent) { CloseHandle(ghNewLocalPolicyEvent); } if (ghForcedPolicyReloadEvent) { CloseHandle(ghForcedPolicyReloadEvent); } if (ghPolicyChangeNotifyEvent) { CloseHandle(ghPolicyChangeNotifyEvent); } if (gbSPDAuditSection) { DeleteCriticalSection(&gcSPDAuditSection); } if (gpSPDSD) { LocalFree(gpSPDSD); } } VOID ClearPAStoreGlobals( ) { if (gpMMFilterState) { PAFreeMMFilterStateList(gpMMFilterState); } if (gpMMPolicyState) { PAFreeMMPolicyStateList(gpMMPolicyState); } if (gpMMAuthState) { PAFreeMMAuthStateList(gpMMAuthState); } if (gpTxFilterState) { PAFreeTxFilterStateList(gpTxFilterState); } if (gpTnFilterState) { PAFreeTnFilterStateList(gpTnFilterState); } if (gpQMPolicyState) { PAFreeQMPolicyStateList(gpQMPolicyState); } }