Source code of Windows XP (NT5)
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.

1186 lines
33 KiB

  1. /////////////////////////////////////////////////////////////
  2. // Copyright(c) 1998, Microsoft Corporation
  3. //
  4. // useparpc.cpp
  5. //
  6. // Created on 8/15/98 by Randyram
  7. // Revisions:
  8. // 2/29/00 - DKalin
  9. // Removed out-of-date PA RPC routines, added Ipsecpol service management
  10. //
  11. // This holds all the init and cleanup code for using the
  12. // SPD API and for using SCM for controlling PA and ipsecpolsvc
  13. // see usepa.h for usage
  14. //
  15. /////////////////////////////////////////////////////////////
  16. #include "ipseccmd.h"
  17. const TCHAR szIpsecpolsvc[] = TEXT("ipsecpolsvc");
  18. bool PAIsRunning(OUT DWORD &dwError, TCHAR *szServ)
  19. {
  20. bool bReturn = true;
  21. dwError = ERROR_SUCCESS;
  22. SERVICE_STATUS ServStat;
  23. memset(&ServStat, 0, sizeof(SERVICE_STATUS));
  24. SC_HANDLE schMan = OpenSCManager(szServ, NULL, SC_MANAGER_ALL_ACCESS);
  25. if (schMan == NULL)
  26. {
  27. dwError = GetLastError();
  28. bReturn = false;
  29. }
  30. else
  31. {
  32. SC_HANDLE schPA = OpenService(schMan, TEXT("policyagent"),
  33. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP);
  34. if (schPA == NULL)
  35. {
  36. dwError = GetLastError();
  37. bReturn = false;
  38. }
  39. else if (QueryServiceStatus(schPA, &ServStat))
  40. {
  41. // check the status finally
  42. if (ServStat.dwCurrentState != SERVICE_RUNNING)
  43. {
  44. bReturn = false;
  45. }
  46. CloseServiceHandle(schPA);
  47. }
  48. CloseServiceHandle(schMan);
  49. }
  50. return bReturn;
  51. }
  52. bool StartPA(OUT DWORD &dwError, OPTIONAL TCHAR *szServ)
  53. {
  54. bool bReturn = true;
  55. dwError = ERROR_SUCCESS;
  56. SERVICE_STATUS ServStat;
  57. memset(&ServStat, 0, sizeof(SERVICE_STATUS));
  58. SC_HANDLE schMan = OpenSCManager(szServ, NULL, SC_MANAGER_ALL_ACCESS);
  59. if (schMan == NULL)
  60. {
  61. dwError = GetLastError();
  62. bReturn = false;
  63. }
  64. else
  65. {
  66. SC_HANDLE schPA = OpenService(schMan, TEXT("policyagent"),
  67. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP);
  68. if (schPA == NULL)
  69. {
  70. dwError = GetLastError();
  71. bReturn = false;
  72. }
  73. else if (QueryServiceStatus(schPA, &ServStat))
  74. {
  75. // check the status finally
  76. if (ServStat.dwCurrentState != SERVICE_RUNNING)
  77. {
  78. if (!StartService(schPA, 0, NULL))
  79. {
  80. dwError = GetLastError();
  81. bReturn = false;
  82. }
  83. }
  84. CloseServiceHandle(schPA);
  85. }
  86. CloseServiceHandle(schMan);
  87. }
  88. return bReturn;
  89. }
  90. /*********************************************************************
  91. FUNCTION: InstallIpsecpolService
  92. PURPOSE: Installs ipsecpolsvc service (incl. copying .exe to system32 dir)
  93. PARAMS:
  94. pszFilename - name of the .exe file (full path recommended)
  95. bFailIfExists - if TRUE, fail if service already exists,
  96. if FALSE, stop service, delete it and proceed
  97. ( default = TRUE )
  98. RETURNS: ERROR_SUCESS or GetLastError code
  99. COMMENTS:
  100. *********************************************************************/
  101. DWORD InstallIpsecpolService (IN LPCTSTR pszFilename, IN OPTIONAL BOOL bFailIfExists)
  102. {
  103. DWORD dwReturn = ERROR_SUCCESS;
  104. // open SCM Manager first
  105. SC_HANDLE schMan = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  106. SC_HANDLE schIpsecpolsvc;
  107. if (schMan == NULL)
  108. {
  109. dwReturn = GetLastError();
  110. }
  111. else
  112. {
  113. // OK, we have handle access to SCM manager
  114. // if bFailIfExists == FALSE, let's check if service is running and stop it
  115. if (!bFailIfExists)
  116. {
  117. if (IsIpsecpolServiceRunning(dwReturn))
  118. {
  119. dwReturn = StopIpsecpolService();
  120. }
  121. }
  122. // continue only if we're okay so far
  123. if (dwReturn != ERROR_SUCCESS)
  124. {
  125. CloseServiceHandle(schMan);
  126. return dwReturn;
  127. }
  128. // now handle copyfile stuff
  129. TCHAR pszDestination[MAX_PATH+1];
  130. TCHAR* pszWindir = _tgetenv(TEXT("WINDIR"));
  131. TCHAR* pTmp;
  132. if (pszWindir == NULL || pszFilename == NULL || pszFilename[0] == 0)
  133. {
  134. CloseServiceHandle(schMan);
  135. return ERROR_PATH_NOT_FOUND;
  136. }
  137. _tcscpy(pszDestination, pszWindir);
  138. _tcscat(pszDestination, TEXT("\\system32\\"));
  139. pTmp = (TCHAR*) _tcsrchr(pszFilename, TEXT('\\'));
  140. if (pTmp == NULL)
  141. {
  142. _tcscat(pszDestination, pszFilename);
  143. }
  144. else
  145. {
  146. _tcscat(pszDestination, pTmp+1);
  147. }
  148. // now copy file
  149. if (!CopyFile(pszFilename, pszDestination, FALSE))
  150. {
  151. CloseServiceHandle(schMan);
  152. return GetLastError();
  153. }
  154. // now delete service if it already exists and bFailIfExists is FALSE
  155. if (!bFailIfExists)
  156. {
  157. // check if it exists and try to delete
  158. schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc,
  159. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | STANDARD_RIGHTS_REQUIRED );
  160. if (schIpsecpolsvc == NULL)
  161. {
  162. dwReturn = GetLastError();
  163. if (dwReturn == ERROR_INVALID_NAME || dwReturn == ERROR_SERVICE_DOES_NOT_EXIST)
  164. {
  165. // doesn't exist, continue normally
  166. dwReturn = ERROR_SUCCESS;
  167. }
  168. else
  169. { // some real error
  170. CloseServiceHandle(schMan);
  171. return dwReturn;
  172. }
  173. }
  174. else
  175. {
  176. // service exists, delete
  177. DeleteService(schIpsecpolsvc);
  178. CloseServiceHandle(schIpsecpolsvc);
  179. }
  180. }
  181. // now create new service
  182. schIpsecpolsvc = CreateService(schMan,
  183. szIpsecpolsvc,
  184. szIpsecpolsvc,
  185. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | STANDARD_RIGHTS_REQUIRED,
  186. SERVICE_WIN32_OWN_PROCESS,
  187. SERVICE_DEMAND_START,
  188. SERVICE_ERROR_NORMAL,
  189. pszDestination,
  190. NULL,
  191. NULL,
  192. NULL,
  193. NULL,
  194. NULL);
  195. if (schIpsecpolsvc == NULL)
  196. {
  197. // some error
  198. CloseServiceHandle(schMan);
  199. return GetLastError();
  200. }
  201. CloseServiceHandle(schIpsecpolsvc);
  202. CloseServiceHandle(schMan);
  203. }
  204. return dwReturn;
  205. } /* InstallIpsecpolService */
  206. /*********************************************************************
  207. FUNCTION: StartIpsecpolService
  208. PURPOSE: Attempts to start ipsecpolsvc service
  209. PARAMS:
  210. pszServ - optional name of the server (default is NULL, start on local machine)
  211. RETURNS: ERROR_SUCESS or GetLastError code
  212. COMMENTS:
  213. *********************************************************************/
  214. DWORD StartIpsecpolService (IN OPTIONAL LPCTSTR pszServ)
  215. {
  216. DWORD dwReturn = ERROR_SUCCESS;
  217. SERVICE_STATUS ServStat;
  218. memset(&ServStat, 0, sizeof(SERVICE_STATUS));
  219. SC_HANDLE schMan = OpenSCManager(pszServ, NULL, SC_MANAGER_ALL_ACCESS);
  220. if (schMan == NULL)
  221. {
  222. dwReturn = GetLastError();
  223. }
  224. else
  225. {
  226. SC_HANDLE schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc,
  227. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP);
  228. if (schIpsecpolsvc == NULL)
  229. {
  230. dwReturn = GetLastError();
  231. }
  232. else if (QueryServiceStatus(schIpsecpolsvc, &ServStat))
  233. {
  234. // check the status finally
  235. if (ServStat.dwCurrentState != SERVICE_RUNNING)
  236. {
  237. if (!StartService(schIpsecpolsvc, 0, NULL))
  238. {
  239. dwReturn = GetLastError();
  240. }
  241. }
  242. CloseServiceHandle(schIpsecpolsvc);
  243. }
  244. CloseServiceHandle(schMan);
  245. }
  246. return dwReturn;
  247. } /* StartIpsecpolService */
  248. /*********************************************************************
  249. FUNCTION: StopIpsecpolService
  250. PURPOSE: Attempts to stop ipsecpolsvc service
  251. PARAMS:
  252. pszServ - optional name of the server (default is NULL, start on local machine)
  253. RETURNS: ERROR_SUCESS or GetLastError code
  254. COMMENTS:
  255. *********************************************************************/
  256. DWORD StopIpsecpolService (IN OPTIONAL LPCTSTR pszServ)
  257. {
  258. DWORD dwReturn = ERROR_SUCCESS;
  259. SERVICE_STATUS ServStat;
  260. memset(&ServStat, 0, sizeof(SERVICE_STATUS));
  261. SC_HANDLE schMan = OpenSCManager(pszServ, NULL, SC_MANAGER_ALL_ACCESS);
  262. if (schMan == NULL)
  263. {
  264. dwReturn = GetLastError();
  265. }
  266. else
  267. {
  268. SC_HANDLE schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc,
  269. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP);
  270. if (schIpsecpolsvc == NULL)
  271. {
  272. dwReturn = GetLastError();
  273. }
  274. else if (QueryServiceStatus(schIpsecpolsvc, &ServStat))
  275. {
  276. // check the status finally
  277. if (ServStat.dwCurrentState == SERVICE_RUNNING)
  278. {
  279. if (!ControlService(schIpsecpolsvc, SERVICE_CONTROL_STOP, &ServStat))
  280. {
  281. dwReturn = GetLastError();
  282. }
  283. }
  284. CloseServiceHandle(schIpsecpolsvc);
  285. }
  286. CloseServiceHandle(schMan);
  287. }
  288. return dwReturn;
  289. } /* StopIpsecpolService */
  290. /*********************************************************************
  291. FUNCTION: IsIpsecpolServiceRunning
  292. PURPOSE: Checks if ipsecpolsvc service is currently running
  293. PARAMS:
  294. dwReturn - holds errors retuned by SCM if any
  295. pszServ - optional name of the server (default is NULL, start on local machine)
  296. RETURNS: TRUE/FALSE
  297. COMMENTS: TRUE returned means service is running
  298. FALSE and dwReturn == ERROR_SUCCESS means service is not running
  299. FALSE and dwReturn != ERROR_SUCCESS means SCM operation failed (dwReturn is error code)
  300. *********************************************************************/
  301. BOOL IsIpsecpolServiceRunning (OUT DWORD &dwReturn, OPTIONAL LPCTSTR pszServ)
  302. {
  303. BOOL bReturn = TRUE;
  304. dwReturn = ERROR_SUCCESS;
  305. SERVICE_STATUS ServStat;
  306. memset(&ServStat, 0, sizeof(SERVICE_STATUS));
  307. SC_HANDLE schMan = OpenSCManager(pszServ, NULL, SC_MANAGER_ALL_ACCESS);
  308. if (schMan == NULL)
  309. {
  310. dwReturn = GetLastError();
  311. bReturn = FALSE;
  312. }
  313. else
  314. {
  315. SC_HANDLE schIpsecpolsvc = OpenService(schMan, szIpsecpolsvc,
  316. SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP);
  317. if (schIpsecpolsvc == NULL)
  318. {
  319. dwReturn = GetLastError();
  320. bReturn = FALSE;
  321. }
  322. else if (QueryServiceStatus(schIpsecpolsvc, &ServStat))
  323. {
  324. // check the status finally
  325. if (ServStat.dwCurrentState != SERVICE_RUNNING)
  326. {
  327. bReturn = FALSE;
  328. }
  329. CloseServiceHandle(schIpsecpolsvc);
  330. }
  331. CloseServiceHandle(schMan);
  332. }
  333. return bReturn;
  334. } /* IsIpsecpolServiceRunning */
  335. /*********************************************************************
  336. FUNCTION: InitIpsecpolsvcRPC
  337. PURPOSE: Get an RPC handle from ipsecpolsvc that can be used to call its APIs
  338. PARAMS:
  339. pszServ - name of the server (pass NULL for the local machine)
  340. hIpsecpolsvc - returned handle
  341. RETURNS: RPC_S_OK or RPC api error code
  342. COMMENTS: Service running is not prereq
  343. *********************************************************************/
  344. RPC_STATUS InitIpsecpolsvcRPC (IN TCHAR *pszServ, OUT handle_t &hIpsecpolsvc)
  345. {
  346. RPC_STATUS status = RPC_S_OK;
  347. TCHAR localProtocol[] = TEXT("ncacn_np");
  348. TCHAR remoteProtocol[] = TEXT("ncacn_np");
  349. TCHAR endpoint[] = TEXT("\\pipe\\ipsecpolsvc");
  350. PUSHORT stringBinding = NULL;
  351. ULONG SecurityLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  352. if (pszServ != 0)
  353. {
  354. if (pszServ[0] == 0)
  355. {
  356. // empty string
  357. pszServ = NULL;
  358. }
  359. }
  360. status = RpcStringBindingCompose(0,
  361. (PUSHORT)((pszServ == NULL) ? localProtocol : remoteProtocol),
  362. (PUSHORT)pszServ,
  363. (PUSHORT)endpoint,
  364. 0,
  365. &stringBinding);
  366. if (status == RPC_S_OK)
  367. {
  368. status = RpcBindingFromStringBinding(stringBinding, &hIpsecpolsvc);
  369. }
  370. if (status == RPC_S_OK)
  371. {
  372. status =
  373. RpcBindingSetAuthInfo(hIpsecpolsvc,
  374. 0,
  375. SecurityLevel,
  376. RPC_C_AUTHN_WINNT,
  377. 0,
  378. 0
  379. );
  380. }
  381. if (stringBinding != NULL)
  382. {
  383. status = RpcStringFree(&stringBinding);
  384. }
  385. return status;
  386. } /* InitIpsecpolsvcRPC */
  387. /*********************************************************************
  388. FUNCTION: ShutdownIpsecpolsvcRPC
  389. PURPOSE: Close RPC handle
  390. PARAMS:
  391. hIpsecpolsvc - handle
  392. RETURNS: RPC_S_OK or RPC api error code
  393. COMMENTS:
  394. *********************************************************************/
  395. RPC_STATUS ShutdownIpsecpolsvcRPC (IN handle_t hIpsecpolsvc)
  396. {
  397. return RpcBindingFree(&hIpsecpolsvc);
  398. } /* ShutdownIpsecpolsvcRPC */
  399. /*********************************************************************
  400. FUNCTION: PlumbIPSecPolicy
  401. PURPOSE: Plumbs IPSEC_IKE_POLICY to the specified machine
  402. PARAMS:
  403. pszServerName - machine name or NULL for local
  404. pIPSecIkePol - pointer to IPSEC_IKE_POLICY.
  405. GUIDs/names must be generated prior to the call
  406. bFailMMIfExists - specifies MM filter behavior
  407. bFailMMIfExists == FALSE will cause the call not to break
  408. on ERROR_MM_FILTER_EXISTS when duplicate MM filters are there
  409. bFailMMIfExists == TRUE will fail on any SPD API error
  410. ppMMFilterHandles - array of mm filter handles will be returned here
  411. ppFilterHandles - array of qm filter handles will be returned here
  412. bPersist - if TRUE, information will be persisted
  413. RETURNS: ERROR_SUCCESS or win32 error code
  414. COMMENTS: CALLER is responsible for freeing the memory for the handle arrays
  415. *********************************************************************/
  416. DWORD
  417. PlumbIPSecPolicy(
  418. IN LPWSTR pServerName,
  419. IN PIPSEC_IKE_POLICY pIPSecIkePol,
  420. IN BOOL bFailMMIfExists,
  421. OUT PHANDLE *ppMMFilterHandles,
  422. OUT PHANDLE *ppFilterHandles,
  423. IN OPTIONAL BOOL bPersist
  424. )
  425. {
  426. DWORD dwReturn = ERROR_SUCCESS;
  427. RPC_STATUS RpcStat = RPC_S_OK;
  428. int i;
  429. HANDLE hFilter;
  430. BOOL bDefaultRule = FALSE; // will be true if default response rule is specified
  431. // default response rule is specified if there is exactly 1 transport filter that is Me-to-Me
  432. if (!pIPSecIkePol)
  433. {
  434. return ERROR_NO_DATA;
  435. }
  436. if (pIPSecIkePol->dwNumFilters == 1 && pIPSecIkePol->QMFilterType == QM_TRANSPORT_FILTER)
  437. {
  438. if (pIPSecIkePol->pTransportFilters[0].SrcAddr.AddrType == IP_ADDR_UNIQUE
  439. && pIPSecIkePol->pTransportFilters[0].SrcAddr.uIpAddr == IP_ADDRESS_ME
  440. && pIPSecIkePol->pTransportFilters[0].DesAddr.AddrType == IP_ADDR_UNIQUE
  441. && pIPSecIkePol->pTransportFilters[0].DesAddr.uIpAddr == IP_ADDRESS_ME
  442. && pIPSecIkePol->pTransportFilters[0].InboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG
  443. && pIPSecIkePol->pTransportFilters[0].OutboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG)
  444. {
  445. bDefaultRule = TRUE;
  446. }
  447. }
  448. // allocate handle arrays first
  449. if (bDefaultRule)
  450. {
  451. *ppMMFilterHandles = *ppFilterHandles = 0;
  452. pIPSecIkePol->AuthInfos.dwFlags |= IPSEC_MM_AUTH_DEFAULT_AUTH;
  453. pIPSecIkePol->IkePol.dwFlags |= IPSEC_MM_POLICY_DEFAULT_POLICY;
  454. pIPSecIkePol->IpsPol.dwFlags |= IPSEC_QM_POLICY_DEFAULT_POLICY;
  455. }
  456. else
  457. {
  458. if (ppMMFilterHandles && pIPSecIkePol->dwNumMMFilters)
  459. {
  460. *ppMMFilterHandles = new HANDLE[pIPSecIkePol->dwNumMMFilters];
  461. if (*ppMMFilterHandles == 0)
  462. {
  463. return ERROR_OUTOFMEMORY;
  464. }
  465. memset(*ppMMFilterHandles, 0, sizeof(HANDLE)*pIPSecIkePol->dwNumMMFilters);
  466. }
  467. if (ppFilterHandles && pIPSecIkePol->dwNumFilters)
  468. {
  469. *ppFilterHandles = new HANDLE[pIPSecIkePol->dwNumFilters];
  470. if (*ppFilterHandles == 0)
  471. {
  472. if (ppMMFilterHandles)
  473. {
  474. if (*ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  475. }
  476. return ERROR_OUTOFMEMORY;
  477. }
  478. memset(*ppFilterHandles, 0, sizeof(HANDLE)*pIPSecIkePol->dwNumFilters);
  479. }
  480. }
  481. // let's go and plumb everything
  482. // authinfos first
  483. if (!UuidIsNil(&(pIPSecIkePol->AuthInfos.gMMAuthID), &RpcStat))
  484. {
  485. dwReturn = AddMMAuthMethods(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->AuthInfos));
  486. }
  487. if (dwReturn != ERROR_SUCCESS)
  488. {
  489. if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  490. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  491. return dwReturn;
  492. }
  493. if (RpcStat != RPC_S_OK)
  494. {
  495. if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  496. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  497. return GetLastError();
  498. }
  499. // mm policy
  500. if (!UuidIsNil(&(pIPSecIkePol->IkePol.gPolicyID), &RpcStat))
  501. {
  502. dwReturn = AddMMPolicy(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->IkePol));
  503. }
  504. if (dwReturn != ERROR_SUCCESS)
  505. {
  506. if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  507. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  508. return dwReturn;
  509. }
  510. if (RpcStat != RPC_S_OK)
  511. {
  512. if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  513. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  514. return GetLastError();
  515. }
  516. // qm policy
  517. if (!UuidIsNil(&(pIPSecIkePol->IpsPol.gPolicyID), &RpcStat))
  518. {
  519. dwReturn = AddQMPolicy(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->IpsPol));
  520. }
  521. if (dwReturn != ERROR_SUCCESS)
  522. {
  523. if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  524. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  525. return dwReturn;
  526. }
  527. if (RpcStat != RPC_S_OK)
  528. {
  529. if (ppMMFilterHandles && *ppMMFilterHandles) { delete[] *ppMMFilterHandles; *ppMMFilterHandles = 0; }
  530. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  531. return GetLastError();
  532. }
  533. if (bDefaultRule)
  534. {
  535. // return here
  536. return dwReturn;
  537. }
  538. // mm filters
  539. for (i = 0; i < (int) pIPSecIkePol->dwNumMMFilters; i++)
  540. {
  541. hFilter = NULL;
  542. if (!UuidIsNil(&(pIPSecIkePol->pMMFilters[i].gFilterID), &RpcStat))
  543. {
  544. dwReturn = AddMMFilter(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->pMMFilters[i]), &hFilter);
  545. }
  546. if (RpcStat != RPC_S_OK)
  547. {
  548. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  549. return GetLastError();
  550. }
  551. if (!bFailMMIfExists && (dwReturn == ERROR_IPSEC_MM_POLICY_EXISTS || dwReturn == ERROR_IPSEC_MM_AUTH_EXISTS || dwReturn == ERROR_IPSEC_MM_FILTER_EXISTS))
  552. {
  553. dwReturn = ERROR_SUCCESS; // it's not actually an error
  554. }
  555. if (dwReturn != ERROR_SUCCESS)
  556. {
  557. if (ppFilterHandles && *ppFilterHandles) { delete[] *ppFilterHandles; *ppFilterHandles = 0; }
  558. return dwReturn;
  559. }
  560. if (ppMMFilterHandles)
  561. {
  562. (*ppMMFilterHandles)[i] = hFilter;
  563. }
  564. }
  565. // qm filters
  566. for (i = 0; i < (int) pIPSecIkePol->dwNumFilters; i++)
  567. {
  568. hFilter = NULL;
  569. if (pIPSecIkePol->QMFilterType == QM_TRANSPORT_FILTER)
  570. {
  571. if (!UuidIsNil(&(pIPSecIkePol->pTransportFilters[i].gFilterID), &RpcStat))
  572. {
  573. dwReturn = AddTransportFilter(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->pTransportFilters[i]), &hFilter);
  574. }
  575. }
  576. else
  577. {
  578. // tunnel
  579. if (!UuidIsNil(&(pIPSecIkePol->pTunnelFilters[i].gFilterID), &RpcStat))
  580. {
  581. dwReturn = AddTunnelFilter(pServerName, bPersist ? PERSIST_SPD_OBJECT : 0, &(pIPSecIkePol->pTunnelFilters[i]), &hFilter);
  582. }
  583. }
  584. if (dwReturn != ERROR_SUCCESS)
  585. {
  586. return dwReturn;
  587. }
  588. if (RpcStat != RPC_S_OK)
  589. {
  590. return GetLastError();
  591. }
  592. if (ppFilterHandles)
  593. {
  594. (*ppFilterHandles)[i] = hFilter;
  595. }
  596. }
  597. return dwReturn;
  598. } /* PlumbIPSecPolicy */
  599. /*********************************************************************
  600. FUNCTION: DeleteIPSecPolicy
  601. PURPOSE: Complementary to PlumbIPSecPolicy, removes IPSEC_IKE_POLICY
  602. PARAMS:
  603. pszServerName - machine name or NULL for local
  604. pIPSecIkePol - pointer to IPSEC_IKE_POLICY.
  605. GUIDs/names must be generated prior to the call
  606. pMMFilterHandles - array of main mode filter handles
  607. pFilterHandles - array of quick mode filter handles
  608. RETURNS: ERROR_SUCCESS or win32 error code
  609. COMMENTS: Function will try to
  610. remove everything specified in the IPSEC_IKE_POLICY structure.
  611. It is possible that one or several errors will be encountered.
  612. Function will continue, but later first error will be returned.
  613. *********************************************************************/
  614. DWORD
  615. DeleteIPSecPolicy(
  616. IN LPWSTR pServerName,
  617. IN PIPSEC_IKE_POLICY pIPSecIkePol,
  618. IN PHANDLE pMMFilterHandles,
  619. IN PHANDLE pFilterHandles
  620. )
  621. {
  622. DWORD dwReturn = ERROR_SUCCESS;
  623. DWORD dwErrorCode = ERROR_SUCCESS;
  624. RPC_STATUS RpcStat = RPC_S_OK;
  625. int i;
  626. // mm filters
  627. if (pMMFilterHandles)
  628. {
  629. for (i = 0; i < (int) pIPSecIkePol->dwNumMMFilters; i++)
  630. {
  631. if (!UuidIsNil(&(pIPSecIkePol->pMMFilters[i].gFilterID), &RpcStat))
  632. {
  633. dwReturn = DeleteMMFilter(pMMFilterHandles[i]);
  634. }
  635. if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS)
  636. {
  637. dwErrorCode = GetLastError();
  638. }
  639. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  640. {
  641. dwErrorCode = dwReturn;
  642. }
  643. }
  644. }
  645. // qm filters
  646. if (pFilterHandles)
  647. {
  648. for (i = 0; i < (int) pIPSecIkePol->dwNumFilters; i++)
  649. {
  650. if (pIPSecIkePol->QMFilterType == QM_TRANSPORT_FILTER)
  651. {
  652. if (!UuidIsNil(&(pIPSecIkePol->pTransportFilters[i].gFilterID), &RpcStat))
  653. {
  654. dwReturn = DeleteTransportFilter(pFilterHandles[i]);
  655. }
  656. }
  657. else
  658. {
  659. // tunnel
  660. if (!UuidIsNil(&(pIPSecIkePol->pTunnelFilters[i].gFilterID), &RpcStat))
  661. {
  662. dwReturn = DeleteTunnelFilter(pFilterHandles[i]);
  663. }
  664. }
  665. if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS)
  666. {
  667. dwErrorCode = GetLastError();
  668. }
  669. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  670. {
  671. dwErrorCode = dwReturn;
  672. }
  673. }
  674. }
  675. // mm auth methods
  676. if (!UuidIsNil(&(pIPSecIkePol->AuthInfos.gMMAuthID), &RpcStat))
  677. {
  678. dwReturn = DeleteMMAuthMethods(pServerName, pIPSecIkePol->AuthInfos.gMMAuthID);
  679. }
  680. if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS)
  681. {
  682. dwErrorCode = GetLastError();
  683. }
  684. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  685. {
  686. dwErrorCode = dwReturn;
  687. }
  688. // mm policy
  689. if (!UuidIsNil(&(pIPSecIkePol->IkePol.gPolicyID), &RpcStat))
  690. {
  691. dwReturn = DeleteMMPolicy(pServerName, pIPSecIkePol->IkePol.pszPolicyName);
  692. }
  693. if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS)
  694. {
  695. dwErrorCode = GetLastError();
  696. }
  697. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  698. {
  699. dwErrorCode = dwReturn;
  700. }
  701. // qm policy
  702. if (!UuidIsNil(&(pIPSecIkePol->IpsPol.gPolicyID), &RpcStat))
  703. {
  704. dwReturn = DeleteQMPolicy(pServerName, pIPSecIkePol->IpsPol.pszPolicyName);
  705. }
  706. if (RpcStat != RPC_S_OK && dwErrorCode == ERROR_SUCCESS)
  707. {
  708. dwErrorCode = GetLastError();
  709. }
  710. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  711. {
  712. dwErrorCode = dwReturn;
  713. }
  714. return dwErrorCode;
  715. } /* DeleteIPSecPolicy */
  716. /*********************************************************************
  717. FUNCTION: DeletePersistedIPSecPolicy
  718. PURPOSE: Complementary to PlumbIPSecPolicy with persistent flag on,
  719. removes persisted policy
  720. PARAMS:
  721. pszServerName - machine name or NULL for local
  722. pPolicyName - policy name prefix, if empty string of NULL,
  723. all persisted policy settings will be removed
  724. RETURNS: ERROR_SUCCESS or win32 error code
  725. COMMENTS: Function will try to
  726. remove everything specified.
  727. It is possible that one or several errors will be encountered.
  728. Function will continue, but later first error will be returned.
  729. *********************************************************************/
  730. DWORD
  731. DeletePersistedIPSecPolicy(
  732. IN LPWSTR pServerName,
  733. IN LPWSTR pPolicyName
  734. )
  735. {
  736. DWORD dwErrorCode, dwReturn;
  737. int i, j;
  738. PMM_FILTER pmmf; // for MM filter calls
  739. PIPSEC_QM_POLICY pipsqmp; // for QM policy calls
  740. PTRANSPORT_FILTER ptf; // for transport filter calls
  741. PTUNNEL_FILTER ptunf; // for tunnel filter calls
  742. PMM_AUTH_METHODS pam; // for auth method calls
  743. PIPSEC_MM_POLICY pipsmmp; // for MM policy calls
  744. DWORD dwCount; // counting objects here
  745. DWORD dwResumeHandle; // handle for continuation calls
  746. DWORD dwReserved; // reserved container
  747. GUID gDefaultGUID = {0}; // NULL GUID value
  748. int iPolNameLen = 0;
  749. HANDLE hFilter;
  750. BOOL bRemoveDefault = FALSE;
  751. dwErrorCode = dwReturn = ERROR_SUCCESS;
  752. if (pPolicyName && *pPolicyName)
  753. {
  754. iPolNameLen = wcslen(pPolicyName);
  755. }
  756. // start with mm filters, enum all
  757. pmmf=NULL;
  758. dwResumeHandle=0;
  759. // make the call(s)
  760. for (i = 0; ;i+=dwCount)
  761. {
  762. BOOL bRemoved = FALSE;
  763. DWORD dwOldResumeHandle = dwResumeHandle;
  764. dwReturn = EnumMMFilters(pServerName, ENUM_GENERIC_FILTERS, gDefaultGUID, &pmmf, 0, &dwCount, &dwResumeHandle);
  765. if (dwReturn == ERROR_NO_DATA || dwCount == 0)
  766. {
  767. dwReturn = ERROR_SUCCESS;
  768. // no more filters
  769. break;
  770. }
  771. if (dwReturn != ERROR_SUCCESS)
  772. {
  773. break;
  774. }
  775. for (j = 0; j < (int) dwCount; j++)
  776. {
  777. // check if it's our filter
  778. if (iPolNameLen == 0|| wcsncmp(pPolicyName, pmmf[j].pszFilterName, iPolNameLen) == 0)
  779. {
  780. dwReturn = OpenMMFilterHandle(pServerName, &(pmmf[j]), &hFilter);
  781. if (dwReturn == ERROR_SUCCESS)
  782. {
  783. dwReturn = DeleteMMFilter(hFilter);
  784. if (dwReturn == ERROR_SUCCESS)
  785. {
  786. bRemoved = TRUE;
  787. }
  788. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  789. {
  790. dwErrorCode = dwReturn;
  791. }
  792. dwReturn = CloseMMFilterHandle(hFilter);
  793. }
  794. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  795. {
  796. dwErrorCode = dwReturn;
  797. }
  798. }
  799. }
  800. SPDApiBufferFree(pmmf);
  801. pmmf=NULL;
  802. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  803. {
  804. dwErrorCode = dwReturn;
  805. }
  806. if (bRemoved)
  807. {
  808. dwResumeHandle = dwOldResumeHandle; // need to restart enumeration!
  809. }
  810. }
  811. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  812. {
  813. dwErrorCode = dwReturn;
  814. }
  815. // transport filters - the routine is similar
  816. ptf=NULL;
  817. dwResumeHandle=0;
  818. // make the call(s)
  819. for (i = 0; ;i+=dwCount)
  820. {
  821. BOOL bRemoved = FALSE;
  822. DWORD dwOldResumeHandle = dwResumeHandle;
  823. dwReturn = EnumTransportFilters(pServerName, ENUM_GENERIC_FILTERS, gDefaultGUID, &ptf, 0, &dwCount, &dwResumeHandle);
  824. if (dwReturn == ERROR_NO_DATA || dwCount == 0)
  825. {
  826. dwReturn = ERROR_SUCCESS;
  827. // no more filters
  828. break;
  829. }
  830. if (dwReturn != ERROR_SUCCESS)
  831. {
  832. break;
  833. }
  834. for (j = 0; j < (int) dwCount; j++)
  835. {
  836. // check if it's our filter
  837. if (iPolNameLen == 0|| wcsncmp(pPolicyName, ptf[j].pszFilterName, iPolNameLen) == 0)
  838. {
  839. dwReturn = OpenTransportFilterHandle(pServerName, &(ptf[j]), &hFilter);
  840. if (dwReturn == ERROR_SUCCESS)
  841. {
  842. dwReturn = DeleteTransportFilter(hFilter);
  843. if (dwReturn == ERROR_SUCCESS)
  844. {
  845. bRemoved = TRUE;
  846. }
  847. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  848. {
  849. dwErrorCode = dwReturn;
  850. }
  851. dwReturn = CloseTransportFilterHandle(hFilter);
  852. }
  853. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  854. {
  855. dwErrorCode = dwReturn;
  856. }
  857. }
  858. }
  859. SPDApiBufferFree(ptf);
  860. ptf=NULL;
  861. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  862. {
  863. dwErrorCode = dwReturn;
  864. }
  865. if (bRemoved)
  866. {
  867. dwResumeHandle = dwOldResumeHandle; // need to restart enumeration!
  868. }
  869. }
  870. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  871. {
  872. dwErrorCode = dwReturn;
  873. }
  874. // tunnel filters
  875. ptunf=NULL;
  876. dwResumeHandle=0;
  877. // make the call(s)
  878. for (i = 0; ;i+=dwCount)
  879. {
  880. BOOL bRemoved = FALSE;
  881. DWORD dwOldResumeHandle = dwResumeHandle;
  882. dwReturn = EnumTunnelFilters(pServerName, ENUM_GENERIC_FILTERS, gDefaultGUID, &ptunf, 0, &dwCount, &dwResumeHandle);
  883. if (dwReturn == ERROR_NO_DATA || dwCount == 0)
  884. {
  885. dwReturn = ERROR_SUCCESS;
  886. // no more filters
  887. break;
  888. }
  889. if (dwReturn != ERROR_SUCCESS)
  890. {
  891. break;
  892. }
  893. for (j = 0; j < (int) dwCount; j++)
  894. {
  895. // check if it's our filter
  896. if (iPolNameLen == 0|| wcsncmp(pPolicyName, ptunf[j].pszFilterName, iPolNameLen) == 0)
  897. {
  898. dwReturn = OpenTunnelFilterHandle(pServerName, &(ptunf[j]), &hFilter);
  899. if (dwReturn == ERROR_SUCCESS)
  900. {
  901. dwReturn = DeleteTunnelFilter(hFilter);
  902. if (dwReturn == ERROR_SUCCESS)
  903. {
  904. bRemoved = TRUE;
  905. }
  906. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  907. {
  908. dwErrorCode = dwReturn;
  909. }
  910. dwReturn = CloseTunnelFilterHandle(hFilter);
  911. }
  912. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  913. {
  914. dwErrorCode = dwReturn;
  915. }
  916. }
  917. }
  918. SPDApiBufferFree(ptunf);
  919. ptunf=NULL;
  920. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  921. {
  922. dwErrorCode = dwReturn;
  923. }
  924. if (bRemoved)
  925. {
  926. dwResumeHandle = dwOldResumeHandle; // need to restart enumeration!
  927. }
  928. }
  929. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  930. {
  931. dwErrorCode = dwReturn;
  932. }
  933. // mm policies
  934. pipsmmp=NULL;
  935. dwResumeHandle=0;
  936. // make the call(s)
  937. for (i = 0; ;i+=dwCount)
  938. {
  939. BOOL bRemoved = FALSE;
  940. DWORD dwOldResumeHandle = dwResumeHandle;
  941. dwReturn = EnumMMPolicies(pServerName, &pipsmmp, 0, &dwCount, &dwResumeHandle);
  942. if (dwReturn == ERROR_NO_DATA || dwCount == 0)
  943. {
  944. dwReturn = ERROR_SUCCESS;
  945. // no more filters
  946. break;
  947. }
  948. if (dwReturn != ERROR_SUCCESS)
  949. {
  950. break;
  951. }
  952. for (j = 0; j < (int) dwCount; j++)
  953. {
  954. // check if it's our mm policy
  955. if (iPolNameLen == 0|| wcsncmp(pPolicyName, pipsmmp[j].pszPolicyName, iPolNameLen) == 0)
  956. {
  957. dwReturn = DeleteMMPolicy(pServerName, pipsmmp[j].pszPolicyName);
  958. if (dwReturn == ERROR_SUCCESS)
  959. {
  960. bRemoved = TRUE;
  961. }
  962. if (dwReturn == ERROR_SUCCESS && (pipsmmp[j].dwFlags & IPSEC_QM_POLICY_DEFAULT_POLICY))
  963. { // got to remove other defaults too
  964. bRemoveDefault = TRUE;
  965. }
  966. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  967. {
  968. dwErrorCode = dwReturn;
  969. }
  970. }
  971. }
  972. SPDApiBufferFree(pipsmmp);
  973. pipsmmp=NULL;
  974. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  975. {
  976. dwErrorCode = dwReturn;
  977. }
  978. if (bRemoved)
  979. {
  980. dwResumeHandle = dwOldResumeHandle; // need to restart enumeration!
  981. }
  982. }
  983. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  984. {
  985. dwErrorCode = dwReturn;
  986. }
  987. // auth methods
  988. pam=NULL;
  989. dwResumeHandle=0;
  990. // make the call(s)
  991. for (i = 0; ;i+=dwCount)
  992. {
  993. BOOL bRemoved = FALSE;
  994. DWORD dwOldResumeHandle = dwResumeHandle;
  995. dwReturn = EnumMMAuthMethods(pServerName, &pam, 0, &dwCount, &dwResumeHandle);
  996. if (dwReturn == ERROR_NO_DATA || dwCount == 0)
  997. {
  998. dwReturn = ERROR_SUCCESS;
  999. // no more filters
  1000. break;
  1001. }
  1002. if (dwReturn != ERROR_SUCCESS)
  1003. {
  1004. break;
  1005. }
  1006. for (j = 0; j < (int) dwCount; j++)
  1007. {
  1008. // check if it's our auth method
  1009. if (bRemoveDefault || (pam[j].dwFlags & IPSEC_MM_AUTH_DEFAULT_AUTH) == 0)
  1010. { // either remove default is set or this is non-default
  1011. dwReturn = DeleteMMAuthMethods(pServerName, pam[j].gMMAuthID);
  1012. if (dwReturn == ERROR_SUCCESS)
  1013. {
  1014. bRemoved = TRUE;
  1015. }
  1016. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  1017. {
  1018. dwErrorCode = dwReturn;
  1019. }
  1020. }
  1021. }
  1022. SPDApiBufferFree(pam);
  1023. pam=NULL;
  1024. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  1025. {
  1026. dwErrorCode = dwReturn;
  1027. }
  1028. if (bRemoved)
  1029. {
  1030. dwResumeHandle = dwOldResumeHandle; // need to restart enumeration!
  1031. }
  1032. }
  1033. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  1034. {
  1035. dwErrorCode = dwReturn;
  1036. }
  1037. // qm policies
  1038. pipsqmp=NULL;
  1039. dwResumeHandle=0;
  1040. // make the call(s)
  1041. for (i = 0; ;i+=dwCount)
  1042. {
  1043. BOOL bRemoved = FALSE;
  1044. DWORD dwOldResumeHandle = dwResumeHandle;
  1045. dwReturn = EnumQMPolicies(pServerName, &pipsqmp, 0, &dwCount, &dwResumeHandle);
  1046. if (dwReturn == ERROR_NO_DATA || dwCount == 0)
  1047. {
  1048. dwReturn = ERROR_SUCCESS;
  1049. // no more filters
  1050. break;
  1051. }
  1052. if (dwReturn != ERROR_SUCCESS)
  1053. {
  1054. break;
  1055. }
  1056. for (j = 0; j < (int) dwCount; j++)
  1057. {
  1058. // check if it's our qm policy
  1059. if (iPolNameLen == 0|| wcsncmp(pPolicyName, pipsqmp[j].pszPolicyName, iPolNameLen) == 0)
  1060. {
  1061. dwReturn = DeleteQMPolicy(pServerName, pipsqmp[j].pszPolicyName);
  1062. if (dwReturn == ERROR_SUCCESS)
  1063. {
  1064. bRemoved = TRUE;
  1065. }
  1066. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  1067. {
  1068. dwErrorCode = dwReturn;
  1069. }
  1070. }
  1071. }
  1072. SPDApiBufferFree(pipsqmp);
  1073. pipsqmp=NULL;
  1074. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  1075. {
  1076. dwErrorCode = dwReturn;
  1077. }
  1078. if (bRemoved)
  1079. {
  1080. dwResumeHandle = dwOldResumeHandle; // need to restart enumeration!
  1081. }
  1082. }
  1083. if (dwReturn != ERROR_SUCCESS && dwErrorCode == ERROR_SUCCESS)
  1084. {
  1085. dwErrorCode = dwReturn;
  1086. }
  1087. return dwErrorCode;
  1088. } /* DeletePersistedIPSecPolicy */