Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

673 lines
15 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 2002 **/
  4. /**********************************************************************/
  5. /*
  6. spdutil.cpp
  7. FILE HISTORY:
  8. */
  9. #include "stdafx.h"
  10. #include "winipsec.h"
  11. #include "ipsec.h"
  12. #include "spdutil.h"
  13. #include "objplus.h"
  14. #include "ipaddres.h"
  15. #include "spddb.h"
  16. #include "server.h"
  17. #define MY_ENCODING_TYPE (X509_ASN_ENCODING)
  18. extern CHashTable g_HashTable;
  19. const DWORD IPSM_PROTOCOL_TCP = 6;
  20. const DWORD IPSM_PROTOCOL_UDP = 17;
  21. const TCHAR c_szSingleAddressMask[] = _T("255.255.255.255");
  22. const ProtocolStringMap c_ProtocolStringMap[] =
  23. {
  24. {0, IDS_PROTOCOL_ANY},
  25. {1, IDS_PROTOCOL_ICMP},
  26. {3, IDS_PROTOCOL_GGP},
  27. {6, IDS_PROTOCOL_TCP},
  28. {8, IDS_PROTOCOL_EGP},
  29. {12, IDS_PROTOCOL_PUP},
  30. {17, IDS_PROTOCOL_UDP},
  31. {20, IDS_PROTOCOL_HMP},
  32. {22, IDS_PROTOCOL_XNS_IDP},
  33. {27, IDS_PROTOCOL_RDP},
  34. {66, IDS_PROTOCOL_RVD}
  35. };
  36. const int c_nProtocols = DimensionOf(c_ProtocolStringMap);
  37. ULONG RevertDwordBytes(DWORD dw)
  38. {
  39. ULONG ulRet;
  40. ulRet = dw >> 24;
  41. ulRet += (dw & 0xFF0000) >> 8;
  42. ulRet += (dw & 0x00FF00) << 8;
  43. ulRet += (dw & 0x0000FF) << 24;
  44. return ulRet;
  45. }
  46. void PortToString
  47. (
  48. PORT port,
  49. CString * pst
  50. )
  51. {
  52. if (0 == port.wPort)
  53. {
  54. pst->LoadString(IDS_PORT_ANY);
  55. }
  56. else
  57. {
  58. pst->Format(_T("%d"), port.wPort);
  59. }
  60. }
  61. void FilterFlagToString
  62. (
  63. FILTER_ACTION FltrFlag,
  64. CString * pst
  65. )
  66. {
  67. pst->Empty();
  68. switch(FltrFlag)
  69. {
  70. case PASS_THRU:
  71. pst->LoadString(IDS_PASS_THROUGH);
  72. break;
  73. case BLOCKING:
  74. pst->LoadString(IDS_BLOCKING);
  75. break;
  76. case NEGOTIATE_SECURITY:
  77. pst->LoadString(IDS_NEG_SEC);
  78. break;
  79. }
  80. }
  81. void ProtocolToString
  82. (
  83. PROTOCOL protocol,
  84. CString * pst
  85. )
  86. {
  87. BOOL fFound = FALSE;
  88. for (int i = 0; i < DimensionOf(c_ProtocolStringMap); i++)
  89. {
  90. if (c_ProtocolStringMap[i].dwProtocol == protocol.dwProtocol)
  91. {
  92. pst->LoadString(c_ProtocolStringMap[i].nStringID);
  93. fFound = TRUE;
  94. }
  95. }
  96. if (!fFound)
  97. {
  98. pst->Format(IDS_OTHER_PROTO, protocol.dwProtocol);
  99. }
  100. }
  101. void InterfaceTypeToString
  102. (
  103. IF_TYPE ifType,
  104. CString * pst
  105. )
  106. {
  107. switch (ifType)
  108. {
  109. case INTERFACE_TYPE_ALL:
  110. pst->LoadString (IDS_IF_TYPE_ALL);
  111. break;
  112. case INTERFACE_TYPE_LAN:
  113. pst->LoadString (IDS_IF_TYPE_LAN);
  114. break;
  115. case INTERFACE_TYPE_DIALUP:
  116. pst->LoadString (IDS_IF_TYPE_RAS);
  117. break;
  118. default:
  119. pst->LoadString (IDS_UNKNOWN);
  120. break;
  121. }
  122. }
  123. void BoolToString
  124. (
  125. BOOL bl,
  126. CString * pst
  127. )
  128. {
  129. if (bl)
  130. pst->LoadString (IDS_YES);
  131. else
  132. pst->LoadString (IDS_NO);
  133. }
  134. void DirectionToString
  135. (
  136. DWORD dwDir,
  137. CString * pst
  138. )
  139. {
  140. switch (dwDir)
  141. {
  142. case FILTER_DIRECTION_INBOUND:
  143. pst->LoadString(IDS_FLTR_DIR_IN);
  144. break;
  145. case FILTER_DIRECTION_OUTBOUND:
  146. pst->LoadString(IDS_FLTR_DIR_OUT);
  147. break;
  148. default:
  149. pst->Empty();
  150. break;
  151. }
  152. }
  153. void DoiEspAlgorithmToString
  154. (
  155. IPSEC_MM_ALGO algo,
  156. CString * pst
  157. )
  158. {
  159. switch (algo.uAlgoIdentifier)
  160. {
  161. case CONF_ALGO_NONE:
  162. pst->LoadString(IDS_DOI_ESP_NONE);
  163. break;
  164. case CONF_ALGO_DES:
  165. pst->LoadString(IDS_DOI_ESP_DES);
  166. break;
  167. case CONF_ALGO_3_DES:
  168. pst->LoadString(IDS_DOI_ESP_3_DES);
  169. break;
  170. default:
  171. pst->Empty();
  172. break;
  173. }
  174. }
  175. void DoiAuthAlgorithmToString
  176. (
  177. IPSEC_MM_ALGO algo,
  178. CString * pst
  179. )
  180. {
  181. switch(algo.uAlgoIdentifier)
  182. {
  183. case AUTH_ALGO_NONE:
  184. pst->LoadString(IDS_DOI_AH_NONE);
  185. break;
  186. case AUTH_ALGO_MD5:
  187. pst->LoadString(IDS_DOI_AH_MD5);
  188. break;
  189. case AUTH_ALGO_SHA1:
  190. pst->LoadString(IDS_DOI_AH_SHA);
  191. break;
  192. default:
  193. pst->Empty();
  194. break;
  195. }
  196. }
  197. void DhGroupToString(DWORD dwGp, CString * pst)
  198. {
  199. switch(dwGp)
  200. {
  201. case DH_GROUP_1:
  202. pst->LoadString(IDS_DHGROUP_LOW);
  203. break;
  204. case DH_GROUP_2:
  205. pst->LoadString(IDS_DHGROUP_MEDIUM);
  206. break;
  207. case DH_GROUP_2048:
  208. pst->LoadString(IDS_DHGROUP_HIGH);
  209. break;
  210. default:
  211. pst->Format(_T("%d"), dwGp);
  212. break;
  213. }
  214. }
  215. void MmAuthToString(MM_AUTH_ENUM auth, CString * pst)
  216. {
  217. switch(auth)
  218. {
  219. case IKE_PRESHARED_KEY:
  220. pst->LoadString(IDS_IKE_PRESHARED_KEY);
  221. break;
  222. case IKE_DSS_SIGNATURE:
  223. pst->LoadString(IDS_IKE_DSS_SIGNATURE);
  224. break;
  225. case IKE_RSA_SIGNATURE:
  226. pst->LoadString(IDS_IKE_RSA_SIGNATURE);
  227. break;
  228. case IKE_RSA_ENCRYPTION:
  229. pst->LoadString(IDS_IKE_RSA_ENCRYPTION);
  230. break;
  231. case IKE_SSPI:
  232. pst->LoadString(IDS_IKE_SSPI);
  233. break;
  234. default:
  235. pst->Empty();
  236. break;
  237. }
  238. }
  239. void KeyLifetimeToString(KEY_LIFETIME lifetime, CString * pst)
  240. {
  241. pst->Format(IDS_KEY_LIFE_TIME, lifetime.uKeyExpirationKBytes, lifetime.uKeyExpirationTime);
  242. }
  243. void IpToString(ULONG ulIp, CString *pst)
  244. {
  245. ULONG ul;
  246. CIpAddress ipAddr;
  247. ul = RevertDwordBytes(ulIp);
  248. ipAddr = ul;
  249. *pst = (CString) ipAddr;
  250. }
  251. void AddressToString(ADDR addr, CString * pst, BOOL * pfIsDnsName)
  252. {
  253. Assert(pst);
  254. if (NULL == pst)
  255. return;
  256. if (pfIsDnsName)
  257. {
  258. *pfIsDnsName = FALSE;
  259. }
  260. ULONG ul;
  261. CIpAddress ipAddr;
  262. pst->Empty();
  263. switch (addr.AddrType)
  264. {
  265. case IP_ADDR_UNIQUE:
  266. if (IP_ADDRESS_ME == addr.uIpAddr)
  267. {
  268. pst->LoadString(IDS_ADDR_ME);
  269. }
  270. else
  271. {
  272. HashEntry *pHashEntry=NULL;
  273. if (g_HashTable.GetObject(&pHashEntry,*(in_addr*)&addr.uIpAddr) != ERROR_SUCCESS) {
  274. ul = RevertDwordBytes(addr.uIpAddr);
  275. ipAddr = ul;
  276. *pst = (CString) ipAddr;
  277. }
  278. else
  279. {
  280. *pst=pHashEntry->HostName;
  281. if (pfIsDnsName)
  282. {
  283. *pfIsDnsName = TRUE;
  284. }
  285. }
  286. }
  287. break;
  288. case IP_ADDR_SUBNET:
  289. if (SUBNET_ADDRESS_ANY == addr.uSubNetMask)
  290. {
  291. pst->LoadString(IDS_ADDR_ANY);
  292. }
  293. else
  294. {
  295. ul = RevertDwordBytes(addr.uIpAddr);
  296. ipAddr = ul;
  297. *pst = (CString) ipAddr;
  298. *pst += _T("(");
  299. ul = RevertDwordBytes(addr.uSubNetMask);
  300. ipAddr = ul;
  301. *pst += (CString) ipAddr;
  302. *pst += _T(")");
  303. }
  304. break;
  305. case IP_ADDR_DNS_SERVER:
  306. pst->LoadString(IDS_FILTER_EXT_DNS_SERVER);
  307. break;
  308. case IP_ADDR_WINS_SERVER:
  309. pst->LoadString(IDS_FILTER_EXT_WINS_SERVER);
  310. break;
  311. case IP_ADDR_DHCP_SERVER:
  312. pst->LoadString(IDS_FILTER_EXT_DHCP_SERVER);
  313. break;
  314. case IP_ADDR_DEFAULT_GATEWAY:
  315. pst->LoadString(IDS_FILTER_EXT_DEF_GATEWAY);
  316. break;
  317. }
  318. }
  319. void IpsecByteBlobToString(const IPSEC_BYTE_BLOB& blob, CString * pst)
  320. {
  321. Assert(pst);
  322. if (NULL == pst)
  323. return;
  324. pst->Empty();
  325. //TODO to translate the blob info to readable strings
  326. }
  327. void QmAlgorithmToString
  328. (
  329. QM_ALGO_TYPE type,
  330. CQmOffer * pOffer,
  331. CString * pst
  332. )
  333. {
  334. Assert(pst);
  335. Assert(pOffer);
  336. if (NULL == pst || NULL == pOffer)
  337. return;
  338. pst->LoadString(IDS_ALGO_NONE);
  339. for (DWORD i = 0; i < pOffer->m_dwNumAlgos; i++)
  340. {
  341. switch(type)
  342. {
  343. case QM_ALGO_AUTH:
  344. if (AUTHENTICATION == pOffer->m_arrAlgos[i].m_Operation)
  345. {
  346. switch(pOffer->m_arrAlgos[i].m_ulAlgo)
  347. {
  348. case AUTH_ALGO_MD5:
  349. pst->LoadString(IDS_DOI_AH_MD5);
  350. break;
  351. case AUTH_ALGO_SHA1:
  352. pst->LoadString(IDS_DOI_AH_SHA);
  353. break;
  354. }
  355. }
  356. break;
  357. case QM_ALGO_ESP_CONF:
  358. if (ENCRYPTION == pOffer->m_arrAlgos[i].m_Operation)
  359. {
  360. switch(pOffer->m_arrAlgos[i].m_ulAlgo)
  361. {
  362. case CONF_ALGO_DES:
  363. pst->LoadString(IDS_DOI_ESP_DES);
  364. break;
  365. case CONF_ALGO_3_DES:
  366. pst->LoadString(IDS_DOI_ESP_3_DES);
  367. break;
  368. }
  369. }
  370. break;
  371. case QM_ALGO_ESP_INTEG:
  372. if (ENCRYPTION == pOffer->m_arrAlgos[i].m_Operation)
  373. {
  374. switch(pOffer->m_arrAlgos[i].m_SecAlgo)
  375. {
  376. case HMAC_AUTH_ALGO_MD5:
  377. pst->LoadString(IDS_HMAC_AH_MD5);
  378. break;
  379. case HMAC_AUTH_ALGO_SHA1:
  380. pst->LoadString(IDS_HMAC_AH_SHA);
  381. break;
  382. }
  383. }
  384. break;
  385. }
  386. }
  387. }
  388. void TnlEpToString
  389. (
  390. QM_FILTER_TYPE FltrType,
  391. ADDR TnlEp,
  392. CString * pst
  393. )
  394. {
  395. Assert(pst);
  396. if (NULL == pst)
  397. return;
  398. if (QM_TUNNEL_FILTER == FltrType)
  399. {
  400. AddressToString(TnlEp, pst);
  401. }
  402. else
  403. {
  404. pst->LoadString(IDS_NOT_AVAILABLE);
  405. }
  406. }
  407. void TnlEpToString
  408. (
  409. FILTER_TYPE FltrType,
  410. ADDR TnlEp,
  411. CString * pst
  412. )
  413. {
  414. Assert(pst);
  415. if (NULL == pst)
  416. return;
  417. if (FILTER_TYPE_TUNNEL == FltrType)
  418. {
  419. AddressToString(TnlEp, pst);
  420. }
  421. else
  422. {
  423. pst->LoadString(IDS_NOT_AVAILABLE);
  424. }
  425. }
  426. void IpsecByteBlobToString1(const IPSEC_BYTE_BLOB& blob, CString * pst)
  427. {
  428. Assert(pst);
  429. if (NULL == pst)
  430. return;
  431. pst->Empty();
  432. WCHAR *pszTemp = NULL;
  433. pszTemp = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,blob.dwSize + sizeof(WCHAR));
  434. memcpy((LPBYTE)pszTemp, blob.pBlob, blob.dwSize);
  435. *pst = pszTemp;
  436. //bug bug
  437. LocalFree(pszTemp);
  438. }
  439. BOOL
  440. GetNameAudit(
  441. IN CRYPT_DATA_BLOB *NameBlob,
  442. IN OUT LPTSTR Name,
  443. IN DWORD NameBufferSize
  444. )
  445. {
  446. DWORD dwCount=0;
  447. DWORD dwSize = 0;
  448. BOOL bRet = TRUE;
  449. dwSize = CertNameToStr(
  450. MY_ENCODING_TYPE, // Encoding type
  451. NameBlob, // CRYPT_DATA_BLOB
  452. CERT_X500_NAME_STR, // Type
  453. Name, // Place to return string
  454. NameBufferSize); // Size of string (chars)
  455. if(dwSize <= 1)
  456. {
  457. dwCount = _tcslen(_TEXT(""))+1;
  458. _tcsncpy(Name, _TEXT(""), dwCount);
  459. bRet = FALSE;
  460. }
  461. return bRet;
  462. }
  463. VOID
  464. GetCertId(
  465. IN PIPSEC_BYTE_BLOB pCertificateChain,
  466. CString * pstCertId
  467. )
  468. {
  469. CRYPT_DATA_BLOB pkcsMsg;
  470. HANDLE hCertStore = NULL;
  471. PCCERT_CONTEXT pPrevCertContext = NULL;
  472. PCCERT_CONTEXT pCertContext = NULL;
  473. _TCHAR pszSubjectName[1024] = {0};
  474. CRYPT_DATA_BLOB NameBlob;
  475. BOOL bRet;
  476. pkcsMsg.pbData=pCertificateChain->pBlob;
  477. pkcsMsg.cbData=pCertificateChain->dwSize;
  478. hCertStore = CertOpenStore( CERT_STORE_PROV_PKCS7,
  479. MY_ENCODING_TYPE | PKCS_7_ASN_ENCODING,
  480. NULL,
  481. CERT_STORE_READONLY_FLAG,
  482. &pkcsMsg);
  483. if ( NULL == hCertStore )
  484. {
  485. goto error;
  486. }
  487. pCertContext = CertEnumCertificatesInStore( hCertStore,
  488. pPrevCertContext);
  489. if ( NULL == pCertContext )
  490. {
  491. goto error;
  492. }
  493. NameBlob = pCertContext->pCertInfo->Subject;
  494. *pstCertId = _T("\0");
  495. DWORD dwRet = CertGetNameString(
  496. pCertContext,
  497. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  498. 0,
  499. NULL,
  500. pszSubjectName,
  501. sizeof(pszSubjectName)/sizeof(pszSubjectName[0])
  502. );
  503. *pstCertId = _T("");
  504. if ( dwRet > 1 )
  505. {
  506. *pstCertId = pszSubjectName;
  507. }
  508. error:
  509. if ( hCertStore )
  510. {
  511. CertCloseStore(hCertStore, 0 );
  512. }
  513. }
  514. void PFSGroupToString(
  515. DWORD dwPFSGroup,
  516. CString * pst
  517. )
  518. {
  519. switch(dwPFSGroup)
  520. {
  521. case 1:
  522. pst->LoadString(IDS_DHGROUP_LOW);
  523. break;
  524. case 2:
  525. pst->LoadString(IDS_DHGROUP_MEDIUM);
  526. break;
  527. case PFS_GROUP_2048:
  528. pst->LoadString(IDS_DHGROUP_HIGH);
  529. break;
  530. case PFS_GROUP_MM:
  531. pst->LoadString(IDS_PFS_GROUP_DERIVED);
  532. break;
  533. case 0:
  534. pst->LoadString(IDS_DHGROUP_UNASSIGNED);
  535. break;
  536. default:
  537. pst->Format(_T("%d"), dwPFSGroup);
  538. break;
  539. }
  540. }
  541. void GetAuthId(PIPSEC_MM_SA pSa, CString * pstAuthId, BOOL bPeer)
  542. {
  543. PIPSEC_BYTE_BLOB pAuthIdBlob = NULL;
  544. PIPSEC_BYTE_BLOB pCertChainBlob = NULL;
  545. //assign to NULL
  546. *pstAuthId = _T("");
  547. if ( bPeer )
  548. {
  549. pAuthIdBlob = (PIPSEC_BYTE_BLOB ) &(pSa->PeerId);
  550. pCertChainBlob = (PIPSEC_BYTE_BLOB) &(pSa->PeerCertificateChain);
  551. }
  552. else
  553. {
  554. pAuthIdBlob = (PIPSEC_BYTE_BLOB) &(pSa->MyId);
  555. pCertChainBlob = (PIPSEC_BYTE_BLOB) &(pSa->MyCertificateChain);
  556. }
  557. if ( (pAuthIdBlob->dwSize > 0) && (pAuthIdBlob->pBlob) )
  558. {
  559. IpsecByteBlobToString1( *pAuthIdBlob, pstAuthId );
  560. return;
  561. }
  562. switch(pSa->MMAuthEnum)
  563. {
  564. case IKE_PRESHARED_KEY:
  565. {
  566. ADDR *pAddr;
  567. ULONG ul;
  568. CIpAddress ipAddr;
  569. //should be just a IP address
  570. if ( bPeer )
  571. {
  572. pAddr = &(pSa->Peer);
  573. }
  574. else
  575. {
  576. pAddr = &(pSa->Me);
  577. }
  578. ul = RevertDwordBytes(pAddr->uIpAddr);
  579. ipAddr = ul;
  580. *pstAuthId = (CString) ipAddr;
  581. }
  582. break;
  583. case IKE_DSS_SIGNATURE:
  584. case IKE_RSA_SIGNATURE:
  585. case IKE_RSA_ENCRYPTION:
  586. //get the id from the cert chain
  587. GetCertId( pCertChainBlob, pstAuthId );
  588. break;
  589. case IKE_SSPI:
  590. //dns name
  591. //not needed to do anything as spd gives the correct id for SSPI case
  592. break;
  593. default:
  594. break;
  595. }
  596. }