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

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