///////////////////////////////////////////////////////////// // Copyright(c) 1998, Microsoft Corporation // // useparpc.cpp // // Created on 8/15/98 by Randyram // Revisions: // 2/29/00 - DKalin // Removed out-of-date PA RPC routines, added Ipsecpol service management // // This holds all the init and cleanup code for using the // SPD API and for using SCM for controlling PA and ipsecpolsvc // see usepa.h for usage // ///////////////////////////////////////////////////////////// #include "ipseccmd.h" const TCHAR szIpsecpolsvc[] = TEXT("ipsecpolsvc"); bool PAIsRunning(OUT DWORD &dwError, TCHAR *szServ) { bool bReturn = true; dwError = ERROR_SUCCESS; SERVICE_STATUS ServStat; memset(&ServStat, 0, sizeof(SERVICE_STATUS)); SC_HANDLE schMan = OpenSCManager(szServ, NULL, SC_MANAGER_ALL_ACCESS); if (schMan == NULL) { dwError = GetLastError(); bReturn = false; } else { SC_HANDLE schPA = OpenService(schMan, TEXT("policyagent"), SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP); if (schPA == NULL) { dwError = GetLastError(); bReturn = false; } else if (QueryServiceStatus(schPA, &ServStat)) { // check the status finally if (ServStat.dwCurrentState != SERVICE_RUNNING) { bReturn = false; } CloseServiceHandle(schPA); } CloseServiceHandle(schMan); } return bReturn; } bool StartPA(OUT DWORD &dwError, OPTIONAL TCHAR *szServ) { bool bReturn = true; dwError = ERROR_SUCCESS; SERVICE_STATUS ServStat; memset(&ServStat, 0, sizeof(SERVICE_STATUS)); SC_HANDLE schMan = OpenSCManager(szServ, NULL, SC_MANAGER_ALL_ACCESS); if (schMan == NULL) { dwError = GetLastError(); bReturn = false; } else { SC_HANDLE schPA = OpenService(schMan, TEXT("policyagent"), SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP); if (schPA == NULL) { dwError = GetLastError(); bReturn = false; } else if (QueryServiceStatus(schPA, &ServStat)) { // check the status finally if (ServStat.dwCurrentState != SERVICE_RUNNING) { if (!StartService(schPA, 0, NULL)) { dwError = GetLastError(); bReturn = false; } } CloseServiceHandle(schPA); } CloseServiceHandle(schMan); } return bReturn; } /********************************************************************* FUNCTION: InstallIpsecpolService PURPOSE: Installs ipsecpolsvc service (incl. copying .exe to system32 dir) PARAMS: pszFilename - name of the .exe file (full path recommended) bFailIfExists - if TRUE, fail if service already exists, if FALSE, stop service, delete it and proceed ( default = TRUE ) RETURNS: ERROR_SUCESS or GetLastError code COMMENTS: *********************************************************************/ DWORD InstallIpsecpolService (IN LPCTSTR pszFilename, IN OPTIONAL BOOL bFailIfExists) { DWORD dwReturn = ERROR_SUCCESS; // open SCM Manager first SC_HANDLE schMan = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); SC_HANDLE schIpsecpolsvc; if (schMan == NULL) { dwReturn = GetLastError(); } else { // OK, we have handle access to SCM manager // if bFailIfExists == FALSE, let's check if service is running and stop it if (!bFailIfExists) { if (IsIpsecpolServiceRunning(dwReturn)) { dwReturn = StopIpsecpolService(); } } // continue only if we're okay so far if (dwReturn != ERROR_SUCCESS) { CloseServiceHandle(schMan); return dwReturn; } // now handle copyfile stuff TCHAR pszDestination[MAX_PATH+1]; TCHAR* pszWindir = _tgetenv(TEXT("WINDIR")); TCHAR* pTmp; if (pszWindir == NULL || pszFilename == NULL || pszFilename[0] == 0) { CloseServiceHandle(schMan); return ERROR_PATH_NOT_FOUND; } _tcscpy(pszDestination, pszWindir); _tcscat(pszDestination, TEXT("\\system32\\")); pTmp = (TCHAR*) _tcsrchr(pszFilename, TEXT('\\')); if (pTmp == NULL) { _tcscat(pszDestination, pszFilename); } else { _tcscat(pszDestination, pTmp+1); } // now copy file if (!CopyFile(pszFilename, pszDestination, FALSE)) { CloseServiceHandle(schMan); return GetLastError(); } // now delete service if it already exists and bFailIfExists is FALSE if (!bFailIfExists) { // check if it exists and try to delete schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | STANDARD_RIGHTS_REQUIRED ); if (schIpsecpolsvc == NULL) { dwReturn = GetLastError(); if (dwReturn == ERROR_INVALID_NAME || dwReturn == ERROR_SERVICE_DOES_NOT_EXIST) { // doesn't exist, continue normally dwReturn = ERROR_SUCCESS; } else { // some real error CloseServiceHandle(schMan); return dwReturn; } } else { // service exists, delete DeleteService(schIpsecpolsvc); CloseServiceHandle(schIpsecpolsvc); } } // now create new service schIpsecpolsvc = CreateService(schMan, szIpsecpolsvc, szIpsecpolsvc, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | STANDARD_RIGHTS_REQUIRED, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, pszDestination, NULL, NULL, NULL, NULL, NULL); if (schIpsecpolsvc == NULL) { // some error CloseServiceHandle(schMan); return GetLastError(); } CloseServiceHandle(schIpsecpolsvc); CloseServiceHandle(schMan); } return dwReturn; } /* InstallIpsecpolService */ /********************************************************************* FUNCTION: StartIpsecpolService PURPOSE: Attempts to start ipsecpolsvc service PARAMS: pszServ - optional name of the server (default is NULL, start on local machine) RETURNS: ERROR_SUCESS or GetLastError code COMMENTS: *********************************************************************/ DWORD StartIpsecpolService (IN OPTIONAL LPCTSTR pszServ) { DWORD dwReturn = ERROR_SUCCESS; SERVICE_STATUS ServStat; memset(&ServStat, 0, sizeof(SERVICE_STATUS)); SC_HANDLE schMan = OpenSCManager(pszServ, NULL, SC_MANAGER_ALL_ACCESS); if (schMan == NULL) { dwReturn = GetLastError(); } else { SC_HANDLE schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP); if (schIpsecpolsvc == NULL) { dwReturn = GetLastError(); } else if (QueryServiceStatus(schIpsecpolsvc, &ServStat)) { // check the status finally if (ServStat.dwCurrentState != SERVICE_RUNNING) { if (!StartService(schIpsecpolsvc, 0, NULL)) { dwReturn = GetLastError(); } } CloseServiceHandle(schIpsecpolsvc); } CloseServiceHandle(schMan); } return dwReturn; } /* StartIpsecpolService */ /********************************************************************* FUNCTION: StopIpsecpolService PURPOSE: Attempts to stop ipsecpolsvc service PARAMS: pszServ - optional name of the server (default is NULL, start on local machine) RETURNS: ERROR_SUCESS or GetLastError code COMMENTS: *********************************************************************/ DWORD StopIpsecpolService (IN OPTIONAL LPCTSTR pszServ) { DWORD dwReturn = ERROR_SUCCESS; SERVICE_STATUS ServStat; memset(&ServStat, 0, sizeof(SERVICE_STATUS)); SC_HANDLE schMan = OpenSCManager(pszServ, NULL, SC_MANAGER_ALL_ACCESS); if (schMan == NULL) { dwReturn = GetLastError(); } else { SC_HANDLE schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP); if (schIpsecpolsvc == NULL) { dwReturn = GetLastError(); } else if (QueryServiceStatus(schIpsecpolsvc, &ServStat)) { // check the status finally if (ServStat.dwCurrentState == SERVICE_RUNNING) { if (!ControlService(schIpsecpolsvc, SERVICE_CONTROL_STOP, &ServStat)) { dwReturn = GetLastError(); } } CloseServiceHandle(schIpsecpolsvc); } CloseServiceHandle(schMan); } return dwReturn; } /* StopIpsecpolService */ /********************************************************************* FUNCTION: IsIpsecpolServiceRunning PURPOSE: Checks if ipsecpolsvc service is currently running PARAMS: dwReturn - holds errors retuned by SCM if any pszServ - optional name of the server (default is NULL, start on local machine) RETURNS: TRUE/FALSE COMMENTS: TRUE returned means service is running FALSE and dwReturn == ERROR_SUCCESS means service is not running FALSE and dwReturn != ERROR_SUCCESS means SCM operation failed (dwReturn is error code) *********************************************************************/ BOOL IsIpsecpolServiceRunning (OUT DWORD &dwReturn, OPTIONAL LPCTSTR pszServ) { BOOL bReturn = TRUE; dwReturn = ERROR_SUCCESS; SERVICE_STATUS ServStat; memset(&ServStat, 0, sizeof(SERVICE_STATUS)); SC_HANDLE schMan = OpenSCManager(pszServ, NULL, SC_MANAGER_ALL_ACCESS); if (schMan == NULL) { dwReturn = GetLastError(); bReturn = FALSE; } else { SC_HANDLE schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP); if (schIpsecpolsvc == NULL) { dwReturn = GetLastError(); bReturn = FALSE; } else if (QueryServiceStatus(schIpsecpolsvc, &ServStat)) { // check the status finally if (ServStat.dwCurrentState != SERVICE_RUNNING) { bReturn = FALSE; } CloseServiceHandle(schIpsecpolsvc); } CloseServiceHandle(schMan); } return bReturn; } /* IsIpsecpolServiceRunning */ /********************************************************************* FUNCTION: InitIpsecpolsvcRPC PURPOSE: Get an RPC handle from ipsecpolsvc that can be used to call its APIs PARAMS: pszServ - name of the server (pass NULL for the local machine) hIpsecpolsvc - returned handle RETURNS: RPC_S_OK or RPC api error code COMMENTS: Service running is not prereq *********************************************************************/ RPC_STATUS InitIpsecpolsvcRPC (IN TCHAR *pszServ, OUT handle_t &hIpsecpolsvc) { RPC_STATUS status = RPC_S_OK; TCHAR localProtocol[] = TEXT("ncacn_np"); TCHAR remoteProtocol[] = TEXT("ncacn_np"); TCHAR endpoint[] = TEXT("\\pipe\\ipsecpolsvc"); PUSHORT stringBinding = NULL; ULONG SecurityLevel = RPC_C_AUTHN_LEVEL_CONNECT; if (pszServ != 0) { if (pszServ[0] == 0) { // empty string pszServ = NULL; } } status = RpcStringBindingCompose(0, (PUSHORT)((pszServ == NULL) ? localProtocol : remoteProtocol), (PUSHORT)pszServ, (PUSHORT)endpoint, 0, &stringBinding); if (status == RPC_S_OK) { status = RpcBindingFromStringBinding(stringBinding, &hIpsecpolsvc); } if (status == RPC_S_OK) { status = RpcBindingSetAuthInfo(hIpsecpolsvc, 0, SecurityLevel, RPC_C_AUTHN_WINNT, 0, 0 ); } if (stringBinding != NULL) { status = RpcStringFree(&stringBinding); } return status; } /* InitIpsecpolsvcRPC */ /********************************************************************* FUNCTION: ShutdownIpsecpolsvcRPC PURPOSE: Close RPC handle PARAMS: hIpsecpolsvc - handle RETURNS: RPC_S_OK or RPC api error code COMMENTS: *********************************************************************/ RPC_STATUS ShutdownIpsecpolsvcRPC (IN handle_t hIpsecpolsvc) { return RpcBindingFree(&hIpsecpolsvc); } /* ShutdownIpsecpolsvcRPC */ /********************************************************************* FUNCTION: PlumbIPSecPolicy PURPOSE: Plumbs IPSEC_IKE_POLICY to the specified machine PARAMS: pszServerName - machine name or NULL for local pIPSecIkePol - pointer to IPSEC_IKE_POLICY. GUIDs/names must be generated prior to the call bFailMMIfExists - specifies MM filter behavior bFailMMIfExists == FALSE will cause the call not to break on ERROR_MM_FILTER_EXISTS when duplicate MM filters are there bFailMMIfExists == TRUE will fail on any SPD API error ppMMFilterHandles - array of mm filter handles will be returned here ppFilterHandles - array of qm filter handles will be returned here bPersist - if TRUE, information will be persisted RETURNS: ERROR_SUCCESS or win32 error code COMMENTS: CALLER is responsible for freeing the memory for the handle arrays *********************************************************************/ DWORD PlumbIPSecPolicy( IN LPWSTR pServerName, IN PIPSEC_IKE_POLICY pIPSecIkePol, IN BOOL bFailMMIfExists, OUT PHANDLE *ppMMFilterHandles, OUT PHANDLE *ppFilterHandles, IN OPTIONAL BOOL bPersist ) { DWORD dwReturn = ERROR_SUCCESS; RPC_STATUS RpcStat = RPC_S_OK; int i; HANDLE hFilter; BOOL bDefaultRule = FALSE; // will be true if default response rule is specified // default response rule is specified if there is exactly 1 transport filter that is Me-to-Me if (!pIPSecIkePol) { return ERROR_NO_DATA; } if (pIPSecIkePol->dwNumFilters == 1 && pIPSecIkePol->QMFilterType == QM_TRANSPORT_FILTER) { if (pIPSecIkePol->pTransportFilters[0].SrcAddr.AddrType == IP_ADDR_UNIQUE && pIPSecIkePol->pTransportFilters[0].SrcAddr.uIpAddr == IP_ADDRESS_ME && pIPSecIkePol->pTransportFilters[0].DesAddr.AddrType == IP_ADDR_UNIQUE && pIPSecIkePol->pTransportFilters[0].DesAddr.uIpAddr == IP_ADDRESS_ME && pIPSecIkePol->pTransportFilters[0].InboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG && pIPSecIkePol->pTransportFilters[0].OutboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG) { bDefaultRule = TRUE; } } // allocate handle arrays first if (bDefaultRule) { *ppMMFilterHandles = *ppFilterHandles = 0; pIPSecIkePol->AuthInfos.dwFlags |= IPSEC_MM_AUTH_DEFAULT_AUTH; pIPSecIkePol->IkePol.dwFlags |= IPSEC_MM_POLICY_DEFAULT_POLICY; pIPSecIkePol->IpsPol.dwFlags |= IPSEC_QM_POLICY_DEFAULT_POLICY; } else { if (ppMMFilterHandles && pIPSecIkePol->dwNumMMFilters) { *ppMMFilterHandles = new HANDLE[pIPSecIkePol->dwNumMMFilters]; if (*ppMMFilterHandles == 0) { return ERROR_OUTOFMEMORY; } memset(*ppMMFilterHandles, 0, sizeof(HANDLE)*pIPSecIkePol->dwNumMMFilters); } if (ppFilterHandles && pIPSecIkePol->dwNumFilters) { *ppFilterHandles = new HANDLE[pIPSecIkePol->dwNumFilters]; if (*ppFilterHandles == 0) { if (ppMMFilterHandles) { if (*ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } } return ERROR_OUTOFMEMORY; } memset(*ppFilterHandles, 0, sizeof(HANDLE)*pIPSecIkePol->dwNumFilters); } } // let's go and plumb everything // authinfos first if (!UuidIsNil(&(pIPSecIkePol->AuthInfos.gMMAuthID), &RpcStat)) { dwReturn = AddMMAuthMethods(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->AuthInfos)); } if (dwReturn != ERROR_SUCCESS) { if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return dwReturn; } if (RpcStat != RPC_S_OK) { if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return GetLastError(); } // mm policy if (!UuidIsNil(&(pIPSecIkePol->IkePol.gPolicyID), &RpcStat)) { dwReturn = AddMMPolicy(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->IkePol)); } if (dwReturn != ERROR_SUCCESS) { if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return dwReturn; } if (RpcStat != RPC_S_OK) { if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return GetLastError(); } // qm policy if (!UuidIsNil(&(pIPSecIkePol->IpsPol.gPolicyID), &RpcStat)) { dwReturn = AddQMPolicy(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->IpsPol)); } if (dwReturn != ERROR_SUCCESS) { if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return dwReturn; } if (RpcStat != RPC_S_OK) { if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; } if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return GetLastError(); } if (bDefaultRule) { // return here return dwReturn; } // mm filters for (i = 0; i < (int) pIPSecIkePol->dwNumMMFilters; i++) { hFilter = NULL; if (!UuidIsNil(&(pIPSecIkePol->pMMFilters[i].gFilterID), &RpcStat)) { dwReturn = AddMMFilter(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->pMMFilters[i]), &hFilter); } if (RpcStat != RPC_S_OK) { if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return GetLastError(); } if (!bFailMMIfExists && (dwReturn == ERROR_IPSEC_MM_POLICY_EXISTS || dwReturn == ERROR_IPSEC_MM_AUTH_EXISTS || dwReturn == ERROR_IPSEC_MM_FILTER_EXISTS)) { dwReturn = ERROR_SUCCESS; // it's not actually an error } if (dwReturn != ERROR_SUCCESS) { if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; } return dwReturn; } if (ppMMFilterHandles) { (*ppMMFilterHandles)[i] = hFilter; } } // qm filters for (i = 0; i < (int) pIPSecIkePol->dwNumFilters; i++) { hFilter = NULL; if (pIPSecIkePol->QMFilterType == QM_TRANSPORT_FILTER) { if (!UuidIsNil(&(pIPSecIkePol->pTransportFilters[i].gFilterID), &RpcStat)) { dwReturn = AddTransportFilter(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->pTransportFilters[i]), &hFilter); } } else { // tunnel if (!UuidIsNil(&(pIPSecIkePol->pTunnelFilters[i].gFilterID), &RpcStat)) { dwReturn = AddTunnelFilter(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->pTunnelFilters[i]), &hFilter); } } if (dwReturn != ERROR_SUCCESS) { return dwReturn; } if (RpcStat != RPC_S_OK) { return GetLastError(); } if (ppFilterHandles) { (*ppFilterHandles)[i] = hFilter; } } return dwReturn; } /* PlumbIPSecPolicy */ /********************************************************************* FUNCTION: DeleteIPSecPolicy PURPOSE: Complementary to PlumbIPSecPolicy, removes IPSEC_IKE_POLICY PARAMS: pszServerName - machine name or NULL for local pIPSecIkePol - pointer to IPSEC_IKE_POLICY. GUIDs/names must be generated prior to the call pMMFilterHandles - array of main mode filter handles pFilterHandles - array of quick mode filter handles RETURNS: ERROR_SUCCESS or win32 error code COMMENTS: Function will try to remove everything specified in the IPSEC_IKE_POLICY structure. It is possible that one or several errors will be encountered. Function will continue, but later first error will be returned. *********************************************************************/ DWORD DeleteIPSecPolicy( IN LPWSTR pServerName, IN PIPSEC_IKE_POLICY pIPSecIkePol, IN PHANDLE pMMFilterHandles, IN PHANDLE pFilterHandles ) { DWORD dwReturn = ERROR_SUCCESS; DWORD dwErrorCode = ERROR_SUCCESS; RPC_STATUS RpcStat = RPC_S_OK; int i; // mm filters if (pMMFilterHandles) { for (i = 0; i < (int) pIPSecIkePol->dwNumMMFilters; i++) { if (!UuidIsNil(&(pIPSecIkePol->pMMFilters[i].gFilterID), &RpcStat)) { dwReturn = DeleteMMFilter(pMMFilterHandles[i]); } if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = GetLastError(); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } // qm filters if (pFilterHandles) { for (i = 0; i < (int) pIPSecIkePol->dwNumFilters; i++) { if (pIPSecIkePol->QMFilterType == QM_TRANSPORT_FILTER) { if (!UuidIsNil(&(pIPSecIkePol->pTransportFilters[i].gFilterID), &RpcStat)) { dwReturn = DeleteTransportFilter(pFilterHandles[i]); } } else { // tunnel if (!UuidIsNil(&(pIPSecIkePol->pTunnelFilters[i].gFilterID), &RpcStat)) { dwReturn = DeleteTunnelFilter(pFilterHandles[i]); } } if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = GetLastError(); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } // mm auth methods if (!UuidIsNil(&(pIPSecIkePol->AuthInfos.gMMAuthID), &RpcStat)) { dwReturn = DeleteMMAuthMethods(pServerName, pIPSecIkePol->AuthInfos.gMMAuthID); } if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = GetLastError(); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // mm policy if (!UuidIsNil(&(pIPSecIkePol->IkePol.gPolicyID), &RpcStat)) { dwReturn = DeleteMMPolicy(pServerName, pIPSecIkePol->IkePol.pszPolicyName); } if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = GetLastError(); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // qm policy if (!UuidIsNil(&(pIPSecIkePol->IpsPol.gPolicyID), &RpcStat)) { dwReturn = DeleteQMPolicy(pServerName, pIPSecIkePol->IpsPol.pszPolicyName); } if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = GetLastError(); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } return dwErrorCode; } /* DeleteIPSecPolicy */ /********************************************************************* FUNCTION: DeletePersistedIPSecPolicy PURPOSE: Complementary to PlumbIPSecPolicy with persistent flag on, removes persisted policy PARAMS: pszServerName - machine name or NULL for local pPolicyName - policy name prefix, if empty string of NULL, all persisted policy settings will be removed RETURNS: ERROR_SUCCESS or win32 error code COMMENTS: Function will try to remove everything specified. It is possible that one or several errors will be encountered. Function will continue, but later first error will be returned. *********************************************************************/ DWORD DeletePersistedIPSecPolicy( IN LPWSTR pServerName, IN LPWSTR pPolicyName ) { DWORD dwErrorCode, dwReturn; int i, j; PMM_FILTER pmmf; // for MM filter calls PIPSEC_QM_POLICY pipsqmp; // for QM policy calls PTRANSPORT_FILTER ptf; // for transport filter calls PTUNNEL_FILTER ptunf; // for tunnel filter calls PMM_AUTH_METHODS pam; // for auth method calls PIPSEC_MM_POLICY pipsmmp; // for MM policy calls DWORD dwCount; // counting objects here DWORD dwResumeHandle; // handle for continuation calls DWORD dwReserved; // reserved container GUID gDefaultGUID = {0}; // NULL GUID value int iPolNameLen = 0; HANDLE hFilter; BOOL bRemoveDefault = FALSE; dwErrorCode = dwReturn = ERROR_SUCCESS; if (pPolicyName && *pPolicyName) { iPolNameLen = wcslen(pPolicyName); } // start with mm filters, enum all pmmf=NULL; dwResumeHandle=0; // make the call(s) for (i = 0; ;i+=dwCount) { BOOL bRemoved = FALSE; DWORD dwOldResumeHandle = dwResumeHandle; dwReturn = EnumMMFilters(pServerName, ENUM_GENERIC_FILTERS, gDefaultGUID, &pmmf, 0, &dwCount, &dwResumeHandle); if (dwReturn == ERROR_NO_DATA || dwCount == 0) { dwReturn = ERROR_SUCCESS; // no more filters break; } if (dwReturn != ERROR_SUCCESS) { break; } for (j = 0; j < (int) dwCount; j++) { // check if it's our filter if (iPolNameLen == 0|| wcsncmp(pPolicyName, pmmf[j].pszFilterName, iPolNameLen) == 0) { dwReturn = OpenMMFilterHandle(pServerName, &(pmmf[j]), &hFilter); if (dwReturn == ERROR_SUCCESS) { dwReturn = DeleteMMFilter(hFilter); if (dwReturn == ERROR_SUCCESS) { bRemoved = TRUE; } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } dwReturn = CloseMMFilterHandle(hFilter); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } SPDApiBufferFree(pmmf); pmmf=NULL; if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } if (bRemoved) { dwResumeHandle = dwOldResumeHandle; // need to restart enumeration! } } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // transport filters - the routine is similar ptf=NULL; dwResumeHandle=0; // make the call(s) for (i = 0; ;i+=dwCount) { BOOL bRemoved = FALSE; DWORD dwOldResumeHandle = dwResumeHandle; dwReturn = EnumTransportFilters(pServerName, ENUM_GENERIC_FILTERS, gDefaultGUID, &ptf, 0, &dwCount, &dwResumeHandle); if (dwReturn == ERROR_NO_DATA || dwCount == 0) { dwReturn = ERROR_SUCCESS; // no more filters break; } if (dwReturn != ERROR_SUCCESS) { break; } for (j = 0; j < (int) dwCount; j++) { // check if it's our filter if (iPolNameLen == 0|| wcsncmp(pPolicyName, ptf[j].pszFilterName, iPolNameLen) == 0) { dwReturn = OpenTransportFilterHandle(pServerName, &(ptf[j]), &hFilter); if (dwReturn == ERROR_SUCCESS) { dwReturn = DeleteTransportFilter(hFilter); if (dwReturn == ERROR_SUCCESS) { bRemoved = TRUE; } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } dwReturn = CloseTransportFilterHandle(hFilter); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } SPDApiBufferFree(ptf); ptf=NULL; if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } if (bRemoved) { dwResumeHandle = dwOldResumeHandle; // need to restart enumeration! } } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // tunnel filters ptunf=NULL; dwResumeHandle=0; // make the call(s) for (i = 0; ;i+=dwCount) { BOOL bRemoved = FALSE; DWORD dwOldResumeHandle = dwResumeHandle; dwReturn = EnumTunnelFilters(pServerName, ENUM_GENERIC_FILTERS, gDefaultGUID, &ptunf, 0, &dwCount, &dwResumeHandle); if (dwReturn == ERROR_NO_DATA || dwCount == 0) { dwReturn = ERROR_SUCCESS; // no more filters break; } if (dwReturn != ERROR_SUCCESS) { break; } for (j = 0; j < (int) dwCount; j++) { // check if it's our filter if (iPolNameLen == 0|| wcsncmp(pPolicyName, ptunf[j].pszFilterName, iPolNameLen) == 0) { dwReturn = OpenTunnelFilterHandle(pServerName, &(ptunf[j]), &hFilter); if (dwReturn == ERROR_SUCCESS) { dwReturn = DeleteTunnelFilter(hFilter); if (dwReturn == ERROR_SUCCESS) { bRemoved = TRUE; } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } dwReturn = CloseTunnelFilterHandle(hFilter); } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } SPDApiBufferFree(ptunf); ptunf=NULL; if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } if (bRemoved) { dwResumeHandle = dwOldResumeHandle; // need to restart enumeration! } } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // mm policies pipsmmp=NULL; dwResumeHandle=0; // make the call(s) for (i = 0; ;i+=dwCount) { BOOL bRemoved = FALSE; DWORD dwOldResumeHandle = dwResumeHandle; dwReturn = EnumMMPolicies(pServerName, &pipsmmp, 0, &dwCount, &dwResumeHandle); if (dwReturn == ERROR_NO_DATA || dwCount == 0) { dwReturn = ERROR_SUCCESS; // no more filters break; } if (dwReturn != ERROR_SUCCESS) { break; } for (j = 0; j < (int) dwCount; j++) { // check if it's our mm policy if (iPolNameLen == 0|| wcsncmp(pPolicyName, pipsmmp[j].pszPolicyName, iPolNameLen) == 0) { dwReturn = DeleteMMPolicy(pServerName, pipsmmp[j].pszPolicyName); if (dwReturn == ERROR_SUCCESS) { bRemoved = TRUE; } if (dwReturn == ERROR_SUCCESS && (pipsmmp[j].dwFlags & IPSEC_QM_POLICY_DEFAULT_POLICY)) { // got to remove other defaults too bRemoveDefault = TRUE; } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } SPDApiBufferFree(pipsmmp); pipsmmp=NULL; if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } if (bRemoved) { dwResumeHandle = dwOldResumeHandle; // need to restart enumeration! } } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // auth methods pam=NULL; dwResumeHandle=0; // make the call(s) for (i = 0; ;i+=dwCount) { BOOL bRemoved = FALSE; DWORD dwOldResumeHandle = dwResumeHandle; dwReturn = EnumMMAuthMethods(pServerName, &pam, 0, &dwCount, &dwResumeHandle); if (dwReturn == ERROR_NO_DATA || dwCount == 0) { dwReturn = ERROR_SUCCESS; // no more filters break; } if (dwReturn != ERROR_SUCCESS) { break; } for (j = 0; j < (int) dwCount; j++) { // check if it's our auth method if (bRemoveDefault || (pam[j].dwFlags & IPSEC_MM_AUTH_DEFAULT_AUTH) == 0) { // either remove default is set or this is non-default dwReturn = DeleteMMAuthMethods(pServerName, pam[j].gMMAuthID); if (dwReturn == ERROR_SUCCESS) { bRemoved = TRUE; } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } SPDApiBufferFree(pam); pam=NULL; if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } if (bRemoved) { dwResumeHandle = dwOldResumeHandle; // need to restart enumeration! } } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } // qm policies pipsqmp=NULL; dwResumeHandle=0; // make the call(s) for (i = 0; ;i+=dwCount) { BOOL bRemoved = FALSE; DWORD dwOldResumeHandle = dwResumeHandle; dwReturn = EnumQMPolicies(pServerName, &pipsqmp, 0, &dwCount, &dwResumeHandle); if (dwReturn == ERROR_NO_DATA || dwCount == 0) { dwReturn = ERROR_SUCCESS; // no more filters break; } if (dwReturn != ERROR_SUCCESS) { break; } for (j = 0; j < (int) dwCount; j++) { // check if it's our qm policy if (iPolNameLen == 0|| wcsncmp(pPolicyName, pipsqmp[j].pszPolicyName, iPolNameLen) == 0) { dwReturn = DeleteQMPolicy(pServerName, pipsqmp[j].pszPolicyName); if (dwReturn == ERROR_SUCCESS) { bRemoved = TRUE; } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } } } SPDApiBufferFree(pipsqmp); pipsqmp=NULL; if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } if (bRemoved) { dwResumeHandle = dwOldResumeHandle; // need to restart enumeration! } } if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS) { dwErrorCode = dwReturn; } return dwErrorCode; } /* DeletePersistedIPSecPolicy */