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.
 
 
 
 
 
 

842 lines
22 KiB

/*++
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"
#ifdef TRACE_ON
#include "ipsecspd.tmh"
#endif
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;
DWORD dwTempError = 0;
WPP_INIT_TRACING(SPD_WPP_APPNAME);
// Sleep(30000);
InitMiscGlobals();
dwError = InitAuditing();
BAIL_ON_WIN32_ERROR(dwError);
InitSPDThruRegistry();
//
// Open the IPSec Driver first, so that if we bail on error later,
// we can still set driver in block mode.
//
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);
// 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 = RegisterServiceCtrlHandlerExW(
IPSECSPD_SERVICE,
IPSecSPDControlHandler,
NULL
);
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 |
SERVICE_ACCEPT_POWEREVENT;
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
);
//
// Get a list of DNS, DHCP, etc servers.
//
(VOID) GetSpecialAddrsList(
&gpSpecialAddrsList
);
gpIpsecPolicyState->PersIncarnationNumber = 0;
dwError = LoadPersistedIPSecInformation();
BAIL_ON_WIN32_ERROR(dwError);
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
);
TRACE(TRC_ERROR, (L"Failed to initialize IKE: %!winerr!", dwError));
}
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
);
TRACE(TRC_ERROR, (L"Failed to start RPC server: %!winerr!", dwError));
}
BAIL_ON_WIN32_ERROR(dwError);
dwError = ServiceWait();
error:
#ifdef TRACE_ON
if (dwError) {
TRACE(TRC_ERROR, (L"Failed to start IPSec PolicyAgent: %!winerr!", dwError));
}
#endif
if (dwError && ghIPSecDriver != INVALID_HANDLE_VALUE) {
dwTempError = SPDSetIPSecDriverOpMode(
(DWORD) IPSEC_BLOCK_MODE
);
if (gbAuditingInitialized) {
AuditOneArgErrorEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
IPSECSVC_SET_DRIVER_BLOCK,
dwError,
FALSE,
TRUE
);
}
}
IPSecSPDShutdown(dwError);
return;
}
DWORD
IPSecSPDUpdateStatus(
)
{
DWORD dwError = 0;
if (!SetServiceStatus(IPSecSPDStatusHandle, &IPSecSPDStatus)) {
dwError = GetLastError();
}
return (dwError);
}
DWORD
IPSecSPDControlHandler(
IN DWORD dwOpCode,
IN DWORD dwEventType,
IN LPVOID lpEventData,
IN LPVOID lpContext
)
{
DWORD dwErr = ERROR_SUCCESS;
switch (dwOpCode)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
if (dwOpCode == SERVICE_CONTROL_SHUTDOWN) {
gdwShutdownFlags = SPD_SHUTDOWN_MACHINE;
} else {
gdwShutdownFlags = SPD_SHUTDOWN_SERVICE;
}
if (IPSecSPDStatus.dwCurrentState != SERVICE_STOP_PENDING) {
IPSecSPDStatus.dwCurrentState = SERVICE_STOP_PENDING;
IPSecSPDStatus.dwCheckPoint = 1;
IPSecSPDStatus.dwWaitHint = 60000;
(void) IPSecSPDUpdateStatus();
SetEvent(ghServiceStopEvent);
return dwErr;
}
break;
case SERVICE_CONTROL_NEW_LOCAL_POLICY:
SetEvent(ghNewLocalPolicyEvent);
break;
case SERVICE_CONTROL_FORCED_POLICY_RELOAD:
SetEvent(ghForcedPolicyReloadEvent);
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_POWEREVENT:
switch ( dwEventType ) {
case PBT_APMRESUMEAUTOMATIC:
case PBT_APMRESUMECRITICAL:
case PBT_APMRESUMESUSPEND:
// Notify IKE of power event, ignore error
if (gbIKENotify) {
IKENotifyPolicyChange(NULL,POLICY_GUID_POWEREVENT_RESUME);
}
break;
default:
break;
}
}
(void) IPSecSPDUpdateStatus();
return (dwErr);
}
VOID
IPSecSPDShutdown(
IN DWORD dwErrorCode
)
{
BOOL bMachineShutdown = FALSE;
TRACE(TRC_INFORMATION, (L"PolicyAgent shutting down."));
bMachineShutdown = gdwShutdownFlags & SPD_SHUTDOWN_MACHINE;
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;
if (bMachineShutdown) {
IKEShutdown(SPD_SHUTDOWN_MACHINE);
} else {
IKEShutdown(SPD_SHUTDOWN_SERVICE);
}
}
if (gpIniMMPolicy) {
FreeIniMMPolicyList(gpIniMMPolicy);
gpIniMMPolicy = NULL;
}
if (gpIniMMAuthMethods) {
FreeIniMMAuthMethodsList(gpIniMMAuthMethods);
gpIniMMAuthMethods = NULL;
}
if (gpIniQMPolicy) {
FreeIniQMPolicyList(gpIniQMPolicy);
gpIniQMPolicy = NULL;
}
if (gpIniMMSFilter) {
FreeIniMMSFilterList(gpIniMMSFilter);
gpIniMMSFilter = NULL;
}
if (gpMMFilterHandle) {
FreeMMFilterHandleList(gpMMFilterHandle);
gpMMFilterHandle = NULL;
}
if (gpIniMMFilter) {
FreeIniMMFilterList(gpIniMMFilter);
gpIniMMFilter = NULL;
}
if (gpIniTxSFilter) {
// Following call will check gShutdownFlags and
// not delete ipsec filters if shutting down machine
(VOID) DeleteTransportFiltersFromIPSec(gpIniTxSFilter);
FreeIniTxSFilterList(gpIniTxSFilter);
gpIniTxSFilter = NULL;
}
if (gpTxFilterHandle) {
FreeTxFilterHandleList(gpTxFilterHandle);
gpTxFilterHandle = NULL;
}
if (gpIniTxFilter) {
FreeIniTxFilterList(gpIniTxFilter);
gpIniTxFilter = NULL;
}
if (gpIniTnSFilter) {
// Following call will check gShutdownFlags and
// not delete ipsec filters if shutting down machine
(VOID) DeleteTunnelFiltersFromIPSec(gpIniTnSFilter);
FreeIniTnSFilterList(gpIniTnSFilter);
gpIniTnSFilter = NULL;
}
if (gpTnFilterHandle) {
FreeTnFilterHandleList(gpTnFilterHandle);
gpTnFilterHandle = NULL;
}
if (gpIniTnFilter) {
FreeIniTnFilterList(gpIniTnFilter);
gpIniTnFilter = NULL;
}
if (!bMachineShutdown) {
(VOID) SPDRegisterIPSecDriverProtocols(
(DWORD) IPSEC_DEREGISTER_PROTOCOLS
);
}
if (ghIPSecDriver != INVALID_HANDLE_VALUE) {
SPDCloseIPSecDriver(ghIPSecDriver);
ghIPSecDriver = INVALID_HANDLE_VALUE;
}
if (gpInterfaceList) {
DestroyInterfaceList(
gpInterfaceList
);
gpInterfaceList = NULL;
}
if (gpSpecialAddrsList) {
FreeSpecialAddrList(
&gpSpecialAddrsList
);
gpSpecialAddrsList = NULL;
}
ClearSPDGlobals();
IPSecSPDStatus.dwCurrentState = SERVICE_STOPPED;
IPSecSPDStatus.dwControlsAccepted = 0;
IPSecSPDStatus.dwCheckPoint = 0;
IPSecSPDStatus.dwWaitHint = 0;
IPSecSPDStatus.dwWin32ExitCode = dwErrorCode;
IPSecSPDStatus.dwServiceSpecificExitCode = 0;
(void) IPSecSPDUpdateStatus();
WPP_CLEANUP();
return;
}
VOID
ClearSPDGlobals(
)
{
DestroyInterfaceChangeEvent();
if (gbSPDSection) {
DeleteCriticalSection(&gcSPDSection);
}
if (gbServerListenSection == TRUE) {
DeleteCriticalSection(&gcServerListenSection);
}
if (ghServiceStopEvent) {
CloseHandle(ghServiceStopEvent);
ghServiceStopEvent = NULL;
}
if (ghNewDSPolicyEvent) {
CloseHandle(ghNewDSPolicyEvent);
ghNewDSPolicyEvent = NULL;
}
if (ghNewLocalPolicyEvent) {
CloseHandle(ghNewLocalPolicyEvent);
ghNewLocalPolicyEvent = NULL;
}
if (ghForcedPolicyReloadEvent) {
CloseHandle(ghForcedPolicyReloadEvent);
ghForcedPolicyReloadEvent = NULL;
}
if (ghPolicyChangeNotifyEvent) {
CloseHandle(ghPolicyChangeNotifyEvent);
ghPolicyChangeNotifyEvent = NULL;
}
if (ghGpupdateRefreshEvent) {
CloseHandle(ghGpupdateRefreshEvent);
ghGpupdateRefreshEvent = NULL;
}
if (gbSPDAuditSection) {
DeleteCriticalSection(&gcSPDAuditSection);
}
gbAuditingInitialized = FALSE;
if (gpSPDSD) {
LocalFree(gpSPDSD);
gpSPDSD = NULL;
}
}
VOID
ClearPAStoreGlobals(
)
{
if (gpMMFilterState) {
PAFreeMMFilterStateList(gpMMFilterState);
gpMMFilterState = NULL;
}
if (gpMMPolicyState) {
PAFreeMMPolicyStateList(gpMMPolicyState);
gpMMPolicyState = NULL;
}
if (gpMMAuthState) {
PAFreeMMAuthStateList(gpMMAuthState);
gpMMAuthState = NULL;
}
if (gpTxFilterState) {
PAFreeTxFilterStateList(gpTxFilterState);
gpTxFilterState = NULL;
}
if (gpTnFilterState) {
PAFreeTnFilterStateList(gpTnFilterState);
gpTnFilterState = NULL;
}
if (gpQMPolicyState) {
PAFreeQMPolicyStateList(gpQMPolicyState);
gpQMPolicyState = NULL;
}
}
VOID
InitMiscGlobals(
)
{
//
// Init globals that aren't cleared on service stop to make sure
// everything's in a known state on start. This allows us to
// stop/restart without having our DLL unloaded/reloaded first.
//
gbSPDRPCServerUp = FALSE;
ghServiceStopEvent = NULL;
gdwServersListening = 0;
gbServerListenSection = FALSE;
gpInterfaceList = NULL;
gpSpecialAddrsList = NULL;
gbwsaStarted = FALSE;
gIfChangeEventSocket = INVALID_SOCKET;
ghIfChangeEvent = NULL;
ghOverlapEvent = NULL;
gpIniTxFilter = NULL;
gpIniTxSFilter = NULL;
gpTxFilterHandle = NULL;
gbSPDSection = FALSE;
gpIniQMPolicy = NULL;
gpIniDefaultQMPolicy = NULL;
gpIniMMPolicy = NULL;
gpIniDefaultMMPolicy = NULL;
gpIniMMFilter = NULL;
gpIniMMSFilter = NULL;
gpMMFilterHandle = NULL;
gpIniMMAuthMethods = NULL;
gpIniDefaultMMAuthMethods = NULL;
gpIpsecPolicyState = &gIpsecPolicyState;
gCurrentPollingInterval = 0;
gDefaultPollingInterval = 166*60; // (seconds).
gdwRetryCount = 0;
gpszIpsecDSPolicyKey = L"SOFTWARE\\Policies\\Microsoft\\Windows\\IPSec\\GPTIPSECPolicy";
gpszIpsecLocalPolicyKey = L"SOFTWARE\\Policies\\Microsoft\\Windows\\IPSec\\Policy\\Local";
gpszIpsecPersistentPolicyKey = L"SOFTWARE\\Policies\\Microsoft\\Windows\\IPSec\\Policy\\Persistent";
gpszIpsecCachePolicyKey = L"SOFTWARE\\Policies\\Microsoft\\Windows\\IPSec\\Policy\\Cache";
gpszDefaultISAKMPPolicyDN = L"SOFTWARE\\Policies\\Microsoft\\Windows\\IPSec\\Policy\\Local\\ipsecISAKMPPolicy{72385234-70FA-11D1-864C-14A300000000}";
gpszLocPolicyAgent = L"SYSTEM\\CurrentControlSet\\Services\\PolicyAgent";
ghNewDSPolicyEvent = NULL;
ghNewLocalPolicyEvent = NULL;
ghForcedPolicyReloadEvent = NULL;
ghPolicyChangeNotifyEvent = NULL;
ghGpupdateRefreshEvent = NULL;
gbLoadedISAKMPDefaults = FALSE;
gpMMPolicyState = NULL;
gpMMAuthState = NULL;
gpMMFilterState = NULL;
gdwMMPolicyCounter = 0;
gdwMMFilterCounter = 0;
gpQMPolicyState = NULL;
gdwQMPolicyCounter = 0;
gpTxFilterState = NULL;
gdwTxFilterCounter = 0;
gpIniTnFilter = NULL;
gpIniTnSFilter = NULL;
gpTnFilterHandle = NULL;
gpTnFilterState = NULL;
gdwTnFilterCounter = 0;
gbIsIKEUp = FALSE;
gpSPDSD = NULL;
gbIKENotify = FALSE;
ghIPSecDriver = INVALID_HANDLE_VALUE;
gbSPDAuditSection = FALSE;
ghIpsecServerModule = NULL;
gbAuditingInitialized = FALSE;
gbIsIoctlPended = FALSE;
gbBackwardSoftSA = FALSE;
gdwShutdownFlags = 0;
gbPersistentPolicyApplied = FALSE;
return;
}
DWORD
QuerySpdPolicyState(
LPWSTR pServerName,
DWORD dwVersion,
PSPD_POLICY_STATE * ppSpdPolicyState,
LPVOID pvReserved
)
{
DWORD dwError = 0;
PSPD_POLICY_STATE pSpdPolicyState = NULL;
dwError = SPDApiBufferAllocate(
sizeof(SPD_POLICY_STATE),
&pSpdPolicyState
);
BAIL_ON_WIN32_ERROR(dwError);
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pSpdPolicyState->PolicyLoadState = gpIpsecPolicyState->CurrentState;
switch (gpIpsecPolicyState->CurrentState) {
case SPD_STATE_DS_APPLY_SUCCESS:
pSpdPolicyState->dwWhenChanged = gpIpsecPolicyState->DSIncarnationNumber;
break;
case SPD_STATE_LOCAL_APPLY_SUCCESS:
case SPD_STATE_CACHE_APPLY_SUCCESS:
pSpdPolicyState->dwWhenChanged = gpIpsecPolicyState->RegIncarnationNumber;
break;
case SPD_STATE_PERSISTENT_APPLY_SUCCESS:
pSpdPolicyState->dwWhenChanged = gpIpsecPolicyState->PersIncarnationNumber;
break;
default:
pSpdPolicyState->dwWhenChanged = 0;
break;
}
LEAVE_SPD_SECTION();
*ppSpdPolicyState = pSpdPolicyState;
return (dwError);
lock:
LEAVE_SPD_SECTION();
error:
if (pSpdPolicyState) {
SPDApiBufferFree(pSpdPolicyState);
}
*ppSpdPolicyState = NULL;
return (dwError);
}
DWORD
SetSpdStateOnError(
DWORD dwPolicySource,
SPD_ACTION SpdAction,
DWORD ActionError,
SPD_STATE * pSpdState
)
{
SPD_STATE SpdPolicyState = 0;
DWORD dwError = ERROR_SUCCESS;
if (!pSpdState) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
// Collapse triplet into one flag:
// Long-winded, but by doing it like this we simplify readability
// of other parts of code.
if (!ActionError) {
if (SpdAction == SPD_POLICY_APPLY) {
switch(dwPolicySource) {
case IPSEC_SOURCE_PERSISTENT:
SpdPolicyState = SPD_STATE_PERSISTENT_APPLY_SUCCESS;
break;
case IPSEC_SOURCE_LOCAL:
SpdPolicyState = SPD_STATE_LOCAL_APPLY_SUCCESS;
break;
case IPSEC_SOURCE_DOMAIN:
SpdPolicyState = SPD_STATE_DS_APPLY_SUCCESS;
break;
case IPSEC_SOURCE_CACHE:
SpdPolicyState = SPD_STATE_CACHE_APPLY_SUCCESS;
break;
}
} else if (SpdAction == SPD_POLICY_LOAD) {
switch(dwPolicySource) {
case IPSEC_SOURCE_PERSISTENT:
SpdPolicyState = SPD_STATE_PERSISTENT_LOAD_SUCCESS;
break;
case IPSEC_SOURCE_LOCAL:
SpdPolicyState = SPD_STATE_LOCAL_LOAD_SUCCESS;
break;
case IPSEC_SOURCE_DOMAIN:
SpdPolicyState = SPD_STATE_DS_LOAD_SUCCESS;
break;
case IPSEC_SOURCE_CACHE:
SpdPolicyState = SPD_STATE_CACHE_LOAD_SUCCESS;
break;
}
}
} else {
if (SpdAction == SPD_POLICY_APPLY) {
switch(dwPolicySource) {
case IPSEC_SOURCE_PERSISTENT:
SpdPolicyState = SPD_STATE_PERSISTENT_APPLY_FAIL;
break;
case IPSEC_SOURCE_LOCAL:
SpdPolicyState = SPD_STATE_LOCAL_APPLY_FAIL;
break;
case IPSEC_SOURCE_DOMAIN:
SpdPolicyState = SPD_STATE_DS_APPLY_FAIL;
break;
case IPSEC_SOURCE_CACHE:
SpdPolicyState = SPD_STATE_CACHE_APPLY_FAIL;
break;
}
} else if (SpdAction == SPD_POLICY_LOAD) {
switch(dwPolicySource) {
case IPSEC_SOURCE_PERSISTENT:
SpdPolicyState = SPD_STATE_PERSISTENT_LOAD_FAIL;
break;
case IPSEC_SOURCE_LOCAL:
SpdPolicyState = SPD_STATE_LOCAL_LOAD_FAIL;
break;
case IPSEC_SOURCE_DOMAIN:
SpdPolicyState = SPD_STATE_DS_LOAD_FAIL;
break;
case IPSEC_SOURCE_CACHE:
SpdPolicyState = SPD_STATE_CACHE_LOAD_FAIL;
break;
}
}
}
(*pSpdState) = SpdPolicyState;
error:
return ERROR_SUCCESS;
}
BOOL
InAcceptableState(
SPD_STATE SpdState
)
{
BOOL AcceptableState = FALSE;
switch (SpdState) {
case SPD_STATE_LOCAL_APPLY_SUCCESS:
case SPD_STATE_DS_APPLY_SUCCESS:
case SPD_STATE_PERSISTENT_APPLY_SUCCESS:
case SPD_STATE_INITIAL:
AcceptableState = TRUE;
break;
}
return AcceptableState;
}