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.

1306 lines
38 KiB

  1. /////////////////////////////////////////////////////////////
  2. // Copyright(c) 2000-2001, Microsoft Corporation
  3. //
  4. // text2spd.cpp
  5. //
  6. // Created on 2/15/00 by DKalin
  7. // Revisions:
  8. // Split into text2spd.cpp and spdutil.cpp 3/27/01 DKalin
  9. //
  10. // Moved the routines to this module from text2pol.cpp 2/15/00 DKalin
  11. //
  12. // Implementation for the text to policy conversion routines that deal directly with SPD structures
  13. //
  14. // Separated from generic routines in text2pol.cpp
  15. //
  16. /////////////////////////////////////////////////////////////
  17. #include "ipseccmd.h"
  18. // if szSrc and/or szDst are passed in,
  19. // caller must provide adequate space
  20. DWORD TextToFilter(IN char *szText, IN OUT T2P_FILTER &Filter, char *szSrc, char *szDst)
  21. {
  22. DWORD dwReturn = T2P_OK; // return code of this function
  23. char *pToken = NULL, *pTmp = NULL;
  24. char szTmp[POTF_MAX_STRLEN];
  25. char *pPortTok = NULL,
  26. *pProtTok = NULL;
  27. BOOL bMirror = false;
  28. if (szText != NULL) // do not assume that caller is smart
  29. {
  30. // We copy szText to szTmp so we can muck with it
  31. // in the process, we
  32. // determine passthru or drop filter
  33. // but first we set this filter to negotiate security and to be not mirrored
  34. // we also set protocol field
  35. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  36. {
  37. // transport filter
  38. // the very first thing we do is check for default response rule specified
  39. // then we set both Inbound and Outbound filter flags to POTF_DEFAULT_RESPONSE_FLAG
  40. // and substitute "DEFAULT" string with "0+0" (Me-to-Me)
  41. if (_stricmp(POTF_FILTER_DEFAULT, szText) == 0)
  42. {
  43. Filter.TransportFilter.InboundFilterFlag = (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG;
  44. Filter.TransportFilter.OutboundFilterFlag = (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG;
  45. szText[0] = '0';
  46. szText[1] = '+';
  47. szText[2] = '0';
  48. szText[3] = '\0';
  49. }
  50. else
  51. {
  52. Filter.TransportFilter.InboundFilterFlag = NEGOTIATE_SECURITY;
  53. Filter.TransportFilter.OutboundFilterFlag = NEGOTIATE_SECURITY;
  54. }
  55. Filter.TransportFilter.bCreateMirror = FALSE;
  56. Filter.TransportFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
  57. Filter.TransportFilter.Protocol.dwProtocol = 0;
  58. }
  59. else
  60. {
  61. // tunnel filter
  62. Filter.TunnelFilter.InboundFilterFlag = NEGOTIATE_SECURITY;
  63. Filter.TunnelFilter.OutboundFilterFlag = NEGOTIATE_SECURITY;
  64. Filter.TunnelFilter.bCreateMirror = FALSE;
  65. Filter.TunnelFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
  66. Filter.TunnelFilter.Protocol.dwProtocol = 0;
  67. UuidCreateNil(&(Filter.TunnelFilter.SrcTunnelAddr.gInterfaceID));
  68. UuidCreateNil(&(Filter.TunnelFilter.DesTunnelAddr.gInterfaceID));
  69. }
  70. pToken = strchr(szText, POTF_PASSTHRU_OPEN_TOKEN);
  71. if (pToken != NULL)
  72. {
  73. if (strrchr(szText, POTF_PASSTHRU_CLOSE_TOKEN) == NULL)
  74. {
  75. dwReturn = T2P_PASSTHRU_NOT_CLOSED;
  76. }
  77. else
  78. {
  79. strcpy(szTmp, szText + 1);
  80. szTmp[strlen(szTmp) - 1] = '\0';
  81. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  82. {
  83. // transport filter
  84. Filter.TransportFilter.InboundFilterFlag = PASS_THRU;
  85. Filter.TransportFilter.OutboundFilterFlag = PASS_THRU;
  86. }
  87. else
  88. {
  89. // tunnel filter
  90. Filter.TunnelFilter.InboundFilterFlag = PASS_THRU;
  91. Filter.TunnelFilter.OutboundFilterFlag = PASS_THRU;
  92. }
  93. }
  94. }
  95. else if ( (pToken = strchr(szText, POTF_DROP_OPEN_TOKEN)) != NULL )
  96. {
  97. if (strrchr(szText, POTF_DROP_CLOSE_TOKEN) == NULL)
  98. {
  99. dwReturn = T2P_DROP_NOT_CLOSED;
  100. }
  101. else
  102. {
  103. strcpy(szTmp, szText + 1);
  104. szTmp[strlen(szTmp) - 1] = '\0';
  105. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  106. {
  107. // transport filter
  108. Filter.TransportFilter.dwFlags |= FILTER_NATURE_BLOCKING;
  109. Filter.TransportFilter.InboundFilterFlag = BLOCKING;
  110. Filter.TransportFilter.OutboundFilterFlag = BLOCKING;
  111. }
  112. else
  113. {
  114. // tunnel filter
  115. Filter.TunnelFilter.dwFlags |= FILTER_NATURE_BLOCKING;
  116. Filter.TunnelFilter.InboundFilterFlag = BLOCKING;
  117. Filter.TunnelFilter.OutboundFilterFlag = BLOCKING;
  118. }
  119. }
  120. }
  121. else
  122. strcpy(szTmp, szText);
  123. // parse into source and dest strings
  124. for (pToken = szText; *pToken != POTF_FILTER_TOKEN &&
  125. *pToken != POTF_FILTER_MIRTOKEN &&
  126. *pToken != '\0'; ++pToken)
  127. ;
  128. if (*pToken == '\0')
  129. {
  130. dwReturn = T2P_NOSRCDEST_TOKEN;
  131. }
  132. else if ( *(pToken + 1) == '\0' )
  133. {
  134. dwReturn = T2P_NO_DESTADDR;
  135. }
  136. else if (T2P_SUCCESS(dwReturn))
  137. {
  138. if (*pToken == POTF_FILTER_MIRTOKEN)
  139. {
  140. bMirror = TRUE;
  141. // set Mirrored = true
  142. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  143. {
  144. // transport filter
  145. Filter.TransportFilter.bCreateMirror = TRUE;
  146. }
  147. else
  148. {
  149. // tunnel filter
  150. Filter.TunnelFilter.bCreateMirror = TRUE;
  151. }
  152. }
  153. if (!bMirror)
  154. pToken = strchr(szTmp, POTF_FILTER_TOKEN);
  155. else
  156. pToken = strchr(szTmp, POTF_FILTER_MIRTOKEN);
  157. *pToken = '\0';
  158. // do the src address
  159. dwReturn = TextToFiltAddr(szTmp, Filter, szSrc);
  160. if (T2P_SUCCESS(dwReturn))
  161. {
  162. // do the dest address
  163. pPortTok = strchr(pToken + 1, POTF_PT_TOKEN);
  164. if (pPortTok == NULL) // no port/prot specified
  165. dwReturn = TextToFiltAddr(pToken + 1, Filter, szDst, true);
  166. else if ( (pProtTok = strchr(pPortTok + 1, POTF_PT_TOKEN)) == NULL )
  167. {
  168. // there is a port but not a protocol specified
  169. // this is illegal (bug 285266)
  170. dwReturn = T2P_INVALID_ADDR;
  171. }
  172. else
  173. {
  174. // there is both port and protocol specified
  175. *pProtTok = '\0';
  176. dwReturn = TextToFiltAddr(pToken + 1, Filter, szDst, true);
  177. if (T2P_SUCCESS(dwReturn))
  178. {
  179. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  180. {
  181. // transport filter
  182. Filter.TransportFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
  183. dwReturn = TextToProtocol(pProtTok + 1, Filter.TransportFilter.Protocol.dwProtocol);
  184. }
  185. else
  186. {
  187. // tunnel filter
  188. Filter.TunnelFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
  189. dwReturn = TextToProtocol(pProtTok + 1, Filter.TunnelFilter.Protocol.dwProtocol);
  190. }
  191. }
  192. }
  193. }
  194. // we're done, do any fixing up of Filter
  195. if (T2P_SUCCESS(dwReturn))
  196. {
  197. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  198. {
  199. // transport filter
  200. // set the GUID
  201. RPC_STATUS RpcStat = UuidCreate(&Filter.TransportFilter.gFilterID);
  202. if (RpcStat != RPC_S_OK && RpcStat != RPC_S_UUID_LOCAL_ONLY)
  203. {
  204. dwReturn = RpcStat;
  205. }
  206. // set the name to be equal to the "text2pol " + GUID
  207. if (T2P_SUCCESS(dwReturn))
  208. {
  209. WCHAR StringTxt[POTF_MAX_STRLEN];
  210. int iReturn;
  211. wcscpy(StringTxt, L"text2pol ");
  212. iReturn = StringFromGUID2(Filter.TransportFilter.gFilterID, StringTxt+wcslen(StringTxt), POTF_MAX_STRLEN-wcslen(StringTxt));
  213. assert(iReturn != 0);
  214. Filter.TransportFilter.pszFilterName = new WCHAR[wcslen(StringTxt)+1];
  215. assert(Filter.TransportFilter.pszFilterName != NULL);
  216. wcscpy(Filter.TransportFilter.pszFilterName, StringTxt);
  217. }
  218. }
  219. else
  220. {
  221. // tunnel filter
  222. // set the GUID
  223. RPC_STATUS RpcStat = UuidCreate(&Filter.TunnelFilter.gFilterID);
  224. if (RpcStat != RPC_S_OK && RpcStat != RPC_S_UUID_LOCAL_ONLY)
  225. {
  226. dwReturn = RpcStat;
  227. }
  228. // set the name to be equal to the "text2pol " + GUID
  229. if (T2P_SUCCESS(dwReturn))
  230. {
  231. WCHAR StringTxt[POTF_MAX_STRLEN];
  232. int iReturn;
  233. wcscpy(StringTxt, L"text2pol ");
  234. iReturn = StringFromGUID2(Filter.TunnelFilter.gFilterID, StringTxt+wcslen(StringTxt), POTF_MAX_STRLEN-wcslen(StringTxt));
  235. assert(iReturn != 0);
  236. Filter.TunnelFilter.pszFilterName = new WCHAR[wcslen(StringTxt)+1];
  237. assert(Filter.TunnelFilter.pszFilterName != NULL);
  238. wcscpy(Filter.TunnelFilter.pszFilterName, StringTxt);
  239. }
  240. }
  241. }
  242. }
  243. }
  244. else // szText is NULL
  245. dwReturn = T2P_NULL_STRING;
  246. return dwReturn;
  247. }
  248. DWORD TextToFiltAddr(IN char *szAddr, IN OUT T2P_FILTER & Filter,
  249. OUT char *szName,
  250. IN bool bDest) // bDest is false
  251. {
  252. DWORD dwReturn = T2P_OK;
  253. IPAddr Address = INADDR_NONE;
  254. IPMask Mask = INADDR_NONE;
  255. WORD Port = 0;
  256. char *pMask = NULL,
  257. *pPort = NULL,
  258. *pPeek = NULL;
  259. bool bInterface = false;
  260. GUID gInterfaceId;
  261. struct hostent *pHostEnt;
  262. if (szAddr != NULL)
  263. {
  264. // copy szAddr so we can muck with it
  265. char szTmp[POTF_MAX_STRLEN];
  266. strcpy(szTmp, szAddr);
  267. // let's see what we have here
  268. if ( (pPort = strrchr(szTmp, POTF_PT_TOKEN)) != NULL )
  269. {
  270. *pPort = '\0';
  271. ++pPort;
  272. }
  273. if ( (pMask = strrchr(szTmp, POTF_MASK_TOKEN)) != NULL )
  274. {
  275. *pMask = '\0';
  276. ++pMask;
  277. }
  278. // first, the easy cases
  279. // To specify ME, use 0 for the address and -1 for the mask
  280. // To specify ANY use 0 for the address and 0 for the mask.
  281. if (szTmp[0] == POTF_ANYADDR_TOKEN)
  282. {
  283. Address = SUBNET_ADDRESS_ANY;
  284. Mask = SUBNET_MASK_ANY;
  285. }
  286. else if (szTmp[0] == POTF_ME_TOKEN)
  287. {
  288. Address = IP_ADDRESS_ME;
  289. Mask = IP_ADDRESS_MASK_NONE;
  290. }
  291. else if (szTmp[0] == POTF_GUID_TOKEN)
  292. { // interface-specific filter
  293. char *pGUIDEnd = NULL;
  294. if ( (pGUIDEnd = strrchr(szTmp, POTF_GUID_END_TOKEN)) != NULL )
  295. {
  296. *pGUIDEnd = '\0';
  297. }
  298. if (pGUIDEnd && UuidFromStringA((unsigned char *)(szTmp+1), &gInterfaceId) == RPC_S_OK)
  299. {
  300. bInterface = true;
  301. }
  302. else
  303. {
  304. dwReturn = T2P_INVALID_ADDR;
  305. }
  306. }
  307. else if (isdnsname(szTmp)) // DNS name
  308. {
  309. pHostEnt = gethostbyname(szTmp);
  310. if (pHostEnt != NULL)
  311. {
  312. Address = *(IPAddr *)pHostEnt->h_addr;
  313. // should check for more here, but not now
  314. // specific host, Mask is 255.255.255.255
  315. Mask = IP_ADDRESS_MASK_NONE;
  316. }
  317. else
  318. {
  319. dwReturn = T2P_DNSLOOKUP_FAILED;
  320. }
  321. if ( szName )
  322. strcpy(szName, szTmp);
  323. }
  324. else // good old dotted notation
  325. {
  326. // process the * shortcut for subnetting
  327. if (strchr(szTmp, POTF_STAR_TOKEN) != NULL)
  328. {
  329. Mask = 0x000000FF;
  330. for (pPeek = szTmp; *pPeek != '\0'; ++pPeek)
  331. {
  332. if ((*pPeek == '.') && (*(pPeek + 1) != POTF_STAR_TOKEN))
  333. Mask |= (Mask << 8);
  334. else if ((*pPeek == '.') && (*(pPeek + 1) != '\0'))
  335. *(pPeek + 1) = '0';
  336. }
  337. }
  338. Address = inet_addr(szTmp);
  339. if (Address == INADDR_NONE)
  340. {
  341. dwReturn = T2P_INVALID_ADDR;
  342. }
  343. else
  344. {
  345. if (pMask != NULL)
  346. {
  347. Mask = inet_addr(pMask);
  348. }
  349. else if (pPeek == NULL)
  350. Mask = IP_ADDRESS_MASK_NONE;
  351. }
  352. }
  353. // now for the port and fill the Filter out
  354. if (T2P_SUCCESS(dwReturn))
  355. {
  356. if (pPort != NULL)
  357. {
  358. Port = (SHORT)atoi(pPort);
  359. }
  360. if (Filter.QMFilterType != QM_TUNNEL_FILTER)
  361. {
  362. // transport filter
  363. if (bDest) // we converted the dest addr
  364. {
  365. if (!bInterface)
  366. {
  367. Filter.TransportFilter.DesAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
  368. Filter.TransportFilter.DesAddr.uIpAddr = Address;
  369. Filter.TransportFilter.DesAddr.uSubNetMask = Mask;
  370. Filter.TransportFilter.DesPort.PortType = PORT_UNIQUE;
  371. Filter.TransportFilter.DesPort.wPort = Port;
  372. UuidCreateNil(&(Filter.TransportFilter.DesAddr.gInterfaceID));
  373. }
  374. else
  375. {
  376. Filter.TransportFilter.DesAddr.AddrType = IP_ADDR_INTERFACE;
  377. Filter.TransportFilter.DesAddr.uIpAddr = IP_ADDRESS_ME;
  378. Filter.TransportFilter.DesAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
  379. Filter.TransportFilter.DesPort.PortType = PORT_UNIQUE;
  380. Filter.TransportFilter.DesPort.wPort = Port;
  381. Filter.TransportFilter.DesAddr.gInterfaceID = gInterfaceId;
  382. }
  383. }
  384. else
  385. {
  386. if (!bInterface)
  387. {
  388. Filter.TransportFilter.SrcAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
  389. Filter.TransportFilter.SrcAddr.uIpAddr = Address;
  390. Filter.TransportFilter.SrcAddr.uSubNetMask = Mask;
  391. Filter.TransportFilter.SrcPort.PortType = PORT_UNIQUE;
  392. Filter.TransportFilter.SrcPort.wPort = Port;
  393. UuidCreateNil(&(Filter.TransportFilter.SrcAddr.gInterfaceID));
  394. }
  395. else
  396. {
  397. Filter.TransportFilter.SrcAddr.AddrType = IP_ADDR_INTERFACE;
  398. Filter.TransportFilter.SrcAddr.uIpAddr = IP_ADDRESS_ME;
  399. Filter.TransportFilter.SrcAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
  400. Filter.TransportFilter.SrcPort.PortType = PORT_UNIQUE;
  401. Filter.TransportFilter.SrcPort.wPort = Port;
  402. Filter.TransportFilter.SrcAddr.gInterfaceID = gInterfaceId;
  403. }
  404. }
  405. }
  406. else
  407. {
  408. // tunnel filter
  409. if (bDest) // we converted the dest addr
  410. {
  411. if (!bInterface)
  412. {
  413. Filter.TunnelFilter.DesAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
  414. Filter.TunnelFilter.DesAddr.uIpAddr = Address;
  415. Filter.TunnelFilter.DesAddr.uSubNetMask = Mask;
  416. Filter.TunnelFilter.DesPort.PortType = PORT_UNIQUE;
  417. Filter.TunnelFilter.DesPort.wPort = Port;
  418. UuidCreateNil(&(Filter.TunnelFilter.DesAddr.gInterfaceID));
  419. }
  420. else
  421. {
  422. Filter.TunnelFilter.DesAddr.AddrType = IP_ADDR_INTERFACE;
  423. Filter.TunnelFilter.DesAddr.uIpAddr = IP_ADDRESS_ME;
  424. Filter.TunnelFilter.DesAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
  425. Filter.TunnelFilter.DesPort.PortType = PORT_UNIQUE;
  426. Filter.TunnelFilter.DesPort.wPort = Port;
  427. Filter.TunnelFilter.DesAddr.gInterfaceID = gInterfaceId;
  428. }
  429. }
  430. else
  431. {
  432. if (!bInterface)
  433. {
  434. Filter.TunnelFilter.SrcAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
  435. Filter.TunnelFilter.SrcAddr.uIpAddr = Address;
  436. Filter.TunnelFilter.SrcAddr.uSubNetMask = Mask;
  437. Filter.TunnelFilter.SrcPort.PortType = PORT_UNIQUE;
  438. Filter.TunnelFilter.SrcPort.wPort = Port;
  439. UuidCreateNil(&(Filter.TunnelFilter.SrcAddr.gInterfaceID));
  440. }
  441. else
  442. {
  443. Filter.TunnelFilter.SrcAddr.AddrType = IP_ADDR_INTERFACE;
  444. Filter.TunnelFilter.SrcAddr.uIpAddr = IP_ADDRESS_ME;
  445. Filter.TunnelFilter.SrcAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
  446. Filter.TunnelFilter.SrcPort.PortType = PORT_UNIQUE;
  447. Filter.TunnelFilter.SrcPort.wPort = Port;
  448. Filter.TunnelFilter.SrcAddr.gInterfaceID = gInterfaceId;
  449. }
  450. }
  451. }
  452. }
  453. }
  454. else
  455. dwReturn = T2P_NULL_STRING;
  456. return dwReturn;
  457. }
  458. DWORD TextToProtocol(IN char *szProt, OUT DWORD & dwProtocol)
  459. {
  460. DWORD dwReturn = T2P_OK;
  461. if (szProt != NULL)
  462. {
  463. // is it special string
  464. if (isalpha(szProt[0]))
  465. {
  466. if (_stricmp(szProt, POTF_TCP_STR) == 0)
  467. dwProtocol = (POTF_TCP_PROTNUM);
  468. else if (_stricmp(szProt, POTF_UDP_STR) == 0)
  469. dwProtocol = (POTF_UDP_PROTNUM);
  470. else if (_stricmp(szProt, POTF_ICMP_STR) == 0)
  471. dwProtocol = (POTF_ICMP_PROTNUM);
  472. else if (_stricmp(szProt, POTF_RAW_STR) == 0)
  473. dwProtocol = (POTF_RAW_PROTNUM);
  474. else
  475. {
  476. dwReturn = T2P_INVALID_PROTOCOL;
  477. }
  478. }
  479. else
  480. {
  481. dwProtocol = ((DWORD)atol(szProt));
  482. }
  483. }
  484. return dwReturn;
  485. }
  486. DWORD TextToOffer(IN char *szText, IN OUT IPSEC_QM_OFFER & Offer)
  487. {
  488. DWORD dwReturn = T2P_OK;
  489. char szTmp[POTF_MAX_STRLEN];
  490. char *pAnd = NULL,
  491. *pOptions = NULL,
  492. *pString = NULL;
  493. if (szText != NULL)
  494. {
  495. // we will for sure overwrite the Count and Algos
  496. // since they are required for valid conversion
  497. Offer.dwNumAlgos = 0;
  498. Offer.dwPFSGroup = 0;
  499. // copy szText so we can muck it up
  500. strcpy(szTmp, szText);
  501. // process Rekey and PFS first
  502. pOptions = strrchr(szTmp, POTF_NEGPOL_CLOSE);
  503. if ((pOptions != NULL) && *(pOptions + 1) != '\0')
  504. {
  505. ++pOptions; // we have options
  506. pString = strchr(pOptions, POTF_NEGPOL_PFS);
  507. if (pString != NULL)
  508. {
  509. char *pStr;
  510. Offer.bPFSRequired = TRUE;
  511. Offer.dwPFSGroup = PFS_GROUP_MM;
  512. pStr = strchr(pString, '1');
  513. if (pStr)
  514. {
  515. Offer.dwPFSGroup = PFS_GROUP_1;
  516. }
  517. pStr = strchr(pString, '2');
  518. if (pStr)
  519. {
  520. Offer.dwPFSGroup = PFS_GROUP_2;
  521. }
  522. *pString = '\0';
  523. }
  524. if (pString != pOptions) // user could have specified just PFS
  525. {
  526. // process key lifetime
  527. // two params specified?
  528. pString = strchr(pOptions, POTF_REKEY_TOKEN);
  529. if (pString != NULL)
  530. {
  531. *pString = '\0';
  532. ++pString;
  533. switch (pString[strlen(pString) - 1])
  534. {
  535. case 'k':
  536. case 'K':
  537. pString[strlen(pString) - 1] = '\0';
  538. Offer.Lifetime.uKeyExpirationKBytes = atol(pString);
  539. if ( Offer.Lifetime.uKeyExpirationKBytes < POTF_MIN_P2LIFE_BYTES )
  540. {
  541. dwReturn = T2P_P2REKEY_TOO_LOW;
  542. }
  543. break;
  544. case 's':
  545. case 'S':
  546. pString[strlen(pString) - 1] = '\0';
  547. Offer.Lifetime.uKeyExpirationTime = atol(pString);
  548. if ( Offer.Lifetime.uKeyExpirationTime < POTF_MIN_P2LIFE_TIME )
  549. {
  550. dwReturn = T2P_P2REKEY_TOO_LOW;
  551. }
  552. break;
  553. default:
  554. dwReturn = T2P_INVALID_P2REKEY_UNIT;
  555. break;
  556. }
  557. }
  558. switch (pOptions[strlen(pOptions) - 1])
  559. {
  560. case 'k':
  561. case 'K':
  562. pOptions[strlen(pOptions) - 1] = '\0';
  563. Offer.Lifetime.uKeyExpirationKBytes = atol(pOptions);
  564. if ( Offer.Lifetime.uKeyExpirationKBytes < POTF_MIN_P2LIFE_BYTES )
  565. {
  566. dwReturn = T2P_P2REKEY_TOO_LOW;
  567. }
  568. break;
  569. case 's':
  570. case 'S':
  571. pOptions[strlen(pOptions) - 1] = '\0';
  572. Offer.Lifetime.uKeyExpirationTime = atol(pOptions);
  573. if ( Offer.Lifetime.uKeyExpirationTime < POTF_MIN_P2LIFE_TIME )
  574. {
  575. dwReturn = T2P_P2REKEY_TOO_LOW;
  576. }
  577. break;
  578. default:
  579. dwReturn = T2P_INVALID_P2REKEY_UNIT;
  580. break;
  581. }
  582. }
  583. // important: we have to do this here so the alginfo
  584. // gets processed ok:
  585. *pOptions = '\0';
  586. }
  587. if ( T2P_SUCCESS(dwReturn) )
  588. {
  589. // now process the ipsec protocol spec AH, ESP
  590. pAnd = strchr(szTmp, POTF_NEGPOL_AND);
  591. if ( pAnd != NULL )
  592. {
  593. // we have an AND proposal
  594. *pAnd = '\0';
  595. ++pAnd;
  596. dwReturn = TextToAlgoInfo(szTmp, Offer.Algos[Offer.dwNumAlgos]);
  597. ++Offer.dwNumAlgos;
  598. if ( T2P_SUCCESS(dwReturn) )
  599. {
  600. dwReturn = TextToAlgoInfo(pAnd, Offer.Algos[Offer.dwNumAlgos]);
  601. ++Offer.dwNumAlgos;
  602. }
  603. }
  604. else
  605. {
  606. dwReturn = TextToAlgoInfo(szTmp, Offer.Algos[Offer.dwNumAlgos]);
  607. ++Offer.dwNumAlgos;
  608. }
  609. }
  610. }
  611. else
  612. dwReturn = T2P_NULL_STRING;
  613. return dwReturn;
  614. }
  615. DWORD TextToAlgoInfo(IN char *szText, OUT IPSEC_QM_ALGO & algoInfo)
  616. {
  617. DWORD dwReturn = T2P_OK;
  618. char szTmp[POTF_MAX_STRLEN];
  619. char *pOpen = NULL,
  620. *pClose = NULL,
  621. *pString = NULL;
  622. // these are used for processing AND to default to NONE
  623. bool bEncryption = false, bAuthentication= false;
  624. if (szText == NULL)
  625. return T2P_NULL_STRING;
  626. // muck with the string so we can copy it ;)
  627. strcpy(szTmp, szText);
  628. algoInfo.uAlgoKeyLen = algoInfo.uAlgoRounds = 0;
  629. pOpen = strchr(szTmp, POTF_NEGPOL_OPEN);
  630. pClose = strrchr(szTmp, POTF_NEGPOL_CLOSE);
  631. if ((pOpen != NULL) && (pClose != NULL) && (*(pClose + 1) == '\0')) // defense
  632. {
  633. *pOpen = '\0';
  634. *pClose = '\0';
  635. ++pOpen;
  636. if (_stricmp(szTmp, POTF_NEGPOL_AH) == 0)
  637. {
  638. if (_stricmp(pOpen, POTF_NEGPOL_MD5) == 0)
  639. algoInfo.uAlgoIdentifier = IPSEC_DOI_AH_MD5;
  640. else if (_stricmp(pOpen, POTF_NEGPOL_SHA) == 0 || _stricmp(pOpen, POTF_NEGPOL_SHA1) == 0)
  641. algoInfo.uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
  642. else
  643. {
  644. dwReturn = T2P_INVALID_HASH_ALG;
  645. }
  646. algoInfo.Operation = AUTHENTICATION;
  647. }
  648. else if (_stricmp(szTmp, POTF_NEGPOL_ESP) == 0)
  649. {
  650. algoInfo.Operation = ENCRYPTION;
  651. pString = strchr(pOpen, POTF_ESPTRANS_TOKEN);
  652. if (pString != NULL)
  653. {
  654. *pString = '\0';
  655. ++pString;
  656. // we allow the hash and encryption to be specified in either
  657. // the first or second field-- hence the long conditionals
  658. if (_stricmp(pOpen, POTF_NEGPOL_DES) == 0)
  659. {
  660. bEncryption = true;
  661. algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
  662. }
  663. else if (_stricmp(pOpen, POTF_NEGPOL_3DES) == 0)
  664. {
  665. bEncryption = true;
  666. algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
  667. }
  668. else if (_stricmp(pOpen, POTF_NEGPOL_MD5) == 0)
  669. {
  670. bAuthentication = true;
  671. algoInfo.uSecAlgoIdentifier = HMAC_AH_MD5;
  672. }
  673. else if (_stricmp(pOpen, POTF_NEGPOL_SHA) == 0 || _stricmp(pOpen, POTF_NEGPOL_SHA1) == 0)
  674. {
  675. bAuthentication = true;
  676. algoInfo.uSecAlgoIdentifier = HMAC_AH_SHA1;
  677. }
  678. else if (_stricmp(pOpen, POTF_NEGPOL_NONE) != 0) // parse error
  679. {
  680. dwReturn = T2P_GENERAL_PARSE_ERROR;
  681. }
  682. // now the second one
  683. if (_stricmp(pString, POTF_NEGPOL_DES) == 0 && !bEncryption)
  684. {
  685. bEncryption = true;
  686. algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
  687. }
  688. else if (_stricmp(pString, POTF_NEGPOL_3DES) == 0 && !bEncryption)
  689. {
  690. bEncryption = true;
  691. algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
  692. }
  693. else if (_stricmp(pString, POTF_NEGPOL_MD5) == 0 && !bAuthentication)
  694. {
  695. bAuthentication = true;
  696. algoInfo.uSecAlgoIdentifier = HMAC_AH_MD5;
  697. }
  698. else if ((_stricmp(pString, POTF_NEGPOL_SHA) == 0 || _stricmp(pString, POTF_NEGPOL_SHA1) == 0) && !bAuthentication)
  699. {
  700. bAuthentication = true;
  701. algoInfo.uSecAlgoIdentifier = HMAC_AH_SHA1;
  702. }
  703. else if (_stricmp(pString, POTF_NEGPOL_NONE) != 0) // parse error
  704. {
  705. dwReturn = T2P_DUP_ALGS;
  706. }
  707. // now, fill in the NONE policies or detect NONE, NONE
  708. if (!bAuthentication && !bEncryption)
  709. {
  710. dwReturn = T2P_NONE_NONE;
  711. }
  712. else if (!bAuthentication)
  713. {
  714. algoInfo.uSecAlgoIdentifier = HMAC_AH_NONE;
  715. }
  716. else if (!bEncryption)
  717. {
  718. algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_NONE;
  719. }
  720. }
  721. else // error
  722. {
  723. dwReturn = T2P_INCOMPLETE_ESPALGS;
  724. }
  725. }
  726. else
  727. {
  728. dwReturn = T2P_INVALID_IPSECPROT;
  729. }
  730. }
  731. else // error
  732. {
  733. dwReturn = T2P_GENERAL_PARSE_ERROR;
  734. }
  735. return dwReturn;
  736. }
  737. DWORD TextToOakleyAuth(IN char *szText, OUT IPSEC_MM_AUTH_INFO & AuthInfo)
  738. {
  739. DWORD dwReturn = T2P_OK;
  740. char *pString = NULL,
  741. *pTmp = NULL;
  742. char *szTmp = NULL;
  743. char *Info = NULL;
  744. if (szText != NULL)
  745. {
  746. // copy szText so we can muck with it
  747. szTmp = new char[strlen(szText)+1];
  748. assert(szTmp != 0);
  749. strcpy(szTmp, szText);
  750. // parse string
  751. if ( (pString = strchr(szTmp, POTF_OAKAUTH_TOKEN)) != NULL )
  752. *pString = '\0';
  753. // not UNICODE compliant
  754. if (tolower(szTmp[0]) == tolower(POTF_OAKAUTH_PRESHARE[0]))
  755. {
  756. if ((pString != NULL) && (strlen(pString + 1) > 0) )
  757. {
  758. ++pString; // now pointing at string
  759. AuthInfo.AuthMethod = IKE_PRESHARED_KEY;
  760. if (*pString == '"') // fix up if the user included quotes
  761. {
  762. ++pString;
  763. pTmp = strrchr(pString, '"');
  764. if (pTmp != NULL)
  765. {
  766. *pTmp = '\0';
  767. }
  768. }
  769. // convert to wide and fill in
  770. Info = new char[strlen(pString) + 1];
  771. assert(Info != NULL);
  772. strcpy(Info, pString);
  773. }
  774. else // no key provided
  775. {
  776. dwReturn = T2P_NO_PRESHARED_KEY;
  777. }
  778. }
  779. else if (tolower(szTmp[0]) == tolower(POTF_OAKAUTH_KERBEROS[0]))
  780. {
  781. AuthInfo.AuthMethod = IKE_SSPI;
  782. }
  783. else if (tolower(szTmp[0]) == tolower(POTF_OAKAUTH_CERT[0]))
  784. {
  785. AuthInfo.AuthMethod = IKE_RSA_SIGNATURE;
  786. if ((pString != NULL) && (strlen(pString + 1) > 0) )
  787. {
  788. // CA is indicated
  789. ++pString; // now pointing at string
  790. Info = new char[strlen(pString) + 1];
  791. assert(Info != NULL);
  792. if (*pString == '"') // fix up if the user included quotes
  793. {
  794. ++pString;
  795. pTmp = strrchr(pString, '"');
  796. if (pTmp != NULL)
  797. {
  798. *pTmp = '\0';
  799. }
  800. }
  801. strcpy(Info, pString);
  802. }
  803. // else the CA will be negotiated
  804. }
  805. else // invalid option
  806. {
  807. dwReturn = T2P_INVALID_AUTH_METHOD;
  808. }
  809. // now convert the ascii to wide char
  810. // authinfo needs to be wide
  811. if (Info != NULL && T2P_SUCCESS(dwReturn))
  812. {
  813. AuthInfo.pAuthInfo = NULL;
  814. AuthInfo.dwAuthInfoSize = 0;
  815. AuthInfo.dwAuthInfoSize = MultiByteToWideChar(CP_THREAD_ACP, 0, Info, -1,
  816. (WCHAR *) AuthInfo.pAuthInfo, 0);
  817. if (AuthInfo.dwAuthInfoSize == 0) // failure
  818. {
  819. dwReturn = T2P_MB2WC_FAILED;
  820. }
  821. else
  822. {
  823. AuthInfo.pAuthInfo = (LPBYTE) new WCHAR[AuthInfo.dwAuthInfoSize];
  824. assert(AuthInfo.pAuthInfo != NULL);
  825. AuthInfo.dwAuthInfoSize = MultiByteToWideChar(CP_THREAD_ACP, 0, Info, -1,
  826. (WCHAR *) AuthInfo.pAuthInfo, AuthInfo.dwAuthInfoSize);
  827. AuthInfo.dwAuthInfoSize--;
  828. AuthInfo.dwAuthInfoSize *= sizeof(WCHAR);
  829. }
  830. if (AuthInfo.dwAuthInfoSize == 0) // failure
  831. {
  832. delete [] AuthInfo.pAuthInfo;
  833. dwReturn = T2P_MB2WC_FAILED;
  834. }
  835. // now do additional conversion if this is cert
  836. if (T2P_SUCCESS(dwReturn) && AuthInfo.AuthMethod == IKE_RSA_SIGNATURE)
  837. {
  838. LPBYTE asnCert;
  839. dwReturn = CM_EncodeName((LPWSTR) AuthInfo.pAuthInfo, &asnCert, &AuthInfo.dwAuthInfoSize);
  840. delete [] AuthInfo.pAuthInfo;
  841. if (dwReturn != ERROR_SUCCESS)
  842. {
  843. dwReturn = T2P_INVALID_AUTH_METHOD;
  844. }
  845. else
  846. {
  847. AuthInfo.pAuthInfo = asnCert;
  848. dwReturn = T2P_OK;
  849. }
  850. }
  851. }
  852. }
  853. else
  854. dwReturn = T2P_NULL_STRING;
  855. if (Info) delete Info;
  856. if (szTmp) delete szTmp;
  857. return dwReturn;
  858. }
  859. DWORD TextToSecMethod(IN char *szText, IN OUT IPSEC_MM_OFFER & SecMethod)
  860. {
  861. DWORD dwReturn = T2P_OK;
  862. char szTmp[POTF_MAX_STRLEN];
  863. char *pString1 = NULL,
  864. *pString2 = NULL;
  865. bool bEncryption = false,
  866. bAuthentication = false;
  867. if (szText == NULL)
  868. return T2P_NULL_STRING;
  869. // copy szText so we can muck it up
  870. strcpy(szTmp, szText);
  871. pString1 = strchr(szTmp, POTF_P1_TOKEN);
  872. pString2 = strrchr(szTmp, POTF_P1_TOKEN);
  873. if ((pString1 != NULL) && (pString2 != NULL) && (pString1 != pString2))
  874. {
  875. // string parsed ok so far
  876. *pString1 = '\0';
  877. *pString2 = '\0';
  878. ++pString1;
  879. ++pString2;
  880. // we allow the hash and encryption to be specified in either
  881. // the first or second field-- hence the long conditionals
  882. if (_stricmp(szTmp, POTF_P1_DES) == 0)
  883. {
  884. bEncryption = true;
  885. SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
  886. SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
  887. }
  888. else if (_stricmp(szTmp, POTF_P1_3DES) == 0)
  889. {
  890. bEncryption = true;
  891. SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
  892. SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
  893. }
  894. else if (_stricmp(szTmp, POTF_P1_MD5) == 0)
  895. {
  896. bAuthentication = true;
  897. SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_MD5;
  898. SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
  899. }
  900. else if (_stricmp(szTmp, POTF_P1_SHA) == 0)
  901. {
  902. bAuthentication = true;
  903. SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
  904. SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
  905. }
  906. else // parse error
  907. {
  908. dwReturn = T2P_GENERAL_PARSE_ERROR;
  909. }
  910. if (_stricmp(pString1, POTF_P1_DES) == 0 && !bEncryption)
  911. {
  912. bEncryption = true;
  913. SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
  914. SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
  915. }
  916. else if (_stricmp(pString1, POTF_P1_3DES) == 0 && !bEncryption)
  917. {
  918. bEncryption = true;
  919. SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
  920. SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
  921. }
  922. else if (_stricmp(pString1, POTF_P1_MD5) == 0 && !bAuthentication)
  923. {
  924. bAuthentication = true;
  925. SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_MD5;
  926. SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
  927. }
  928. else if (_stricmp(pString1, POTF_P1_SHA) == 0 && !bAuthentication)
  929. {
  930. bAuthentication = true;
  931. SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
  932. SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
  933. }
  934. else // parse error
  935. {
  936. dwReturn = T2P_DUP_ALGS;
  937. }
  938. // now for the group
  939. if (isdigit(pString2[0]))
  940. {
  941. switch (pString2[0])
  942. {
  943. case '1':
  944. SecMethod.dwDHGroup = POTF_OAKLEY_GROUP1;
  945. break;
  946. case '2':
  947. SecMethod.dwDHGroup = POTF_OAKLEY_GROUP2;
  948. break;
  949. default:
  950. dwReturn = T2P_INVALID_P1GROUP;
  951. break;
  952. }
  953. }
  954. else
  955. {
  956. dwReturn = T2P_P1GROUP_MISSING;
  957. }
  958. }
  959. else // parse error
  960. {
  961. dwReturn = T2P_GENERAL_PARSE_ERROR;
  962. }
  963. return dwReturn;
  964. }
  965. DWORD TextToP1Rekey(IN char *szText, IN OUT KEY_LIFETIME & LifeTime, OUT DWORD & QMLim)
  966. {
  967. DWORD dwReturn = T2P_OK;
  968. char szTmp[POTF_MAX_STRLEN];
  969. char *pString = NULL;
  970. if (!szText)
  971. return T2P_NULL_STRING;
  972. // copy szText so we can muck it up
  973. strcpy(szTmp, szText);
  974. // two params specified?
  975. pString = strchr(szTmp, POTF_QM_TOKEN);
  976. if (pString != NULL)
  977. {
  978. *pString = '\0';
  979. ++pString;
  980. switch (pString[strlen(pString) - 1])
  981. {
  982. case 'q':
  983. case 'Q':
  984. pString[strlen(pString) - 1] = '\0';
  985. QMLim = atol(pString);
  986. break;
  987. case 's':
  988. case 'S':
  989. pString[strlen(pString) - 1] = '\0';
  990. LifeTime.uKeyExpirationTime = atol(pString);
  991. break;
  992. default:
  993. dwReturn = T2P_INVALID_P1REKEY_UNIT;
  994. break;
  995. }
  996. }
  997. switch (szTmp[strlen(szTmp) - 1])
  998. {
  999. case 'q':
  1000. case 'Q':
  1001. szTmp[strlen(szTmp) - 1] = '\0';
  1002. QMLim = atol(szTmp);
  1003. break;
  1004. case 's':
  1005. case 'S':
  1006. szTmp[strlen(szTmp) - 1] = '\0';
  1007. LifeTime.uKeyExpirationTime = atol(szTmp);
  1008. break;
  1009. default:
  1010. dwReturn = T2P_INVALID_P1REKEY_UNIT;
  1011. break;
  1012. }
  1013. return dwReturn;
  1014. }
  1015. // caveat, won't go deep into DNS
  1016. DWORD TextToIPAddr(IN char *szText, IN OUT IPAddr & Address)
  1017. {
  1018. DWORD dwReturn = T2P_OK;
  1019. struct hostent *pHostEnt;
  1020. if (szText != NULL)
  1021. {
  1022. if (!strcmp(szText, POTF_ME_TUNNEL))
  1023. {
  1024. Address = 0;
  1025. }
  1026. else if (isdnsname(szText)) // DNS name
  1027. {
  1028. pHostEnt = gethostbyname(szText);
  1029. if (pHostEnt != NULL)
  1030. {
  1031. Address = *(IPAddr *)pHostEnt->h_addr;
  1032. // should check for more here, but not now
  1033. }
  1034. else
  1035. {
  1036. dwReturn = T2P_DNSLOOKUP_FAILED;
  1037. }
  1038. }
  1039. else // good old dotted notation
  1040. {
  1041. Address = inet_addr(szText);
  1042. if (Address == INADDR_NONE)
  1043. {
  1044. dwReturn = T2P_INVALID_ADDR;
  1045. }
  1046. }
  1047. }
  1048. else
  1049. {
  1050. dwReturn = T2P_NULL_STRING;
  1051. }
  1052. return dwReturn;
  1053. }
  1054. // if szSrc and/or szDst are passed in,
  1055. // caller must provide adequate space
  1056. DWORD TextToMMFilter(IN char *szText, IN OUT MM_FILTER &Filter, char *szSrc, char *szDst)
  1057. {
  1058. DWORD dwReturn = T2P_OK; // return code of this function
  1059. char *pToken = NULL, *pTmp = NULL;
  1060. char szTmp[POTF_MAX_STRLEN];
  1061. char *pPortTok = NULL,
  1062. *pProtTok = NULL;
  1063. BOOL bMirror = false;
  1064. T2P_FILTER t2pFilter; // for TextToFilterAddr calls
  1065. if (szText != NULL) // do not assume that caller is smart
  1066. {
  1067. // We copy szText to szTmp so we can muck with it
  1068. // in the process, we
  1069. // determine passthru or drop filter
  1070. // but first we set this filter to negotiate security and to be not mirrored
  1071. // we also set protocol field
  1072. Filter.bCreateMirror = FALSE;
  1073. // set up T2P_FILTER
  1074. t2pFilter.QMFilterType = QM_TRANSPORT_FILTER;
  1075. memset(&t2pFilter.TransportFilter, 0, sizeof(TRANSPORT_FILTER));
  1076. pToken = strchr(szText, POTF_PASSTHRU_OPEN_TOKEN);
  1077. if (pToken != NULL)
  1078. {
  1079. dwReturn = T2P_GENERAL_PARSE_ERROR;
  1080. }
  1081. else if ( (pToken = strchr(szText, POTF_DROP_OPEN_TOKEN)) != NULL )
  1082. {
  1083. dwReturn = T2P_GENERAL_PARSE_ERROR;
  1084. }
  1085. else
  1086. strcpy(szTmp, szText);
  1087. // parse into source and dest strings
  1088. for (pToken = szText; *pToken != POTF_FILTER_TOKEN &&
  1089. *pToken != POTF_FILTER_MIRTOKEN &&
  1090. *pToken != '\0'; ++pToken)
  1091. ;
  1092. if (*pToken == '\0')
  1093. {
  1094. dwReturn = T2P_NOSRCDEST_TOKEN;
  1095. }
  1096. else if ( *(pToken + 1) == '\0' )
  1097. {
  1098. dwReturn = T2P_NO_DESTADDR;
  1099. }
  1100. else if (T2P_SUCCESS(dwReturn))
  1101. {
  1102. if (*pToken == POTF_FILTER_MIRTOKEN)
  1103. {
  1104. bMirror = TRUE;
  1105. // set Mirrored = true
  1106. Filter.bCreateMirror = TRUE;
  1107. }
  1108. if (!bMirror)
  1109. pToken = strchr(szTmp, POTF_FILTER_TOKEN);
  1110. else
  1111. pToken = strchr(szTmp, POTF_FILTER_MIRTOKEN);
  1112. *pToken = '\0';
  1113. // check for port presence
  1114. pPortTok = strchr(szTmp, POTF_PT_TOKEN);
  1115. if (pPortTok != NULL)
  1116. {
  1117. dwReturn = T2P_GENERAL_PARSE_ERROR;
  1118. }
  1119. else
  1120. {
  1121. // do the src address
  1122. dwReturn = TextToFiltAddr(szTmp, t2pFilter, szSrc);
  1123. // copy src address
  1124. Filter.SrcAddr = t2pFilter.TransportFilter.SrcAddr;
  1125. }
  1126. if (T2P_SUCCESS(dwReturn))
  1127. {
  1128. // do the dest address
  1129. pPortTok = strchr(pToken + 1, POTF_PT_TOKEN);
  1130. if (pPortTok == NULL) // no port/prot specified
  1131. {
  1132. dwReturn = TextToFiltAddr(pToken + 1, t2pFilter, szDst, true);
  1133. // copy dest address
  1134. Filter.DesAddr = t2pFilter.TransportFilter.DesAddr;
  1135. }
  1136. else
  1137. {
  1138. // error
  1139. dwReturn = T2P_GENERAL_PARSE_ERROR;
  1140. }
  1141. }
  1142. // we're done, do any fixing up of Filter
  1143. if (T2P_SUCCESS(dwReturn))
  1144. {
  1145. // set the GUID
  1146. RPC_STATUS RpcStat = UuidCreate(&Filter.gFilterID);
  1147. if (RpcStat != RPC_S_OK && RpcStat != RPC_S_UUID_LOCAL_ONLY)
  1148. {
  1149. dwReturn = RpcStat;
  1150. }
  1151. // set the name to be equal to the "text2pol " + GUID
  1152. if (T2P_SUCCESS(dwReturn))
  1153. {
  1154. WCHAR StringTxt[POTF_MAX_STRLEN];
  1155. int iReturn;
  1156. wcscpy(StringTxt, L"text2pol ");
  1157. iReturn = StringFromGUID2(Filter.gFilterID, StringTxt+wcslen(StringTxt), POTF_MAX_STRLEN-wcslen(StringTxt));
  1158. assert(iReturn != 0);
  1159. Filter.pszFilterName = new WCHAR[wcslen(StringTxt)+1];
  1160. assert(Filter.pszFilterName != NULL);
  1161. wcscpy(Filter.pszFilterName, StringTxt);
  1162. }
  1163. }
  1164. }
  1165. }
  1166. else // szText is NULL
  1167. dwReturn = T2P_NULL_STRING;
  1168. return dwReturn;
  1169. }
  1170.