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.

967 lines
27 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 2000
  4. //
  5. // Module Name:
  6. //
  7. // ipsec.c
  8. //
  9. // Abstract:
  10. //
  11. // IP Security stats for netdiag
  12. //
  13. // Author:
  14. //
  15. // DKalin - 8/3/1999
  16. //
  17. // Environment:
  18. //
  19. // User mode only.
  20. // Contains NT-specific code.
  21. //
  22. // Revision History:
  23. //
  24. // Changed behavior for Whistler - now we report registry/OU settings only
  25. // More specific code moved to ipseccmd.exe tool
  26. //--
  27. #include "precomp.h"
  28. #include <snmp.h>
  29. #include "tcpinfo.h"
  30. #include "ipinfo.h"
  31. #include "llinfo.h"
  32. #include <windows.h>
  33. #include <winsock2.h>
  34. #include <ipexport.h>
  35. #include <icmpapi.h>
  36. #include <stdlib.h>
  37. #include <assert.h>
  38. #include <tchar.h>
  39. #include <wincrypt.h>
  40. #include <stdio.h>
  41. #include <objbase.h>
  42. #include <dsgetdc.h>
  43. #include <lm.h>
  44. #include <userenv.h>
  45. #define MAXSTRLEN (1024)
  46. #define STRING_TEXT_SIZE 4096
  47. #define NETDIAG_TEXT_LIMIT 3072
  48. // policy source constants
  49. #define PS_NO_POLICY 0
  50. #define PS_DS_POLICY 1
  51. #define PS_LOC_POLICY 2
  52. // magic strings
  53. #define IPSEC_SERVICE_NAME TEXT("policyagent")
  54. #define GPEXT_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions")
  55. TCHAR pcszGPTIPSecKey[] = TEXT("SOFTWARE\\Policies\\Microsoft\\Windows\\IPSEC\\GPTIPSECPolicy");
  56. TCHAR pcszGPTIPSecName[] = TEXT("DSIPSECPolicyName");
  57. TCHAR pcszGPTIPSecFlags[] = TEXT("DSIPSECPolicyFlags");
  58. TCHAR pcszGPTIPSecPath[] = TEXT("DSIPSECPolicyPath");
  59. TCHAR pcszLocIPSecKey[] = TEXT("SOFTWARE\\Policies\\Microsoft\\Windows\\IPSEC\\Policy\\Local");
  60. TCHAR pcszLocIPSecPol[] = TEXT("ActivePolicy");
  61. TCHAR pcszCacheIPSecKey[] = TEXT("SOFTWARE\\Policies\\Microsoft\\Windows\\IPSEC\\Policy\\Cache");
  62. TCHAR pcszIPSecPolicy[] = TEXT("ipsecPolicy");
  63. TCHAR pcszIPSecName[] = TEXT("ipsecName");
  64. TCHAR pcszIPSecDesc[] = TEXT("description");
  65. TCHAR pcszIPSecTimestamp[] = TEXT("whenChanged");
  66. // BAIL_xx defines
  67. #define BAIL_ON_WIN32_ERROR(dwError) \
  68. if (dwError) {\
  69. goto error; \
  70. }
  71. #define BAIL_ON_FAILURE(hr) \
  72. if (FAILED(hr)) {\
  73. goto error; \
  74. }
  75. typedef struct
  76. {
  77. int iPolicySource; // one of the three constants mentioned above
  78. TCHAR pszPolicyName[MAXSTRLEN]; // policy name
  79. TCHAR pszPolicyDesc[MAXSTRLEN]; // policy description
  80. TCHAR pszPolicyPath[MAXSTRLEN]; // policy path (DN or RegKey)
  81. time_t timestamp; // last updated time
  82. } POLICY_INFO, *PPOLICY_INFO;
  83. typedef struct
  84. {
  85. SERVICE_STATUS servStat; // service status
  86. QUERY_SERVICE_CONFIG servConfig; // service configuration
  87. } SERVICE_INFO, *PSERVICE_INFO;
  88. typedef struct
  89. {
  90. TCHAR pszComputerOU[MAXSTRLEN]; // this computer' OU name
  91. PGROUP_POLICY_OBJECT pGPO; // GPO that is assigning IPSec Policy
  92. TCHAR pszPolicyOU [MAXSTRLEN]; // OU that has the GPO assigned
  93. } DS_POLICY_INFO, *PDS_POLICY_INFO;
  94. DWORD MyFormatMessage ( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId,
  95. LPTSTR lpBuffer, DWORD nSize, va_list *Arguments );
  96. void reportError ( HRESULT hr, NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults );
  97. void reportServiceInfo ( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults );
  98. HRESULT getPolicyInfo ( );
  99. DWORD getMorePolicyInfo ( );
  100. DWORD getServiceInfo ( PSERVICE_INFO pInfo );
  101. PGROUP_POLICY_OBJECT getIPSecGPO ( );
  102. void StringToGuid( TCHAR * szValue, GUID * pGuid );
  103. BOOL bTestSkipped = FALSE;
  104. BOOL bTestPassed = FALSE;
  105. POLICY_INFO piAssignedPolicy;
  106. SERVICE_INFO siIPSecStatus;
  107. DS_POLICY_INFO dpiAssignedPolicy;
  108. TCHAR pszBuf[STRING_TEXT_SIZE];
  109. WCHAR StringTxt[STRING_TEXT_SIZE];
  110. BOOL
  111. IPSecTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  112. //++
  113. // Description:
  114. // This is IPSec test
  115. //
  116. // Arguments:
  117. // None.
  118. //
  119. // Author:
  120. // DKalin 08/03/99
  121. //--
  122. {
  123. DWORD dwError = ERROR_SUCCESS;
  124. HRESULT hr = ERROR_SUCCESS;
  125. PGROUP_POLICY_OBJECT pGPO = NULL;
  126. PrintStatusMessage( pParams, 4, IDS_IPSEC_STATUS_MSG );
  127. InitializeListHead(&pResults->IPSec.lmsgGlobalOutput);
  128. InitializeListHead(&pResults->IPSec.lmsgAdditOutput);
  129. dwError = getServiceInfo(&siIPSecStatus);
  130. if (dwError != ERROR_SUCCESS || siIPSecStatus.servStat.dwCurrentState != SERVICE_RUNNING)
  131. {
  132. // test skipped
  133. bTestSkipped = TRUE;
  134. if (dwError == ERROR_SERVICE_DOES_NOT_EXIST)
  135. {
  136. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  137. IDS_IPSEC_PA_NOT_INSTALLED );
  138. }
  139. else if (dwError == ERROR_SUCCESS)
  140. {
  141. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  142. IDS_IPSEC_PA_NOT_STARTED );
  143. reportServiceInfo(pParams, pResults);
  144. }
  145. else
  146. {
  147. // some error
  148. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  149. IDS_IPSEC_PA_NO_INFO );
  150. reportError(dwError, pParams, pResults);
  151. }
  152. return S_OK;
  153. }
  154. else
  155. {
  156. // test passed
  157. bTestPassed = TRUE;
  158. reportServiceInfo(pParams, pResults);
  159. hr = getPolicyInfo();
  160. if (hr != ERROR_SUCCESS)
  161. {
  162. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  163. IDS_IPSEC_NO_POLICY_INFO );
  164. reportError(hr, pParams, pResults);
  165. }
  166. else
  167. {
  168. switch (piAssignedPolicy.iPolicySource)
  169. {
  170. case PS_NO_POLICY:
  171. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  172. IDS_IPSEC_NO_POLICY );
  173. break;
  174. case PS_DS_POLICY:
  175. getMorePolicyInfo();
  176. pGPO = getIPSecGPO();
  177. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  178. IDS_IPSEC_DS_POLICY );
  179. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  180. IDS_IPSEC_POLICY_NAME, piAssignedPolicy.pszPolicyName );
  181. // description and timestamp - not available yet
  182. /*
  183. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  184. IDS_IPSEC_DESCRIPTION, piAssignedPolicy.pszPolicyDesc );
  185. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  186. IDS_IPSEC_TIMESTAMP );
  187. if (piAssignedPolicy.timestamp == 0)
  188. {
  189. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  190. IDS_GLOBAL_ADAPTER_UNKNOWN);
  191. }
  192. else
  193. {
  194. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  195. IDSSZ_GLOBAL_String, _tctime(&(piAssignedPolicy.timestamp)));
  196. }
  197. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  198. IDS_GLOBAL_EmptyLine);
  199. */
  200. // GPO / OU
  201. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  202. IDS_IPSEC_GPO);
  203. if (pGPO)
  204. {
  205. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  206. IDSSZ_GLOBAL_String, pGPO->lpDisplayName);
  207. }
  208. else
  209. {
  210. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  211. IDS_GLOBAL_ADAPTER_UNKNOWN);
  212. }
  213. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  214. IDS_GLOBAL_EmptyLine);
  215. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  216. IDS_IPSEC_OU);
  217. if (pGPO)
  218. {
  219. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  220. IDSSZ_GLOBAL_String, pGPO->lpLink);
  221. }
  222. else
  223. {
  224. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  225. IDS_GLOBAL_ADAPTER_UNKNOWN);
  226. }
  227. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  228. IDS_GLOBAL_EmptyLine);
  229. // policy path
  230. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  231. IDS_IPSEC_POLICY_PATH);
  232. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  233. IDSSZ_GLOBAL_StringLine, piAssignedPolicy.pszPolicyPath);
  234. // cleanup GPO
  235. if (pGPO)
  236. {
  237. FreeGPOList (pGPO);
  238. }
  239. break;
  240. case PS_LOC_POLICY:
  241. getMorePolicyInfo();
  242. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  243. IDS_IPSEC_LOC_POLICY );
  244. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  245. IDS_IPSEC_POLICY_NAME, piAssignedPolicy.pszPolicyName );
  246. // description and timestamp
  247. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  248. IDS_IPSEC_DESCRIPTION, piAssignedPolicy.pszPolicyDesc );
  249. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  250. IDS_IPSEC_TIMESTAMP );
  251. if (piAssignedPolicy.timestamp == 0)
  252. {
  253. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  254. IDS_GLOBAL_ADAPTER_UNKNOWN);
  255. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  256. IDS_GLOBAL_EmptyLine);
  257. }
  258. else
  259. {
  260. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  261. IDSSZ_GLOBAL_String, _tctime(&(piAssignedPolicy.timestamp)));
  262. }
  263. // local policy path
  264. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  265. IDS_IPSEC_POLICY_PATH);
  266. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  267. IDS_IPSEC_LOCAL_PATH, piAssignedPolicy.pszPolicyPath);
  268. break;
  269. }
  270. }
  271. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  272. IDS_IPSEC_IPSECCMD );
  273. }
  274. return S_OK;
  275. }
  276. void IPSecGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
  277. {
  278. PrintMessage(pParams, IDS_GLOBAL_EmptyLine);
  279. if (bTestSkipped)
  280. {
  281. PrintTestTitleResult(pParams, IDS_IPSEC_LONG, IDS_IPSEC_SHORT, FALSE, S_FALSE, 0);
  282. }
  283. if (bTestPassed)
  284. {
  285. PrintTestTitleResult(pParams, IDS_IPSEC_LONG, IDS_IPSEC_SHORT, TRUE, S_OK, 0);
  286. }
  287. PrintMessageList(pParams, &pResults->IPSec.lmsgGlobalOutput);
  288. PrintMessageList(pParams, &pResults->IPSec.lmsgAdditOutput);
  289. }
  290. void IPSecPerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults, INTERFACE_RESULT *pInterfaceResults)
  291. {
  292. return;
  293. }
  294. void IPSecCleanup(IN NETDIAG_PARAMS *pParams,
  295. IN OUT NETDIAG_RESULT *pResults)
  296. {
  297. MessageListCleanUp(&pResults->IPSec.lmsgGlobalOutput);
  298. MessageListCleanUp(&pResults->IPSec.lmsgAdditOutput);
  299. }
  300. //#define MSG_HANDLE_INVALID TEXT("Handle is invalid. Is IPSEC Policy Agent Service running?")
  301. // this will call SDK' FormatMessage function but will also correct some awkward messages
  302. // will work only for FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM flag combination
  303. DWORD MyFormatMessage(
  304. DWORD dwFlags, // source and processing options
  305. LPCVOID lpSource, // pointer to message source
  306. DWORD dwMessageId, // requested message identifier
  307. DWORD dwLanguageId, // language identifier for requested message
  308. LPTSTR lpBuffer, // pointer to message buffer
  309. DWORD nSize, // maximum size of message buffer
  310. va_list *Arguments // pointer to array of message inserts
  311. )
  312. {
  313. LPTSTR* tmp = (LPTSTR*) lpBuffer;
  314. switch (dwMessageId)
  315. {
  316. /* case ERROR_INVALID_HANDLE: // patch for "handle is invalid" message. Suggest to check if service is started
  317. if (dwFlags == (FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM))
  318. {
  319. *tmp = (LPTSTR) malloc((_tcslen(MSG_HANDLE_INVALID)+1)*sizeof(TCHAR));
  320. _tcscpy(*tmp, MSG_HANDLE_INVALID);
  321. return _tcslen(*tmp);
  322. }
  323. else
  324. {
  325. return FormatMessage(dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,Arguments);
  326. }
  327. */ default: // call standard method
  328. return FormatMessage(dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,Arguments);
  329. }
  330. }
  331. /********************************************************************
  332. FUNCTION: getPolicyInfo
  333. PURPOSE: gets information about currently assigned policy
  334. into piAssignedPolicy global structure
  335. INPUT: none
  336. RETURNS: HRESULT. Will return ERROR_SUCCESS if everything is fine.
  337. *********************************************************************/
  338. HRESULT getPolicyInfo ( )
  339. {
  340. LONG lRegistryCallResult;
  341. HKEY hRegKey;
  342. DWORD dwType; // for RegQueryValueEx
  343. DWORD dwBufLen; // for RegQueryValueEx
  344. lRegistryCallResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  345. pcszGPTIPSecKey,
  346. 0,
  347. KEY_READ,
  348. &hRegKey);
  349. if (lRegistryCallResult == ERROR_SUCCESS)
  350. {
  351. DWORD dwType;
  352. DWORD dwValue;
  353. DWORD dwLength = sizeof(DWORD);
  354. // query for flags, if flags aint' there or equal to 0, we don't have domain policy
  355. lRegistryCallResult = RegQueryValueEx(hRegKey,
  356. pcszGPTIPSecFlags,
  357. NULL,
  358. &dwType,
  359. (LPBYTE)&dwValue,
  360. &dwLength);
  361. if (lRegistryCallResult == ERROR_SUCCESS)
  362. {
  363. if (dwValue == 0)
  364. lRegistryCallResult = ERROR_FILE_NOT_FOUND;
  365. }
  366. // now get name
  367. if (lRegistryCallResult == ERROR_SUCCESS)
  368. {
  369. dwBufLen = MAXSTRLEN*sizeof(TCHAR);
  370. lRegistryCallResult = RegQueryValueEx( hRegKey,
  371. pcszGPTIPSecName,
  372. NULL,
  373. &dwType, // will be REG_SZ
  374. (LPBYTE) pszBuf,
  375. &dwBufLen);
  376. }
  377. }
  378. if (lRegistryCallResult == ERROR_SUCCESS)
  379. {
  380. piAssignedPolicy.iPolicySource = PS_DS_POLICY;
  381. piAssignedPolicy.pszPolicyPath[0] = 0;
  382. _tcscpy(piAssignedPolicy.pszPolicyName, pszBuf);
  383. dwBufLen = MAXSTRLEN*sizeof(TCHAR);
  384. lRegistryCallResult = RegQueryValueEx( hRegKey,
  385. pcszGPTIPSecPath,
  386. NULL,
  387. &dwType, // will be REG_SZ
  388. (LPBYTE) pszBuf,
  389. &dwBufLen);
  390. if (lRegistryCallResult == ERROR_SUCCESS)
  391. {
  392. _tcscpy(piAssignedPolicy.pszPolicyPath, pszBuf);
  393. }
  394. RegCloseKey(hRegKey);
  395. return ERROR_SUCCESS;
  396. }
  397. else
  398. {
  399. RegCloseKey(hRegKey);
  400. if (lRegistryCallResult == ERROR_FILE_NOT_FOUND)
  401. { // DS reg key not found, check local
  402. lRegistryCallResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  403. pcszLocIPSecKey,
  404. 0,
  405. KEY_READ,
  406. &hRegKey);
  407. if (lRegistryCallResult == ERROR_SUCCESS)
  408. {
  409. dwBufLen = MAXSTRLEN*sizeof(TCHAR);
  410. lRegistryCallResult = RegQueryValueEx( hRegKey,
  411. pcszLocIPSecPol,
  412. NULL,
  413. &dwType, // will be REG_SZ
  414. (LPBYTE) pszBuf,
  415. &dwBufLen);
  416. }
  417. else
  418. {
  419. return lRegistryCallResult; // return whatever error we got
  420. }
  421. RegCloseKey(hRegKey);
  422. if (lRegistryCallResult == ERROR_FILE_NOT_FOUND)
  423. { // no policy assigned
  424. piAssignedPolicy.iPolicySource = PS_NO_POLICY;
  425. piAssignedPolicy.pszPolicyPath[0] = 0;
  426. piAssignedPolicy.pszPolicyName[0] = 0;
  427. return ERROR_SUCCESS;
  428. }
  429. else
  430. { // read it
  431. lRegistryCallResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  432. pszBuf,
  433. 0,
  434. KEY_READ,
  435. &hRegKey);
  436. _tcscpy(piAssignedPolicy.pszPolicyPath, pszBuf);
  437. if (lRegistryCallResult == ERROR_SUCCESS)
  438. {
  439. dwBufLen = MAXSTRLEN*sizeof(TCHAR);
  440. lRegistryCallResult = RegQueryValueEx( hRegKey,
  441. pcszIPSecName,
  442. NULL,
  443. &dwType, // will be REG_SZ
  444. (LPBYTE) pszBuf,
  445. &dwBufLen);
  446. }
  447. RegCloseKey(hRegKey);
  448. if (lRegistryCallResult == ERROR_FILE_NOT_FOUND)
  449. { // no policy assigned
  450. piAssignedPolicy.iPolicySource = PS_NO_POLICY;
  451. piAssignedPolicy.pszPolicyPath[0] = 0;
  452. return ERROR_SUCCESS;
  453. }
  454. else if (lRegistryCallResult == ERROR_SUCCESS)
  455. { // found it
  456. piAssignedPolicy.iPolicySource = PS_LOC_POLICY;
  457. _tcscpy(piAssignedPolicy.pszPolicyName, pszBuf);
  458. }
  459. }
  460. }
  461. return (HRESULT) lRegistryCallResult;
  462. }
  463. }
  464. /********************************************************************
  465. FUNCTION: getServiceInfo
  466. PURPOSE: gets information about current state and configuration of IPSec Service
  467. into *pInfo structure
  468. INPUT: pInfo - pointer to SERVICE_INFO structure which will be updated with current information
  469. TODO:
  470. RETURNS: Win32 error codes. Will return ERROR_SUCCESS if everything is fine.
  471. ERROR_SERVICE_DOES_NOT_EXIST is returned is service is not installed on the system
  472. *********************************************************************/
  473. DWORD getServiceInfo ( OUT PSERVICE_INFO pInfo )
  474. {
  475. DWORD dwError = ERROR_SUCCESS;
  476. DWORD dwRequiredSize = 0;
  477. PVOID pLargeConfig = 0;
  478. SC_HANDLE schMan = NULL;
  479. SC_HANDLE schPA = NULL;
  480. if (!pInfo)
  481. {
  482. return ERROR_INVALID_PARAMETER;
  483. }
  484. memset(&(pInfo->servStat), 0, sizeof(SERVICE_STATUS));
  485. memset(&(pInfo->servConfig), 0, sizeof(QUERY_SERVICE_CONFIG));
  486. schMan = OpenSCManager(NULL, NULL, GENERIC_READ);
  487. if (schMan == NULL)
  488. {
  489. dwError = GetLastError();
  490. goto error;
  491. }
  492. schPA = OpenService(schMan, IPSEC_SERVICE_NAME, GENERIC_READ);
  493. if (schMan == NULL)
  494. {
  495. dwError = GetLastError();
  496. goto error;
  497. }
  498. if (!QueryServiceStatus(schPA, &(pInfo->servStat)))
  499. {
  500. dwError = GetLastError();
  501. goto error;
  502. }
  503. if (!QueryServiceConfig(schPA, &(pInfo->servConfig), sizeof(QUERY_SERVICE_CONFIG), &dwRequiredSize))
  504. {
  505. dwError = GetLastError();
  506. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  507. {
  508. pLargeConfig = malloc(dwRequiredSize);
  509. if (!pLargeConfig)
  510. {
  511. goto error;
  512. }
  513. if (!QueryServiceConfig(schPA, (LPQUERY_SERVICE_CONFIG) pLargeConfig, dwRequiredSize, &dwRequiredSize))
  514. {
  515. dwError = GetLastError();
  516. goto error;
  517. }
  518. // else we just got the information, copy over to *pInfo
  519. memcpy(&(pInfo->servConfig), pLargeConfig, sizeof(QUERY_SERVICE_CONFIG));
  520. dwError = ERROR_SUCCESS;
  521. }
  522. goto error;
  523. }
  524. error:
  525. if (schPA)
  526. CloseServiceHandle(schPA);
  527. if (schMan)
  528. CloseServiceHandle(schMan);
  529. if (pLargeConfig)
  530. {
  531. free(pLargeConfig);
  532. }
  533. return dwError;
  534. }
  535. /********************************************************************
  536. FUNCTION: reportError
  537. PURPOSE: prints out message code and message itself
  538. INPUT: HRESULT - error code
  539. RETURNS: none
  540. *********************************************************************/
  541. void reportError ( HRESULT hr, NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults )
  542. {
  543. LPTSTR msg = NULL;
  544. MyFormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
  545. NULL, hr, 0, (LPTSTR) &msg, 0, NULL );
  546. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  547. IDS_IPSEC_ERROR_MSG, hr, msg );
  548. }
  549. /********************************************************************
  550. FUNCTION: reportServiceInfo
  551. PURPOSE: prints out service status and startup information
  552. INPUT: none
  553. RETURNS: none
  554. *********************************************************************/
  555. void reportServiceInfo ( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults )
  556. {
  557. // print status information
  558. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  559. IDS_IPSEC_PA_STATUS );
  560. switch (siIPSecStatus.servStat.dwCurrentState)
  561. {
  562. case SERVICE_RUNNING:
  563. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  564. IDS_IPSEC_PA_STARTED );
  565. break;
  566. case SERVICE_STOPPED:
  567. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  568. IDS_IPSEC_PA_STOPPED );
  569. break;
  570. case SERVICE_PAUSED:
  571. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  572. IDS_IPSEC_PA_PAUSED );
  573. break;
  574. default:
  575. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  576. IDS_GLOBAL_ADAPTER_UNKNOWN);
  577. break;
  578. }
  579. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  580. IDS_GLOBAL_EmptyLine);
  581. // print config information
  582. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  583. IDS_IPSEC_PA_STARTUP );
  584. switch (siIPSecStatus.servConfig.dwStartType)
  585. {
  586. case SERVICE_AUTO_START:
  587. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  588. IDS_IPSEC_PA_AUTOMATIC );
  589. break;
  590. case SERVICE_DEMAND_START:
  591. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  592. IDS_IPSEC_PA_MANUAL );
  593. break;
  594. case SERVICE_DISABLED:
  595. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  596. IDS_IPSEC_PA_DISABLED );
  597. break;
  598. default:
  599. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  600. IDS_GLOBAL_ADAPTER_UNKNOWN);
  601. break;
  602. }
  603. AddMessageToList( &pResults->IPSec.lmsgGlobalOutput, Nd_Verbose,
  604. IDS_GLOBAL_EmptyLine);
  605. }
  606. /********************************************************************
  607. FUNCTION: getIPSecGPO
  608. PURPOSE: returns GPO that is assigning IPSec Policy
  609. INPUT: none
  610. RETURNS: pointer to GROUP_POLICY_OBJECT structure
  611. NULL if policy is not assigned or if GPO information is not retrievable
  612. NOTES: Tested only with domain GPOs
  613. Behaves unpredictably when run for the computer
  614. that does not have active Directory IPSec policy assigned
  615. CALLER is responsible for freeing the memory!
  616. *********************************************************************/
  617. PGROUP_POLICY_OBJECT getIPSecGPO ( )
  618. {
  619. HKEY hKey, hSubKey;
  620. DWORD dwType, dwSize, dwIndex, dwNameSize;
  621. LONG lResult;
  622. TCHAR szName[50];
  623. GUID guid;
  624. PGROUP_POLICY_OBJECT pGPO, pGPOTemp;
  625. PGROUP_POLICY_OBJECT pGPOReturn = NULL;
  626. DWORD dwResult;
  627. //
  628. // Enumerate the extensions
  629. //
  630. lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, GPEXT_KEY, 0, KEY_READ, &hKey);
  631. if (lResult == ERROR_SUCCESS)
  632. {
  633. dwIndex = 0;
  634. dwNameSize = 50;
  635. while ((dwResult = RegEnumKeyEx (hKey, dwIndex++, szName, &dwNameSize, NULL, NULL,
  636. NULL, NULL)) == ERROR_SUCCESS)
  637. {
  638. dwNameSize = 50;
  639. //
  640. // Skip the registry extension since we did it above
  641. //
  642. if (lstrcmpi(TEXT("{35378EAC-683F-11D2-A89A-00C04FBBCFA2}"), szName))
  643. {
  644. //
  645. // Get the list of GPOs this extension applied
  646. //
  647. StringToGuid(szName, &guid);
  648. lResult = GetAppliedGPOList (GPO_LIST_FLAG_MACHINE, NULL, NULL,
  649. &guid, &pGPO);
  650. if (lResult == ERROR_SUCCESS)
  651. {
  652. if (pGPO)
  653. {
  654. //
  655. // Get the extension's friendly display name
  656. //
  657. lResult = RegOpenKeyEx (hKey, szName, 0, KEY_READ, &hSubKey);
  658. if (lResult == ERROR_SUCCESS)
  659. {
  660. if (!lstrcmpi(TEXT("{e437bc1c-aa7d-11d2-a382-00c04f991e27}"), szName))
  661. {
  662. // found IPSec
  663. return pGPO;
  664. }
  665. else
  666. {
  667. FreeGPOList(pGPO);
  668. }
  669. }
  670. }
  671. }
  672. }
  673. }
  674. }
  675. return pGPOReturn;
  676. }
  677. //*************************************************************
  678. //
  679. // StringToGuid()
  680. //
  681. // Purpose: Converts a GUID in string format to a GUID structure
  682. //
  683. // Parameters: szValue - guid in string format
  684. // pGuid - guid structure receiving the guid
  685. //
  686. //
  687. // Return: void
  688. //
  689. //*************************************************************
  690. void StringToGuid( TCHAR * szValue, GUID * pGuid )
  691. {
  692. TCHAR wc;
  693. INT i;
  694. //
  695. // If the first character is a '{', skip it
  696. //
  697. if ( szValue[0] == TEXT('{') )
  698. szValue++;
  699. //
  700. // Since szValue may be used again, no permanent modification to
  701. // it is be made.
  702. //
  703. wc = szValue[8];
  704. szValue[8] = 0;
  705. pGuid->Data1 = _tcstoul( &szValue[0], 0, 16 );
  706. szValue[8] = wc;
  707. wc = szValue[13];
  708. szValue[13] = 0;
  709. pGuid->Data2 = (USHORT)_tcstoul( &szValue[9], 0, 16 );
  710. szValue[13] = wc;
  711. wc = szValue[18];
  712. szValue[18] = 0;
  713. pGuid->Data3 = (USHORT)_tcstoul( &szValue[14], 0, 16 );
  714. szValue[18] = wc;
  715. wc = szValue[21];
  716. szValue[21] = 0;
  717. pGuid->Data4[0] = (unsigned char)_tcstoul( &szValue[19], 0, 16 );
  718. szValue[21] = wc;
  719. wc = szValue[23];
  720. szValue[23] = 0;
  721. pGuid->Data4[1] = (unsigned char)_tcstoul( &szValue[21], 0, 16 );
  722. szValue[23] = wc;
  723. for ( i = 0; i < 6; i++ )
  724. {
  725. wc = szValue[26+i*2];
  726. szValue[26+i*2] = 0;
  727. pGuid->Data4[2+i] = (unsigned char)_tcstoul( &szValue[24+i*2], 0, 16 );
  728. szValue[26+i*2] = wc;
  729. }
  730. }
  731. /********************************************************************
  732. FUNCTION: getMorePolicyInfo
  733. PURPOSE: gets additional information about currently assigned policy
  734. into piAssignedPolicy global structure
  735. INPUT: none, uses global piAssignedPolicy structure
  736. particularly
  737. iPolicySource
  738. pszPolicyName
  739. pszPolicyPath
  740. fields
  741. RETURNS: HRESULT. Will return ERROR_SUCCESS if everything is fine.
  742. Currently fills pszPolicyDesc and timestamp fields of the global structure
  743. NOTES: This is separate from getPolicyInfo routine for two reasons
  744. a) the information obtained here is optional and error during this particular routine
  745. is not considered fatal
  746. b) the code structure is simpler as this routine is "built on top" of what getPolicyInfo provides
  747. *********************************************************************/
  748. DWORD getMorePolicyInfo ( )
  749. {
  750. DWORD dwError = ERROR_SUCCESS;
  751. HKEY hRegKey = NULL;
  752. DWORD dwType; // for RegQueryValueEx
  753. DWORD dwBufLen; // for RegQueryValueEx
  754. DWORD dwValue;
  755. DWORD dwLength = sizeof(DWORD);
  756. PTCHAR* ppszExplodeDN = NULL;
  757. // set some default values
  758. piAssignedPolicy.pszPolicyDesc[0] = 0;
  759. piAssignedPolicy.timestamp = 0;
  760. switch (piAssignedPolicy.iPolicySource)
  761. {
  762. case PS_LOC_POLICY:
  763. // open the key
  764. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  765. piAssignedPolicy.pszPolicyPath,
  766. 0,
  767. KEY_READ,
  768. &hRegKey);
  769. BAIL_ON_WIN32_ERROR(dwError);
  770. // timestamp
  771. dwError = RegQueryValueEx(hRegKey,
  772. pcszIPSecTimestamp,
  773. NULL,
  774. &dwType,
  775. (LPBYTE)&dwValue,
  776. &dwLength);
  777. BAIL_ON_WIN32_ERROR(dwError);
  778. piAssignedPolicy.timestamp = dwValue;
  779. // description
  780. dwBufLen = MAXSTRLEN*sizeof(TCHAR);
  781. dwError = RegQueryValueEx( hRegKey,
  782. pcszIPSecDesc,
  783. NULL,
  784. &dwType, // will be REG_SZ
  785. (LPBYTE) pszBuf,
  786. &dwBufLen);
  787. BAIL_ON_WIN32_ERROR(dwError);
  788. _tcscpy(piAssignedPolicy.pszPolicyDesc, pszBuf);
  789. break;
  790. case PS_DS_POLICY:
  791. // get the policy name from DN
  792. _tcscpy(pszBuf, pcszCacheIPSecKey);
  793. ppszExplodeDN = ldap_explode_dn(piAssignedPolicy.pszPolicyPath, 1);
  794. if (!ppszExplodeDN)
  795. {
  796. goto error;
  797. }
  798. _tcscat(pszBuf, TEXT("\\"));
  799. _tcscat(pszBuf, ppszExplodeDN[0]);
  800. // open the regkey
  801. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  802. pszBuf,
  803. 0,
  804. KEY_READ,
  805. &hRegKey);
  806. BAIL_ON_WIN32_ERROR(dwError);
  807. /* - tomestamp and description are not available yet
  808. // timestamp
  809. dwError = RegQueryValueEx(hRegKey,
  810. pcszIPSecTimestamp,
  811. NULL,
  812. &dwType,
  813. (LPBYTE)&dwValue,
  814. &dwLength);
  815. BAIL_ON_WIN32_ERROR(dwError);
  816. piAssignedPolicy.timestamp = dwValue;
  817. // description
  818. dwBufLen = MAXSTRLEN*sizeof(TCHAR);
  819. dwError = RegQueryValueEx( hRegKey,
  820. pcszIPSecDesc,
  821. NULL,
  822. &dwType, // will be REG_SZ
  823. (LPBYTE) pszBuf,
  824. &dwBufLen);
  825. BAIL_ON_WIN32_ERROR(dwError);
  826. _tcscpy(piAssignedPolicy.pszPolicyDesc, pszBuf);
  827. */
  828. break;
  829. }
  830. error:
  831. if (hRegKey)
  832. {
  833. RegCloseKey(hRegKey);
  834. }
  835. if (ppszExplodeDN)
  836. {
  837. ldap_value_free(ppszExplodeDN);
  838. }
  839. return dwError;
  840. }