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.

2214 lines
54 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // IP Security Policy/Association management tool.
  14. //
  15. #include <winsock2.h>
  16. #include <ws2tcpip.h>
  17. #include <ws2ip6.h>
  18. #include <ntddip6.h>
  19. #include <ip6.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. //
  23. // Localization library and MessageIds.
  24. //
  25. #include <nls.h>
  26. #include "localmsg.h"
  27. #include "ipsec.h"
  28. #define MAX_KEY_SIZE 1024
  29. typedef struct ipv6_create_sa_and_key {
  30. IPV6_CREATE_SECURITY_ASSOCIATION SA;
  31. unsigned char Key[MAX_KEY_SIZE];
  32. } IPV6_CREATE_SA_AND_KEY;
  33. void CreateSecurityPolicyFile(char *BaseName);
  34. void CreateSecurityAssociationFile(char *BaseName);
  35. void DisplaySecurityPolicyList(unsigned int Interface);
  36. void DisplaySecurityAssociationList(void);
  37. void ReadConfigurationFile(char *BaseName, int Type);
  38. void DeleteSecurityEntry(int Type, unsigned int Index);
  39. int AdminAccess = TRUE;
  40. HANDLE V6Stack;
  41. IPv6Addr UnspecifiedAddr = { 0 };
  42. //
  43. // Entry types.
  44. //
  45. #define POLICY 1
  46. #define ASSOCIATION 0
  47. //
  48. // Amount of "____" space.
  49. //
  50. #define SA_FILE_BORDER 251 // orig 236
  51. #define SP_FILE_BORDER 273 // was 263, orig 258
  52. //
  53. // Transport Protocols
  54. //
  55. #define IP_PROTOCOL_TCP 6
  56. #define IP_PROTOCOL_UDP 17
  57. #define IP_PROTOCOL_ICMPv6 58
  58. PWCHAR
  59. GetString(int ErrorCode, BOOL System)
  60. {
  61. DWORD Count;
  62. static WCHAR ErrorString[2048]; // a 2K static buffer should suffice
  63. Count = FormatMessageW(
  64. (System
  65. ? FORMAT_MESSAGE_FROM_SYSTEM
  66. : FORMAT_MESSAGE_FROM_HMODULE) |
  67. FORMAT_MESSAGE_IGNORE_INSERTS |
  68. FORMAT_MESSAGE_MAX_WIDTH_MASK,
  69. 0,
  70. ErrorCode,
  71. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  72. ErrorString,
  73. 2048,
  74. NULL);
  75. if (Count == 0) { // failure
  76. return L""; // return a null string
  77. }
  78. return ErrorString; // success
  79. }
  80. #define GetErrorString(ErrorCode) GetString(ErrorCode, TRUE)
  81. void
  82. usage(void)
  83. {
  84. NlsPutMsg(STDOUT, IPSEC_MESSAGE_0);
  85. // printf("\nManipulates IPv6 IPSec security policies and associations.\n\n");
  86. // printf("IPSEC6 [SP [interface] | SA | [L | S] database | "
  87. // "D [SP | SA] index]\n\n");
  88. // printf(" SP [interface] Displays the security policies.\n");
  89. // printf(" SA Displays the security associations.\n");
  90. // printf(" L database Loads the SP and SA entries from the given "
  91. // "database files;\n"
  92. // " database should be the filename without an "
  93. // "extension.\n");
  94. // printf(" S database Saves the current SP and SA entries to the "
  95. // "given database\n"
  96. // " files; database should be the filename "
  97. // "sans extension.\n");
  98. // printf(" D [SP | SA] index Deletes the given policy or association.\n");
  99. // printf("\nSome subcommands require local Administrator privileges.\n");
  100. exit(1);
  101. }
  102. void
  103. ausage(void)
  104. {
  105. NlsPutMsg(STDOUT, IPSEC_MESSAGE_1);
  106. // printf("You do not have local Administrator privileges.\n");
  107. exit(1);
  108. }
  109. void
  110. MakeLowerCase(char *String)
  111. {
  112. while(*String != '\0')
  113. *String++ = (char)tolower(*String);
  114. }
  115. int __cdecl
  116. main(int argc, char **argv)
  117. {
  118. int Error;
  119. WSADATA WsaData;
  120. Error = WSAStartup(MAKEWORD(2, 0), &WsaData);
  121. if (Error) {
  122. NlsPutMsg(STDOUT, IPSEC_MESSAGE_2, Error);
  123. // printf("Unable to initialize Windows Sockets, error code %d.\n", Error);
  124. exit(1);
  125. }
  126. //
  127. // First request write access.
  128. // This will fail if the process does not have local Administrator privs.
  129. //
  130. V6Stack = CreateFileW(WIN_IPV6_DEVICE_NAME,
  131. GENERIC_WRITE,
  132. FILE_SHARE_READ | FILE_SHARE_WRITE,
  133. NULL, // security attributes
  134. OPEN_EXISTING,
  135. 0, // flags & attributes
  136. NULL); // template file
  137. if (V6Stack == INVALID_HANDLE_VALUE) {
  138. //
  139. // We will not have Administrator access to the stack.
  140. //
  141. AdminAccess = FALSE;
  142. V6Stack = CreateFileW(WIN_IPV6_DEVICE_NAME,
  143. 0,
  144. FILE_SHARE_READ | FILE_SHARE_WRITE,
  145. NULL, // security attributes
  146. OPEN_EXISTING,
  147. 0, // flags & attributes
  148. NULL); // template file
  149. if (V6Stack == INVALID_HANDLE_VALUE) {
  150. NlsPutMsg(STDOUT, IPSEC_MESSAGE_3);
  151. // printf("Could not access IPv6 protocol stack.\n");
  152. exit(1);
  153. }
  154. }
  155. if (argc < 2) {
  156. usage();
  157. }
  158. MakeLowerCase(argv[1]);
  159. if (!strcmp(argv[1], "sp")) {
  160. unsigned int Interface;
  161. if (argc == 2) {
  162. Interface = 0;
  163. } else {
  164. Interface = atoi(argv[2]);
  165. }
  166. DisplaySecurityPolicyList(Interface);
  167. } else if (!strcmp(argv[1], "sa")) {
  168. DisplaySecurityAssociationList();
  169. } else if (!strcmp(argv[1], "s")) {
  170. if (argc != 3) {
  171. usage();
  172. }
  173. CreateSecurityPolicyFile(argv[2]);
  174. CreateSecurityAssociationFile(argv[2]);
  175. } else if (!strcmp(argv[1], "l")) {
  176. if (!AdminAccess)
  177. ausage();
  178. if (argc != 3) {
  179. usage();
  180. }
  181. ReadConfigurationFile(argv[2], POLICY);
  182. ReadConfigurationFile(argv[2], ASSOCIATION);
  183. } else if (!strcmp(argv[1], "d")) {
  184. unsigned int Index;
  185. int Type;
  186. if (!AdminAccess)
  187. ausage();
  188. if (argc != 4) {
  189. usage();
  190. }
  191. MakeLowerCase(argv[3]);
  192. if (!strcmp(argv[3], "all")) {
  193. Index = 0;
  194. } else {
  195. Index = atol(argv[3]);
  196. if (Index <= 0) {
  197. NlsPutMsg(STDOUT, IPSEC_MESSAGE_4);
  198. // printf("Invalid entry number.\n");
  199. exit(1);
  200. }
  201. }
  202. MakeLowerCase(argv[2]);
  203. if (!strcmp(argv[2], "sp")) {
  204. Type = POLICY;
  205. } else if (!strcmp(argv[2], "sa")) {
  206. Type = ASSOCIATION;
  207. } else {
  208. usage();
  209. }
  210. DeleteSecurityEntry(Type, Index);
  211. } else {
  212. usage();
  213. }
  214. return(0);
  215. }
  216. //* GetSecurityPolicyEntry
  217. //
  218. // Retrieves a Security Policy from the in-kernel list, given its index.
  219. // A query for index zero will return the first index on the list.
  220. //
  221. DWORD // Returns: Windows error code.
  222. GetSecurityPolicyEntry(
  223. unsigned int Interface, // IF index or 0 to wildcard.
  224. unsigned long Index, // Index to lookup, or 0 for first.
  225. IPV6_INFO_SECURITY_POLICY_LIST *Info) // Where to return SP info.
  226. {
  227. IPV6_QUERY_SECURITY_POLICY_LIST Query;
  228. unsigned int BytesReturned;
  229. Query.SPInterface = Interface;
  230. Query.Index = Index;
  231. if (!DeviceIoControl(V6Stack, IOCTL_IPV6_QUERY_SECURITY_POLICY_LIST,
  232. &Query, sizeof(Query), Info, sizeof(*Info),
  233. &BytesReturned, NULL)) {
  234. return GetLastError();
  235. }
  236. if (BytesReturned != sizeof(*Info))
  237. return ERROR_GEN_FAILURE;
  238. return ERROR_SUCCESS;
  239. }
  240. //* CreateSecurityPolicyEntry
  241. //
  242. // Creates a Security Policy entry on the in-kernel list.
  243. //
  244. DWORD // Returns Windows error code.
  245. CreateSecurityPolicyEntry(
  246. IPV6_CREATE_SECURITY_POLICY *NewSP) // Policy to add to kernel.
  247. {
  248. unsigned int BytesReturned;
  249. if (!DeviceIoControl(V6Stack, IOCTL_IPV6_CREATE_SECURITY_POLICY,
  250. NewSP, sizeof(*NewSP), NULL, 0,
  251. &BytesReturned, NULL)) {
  252. return GetLastError();
  253. }
  254. //
  255. // When DeviceIoControl is given a null output buffer, the value returned
  256. // in BytesReturned is undefined. Therefore, we don't check for 0 here.
  257. //
  258. return ERROR_SUCCESS;
  259. }
  260. DWORD
  261. DeleteSecurityPolicyEntry(unsigned int Index)
  262. {
  263. IPV6_QUERY_SECURITY_POLICY_LIST Query;
  264. unsigned long BytesReturned;
  265. Query.Index = Index;
  266. if (!DeviceIoControl(V6Stack, IOCTL_IPV6_DELETE_SECURITY_POLICY,
  267. &Query, sizeof(Query), NULL, 0,
  268. &BytesReturned, NULL)) {
  269. return GetLastError();
  270. }
  271. //
  272. // When DeviceIoControl is given a null output buffer, the value returned
  273. // in BytesReturned is undefined. Therefore, we don't check for 0 here.
  274. //
  275. return ERROR_SUCCESS;
  276. }
  277. //* GetSecurityAssociationEntry
  278. //
  279. // Retrieves a Security Association from the in-kernel list, given its index.
  280. // A query for index zero will return the first index on the list.
  281. //
  282. DWORD
  283. GetSecurityAssociationEntry(
  284. unsigned long Index, // Index to query; 0 for first.
  285. IPV6_INFO_SECURITY_ASSOCIATION_LIST *Info) // Where to return SA info.
  286. {
  287. IPV6_QUERY_SECURITY_ASSOCIATION_LIST Query;
  288. unsigned int BytesReturned;
  289. Query.Index = Index;
  290. if (!DeviceIoControl(V6Stack, IOCTL_IPV6_QUERY_SECURITY_ASSOCIATION_LIST,
  291. &Query, sizeof(Query), Info, sizeof(*Info),
  292. &BytesReturned, NULL)) {
  293. return GetLastError();
  294. }
  295. if (BytesReturned != sizeof(*Info))
  296. return ERROR_GEN_FAILURE;
  297. return ERROR_SUCCESS;
  298. }
  299. //* CreateSecurityAssociationEntry
  300. //
  301. // Creates a Security Association entry on the in-kernel list.
  302. //
  303. DWORD // Returns Windows error code.
  304. CreateSecurityAssociationEntry(
  305. IPV6_CREATE_SA_AND_KEY *NewSA) // Association (and key) to add to kernel.
  306. {
  307. unsigned int BytesReturned;
  308. if (!DeviceIoControl(V6Stack, IOCTL_IPV6_CREATE_SECURITY_ASSOCIATION,
  309. &NewSA->SA, sizeof(NewSA->SA) + NewSA->SA.RawKeySize,
  310. NULL, 0, &BytesReturned, NULL)) {
  311. return GetLastError();
  312. }
  313. //
  314. // When DeviceIoControl is given a null output buffer, the value returned
  315. // in BytesReturned is undefined. Therefore, we don't check for 0 here.
  316. //
  317. return ERROR_SUCCESS;
  318. }
  319. DWORD
  320. DeleteSecurityAssociationEntry(unsigned int Index)
  321. {
  322. IPV6_QUERY_SECURITY_ASSOCIATION_LIST Query;
  323. unsigned long BytesReturned;
  324. Query.Index = Index;
  325. if (!DeviceIoControl(V6Stack, IOCTL_IPV6_DELETE_SECURITY_ASSOCIATION,
  326. &Query, sizeof(Query), NULL, 0,
  327. &BytesReturned, NULL)) {
  328. return GetLastError();
  329. }
  330. //
  331. // When DeviceIoControl is given a null output buffer, the value returned
  332. // in BytesReturned is undefined. Therefore, we don't check for 0 here.
  333. //
  334. return ERROR_SUCCESS;
  335. }
  336. //* DeleteSecurityEntry - delete a security policy or association entry.
  337. //
  338. // Note: In the "delete all" case, it'd be much simpler not to query and
  339. // just delete wildcard until the list came up empty, but then we couldn't
  340. // report the index of any entries that failed to delete.
  341. //
  342. void
  343. DeleteSecurityEntry(
  344. int Type, // Type of entry (POLICY or ASSOCIATION).
  345. unsigned int Index) // Index of entry to delete (0 to delete all).
  346. {
  347. int EntriesDeleted = 0;
  348. int All = FALSE;
  349. DWORD Error;
  350. if (Index == 0) {
  351. All = TRUE;
  352. }
  353. do {
  354. if (All) {
  355. //
  356. // Deleting all entries. Find first on (remaining) list.
  357. //
  358. if (Type == POLICY) {
  359. IPV6_INFO_SECURITY_POLICY_LIST Info;
  360. Error = GetSecurityPolicyEntry(0, 0, &Info);
  361. if (Error == ERROR_SUCCESS) {
  362. Index = Info.SPIndex; // First entry.
  363. } else if (Error == ERROR_NO_MATCH) {
  364. Index = 0; // No more entries exist.
  365. break;
  366. } else {
  367. NlsPutMsg(STDOUT, IPSEC_MESSAGE_5,
  368. Error, GetErrorString(Error));
  369. // printf("\nError %u accessing Security Policies: %s.\n",
  370. // Error, strerror(Error));
  371. exit(1);
  372. }
  373. } else {
  374. IPV6_INFO_SECURITY_ASSOCIATION_LIST Info;
  375. Error = GetSecurityAssociationEntry(0, &Info);
  376. if (Error == ERROR_SUCCESS) {
  377. Index = Info.SAIndex; // First entry.
  378. } else if (Error == ERROR_NO_MATCH) {
  379. Index = 0; // No more entries exist.
  380. break;
  381. } else {
  382. NlsPutMsg(STDOUT, IPSEC_MESSAGE_6,
  383. Error, GetErrorString(Error));
  384. // printf("\nError %u accessing Security Associations: %s.\n",
  385. // Error, strerror(Error));
  386. exit(1);
  387. }
  388. }
  389. }
  390. if (Type == POLICY) {
  391. Error = DeleteSecurityPolicyEntry(Index);
  392. } else {
  393. Error = DeleteSecurityAssociationEntry(Index);
  394. }
  395. if (Error == ERROR_SUCCESS) {
  396. EntriesDeleted++;
  397. } else {
  398. if (Error == ERROR_NO_MATCH) {
  399. if (!All) {
  400. NlsPutMsg(STDOUT, IPSEC_MESSAGE_7, Index);
  401. // printf("Error deleting entry %u: entry doesn't exist.\n", Index);
  402. }
  403. // Otherwise silently ignore ...
  404. } else if (Error == ERROR_GEN_FAILURE) {
  405. NlsPutMsg(STDOUT, IPSEC_MESSAGE_8, Index);
  406. // printf("Error deleting entry %u.\n", Index);
  407. } else {
  408. if (Type) {
  409. NlsPutMsg(STDOUT, IPSEC_MESSAGE_9,
  410. Error, GetErrorString(Error));
  411. } else {
  412. NlsPutMsg(STDOUT, IPSEC_MESSAGE_56,
  413. Error, GetErrorString(Error));
  414. }
  415. // printf("Error %u accessing security %s: %s.\n", Error,
  416. // Type ? "policies" : "associations", strerror(Error));
  417. break;
  418. }
  419. }
  420. } while (All);
  421. if (Type == POLICY) {
  422. if (EntriesDeleted == 1) {
  423. NlsPutMsg(STDOUT, IPSEC_MESSAGE_10, EntriesDeleted);
  424. } else {
  425. NlsPutMsg(STDOUT, IPSEC_MESSAGE_57, EntriesDeleted);
  426. }
  427. // printf("Deleted %d polic%s (and any dependent associations).\n",
  428. // EntriesDeleted, EntriesDeleted == 1 ? "y" : "ies");
  429. } else {
  430. if (EntriesDeleted == 1) {
  431. NlsPutMsg(STDOUT, IPSEC_MESSAGE_11, EntriesDeleted);
  432. } else {
  433. NlsPutMsg(STDOUT, IPSEC_MESSAGE_58, EntriesDeleted);
  434. }
  435. // printf("Deleted %d association%s.\n", EntriesDeleted,
  436. // EntriesDeleted == 1 ? "" : "s");
  437. }
  438. }
  439. //* ParseAddress - convert address string to binary representation.
  440. //
  441. int
  442. ParseAddress(char *AddrString, IPv6Addr *Address)
  443. {
  444. struct addrinfo Hint;
  445. struct addrinfo *Result;
  446. memset(&Hint, 0, sizeof Hint);
  447. Hint.ai_family = PF_INET6;
  448. if (getaddrinfo(AddrString, NULL, &Hint, &Result))
  449. return FALSE;
  450. *Address = ((struct sockaddr_in6 *)Result->ai_addr)->sin6_addr;
  451. freeaddrinfo(Result);
  452. return TRUE;
  453. }
  454. //* FormatIPv6Address - convert binary address to string representation.
  455. //
  456. // This is only used in printing SAs, thus the unspecified address
  457. // means "take from policy".
  458. //
  459. char *
  460. FormatIPv6Address(IPv6Addr *Address)
  461. {
  462. static char Buffer[46];
  463. if (IN6_ADDR_EQUAL(Address, &UnspecifiedAddr)) {
  464. strcpy(Buffer, "POLICY");
  465. } else {
  466. struct sockaddr_in6 SockAddr;
  467. memset(&SockAddr, 0, sizeof(SockAddr));
  468. SockAddr.sin6_family = AF_INET6;
  469. memcpy(&SockAddr.sin6_addr, Address, sizeof(*Address));
  470. if (getnameinfo((struct sockaddr *)&SockAddr, sizeof(SockAddr), Buffer,
  471. sizeof(Buffer), NULL, 0, NI_NUMERICHOST)) {
  472. strcpy(Buffer, "<invalid>");
  473. }
  474. }
  475. return Buffer;
  476. }
  477. int
  478. ParseSAAdressEntry(char *AddrString, IPv6Addr *Address)
  479. {
  480. if (!strcmp(AddrString, "POLICY")) {
  481. *Address = UnspecifiedAddr;
  482. } else {
  483. if (!ParseAddress(AddrString, Address)) {
  484. return(FALSE);
  485. }
  486. }
  487. return(TRUE);
  488. }
  489. char *
  490. FormatSPAddressEntry(IPv6Addr *AddressStart, IPv6Addr *AddressEnd,
  491. unsigned int AddressField)
  492. {
  493. const char *PointerReturn;
  494. static char Buffer[100];
  495. char TempBuffer[100];
  496. DWORD Buflen = sizeof Buffer;
  497. struct sockaddr_in6 sin6;
  498. switch (AddressField) {
  499. case WILDCARD_VALUE:
  500. strcpy(Buffer, "*");
  501. break;
  502. case SINGLE_VALUE:
  503. sin6.sin6_family = AF_INET6;
  504. sin6.sin6_port = 0;
  505. sin6.sin6_flowinfo = 0;
  506. sin6.sin6_scope_id = 0;
  507. memcpy(&sin6.sin6_addr, AddressStart, sizeof *AddressStart);
  508. if (WSAAddressToString((struct sockaddr *) &sin6,
  509. sizeof sin6,
  510. NULL, // LPWSAPROTOCOL_INFO
  511. Buffer,
  512. &Buflen) == SOCKET_ERROR) {
  513. strcpy(Buffer, "???");
  514. }
  515. break;
  516. case RANGE_VALUE:
  517. sin6.sin6_family = AF_INET6;
  518. sin6.sin6_port = 0;
  519. sin6.sin6_flowinfo = 0;
  520. sin6.sin6_scope_id = 0;
  521. memcpy(&sin6.sin6_addr, AddressStart, sizeof *AddressStart);
  522. if (WSAAddressToString((struct sockaddr *) &sin6,
  523. sizeof sin6,
  524. NULL, // LPWSAPROTOCOL_INFO
  525. Buffer,
  526. &Buflen) == SOCKET_ERROR) {
  527. strcpy(Buffer, "???");
  528. }
  529. memcpy(&sin6.sin6_addr, AddressEnd, sizeof *AddressEnd);
  530. sin6.sin6_family = AF_INET6;
  531. sin6.sin6_port = 0;
  532. sin6.sin6_flowinfo = 0;
  533. sin6.sin6_scope_id = 0;
  534. if (WSAAddressToString((struct sockaddr *) &sin6,
  535. sizeof sin6,
  536. NULL, // LPWSAPROTOCOL_INFO
  537. TempBuffer,
  538. &Buflen) == SOCKET_ERROR) {
  539. strcpy(TempBuffer, "???");
  540. }
  541. strcat(Buffer, "-");
  542. strcat(Buffer, TempBuffer);
  543. break;
  544. default:
  545. strcpy(Buffer, "???");
  546. break;
  547. }
  548. return Buffer;
  549. }
  550. //* Parse an address entry
  551. //
  552. // Valid forms include:
  553. // The wildcard indicator, "*"
  554. // A single address, e.g. "2001::1"
  555. // A range of addresses, e.g. "2001::1-2001::ffff"
  556. //
  557. void
  558. ParseSPAddressEntry(
  559. char *EntryString, // String we're given to parse.
  560. IPv6Addr *AddressStart, // Return start of range, or single address.
  561. IPv6Addr *AddressEnd, // Return end of range, or unspecified.
  562. unsigned int *AddressType) // Return entry type: WILDCARD, SINGLE, RANGE.
  563. {
  564. char *RangeEntry;
  565. RangeEntry = strchr(EntryString, '-');
  566. if (RangeEntry == NULL) {
  567. //
  568. // Should be a wildcard, or single value.
  569. //
  570. if (!strcmp(EntryString, "*")) {
  571. *AddressType = WILDCARD_VALUE;
  572. *AddressStart = UnspecifiedAddr;
  573. } else {
  574. if (!ParseAddress(EntryString, AddressStart)) {
  575. NlsPutMsg(STDOUT, IPSEC_MESSAGE_12, EntryString);
  576. // printf("Bad IPv6 Address, %s.\n", EntryString);
  577. exit(1);
  578. }
  579. *AddressType = SINGLE_VALUE;
  580. }
  581. *AddressEnd = UnspecifiedAddr;
  582. } else {
  583. //
  584. // We were given a range.
  585. // Break entry string into two and parse separately.
  586. //
  587. *RangeEntry++ = '\0';
  588. if (!ParseAddress(EntryString, AddressStart)) {
  589. NlsPutMsg(STDOUT, IPSEC_MESSAGE_13, EntryString);
  590. // printf("Bad IPv6 Start Address Range, %s.\n", EntryString);
  591. exit(1);
  592. }
  593. if (!ParseAddress(RangeEntry, AddressEnd)) {
  594. NlsPutMsg(STDOUT, IPSEC_MESSAGE_14, RangeEntry);
  595. // printf("Bad IPv6 End Address Range, %s.\n", RangeEntry);
  596. exit(1);
  597. }
  598. *AddressType = RANGE_VALUE;
  599. }
  600. }
  601. char *
  602. FormatIPSecProto(unsigned int ProtoNum)
  603. {
  604. char *Result;
  605. switch(ProtoNum) {
  606. case IP_PROTOCOL_AH:
  607. Result = "AH";
  608. break;
  609. case IP_PROTOCOL_ESP:
  610. Result = "ESP";
  611. break;
  612. case NONE:
  613. Result = "NONE";
  614. break;
  615. default:
  616. Result = "???";
  617. break;
  618. }
  619. return Result;
  620. }
  621. unsigned int
  622. ParseIPSecProto(char *Protocol)
  623. {
  624. unsigned int Result;
  625. if (!strcmp(Protocol, "AH")) {
  626. Result = IP_PROTOCOL_AH;
  627. } else if (!strcmp(Protocol, "ESP")) {
  628. Result = IP_PROTOCOL_ESP;
  629. } else if (!strcmp(Protocol, "NONE")) {
  630. Result = NONE;
  631. } else {
  632. NlsPutMsg(STDOUT, IPSEC_MESSAGE_15, Protocol);
  633. // printf("Bad IPsec Protocol Value Entry %s.\n", Protocol);
  634. exit(1);
  635. }
  636. return Result;
  637. }
  638. char *
  639. FormatIPSecMode(unsigned int Mode)
  640. {
  641. char *Result;
  642. switch(Mode) {
  643. case TRANSPORT:
  644. Result = "TRANSPORT";
  645. break;
  646. case TUNNEL:
  647. Result = "TUNNEL";
  648. break;
  649. case NONE:
  650. Result = "*";
  651. break;
  652. default:
  653. Result = "???";
  654. break;
  655. }
  656. return Result;
  657. }
  658. unsigned int
  659. ParseIPSecMode(char *Mode)
  660. {
  661. unsigned int Result;
  662. if (!strcmp(Mode, "TRANSPORT")) {
  663. Result = TRANSPORT;
  664. } else if (!strcmp(Mode, "TUNNEL")) {
  665. Result = TUNNEL;
  666. } else if (!strcmp(Mode, "*")) {
  667. Result = NONE;
  668. } else {
  669. NlsPutMsg(STDOUT, IPSEC_MESSAGE_16, Mode);
  670. // printf("Bad IPsec Mode Value Entry %s.\n", Mode);
  671. exit(1);
  672. }
  673. return Result;
  674. }
  675. char *
  676. FormatRemoteGW(unsigned int Mode, IPv6Addr *Address)
  677. {
  678. switch (Mode) {
  679. case TRANSPORT:
  680. return "*";
  681. case TUNNEL:
  682. case NONE:
  683. if (IN6_ADDR_EQUAL(Address, &UnspecifiedAddr)) {
  684. return "*";
  685. } else {
  686. return FormatIPv6Address(Address);
  687. }
  688. }
  689. return NULL;
  690. }
  691. int
  692. ParseRemoteGW(
  693. char *AddrString,
  694. IPv6Addr *Address,
  695. unsigned int Mode)
  696. {
  697. switch (Mode) {
  698. case TRANSPORT:
  699. *Address = UnspecifiedAddr;
  700. break;
  701. case TUNNEL:
  702. case NONE:
  703. if (!strcmp(AddrString, "*")) {
  704. *Address = UnspecifiedAddr;
  705. } else
  706. if (!ParseAddress(AddrString, Address)) {
  707. NlsPutMsg(STDOUT, IPSEC_MESSAGE_17);
  708. // printf("Bad IPv6 Address for RemoteGWIPAddr.\n");
  709. exit(1);
  710. }
  711. break;
  712. default:
  713. break;
  714. }
  715. return TRUE;
  716. }
  717. char *
  718. FormatSATransportProto(unsigned short Protocol)
  719. {
  720. char *Result;
  721. switch (Protocol) {
  722. case IP_PROTOCOL_TCP:
  723. Result = "TCP";
  724. break;
  725. case IP_PROTOCOL_UDP:
  726. Result = "UDP";
  727. break;
  728. case IP_PROTOCOL_ICMPv6:
  729. Result = "ICMP";
  730. break;
  731. case NONE:
  732. Result = "POLICY";
  733. break;
  734. default:
  735. Result = "???";
  736. break;
  737. }
  738. return Result;
  739. }
  740. unsigned short
  741. ParseSATransportProto(char *Protocol)
  742. {
  743. unsigned short Result;
  744. if (!strcmp(Protocol, "TCP")) {
  745. Result = IP_PROTOCOL_TCP;
  746. } else if (!strcmp(Protocol, "UDP")) {
  747. Result = IP_PROTOCOL_UDP;
  748. } else if (!strcmp(Protocol, "ICMP")) {
  749. Result = IP_PROTOCOL_ICMPv6;
  750. } else if (!strcmp(Protocol, "POLICY")) {
  751. Result = NONE;
  752. } else {
  753. NlsPutMsg(STDOUT, IPSEC_MESSAGE_18, Protocol);
  754. // printf("Bad Protocol Value %s.\n", Protocol);
  755. exit(1);
  756. }
  757. return Result;
  758. }
  759. char *
  760. FormatSPTransportProto(unsigned short Protocol)
  761. {
  762. char *Result;
  763. switch (Protocol) {
  764. case IP_PROTOCOL_TCP:
  765. Result = "TCP";
  766. break;
  767. case IP_PROTOCOL_UDP:
  768. Result = "UDP";
  769. break;
  770. case IP_PROTOCOL_ICMPv6:
  771. Result = "ICMP";
  772. break;
  773. case NONE:
  774. Result = "*";
  775. break;
  776. default:
  777. Result = "???";
  778. break;
  779. }
  780. return Result;
  781. }
  782. unsigned short
  783. ParseSPTransportProto(char *Protocol)
  784. {
  785. unsigned short Result;
  786. if (!strcmp(Protocol, "TCP")) {
  787. Result = IP_PROTOCOL_TCP;
  788. } else if (!strcmp(Protocol, "UDP")) {
  789. Result = IP_PROTOCOL_UDP;
  790. } else if (!strcmp(Protocol, "ICMP")) {
  791. Result = IP_PROTOCOL_ICMPv6;
  792. } else if (!strcmp(Protocol, "*")) {
  793. Result = NONE;
  794. } else {
  795. NlsPutMsg(STDOUT, IPSEC_MESSAGE_18, Protocol);
  796. // printf("Bad Protocol Value %s.\n", Protocol);
  797. exit(1);
  798. }
  799. return Result;
  800. }
  801. char *
  802. FormatSAPort(unsigned short Port)
  803. {
  804. static char Buffer[11];
  805. if (Port == NONE) {
  806. strcpy(Buffer, "POLICY");
  807. } else {
  808. _itoa(Port, Buffer, 10);
  809. }
  810. return Buffer;
  811. }
  812. unsigned int
  813. ParseSAPort(char *Port)
  814. {
  815. unsigned int Result;
  816. if (!strcmp(Port, "POLICY") || !strcmp(Port, " ")) {
  817. Result = NONE;
  818. } else {
  819. Result = atoi(Port);
  820. }
  821. return Result;
  822. }
  823. char *
  824. FormatSPPort(
  825. unsigned short PortStart,
  826. unsigned short PortEnd,
  827. unsigned int PortField)
  828. {
  829. char TempBuffer[11];
  830. static char Buffer[22];
  831. switch (PortField) {
  832. case WILDCARD_VALUE:
  833. strcpy(Buffer, "*");
  834. break;
  835. case RANGE_VALUE:
  836. _itoa(PortEnd, TempBuffer, 10);
  837. _itoa(PortStart, Buffer, 10);
  838. strcat(Buffer, "-");
  839. strcat(Buffer, TempBuffer);
  840. break;
  841. case SINGLE_VALUE:
  842. _itoa(PortStart, Buffer, 10);
  843. break;
  844. default:
  845. strcpy(Buffer, "???");
  846. break;
  847. }
  848. return Buffer;
  849. }
  850. void
  851. ParseSPPort(
  852. char *EntryString,
  853. unsigned short *PortStart,
  854. unsigned short *PortEnd,
  855. unsigned int *PortField)
  856. {
  857. char *RangeEntry;
  858. RangeEntry = strchr(EntryString, '-');
  859. if (RangeEntry == NULL) {
  860. //
  861. // Should be a wildcard, or a single value.
  862. //
  863. if (!strcmp(EntryString, "*")) {
  864. *PortField = WILDCARD_VALUE;
  865. *PortStart = NONE;
  866. } else {
  867. *PortField = SINGLE_VALUE;
  868. *PortStart = (unsigned short)atoi(EntryString);
  869. }
  870. *PortEnd = NONE;
  871. } else {
  872. //
  873. // We were given a range.
  874. // Break entry string into two and parse separately.
  875. //
  876. *RangeEntry++ = '\0';
  877. *PortStart = (unsigned short)atoi(EntryString);
  878. *PortEnd = (unsigned short)atoi(RangeEntry);
  879. *PortField = RANGE_VALUE;
  880. }
  881. }
  882. unsigned char *
  883. FormatSelector(unsigned int Selector)
  884. {
  885. char *Buffer;
  886. switch (Selector) {
  887. case PACKET_SELECTOR:
  888. Buffer = "+";
  889. break;
  890. case POLICY_SELECTOR:
  891. Buffer = "-";
  892. break;
  893. default:
  894. Buffer = "?";
  895. break;
  896. }
  897. return Buffer;
  898. }
  899. unsigned int
  900. ParseSelector(char *Selector)
  901. {
  902. unsigned int Result;
  903. if (!strcmp(Selector, "+")) {
  904. Result = PACKET_SELECTOR;
  905. } else if (!strcmp(Selector, "-")) {
  906. Result = POLICY_SELECTOR;
  907. } else {
  908. NlsPutMsg(STDOUT, IPSEC_MESSAGE_19);
  909. // printf("Bad value for one of the selector types.\n");
  910. exit(1);
  911. }
  912. return Result;
  913. }
  914. char *
  915. FormatIndex(unsigned long Index)
  916. {
  917. static char Buffer[11];
  918. switch (Index) {
  919. case NONE:
  920. strcpy(Buffer, "NONE");
  921. break;
  922. default:
  923. _itoa(Index, Buffer, 10);
  924. break;
  925. }
  926. return Buffer;
  927. }
  928. unsigned long
  929. ParseIndex(char *Index)
  930. {
  931. unsigned long Result;
  932. if (!strcmp(Index, "NONE")) {
  933. Result = NONE;
  934. } else {
  935. Result = atoi(Index);
  936. }
  937. return Result;
  938. }
  939. char *
  940. FormatDirection(unsigned int Direction)
  941. {
  942. char *Buffer;
  943. switch (Direction) {
  944. case INBOUND:
  945. Buffer = "INBOUND";
  946. break;
  947. case OUTBOUND:
  948. Buffer = "OUTBOUND";
  949. break;
  950. case BIDIRECTIONAL:
  951. Buffer = "BIDIRECT";
  952. break;
  953. default:
  954. Buffer = "???";
  955. break;
  956. }
  957. return Buffer;
  958. }
  959. unsigned int
  960. ParseDirection(char *Direction)
  961. {
  962. unsigned int Result;
  963. if (!strcmp(Direction, "INBOUND")) {
  964. Result = INBOUND;
  965. } else if (!strcmp(Direction, "OUTBOUND")) {
  966. Result = OUTBOUND;
  967. } else if (!strcmp(Direction, "BIDIRECT")) {
  968. Result = BIDIRECTIONAL;
  969. } else {
  970. NlsPutMsg(STDOUT, IPSEC_MESSAGE_20, Direction);
  971. // printf("Bad Direction Value Entry %s.\n", Direction);
  972. exit(1);
  973. }
  974. return Result;
  975. }
  976. char *
  977. FormatIPSecAction(unsigned int PolicyFlag)
  978. {
  979. char *Result;
  980. switch (PolicyFlag) {
  981. case IPSEC_BYPASS:
  982. Result = "BYPASS";
  983. break;
  984. case IPSEC_DISCARD:
  985. Result = "DISCARD";
  986. break;
  987. case IPSEC_APPLY:
  988. Result = "APPLY";
  989. break;
  990. case IPSEC_APPCHOICE:
  991. Result = "APPCHOICE";
  992. break;
  993. default:
  994. Result = "???";
  995. break;
  996. }
  997. return Result;
  998. }
  999. unsigned int
  1000. ParseIPSecAction(char *Action)
  1001. {
  1002. unsigned int Result;
  1003. if (!strcmp(Action, "BYPASS")) {
  1004. Result = IPSEC_BYPASS;
  1005. } else if (!strcmp(Action, "DISCARD")) {
  1006. Result = IPSEC_DISCARD;
  1007. } else if (!strcmp(Action, "APPLY")) {
  1008. Result = IPSEC_APPLY;
  1009. } else if (!strcmp(Action, "APPCHOICE")) {
  1010. Result = IPSEC_APPCHOICE;
  1011. } else {
  1012. NlsPutMsg(STDOUT, IPSEC_MESSAGE_21, Action);
  1013. // printf("Bad IPSec Action Value Entry %s.\n", Action);
  1014. exit(1);
  1015. }
  1016. return Result;
  1017. }
  1018. char *
  1019. FormatAuthAlg(unsigned int AlgorithmId)
  1020. {
  1021. char *Result;
  1022. switch (AlgorithmId) {
  1023. case ALGORITHM_NULL:
  1024. Result = "NULL";
  1025. break;
  1026. case ALGORITHM_HMAC_MD5:
  1027. Result = "HMAC-MD5";
  1028. break;
  1029. case ALGORITHM_HMAC_MD5_96:
  1030. Result = "HMAC-MD5-96";
  1031. break;
  1032. case ALGORITHM_HMAC_SHA1:
  1033. Result = "HMAC-SHA1";
  1034. break;
  1035. case ALGORITHM_HMAC_SHA1_96:
  1036. Result = "HMAC-SHA1-96";
  1037. break;
  1038. default:
  1039. Result = "???";
  1040. break;
  1041. }
  1042. return Result;
  1043. }
  1044. unsigned int
  1045. ParseAuthAlg(char *AuthAlg)
  1046. {
  1047. if (!strcmp(AuthAlg, "NULL")) {
  1048. return ALGORITHM_NULL;
  1049. }
  1050. if (!strcmp(AuthAlg, "HMAC-MD5")) {
  1051. return ALGORITHM_HMAC_MD5;
  1052. }
  1053. if (!strcmp(AuthAlg, "HMAC-MD5-96")) {
  1054. return ALGORITHM_HMAC_MD5_96;
  1055. }
  1056. if (!strcmp(AuthAlg, "HMAC-SHA1")) {
  1057. return ALGORITHM_HMAC_SHA1;
  1058. }
  1059. if (!strcmp(AuthAlg, "HMAC-SHA1-96")) {
  1060. return ALGORITHM_HMAC_SHA1_96;
  1061. }
  1062. NlsPutMsg(STDOUT, IPSEC_MESSAGE_22, AuthAlg);
  1063. // printf("Bad Authentication Algorithm Value Entry %s.\n", AuthAlg);
  1064. exit(1);
  1065. }
  1066. unsigned int
  1067. ReadKeyFile(
  1068. char *FileName,
  1069. unsigned char *Key)
  1070. {
  1071. FILE *KeyFile;
  1072. unsigned int KeySize;
  1073. if (!strcmp(FileName, "NONE")) {
  1074. // This is for NULL algorithm.
  1075. strcpy(Key, "NO KEY");
  1076. KeySize = strlen(Key);
  1077. } else {
  1078. if ((KeyFile = fopen(FileName, "r")) == NULL) {
  1079. return 0;
  1080. }
  1081. KeySize = fread(Key, sizeof(unsigned char), MAX_KEY_SIZE, KeyFile);
  1082. fclose(KeyFile);
  1083. }
  1084. return KeySize;
  1085. }
  1086. //* PrintSecurityPolicyEntry
  1087. //
  1088. // Print out the security policy entry, "nicely"? formatted,
  1089. // to the given file.
  1090. //
  1091. PrintSecurityPolicyEntry(
  1092. FILE *File,
  1093. IPV6_INFO_SECURITY_POLICY_LIST *SPEntry)
  1094. {
  1095. fprintf(File, "%-10lu", SPEntry->SPIndex);
  1096. fprintf(File, "%-2s", FormatSelector(SPEntry->RemoteAddrSelector));
  1097. fprintf(File, "%-45s", FormatSPAddressEntry(&(SPEntry->RemoteAddr),
  1098. &(SPEntry->RemoteAddrData),
  1099. SPEntry->RemoteAddrField));
  1100. fprintf(File, "%-2s", FormatSelector(SPEntry->LocalAddrSelector));
  1101. fprintf(File, "%-45s", FormatSPAddressEntry(&(SPEntry->LocalAddr),
  1102. &(SPEntry->LocalAddrData),
  1103. SPEntry->LocalAddrField));
  1104. fprintf(File, "%-2s", FormatSelector(SPEntry->TransportProtoSelector));
  1105. fprintf(File, "%-12s", FormatSPTransportProto(SPEntry->TransportProto));
  1106. fprintf(File, "%-2s", FormatSelector(SPEntry->RemotePortSelector));
  1107. fprintf(File, "%-12s", FormatSPPort(SPEntry->RemotePort,
  1108. SPEntry->RemotePortData,
  1109. SPEntry->RemotePortField));
  1110. fprintf(File, "%-2s", FormatSelector(SPEntry->LocalPortSelector));
  1111. fprintf(File, "%-12s", FormatSPPort(SPEntry->LocalPort,
  1112. SPEntry->LocalPortData,
  1113. SPEntry->LocalPortField));
  1114. fprintf(File, "%-15s", FormatIPSecProto(SPEntry->IPSecProtocol));
  1115. fprintf(File, "%-12s", FormatIPSecMode(SPEntry->IPSecMode));
  1116. fprintf(File, "%-45s", FormatRemoteGW(SPEntry->IPSecMode,
  1117. &(SPEntry->RemoteSecurityGWAddr)));
  1118. fprintf(File, "%-15s", FormatIndex(SPEntry->SABundleIndex));
  1119. fprintf(File, "%-12s", FormatDirection(SPEntry->Direction));
  1120. fprintf(File, "%-12s", FormatIPSecAction(SPEntry->IPSecAction));
  1121. fprintf(File, "%-15u", SPEntry->SPInterface);
  1122. fprintf(File, ";\n");
  1123. }
  1124. //* PrintSecurityPolicyHeader
  1125. //
  1126. // Print out the security policy header fields to the given file.
  1127. //
  1128. PrintSecurityPolicyHeader(
  1129. FILE *File)
  1130. {
  1131. int Loop;
  1132. fprintf(File, "%-10s", "Policy");
  1133. fprintf(File, "%-2s", " ");
  1134. fprintf(File, "%-45s", "RemoteIPAddr");
  1135. fprintf(File, "%-2s", " ");
  1136. fprintf(File, "%-45s", "LocalIPAddr");
  1137. fprintf(File, "%-2s", " ");
  1138. fprintf(File, "%-12s", "Protocol");
  1139. fprintf(File, "%-2s", " ");
  1140. fprintf(File, "%-12s", "RemotePort");
  1141. fprintf(File, "%-2s", " ");
  1142. fprintf(File, "%-12s", "LocalPort");
  1143. fprintf(File, "%-15s", "IPSecProtocol");
  1144. fprintf(File, "%-12s", "IPSecMode");
  1145. fprintf(File, "%-45s", "RemoteGWIPAddr");
  1146. fprintf(File, "%-15s", "SABundleIndex");
  1147. fprintf(File, "%-12s", "Direction");
  1148. fprintf(File, "%-12s", "Action");
  1149. fprintf(File, "%-15s", "InterfaceIndex");
  1150. fprintf(File, "\n");
  1151. for (Loop = 0; Loop < SP_FILE_BORDER; Loop++) {
  1152. fprintf(File, "_");
  1153. }
  1154. fprintf(File, "\n");
  1155. }
  1156. //* PrintSecurityPolicyFooter
  1157. //
  1158. // Print out the security policy footer to the given file.
  1159. //
  1160. PrintSecurityPolicyFooter(
  1161. FILE *File)
  1162. {
  1163. int Loop;
  1164. for (Loop = 0; Loop < SP_FILE_BORDER; Loop++) {
  1165. fprintf(File, "_");
  1166. }
  1167. fprintf(File, "\n\n");
  1168. fprintf(File, "- = Take selector from policy.\n");
  1169. fprintf(File, "+ = Take selector from packet.\n");
  1170. }
  1171. //* PrintSecurityAssociationEntry
  1172. //
  1173. // Print out the security association entry, "nicely"? formatted,
  1174. // to the given file.
  1175. //
  1176. PrintSecurityAssociationEntry(
  1177. FILE *File,
  1178. IPV6_INFO_SECURITY_ASSOCIATION_LIST *SAEntry)
  1179. {
  1180. fprintf(File, "%-10lu", SAEntry->SAIndex);
  1181. fprintf(File, "%-15lu", SAEntry->SPI);
  1182. fprintf(File, "%-45s", FormatIPv6Address(&(SAEntry->SADestAddr)));
  1183. fprintf(File, "%-45s", FormatIPv6Address(&(SAEntry->DestAddr)));
  1184. fprintf(File, "%-45s", FormatIPv6Address(&(SAEntry->SrcAddr)));
  1185. fprintf(File, "%-12s", FormatSATransportProto(SAEntry->TransportProto));
  1186. fprintf(File, "%-12s", FormatSAPort(SAEntry->DestPort));
  1187. fprintf(File, "%-12s", FormatSAPort(SAEntry->SrcPort));
  1188. fprintf(File, "%-12s", FormatAuthAlg(SAEntry->AlgorithmId));
  1189. fprintf(File, "%-15s", " ");
  1190. fprintf(File, "%-12s", FormatDirection(SAEntry->Direction));
  1191. fprintf(File, "%-15lu", SAEntry->SecPolicyIndex);
  1192. fprintf(File, "%-1;");
  1193. fprintf(File, "\n");
  1194. }
  1195. //* PrintSecurityAssociationHeader
  1196. //
  1197. // Print out the security association header fields to the given file.
  1198. //
  1199. PrintSecurityAssociationHeader(
  1200. FILE *File)
  1201. {
  1202. int Loop;
  1203. fprintf(File, "Security Association List\n\n");
  1204. fprintf(File, "%-10s", "SAEntry");
  1205. fprintf(File, "%-15s", "SPI");
  1206. fprintf(File, "%-45s", "SADestIPAddr");
  1207. fprintf(File, "%-45s", "DestIPAddr");
  1208. fprintf(File, "%-45s", "SrcIPAddr");
  1209. fprintf(File, "%-12s", "Protocol");
  1210. fprintf(File, "%-12s", "DestPort");
  1211. fprintf(File, "%-12s", "SrcPort");
  1212. fprintf(File, "%-12s", "AuthAlg");
  1213. fprintf(File, "%-15s", "KeyFile");
  1214. fprintf(File, "%-12s", "Direction");
  1215. fprintf(File, "%-15s", "SecPolicyIndex");
  1216. fprintf(File, "\n");
  1217. for (Loop = 0; Loop < SA_FILE_BORDER; Loop++) {
  1218. fprintf(File, "_");
  1219. }
  1220. fprintf(File, "\n");
  1221. }
  1222. //* PrintSecurityAssociationFooter
  1223. //
  1224. // Print out the security association footer to the given file.
  1225. //
  1226. PrintSecurityAssociationFooter(
  1227. FILE *File)
  1228. {
  1229. int Loop;
  1230. for (Loop = 0; Loop < SA_FILE_BORDER; Loop++) {
  1231. fprintf(File, "_");
  1232. }
  1233. fprintf(File, "\n");
  1234. }
  1235. void
  1236. CreateSecurityPolicyFile(char *BaseName)
  1237. {
  1238. IPV6_INFO_SECURITY_POLICY_LIST Info;
  1239. char FileName[MAX_PATH + 1];
  1240. FILE *File;
  1241. unsigned long Index;
  1242. DWORD Error;
  1243. //
  1244. // Copy the filename from the command line to our own buffer so we can
  1245. // append an extension to it. We reserve at least 4 characters for the
  1246. // extension. The strncpy function will zero fill up to the limit of
  1247. // the copy, thus the character at the limit will be NULL unless the
  1248. // command line field was too long to fit.
  1249. //
  1250. strncpy(FileName, BaseName, MAX_PATH - 3);
  1251. if (FileName[MAX_PATH - 4] != 0) {
  1252. NlsPutMsg(STDOUT, IPSEC_MESSAGE_23);
  1253. // printf("\nFilename length is too long.\n");
  1254. exit(1);
  1255. }
  1256. strcat(FileName, ".spd");
  1257. if ((File = fopen(FileName, "w+")) == NULL) {
  1258. NlsPutMsg(STDOUT, IPSEC_MESSAGE_24, FileName);
  1259. // printf("\nFile %s could not be opened.\n", FileName);
  1260. exit(1);
  1261. }
  1262. //
  1263. // Find index of first policy on the in-kernel list.
  1264. //
  1265. Error = GetSecurityPolicyEntry(0, 0, &Info);
  1266. switch (Error) {
  1267. case ERROR_SUCCESS:
  1268. Index = Info.SPIndex; // First entry.
  1269. break;
  1270. case ERROR_NO_MATCH:
  1271. Index = 0; // No entries exist.
  1272. break;
  1273. default:
  1274. NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error));
  1275. // printf("\nError %u reading Security Policies: %s.\n",
  1276. // Error, strerror(Error));
  1277. Index = 0;
  1278. break;
  1279. }
  1280. fprintf(File, "\nSecurity Policy List\n\n");
  1281. PrintSecurityPolicyHeader(File);
  1282. //
  1283. // Loop through all the policies on the list.
  1284. //
  1285. while (Index != 0) {
  1286. Error = GetSecurityPolicyEntry(0, Index, &Info);
  1287. if (Error != ERROR_SUCCESS) {
  1288. NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error));
  1289. // printf("\nError %u reading Security Policies: %s.\n",
  1290. // Error, strerror(Error));
  1291. break;
  1292. }
  1293. PrintSecurityPolicyEntry(File, &Info);
  1294. Index = Info.NextSPIndex;
  1295. }
  1296. PrintSecurityPolicyFooter(File);
  1297. fclose(File);
  1298. NlsPutMsg(STDOUT, IPSEC_MESSAGE_26, FileName);
  1299. // printf("Security Policy Data -> %s\n", FileName);
  1300. return;
  1301. }
  1302. void
  1303. CreateSecurityAssociationFile(char *BaseName)
  1304. {
  1305. IPV6_INFO_SECURITY_ASSOCIATION_LIST Info;
  1306. char FileName[MAX_PATH + 1];
  1307. FILE *File;
  1308. unsigned long Index;
  1309. DWORD Error;
  1310. //
  1311. // Copy the filename from the command line to our own buffer so we can
  1312. // append an extension to it. We reserve at least 4 characters for the
  1313. // extension. The strncpy function will zero fill up to the limit of
  1314. // the copy, thus the character at the limit will be NULL unless the
  1315. // command line field was too long to fit.
  1316. //
  1317. strncpy(FileName, BaseName, MAX_PATH - 3);
  1318. if (FileName[MAX_PATH - 4] != 0) {
  1319. NlsPutMsg(STDOUT, IPSEC_MESSAGE_27);
  1320. // printf("\nFilename length is too long.\n");
  1321. exit(1);
  1322. }
  1323. strcat(FileName, ".sad");
  1324. if ((File = fopen(FileName, "w+")) == NULL) {
  1325. NlsPutMsg(STDOUT, IPSEC_MESSAGE_28, FileName);
  1326. // printf("\nFile %s could not be opened.\n", FileName);
  1327. exit(1);
  1328. }
  1329. //
  1330. // Find index of first association on the in-kernel list.
  1331. //
  1332. Error = GetSecurityAssociationEntry(0, &Info);
  1333. switch (Error) {
  1334. case ERROR_SUCCESS:
  1335. Index = Info.SAIndex; // First entry.
  1336. break;
  1337. case ERROR_NO_MATCH:
  1338. Index = 0; // No entries exist.
  1339. break;
  1340. default:
  1341. NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error));
  1342. // printf("\nError %u reading Security Associations: %s.\n",
  1343. // Error, strerror(Error));
  1344. Index = 0;
  1345. break;
  1346. }
  1347. PrintSecurityAssociationHeader(File);
  1348. //
  1349. // Loop through all the associations on the list.
  1350. //
  1351. while (Index != 0) {
  1352. Error = GetSecurityAssociationEntry(Index, &Info);
  1353. if (Error != ERROR_SUCCESS) {
  1354. NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error));
  1355. // printf("\nError %u reading Security Associations: %s.\n",
  1356. // Error, strerror(Error));
  1357. break;
  1358. }
  1359. PrintSecurityAssociationEntry(File, &Info);
  1360. Index = Info.NextSAIndex;
  1361. }
  1362. PrintSecurityAssociationFooter(File);
  1363. fclose(File);
  1364. NlsPutMsg(STDOUT, IPSEC_MESSAGE_30, FileName);
  1365. // printf("Security Association Data -> %s\n", FileName);
  1366. return;
  1367. }
  1368. void
  1369. DisplaySecurityPolicyList(unsigned int Interface)
  1370. {
  1371. IPV6_INFO_SECURITY_POLICY_LIST Info;
  1372. unsigned long Index;
  1373. DWORD Error;
  1374. //
  1375. // Find index of first policy on the in-kernel list.
  1376. //
  1377. Error = GetSecurityPolicyEntry(Interface, 0, &Info);
  1378. switch (Error) {
  1379. case ERROR_SUCCESS:
  1380. Index = Info.SPIndex; // First entry.
  1381. break;
  1382. case ERROR_NOT_FOUND:
  1383. NlsPutMsg(STDOUT, IPSEC_MESSAGE_31, Interface);
  1384. // printf("Interface %u does not exist.\n", Interface);
  1385. exit(1);
  1386. case ERROR_NO_MATCH:
  1387. NlsPutMsg(STDOUT, IPSEC_MESSAGE_32);
  1388. // printf("No Security Policies exist");
  1389. if (Interface != 0) {
  1390. NlsPutMsg(STDOUT, IPSEC_MESSAGE_33, Interface);
  1391. // printf(" for interface %d", Interface);
  1392. }
  1393. NlsPutMsg(STDOUT, IPSEC_MESSAGE_34);
  1394. // printf(".\n");
  1395. exit(1);
  1396. default:
  1397. NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error));
  1398. // printf("\nError %u reading Security Policies: %s.\n",
  1399. // Error, strerror(Error));
  1400. exit(1);
  1401. }
  1402. if (Interface == 0) {
  1403. NlsPutMsg(STDOUT, IPSEC_MESSAGE_35);
  1404. // printf("\nAll Security Policies\n\n");
  1405. } else {
  1406. NlsPutMsg(STDOUT, IPSEC_MESSAGE_36, Interface);
  1407. // printf("\nSecurity Policy List for Interface %d\n\n", Interface);
  1408. }
  1409. PrintSecurityPolicyHeader(stdout);
  1410. //
  1411. // Loop through all the policies on the list.
  1412. //
  1413. while (Index != 0) {
  1414. Error = GetSecurityPolicyEntry(Interface, Index, &Info);
  1415. if (Error != ERROR_SUCCESS) {
  1416. NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error));
  1417. // printf("\nError %u reading Security Policies: %s.\n",
  1418. // Error, strerror(Error));
  1419. exit(1);
  1420. }
  1421. PrintSecurityPolicyEntry(stdout, &Info);
  1422. Index = Info.NextSPIndex;
  1423. }
  1424. PrintSecurityPolicyFooter(stdout);
  1425. return;
  1426. }
  1427. void
  1428. DisplaySecurityAssociationList(void)
  1429. {
  1430. IPV6_INFO_SECURITY_ASSOCIATION_LIST Info;
  1431. unsigned long Index;
  1432. DWORD Error;
  1433. //
  1434. // Find index of first association on the in-kernel list.
  1435. //
  1436. Error = GetSecurityAssociationEntry(0, &Info);
  1437. switch (Error) {
  1438. case ERROR_SUCCESS:
  1439. Index = Info.SAIndex; // First entry.
  1440. break;
  1441. case ERROR_NO_MATCH:
  1442. // There are no SA entries yet.
  1443. NlsPutMsg(STDOUT, IPSEC_MESSAGE_37);
  1444. // printf("No Security Associations exist.\n");
  1445. exit(1);
  1446. default:
  1447. NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error));
  1448. // printf("\nError %u reading Security Associations: %s.\n",
  1449. // Error, strerror(Error));
  1450. exit(1);
  1451. }
  1452. NlsPutMsg(STDOUT, IPSEC_MESSAGE_38);
  1453. // printf("\n");
  1454. PrintSecurityAssociationHeader(stdout);
  1455. //
  1456. // Loop through all the associations on the list.
  1457. //
  1458. while (Index != 0) {
  1459. Error = GetSecurityAssociationEntry(Index, &Info);
  1460. if (Error != ERROR_SUCCESS) {
  1461. NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error));
  1462. // printf("\nError %u reading Security Associations: %s.\n",
  1463. // Error, strerror(Error));
  1464. exit(1);
  1465. }
  1466. PrintSecurityAssociationEntry(stdout, &Info);
  1467. Index = Info.NextSAIndex;
  1468. }
  1469. PrintSecurityAssociationFooter(stdout);
  1470. return;
  1471. }
  1472. int
  1473. ParseSPLine(
  1474. char *Line, // Line to parse.
  1475. IPV6_CREATE_SECURITY_POLICY *SP) // Where to put the data.
  1476. {
  1477. char *Token;
  1478. Token = strtok(Line, " ");
  1479. if (Token == NULL) {
  1480. return FALSE;
  1481. }
  1482. // Policy Number.
  1483. SP->SPIndex = atol(Token);
  1484. // RemoteIPAddr Selector.
  1485. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1486. SP->RemoteAddrSelector = ParseSelector(Token);
  1487. // RemoteIPAddr.
  1488. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1489. ParseSPAddressEntry(Token, &SP->RemoteAddr, &SP->RemoteAddrData,
  1490. &SP->RemoteAddrField);
  1491. // LocalIPAddr Selector.
  1492. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1493. SP->LocalAddrSelector = ParseSelector(Token);
  1494. // LocalIPAddr.
  1495. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1496. ParseSPAddressEntry(Token, &SP->LocalAddr, &SP->LocalAddrData,
  1497. &SP->LocalAddrField);
  1498. // Protocol Selector.
  1499. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1500. SP->TransportProtoSelector = ParseSelector(Token);
  1501. // Protocol.
  1502. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1503. SP->TransportProto = ParseSPTransportProto(Token);
  1504. // RemotePort Selector.
  1505. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1506. SP->RemotePortSelector = ParseSelector(Token);
  1507. // RemotePort.
  1508. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1509. ParseSPPort(Token, &SP->RemotePort, &SP->RemotePortData,
  1510. &SP->RemotePortField);
  1511. // LocalPort Selector.
  1512. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1513. SP->LocalPortSelector = ParseSelector(Token);
  1514. // Local Port.
  1515. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1516. ParseSPPort(Token, &SP->LocalPort, &SP->LocalPortData,
  1517. &SP->LocalPortField);
  1518. // IPSecProtocol.
  1519. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1520. SP->IPSecProtocol = ParseIPSecProto(Token);
  1521. // IPSecMode.
  1522. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1523. SP->IPSecMode = ParseIPSecMode(Token);
  1524. // RemoteGWIPAddr.
  1525. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1526. ParseRemoteGW(Token, &SP->RemoteSecurityGWAddr, SP->IPSecMode);
  1527. // SABundleIndex.
  1528. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1529. SP->SABundleIndex = ParseIndex(Token);
  1530. // Direction.
  1531. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1532. SP->Direction = ParseDirection(Token);
  1533. // Action.
  1534. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1535. SP->IPSecAction = ParseIPSecAction(Token);
  1536. // Interface SP.
  1537. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1538. SP->SPInterface = atol(Token);
  1539. // End of current policy.
  1540. // REVIEW: Insist that nothing follows final valid field on the line?
  1541. // if ((Token = strtok(NULL, " ")) != NULL) return FALSE;
  1542. return TRUE;
  1543. }
  1544. int
  1545. ParseSALine(
  1546. char *Line, // Line to parse.
  1547. IPV6_CREATE_SA_AND_KEY *SAAndKey) // Where to put the data.
  1548. {
  1549. char *Token;
  1550. IPV6_CREATE_SECURITY_ASSOCIATION *SA = &(SAAndKey->SA);
  1551. Token = strtok(Line, " ");
  1552. if (Token == NULL) {
  1553. return FALSE;
  1554. }
  1555. // Security Association Entry Number.
  1556. SA->SAIndex = atol(Token);
  1557. // SPI
  1558. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1559. SA->SPI = atol(Token);
  1560. // SADestAddr
  1561. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1562. ParseSAAdressEntry(Token, &SA->SADestAddr);
  1563. // DestIPAddr
  1564. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1565. ParseSAAdressEntry(Token, &SA->DestAddr);
  1566. // SrcIPAddr
  1567. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1568. ParseSAAdressEntry(Token, &SA->SrcAddr);
  1569. // Protocol
  1570. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1571. SA->TransportProto = ParseSATransportProto(Token);
  1572. // DestPort
  1573. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1574. SA->DestPort = (unsigned short)ParseSAPort(Token);
  1575. // SrcPort
  1576. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1577. SA->SrcPort = (unsigned short)ParseSAPort(Token);
  1578. // AuthAlg
  1579. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1580. SA->AlgorithmId = ParseAuthAlg(Token);
  1581. // KeyFile
  1582. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1583. SA->RawKeySize = ReadKeyFile(Token, SAAndKey->Key);
  1584. if (SA->RawKeySize == 0) {
  1585. NlsPutMsg(STDOUT, IPSEC_MESSAGE_39, Token);
  1586. // printf("Error reading key file %s\n", Token);
  1587. return FALSE;
  1588. }
  1589. // Direction
  1590. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1591. SA->Direction = ParseDirection(Token);
  1592. // SecPolicyIndex
  1593. if ((Token = strtok(NULL, " ")) == NULL) return FALSE;
  1594. SA->SecPolicyIndex = atol(Token);
  1595. // End of current association.
  1596. // REVIEW: Insist that nothing follows final valid field on the line?
  1597. // if ((Token = strtok(NULL, " ")) != NULL) return FALSE;
  1598. return TRUE;
  1599. }
  1600. void
  1601. ReadConfigurationFile(char *BaseName, int Type)
  1602. {
  1603. char Buffer[SP_FILE_BORDER + 2]; // Note: SP_FILE_BORDER > SA_FILE_BORDER
  1604. char FileName[MAX_PATH + 1];
  1605. unsigned int MaxLineLengthPlusOne, LineLength, Line;
  1606. FILE *File;
  1607. int ParseIt = 0;
  1608. IPV6_CREATE_SECURITY_POLICY SPEntry;
  1609. IPV6_CREATE_SA_AND_KEY SAEntry;
  1610. int Policies = 0;
  1611. int Associations = 0;
  1612. DWORD Error;
  1613. //
  1614. // Copy the filename from the command line to our own buffer so we can
  1615. // append an extension to it. We reserve at least 4 characters for the
  1616. // extension. The strncpy function will zero fill up to the limit of
  1617. // the copy, thus the character at the limit will be NULL unless the
  1618. // command line field was too long to fit.
  1619. //
  1620. strncpy(FileName, BaseName, MAX_PATH - 3);
  1621. if (FileName[MAX_PATH - 4] != 0) {
  1622. NlsPutMsg(STDOUT, IPSEC_MESSAGE_40);
  1623. // printf("\nFilename length is too long.\n");
  1624. exit(1);
  1625. }
  1626. //
  1627. // Add appropriate file extension.
  1628. // Maximum line length is the size of the field entries
  1629. // plus one for the newline character. Since we need to
  1630. // fgets with a value one greater than the max that can
  1631. // be read in, we add that onto the maximum line length
  1632. // to get MaxLineLengthPlusOne. Saves us an add later.
  1633. //
  1634. if (Type == POLICY) {
  1635. strcat(FileName, ".spd");
  1636. MaxLineLengthPlusOne = SP_FILE_BORDER + 2;
  1637. } else {
  1638. if (Type == ASSOCIATION) {
  1639. strcat(FileName, ".sad");
  1640. MaxLineLengthPlusOne = SA_FILE_BORDER + 2;
  1641. } else {
  1642. NlsPutMsg(STDOUT, IPSEC_MESSAGE_41);
  1643. // printf("\nReadConfigurationFile routine called incorrectly.\n");
  1644. exit(1);
  1645. }
  1646. }
  1647. if ((File = fopen(FileName, "r")) == NULL) {
  1648. NlsPutMsg(STDOUT, IPSEC_MESSAGE_42, FileName);
  1649. // printf("\nFile %s could not be opened.\n", FileName);
  1650. exit(1);
  1651. }
  1652. for (Line = 1; !feof(File); Line++) {
  1653. if (fgets(Buffer, MaxLineLengthPlusOne, File) == NULL)
  1654. break;
  1655. LineLength = strlen(Buffer);
  1656. // printf("Line = %u, Length = %u: %s.\n", Line, LineLength, Buffer);
  1657. if (Buffer[LineLength - 1] != '\n') {
  1658. NlsPutMsg(STDOUT, IPSEC_MESSAGE_43, Line);
  1659. // printf("Error on line %u, line too long.\n", Line);
  1660. break;
  1661. } else {
  1662. Buffer[LineLength - 1] = '\0';
  1663. }
  1664. if (ParseIt) {
  1665. if (Buffer[0] == '_')
  1666. break;
  1667. if (Type == POLICY) {
  1668. if (!ParseSPLine(Buffer, &SPEntry)) {
  1669. NlsPutMsg(STDOUT, IPSEC_MESSAGE_44, Line);
  1670. // printf("Error parsing SP entry fields on line %u.\n", Line);
  1671. break;
  1672. } else {
  1673. Error = CreateSecurityPolicyEntry(&SPEntry);
  1674. if (Error == ERROR_ALREADY_EXISTS) {
  1675. NlsPutMsg(STDOUT, IPSEC_MESSAGE_45,
  1676. Line, SPEntry.SPIndex);
  1677. // printf("Error on line %u: a policy with index %u "
  1678. // "already exists.\n", Line, SPEntry.SPIndex);
  1679. continue;
  1680. }
  1681. if (Error == ERROR_NOT_FOUND) {
  1682. NlsPutMsg(STDOUT, IPSEC_MESSAGE_46,
  1683. Line, SPEntry.SPIndex);
  1684. // printf("Error on line %u: policy %u specifies a "
  1685. // "non-existent interface.\n",
  1686. // Line, SPEntry.SPIndex);
  1687. continue;
  1688. }
  1689. if (Error != ERROR_SUCCESS) {
  1690. NlsPutMsg(STDOUT, IPSEC_MESSAGE_47,
  1691. Error,
  1692. Line,
  1693. SPEntry.SPIndex,
  1694. GetErrorString(Error));
  1695. // printf("Error %u on line %u, policy %u: %s.\n",
  1696. // Error, Line, SPEntry.SPIndex, strerror(Error));
  1697. break;
  1698. }
  1699. Policies++;
  1700. }
  1701. } else {
  1702. if (!ParseSALine(Buffer, &SAEntry)) {
  1703. NlsPutMsg(STDOUT, IPSEC_MESSAGE_48, Line);
  1704. // printf("Error parsing SA entry fields on line %u.\n", Line);
  1705. break;
  1706. } else {
  1707. Error = CreateSecurityAssociationEntry(&SAEntry);
  1708. if (Error == ERROR_ALREADY_EXISTS) {
  1709. NlsPutMsg(STDOUT, IPSEC_MESSAGE_49,
  1710. Line, SAEntry.SA.SAIndex);
  1711. // printf("Error on line %u: an association with index "
  1712. // "%u already exists.\n", Line,
  1713. // SAEntry.SA.SAIndex);
  1714. continue;
  1715. }
  1716. if (Error != ERROR_SUCCESS) {
  1717. NlsPutMsg(STDOUT, IPSEC_MESSAGE_50,
  1718. Error, SAEntry.SA.SAIndex, GetErrorString(Error));
  1719. // printf("Error %u adding association %u: %s.\n",
  1720. // Error, SAEntry.SA.SAIndex, strerror(Error));
  1721. break;
  1722. }
  1723. Associations++;
  1724. }
  1725. }
  1726. }
  1727. if (Buffer[0] == '_')
  1728. ParseIt = TRUE;
  1729. }
  1730. if (Type == POLICY) {
  1731. if (Policies == 1) {
  1732. NlsPutMsg(STDOUT, IPSEC_MESSAGE_51, Policies);
  1733. } else {
  1734. NlsPutMsg(STDOUT, IPSEC_MESSAGE_59, Policies);
  1735. }
  1736. // printf("Added %d polic%s.\n", Policies, Policies == 1 ? "y" : "ies");
  1737. } else {
  1738. if (Associations == 1) {
  1739. NlsPutMsg(STDOUT, IPSEC_MESSAGE_52, Associations);
  1740. } else {
  1741. NlsPutMsg(STDOUT, IPSEC_MESSAGE_60, Associations);
  1742. }
  1743. // printf("Added %d association%s.\n",
  1744. // Associations, Associations == 1 ? "" : "s");
  1745. }
  1746. }