// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) // // Copyright (c) 1985-2000 Microsoft Corporation // // This file is part of the Microsoft Research IPv6 Network Protocol Stack. // You should have received a copy of the Microsoft End-User License Agreement // for this software along with this release; see the file "license.txt". // If not, please see http://www.research.microsoft.com/msripv6/license.htm, // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399. // // Abstract: // // IP Security Policy/Association management tool. // #include #include #include #include #include #include #include // // Localization library and MessageIds. // #include #include "localmsg.h" #include "ipsec.h" #define MAX_KEY_SIZE 1024 typedef struct ipv6_create_sa_and_key { IPV6_CREATE_SECURITY_ASSOCIATION SA; unsigned char Key[MAX_KEY_SIZE]; } IPV6_CREATE_SA_AND_KEY; void CreateSecurityPolicyFile(char *BaseName); void CreateSecurityAssociationFile(char *BaseName); void DisplaySecurityPolicyList(unsigned int Interface); void DisplaySecurityAssociationList(void); void ReadConfigurationFile(char *BaseName, int Type); void DeleteSecurityEntry(int Type, unsigned int Index); int AdminAccess = TRUE; HANDLE V6Stack; IPv6Addr UnspecifiedAddr = { 0 }; // // Entry types. // #define POLICY 1 #define ASSOCIATION 0 // // Amount of "____" space. // #define SA_FILE_BORDER 251 // orig 236 #define SP_FILE_BORDER 273 // was 263, orig 258 // // Transport Protocols // #define IP_PROTOCOL_TCP 6 #define IP_PROTOCOL_UDP 17 #define IP_PROTOCOL_ICMPv6 58 PWCHAR GetString(int ErrorCode, BOOL System) { DWORD Count; static WCHAR ErrorString[2048]; // a 2K static buffer should suffice Count = FormatMessageW( (System ? FORMAT_MESSAGE_FROM_SYSTEM : FORMAT_MESSAGE_FROM_HMODULE) | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ErrorString, 2048, NULL); if (Count == 0) { // failure return L""; // return a null string } return ErrorString; // success } #define GetErrorString(ErrorCode) GetString(ErrorCode, TRUE) void usage(void) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_0); // printf("\nManipulates IPv6 IPSec security policies and associations.\n\n"); // printf("IPSEC6 [SP [interface] | SA | [L | S] database | " // "D [SP | SA] index]\n\n"); // printf(" SP [interface] Displays the security policies.\n"); // printf(" SA Displays the security associations.\n"); // printf(" L database Loads the SP and SA entries from the given " // "database files;\n" // " database should be the filename without an " // "extension.\n"); // printf(" S database Saves the current SP and SA entries to the " // "given database\n" // " files; database should be the filename " // "sans extension.\n"); // printf(" D [SP | SA] index Deletes the given policy or association.\n"); // printf("\nSome subcommands require local Administrator privileges.\n"); exit(1); } void ausage(void) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_1); // printf("You do not have local Administrator privileges.\n"); exit(1); } void MakeLowerCase(char *String) { while(*String != '\0') *String++ = (char)tolower(*String); } int __cdecl main(int argc, char **argv) { int Error; WSADATA WsaData; Error = WSAStartup(MAKEWORD(2, 0), &WsaData); if (Error) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_2, Error); // printf("Unable to initialize Windows Sockets, error code %d.\n", Error); exit(1); } // // First request write access. // This will fail if the process does not have local Administrator privs. // V6Stack = CreateFileW(WIN_IPV6_DEVICE_NAME, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes OPEN_EXISTING, 0, // flags & attributes NULL); // template file if (V6Stack == INVALID_HANDLE_VALUE) { // // We will not have Administrator access to the stack. // AdminAccess = FALSE; V6Stack = CreateFileW(WIN_IPV6_DEVICE_NAME, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes OPEN_EXISTING, 0, // flags & attributes NULL); // template file if (V6Stack == INVALID_HANDLE_VALUE) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_3); // printf("Could not access IPv6 protocol stack.\n"); exit(1); } } if (argc < 2) { usage(); } MakeLowerCase(argv[1]); if (!strcmp(argv[1], "sp")) { unsigned int Interface; if (argc == 2) { Interface = 0; } else { Interface = atoi(argv[2]); } DisplaySecurityPolicyList(Interface); } else if (!strcmp(argv[1], "sa")) { DisplaySecurityAssociationList(); } else if (!strcmp(argv[1], "s")) { if (argc != 3) { usage(); } CreateSecurityPolicyFile(argv[2]); CreateSecurityAssociationFile(argv[2]); } else if (!strcmp(argv[1], "l")) { if (!AdminAccess) ausage(); if (argc != 3) { usage(); } ReadConfigurationFile(argv[2], POLICY); ReadConfigurationFile(argv[2], ASSOCIATION); } else if (!strcmp(argv[1], "d")) { unsigned int Index; int Type; if (!AdminAccess) ausage(); if (argc != 4) { usage(); } MakeLowerCase(argv[3]); if (!strcmp(argv[3], "all")) { Index = 0; } else { Index = atol(argv[3]); if (Index <= 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_4); // printf("Invalid entry number.\n"); exit(1); } } MakeLowerCase(argv[2]); if (!strcmp(argv[2], "sp")) { Type = POLICY; } else if (!strcmp(argv[2], "sa")) { Type = ASSOCIATION; } else { usage(); } DeleteSecurityEntry(Type, Index); } else { usage(); } return(0); } //* GetSecurityPolicyEntry // // Retrieves a Security Policy from the in-kernel list, given its index. // A query for index zero will return the first index on the list. // DWORD // Returns: Windows error code. GetSecurityPolicyEntry( unsigned int Interface, // IF index or 0 to wildcard. unsigned long Index, // Index to lookup, or 0 for first. IPV6_INFO_SECURITY_POLICY_LIST *Info) // Where to return SP info. { IPV6_QUERY_SECURITY_POLICY_LIST Query; unsigned int BytesReturned; Query.SPInterface = Interface; Query.Index = Index; if (!DeviceIoControl(V6Stack, IOCTL_IPV6_QUERY_SECURITY_POLICY_LIST, &Query, sizeof(Query), Info, sizeof(*Info), &BytesReturned, NULL)) { return GetLastError(); } if (BytesReturned != sizeof(*Info)) return ERROR_GEN_FAILURE; return ERROR_SUCCESS; } //* CreateSecurityPolicyEntry // // Creates a Security Policy entry on the in-kernel list. // DWORD // Returns Windows error code. CreateSecurityPolicyEntry( IPV6_CREATE_SECURITY_POLICY *NewSP) // Policy to add to kernel. { unsigned int BytesReturned; if (!DeviceIoControl(V6Stack, IOCTL_IPV6_CREATE_SECURITY_POLICY, NewSP, sizeof(*NewSP), NULL, 0, &BytesReturned, NULL)) { return GetLastError(); } // // When DeviceIoControl is given a null output buffer, the value returned // in BytesReturned is undefined. Therefore, we don't check for 0 here. // return ERROR_SUCCESS; } DWORD DeleteSecurityPolicyEntry(unsigned int Index) { IPV6_QUERY_SECURITY_POLICY_LIST Query; unsigned long BytesReturned; Query.Index = Index; if (!DeviceIoControl(V6Stack, IOCTL_IPV6_DELETE_SECURITY_POLICY, &Query, sizeof(Query), NULL, 0, &BytesReturned, NULL)) { return GetLastError(); } // // When DeviceIoControl is given a null output buffer, the value returned // in BytesReturned is undefined. Therefore, we don't check for 0 here. // return ERROR_SUCCESS; } //* GetSecurityAssociationEntry // // Retrieves a Security Association from the in-kernel list, given its index. // A query for index zero will return the first index on the list. // DWORD GetSecurityAssociationEntry( unsigned long Index, // Index to query; 0 for first. IPV6_INFO_SECURITY_ASSOCIATION_LIST *Info) // Where to return SA info. { IPV6_QUERY_SECURITY_ASSOCIATION_LIST Query; unsigned int BytesReturned; Query.Index = Index; if (!DeviceIoControl(V6Stack, IOCTL_IPV6_QUERY_SECURITY_ASSOCIATION_LIST, &Query, sizeof(Query), Info, sizeof(*Info), &BytesReturned, NULL)) { return GetLastError(); } if (BytesReturned != sizeof(*Info)) return ERROR_GEN_FAILURE; return ERROR_SUCCESS; } //* CreateSecurityAssociationEntry // // Creates a Security Association entry on the in-kernel list. // DWORD // Returns Windows error code. CreateSecurityAssociationEntry( IPV6_CREATE_SA_AND_KEY *NewSA) // Association (and key) to add to kernel. { unsigned int BytesReturned; if (!DeviceIoControl(V6Stack, IOCTL_IPV6_CREATE_SECURITY_ASSOCIATION, &NewSA->SA, sizeof(NewSA->SA) + NewSA->SA.RawKeySize, NULL, 0, &BytesReturned, NULL)) { return GetLastError(); } // // When DeviceIoControl is given a null output buffer, the value returned // in BytesReturned is undefined. Therefore, we don't check for 0 here. // return ERROR_SUCCESS; } DWORD DeleteSecurityAssociationEntry(unsigned int Index) { IPV6_QUERY_SECURITY_ASSOCIATION_LIST Query; unsigned long BytesReturned; Query.Index = Index; if (!DeviceIoControl(V6Stack, IOCTL_IPV6_DELETE_SECURITY_ASSOCIATION, &Query, sizeof(Query), NULL, 0, &BytesReturned, NULL)) { return GetLastError(); } // // When DeviceIoControl is given a null output buffer, the value returned // in BytesReturned is undefined. Therefore, we don't check for 0 here. // return ERROR_SUCCESS; } //* DeleteSecurityEntry - delete a security policy or association entry. // // Note: In the "delete all" case, it'd be much simpler not to query and // just delete wildcard until the list came up empty, but then we couldn't // report the index of any entries that failed to delete. // void DeleteSecurityEntry( int Type, // Type of entry (POLICY or ASSOCIATION). unsigned int Index) // Index of entry to delete (0 to delete all). { int EntriesDeleted = 0; int All = FALSE; DWORD Error; if (Index == 0) { All = TRUE; } do { if (All) { // // Deleting all entries. Find first on (remaining) list. // if (Type == POLICY) { IPV6_INFO_SECURITY_POLICY_LIST Info; Error = GetSecurityPolicyEntry(0, 0, &Info); if (Error == ERROR_SUCCESS) { Index = Info.SPIndex; // First entry. } else if (Error == ERROR_NO_MATCH) { Index = 0; // No more entries exist. break; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_5, Error, GetErrorString(Error)); // printf("\nError %u accessing Security Policies: %s.\n", // Error, strerror(Error)); exit(1); } } else { IPV6_INFO_SECURITY_ASSOCIATION_LIST Info; Error = GetSecurityAssociationEntry(0, &Info); if (Error == ERROR_SUCCESS) { Index = Info.SAIndex; // First entry. } else if (Error == ERROR_NO_MATCH) { Index = 0; // No more entries exist. break; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_6, Error, GetErrorString(Error)); // printf("\nError %u accessing Security Associations: %s.\n", // Error, strerror(Error)); exit(1); } } } if (Type == POLICY) { Error = DeleteSecurityPolicyEntry(Index); } else { Error = DeleteSecurityAssociationEntry(Index); } if (Error == ERROR_SUCCESS) { EntriesDeleted++; } else { if (Error == ERROR_NO_MATCH) { if (!All) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_7, Index); // printf("Error deleting entry %u: entry doesn't exist.\n", Index); } // Otherwise silently ignore ... } else if (Error == ERROR_GEN_FAILURE) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_8, Index); // printf("Error deleting entry %u.\n", Index); } else { if (Type) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_9, Error, GetErrorString(Error)); } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_56, Error, GetErrorString(Error)); } // printf("Error %u accessing security %s: %s.\n", Error, // Type ? "policies" : "associations", strerror(Error)); break; } } } while (All); if (Type == POLICY) { if (EntriesDeleted == 1) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_10, EntriesDeleted); } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_57, EntriesDeleted); } // printf("Deleted %d polic%s (and any dependent associations).\n", // EntriesDeleted, EntriesDeleted == 1 ? "y" : "ies"); } else { if (EntriesDeleted == 1) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_11, EntriesDeleted); } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_58, EntriesDeleted); } // printf("Deleted %d association%s.\n", EntriesDeleted, // EntriesDeleted == 1 ? "" : "s"); } } //* ParseAddress - convert address string to binary representation. // int ParseAddress(char *AddrString, IPv6Addr *Address) { struct addrinfo Hint; struct addrinfo *Result; memset(&Hint, 0, sizeof Hint); Hint.ai_family = PF_INET6; if (getaddrinfo(AddrString, NULL, &Hint, &Result)) return FALSE; *Address = ((struct sockaddr_in6 *)Result->ai_addr)->sin6_addr; freeaddrinfo(Result); return TRUE; } //* FormatIPv6Address - convert binary address to string representation. // // This is only used in printing SAs, thus the unspecified address // means "take from policy". // char * FormatIPv6Address(IPv6Addr *Address) { static char Buffer[46]; if (IN6_ADDR_EQUAL(Address, &UnspecifiedAddr)) { strcpy(Buffer, "POLICY"); } else { struct sockaddr_in6 SockAddr; memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin6_family = AF_INET6; memcpy(&SockAddr.sin6_addr, Address, sizeof(*Address)); if (getnameinfo((struct sockaddr *)&SockAddr, sizeof(SockAddr), Buffer, sizeof(Buffer), NULL, 0, NI_NUMERICHOST)) { strcpy(Buffer, ""); } } return Buffer; } int ParseSAAdressEntry(char *AddrString, IPv6Addr *Address) { if (!strcmp(AddrString, "POLICY")) { *Address = UnspecifiedAddr; } else { if (!ParseAddress(AddrString, Address)) { return(FALSE); } } return(TRUE); } char * FormatSPAddressEntry(IPv6Addr *AddressStart, IPv6Addr *AddressEnd, unsigned int AddressField) { const char *PointerReturn; static char Buffer[100]; char TempBuffer[100]; DWORD Buflen = sizeof Buffer; struct sockaddr_in6 sin6; switch (AddressField) { case WILDCARD_VALUE: strcpy(Buffer, "*"); break; case SINGLE_VALUE: sin6.sin6_family = AF_INET6; sin6.sin6_port = 0; sin6.sin6_flowinfo = 0; sin6.sin6_scope_id = 0; memcpy(&sin6.sin6_addr, AddressStart, sizeof *AddressStart); if (WSAAddressToString((struct sockaddr *) &sin6, sizeof sin6, NULL, // LPWSAPROTOCOL_INFO Buffer, &Buflen) == SOCKET_ERROR) { strcpy(Buffer, "???"); } break; case RANGE_VALUE: sin6.sin6_family = AF_INET6; sin6.sin6_port = 0; sin6.sin6_flowinfo = 0; sin6.sin6_scope_id = 0; memcpy(&sin6.sin6_addr, AddressStart, sizeof *AddressStart); if (WSAAddressToString((struct sockaddr *) &sin6, sizeof sin6, NULL, // LPWSAPROTOCOL_INFO Buffer, &Buflen) == SOCKET_ERROR) { strcpy(Buffer, "???"); } memcpy(&sin6.sin6_addr, AddressEnd, sizeof *AddressEnd); sin6.sin6_family = AF_INET6; sin6.sin6_port = 0; sin6.sin6_flowinfo = 0; sin6.sin6_scope_id = 0; if (WSAAddressToString((struct sockaddr *) &sin6, sizeof sin6, NULL, // LPWSAPROTOCOL_INFO TempBuffer, &Buflen) == SOCKET_ERROR) { strcpy(TempBuffer, "???"); } strcat(Buffer, "-"); strcat(Buffer, TempBuffer); break; default: strcpy(Buffer, "???"); break; } return Buffer; } //* Parse an address entry // // Valid forms include: // The wildcard indicator, "*" // A single address, e.g. "2001::1" // A range of addresses, e.g. "2001::1-2001::ffff" // void ParseSPAddressEntry( char *EntryString, // String we're given to parse. IPv6Addr *AddressStart, // Return start of range, or single address. IPv6Addr *AddressEnd, // Return end of range, or unspecified. unsigned int *AddressType) // Return entry type: WILDCARD, SINGLE, RANGE. { char *RangeEntry; RangeEntry = strchr(EntryString, '-'); if (RangeEntry == NULL) { // // Should be a wildcard, or single value. // if (!strcmp(EntryString, "*")) { *AddressType = WILDCARD_VALUE; *AddressStart = UnspecifiedAddr; } else { if (!ParseAddress(EntryString, AddressStart)) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_12, EntryString); // printf("Bad IPv6 Address, %s.\n", EntryString); exit(1); } *AddressType = SINGLE_VALUE; } *AddressEnd = UnspecifiedAddr; } else { // // We were given a range. // Break entry string into two and parse separately. // *RangeEntry++ = '\0'; if (!ParseAddress(EntryString, AddressStart)) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_13, EntryString); // printf("Bad IPv6 Start Address Range, %s.\n", EntryString); exit(1); } if (!ParseAddress(RangeEntry, AddressEnd)) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_14, RangeEntry); // printf("Bad IPv6 End Address Range, %s.\n", RangeEntry); exit(1); } *AddressType = RANGE_VALUE; } } char * FormatIPSecProto(unsigned int ProtoNum) { char *Result; switch(ProtoNum) { case IP_PROTOCOL_AH: Result = "AH"; break; case IP_PROTOCOL_ESP: Result = "ESP"; break; case NONE: Result = "NONE"; break; default: Result = "???"; break; } return Result; } unsigned int ParseIPSecProto(char *Protocol) { unsigned int Result; if (!strcmp(Protocol, "AH")) { Result = IP_PROTOCOL_AH; } else if (!strcmp(Protocol, "ESP")) { Result = IP_PROTOCOL_ESP; } else if (!strcmp(Protocol, "NONE")) { Result = NONE; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_15, Protocol); // printf("Bad IPsec Protocol Value Entry %s.\n", Protocol); exit(1); } return Result; } char * FormatIPSecMode(unsigned int Mode) { char *Result; switch(Mode) { case TRANSPORT: Result = "TRANSPORT"; break; case TUNNEL: Result = "TUNNEL"; break; case NONE: Result = "*"; break; default: Result = "???"; break; } return Result; } unsigned int ParseIPSecMode(char *Mode) { unsigned int Result; if (!strcmp(Mode, "TRANSPORT")) { Result = TRANSPORT; } else if (!strcmp(Mode, "TUNNEL")) { Result = TUNNEL; } else if (!strcmp(Mode, "*")) { Result = NONE; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_16, Mode); // printf("Bad IPsec Mode Value Entry %s.\n", Mode); exit(1); } return Result; } char * FormatRemoteGW(unsigned int Mode, IPv6Addr *Address) { switch (Mode) { case TRANSPORT: return "*"; case TUNNEL: case NONE: if (IN6_ADDR_EQUAL(Address, &UnspecifiedAddr)) { return "*"; } else { return FormatIPv6Address(Address); } } return NULL; } int ParseRemoteGW( char *AddrString, IPv6Addr *Address, unsigned int Mode) { switch (Mode) { case TRANSPORT: *Address = UnspecifiedAddr; break; case TUNNEL: case NONE: if (!strcmp(AddrString, "*")) { *Address = UnspecifiedAddr; } else if (!ParseAddress(AddrString, Address)) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_17); // printf("Bad IPv6 Address for RemoteGWIPAddr.\n"); exit(1); } break; default: break; } return TRUE; } char * FormatSATransportProto(unsigned short Protocol) { char *Result; switch (Protocol) { case IP_PROTOCOL_TCP: Result = "TCP"; break; case IP_PROTOCOL_UDP: Result = "UDP"; break; case IP_PROTOCOL_ICMPv6: Result = "ICMP"; break; case NONE: Result = "POLICY"; break; default: Result = "???"; break; } return Result; } unsigned short ParseSATransportProto(char *Protocol) { unsigned short Result; if (!strcmp(Protocol, "TCP")) { Result = IP_PROTOCOL_TCP; } else if (!strcmp(Protocol, "UDP")) { Result = IP_PROTOCOL_UDP; } else if (!strcmp(Protocol, "ICMP")) { Result = IP_PROTOCOL_ICMPv6; } else if (!strcmp(Protocol, "POLICY")) { Result = NONE; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_18, Protocol); // printf("Bad Protocol Value %s.\n", Protocol); exit(1); } return Result; } char * FormatSPTransportProto(unsigned short Protocol) { char *Result; switch (Protocol) { case IP_PROTOCOL_TCP: Result = "TCP"; break; case IP_PROTOCOL_UDP: Result = "UDP"; break; case IP_PROTOCOL_ICMPv6: Result = "ICMP"; break; case NONE: Result = "*"; break; default: Result = "???"; break; } return Result; } unsigned short ParseSPTransportProto(char *Protocol) { unsigned short Result; if (!strcmp(Protocol, "TCP")) { Result = IP_PROTOCOL_TCP; } else if (!strcmp(Protocol, "UDP")) { Result = IP_PROTOCOL_UDP; } else if (!strcmp(Protocol, "ICMP")) { Result = IP_PROTOCOL_ICMPv6; } else if (!strcmp(Protocol, "*")) { Result = NONE; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_18, Protocol); // printf("Bad Protocol Value %s.\n", Protocol); exit(1); } return Result; } char * FormatSAPort(unsigned short Port) { static char Buffer[11]; if (Port == NONE) { strcpy(Buffer, "POLICY"); } else { _itoa(Port, Buffer, 10); } return Buffer; } unsigned int ParseSAPort(char *Port) { unsigned int Result; if (!strcmp(Port, "POLICY") || !strcmp(Port, " ")) { Result = NONE; } else { Result = atoi(Port); } return Result; } char * FormatSPPort( unsigned short PortStart, unsigned short PortEnd, unsigned int PortField) { char TempBuffer[11]; static char Buffer[22]; switch (PortField) { case WILDCARD_VALUE: strcpy(Buffer, "*"); break; case RANGE_VALUE: _itoa(PortEnd, TempBuffer, 10); _itoa(PortStart, Buffer, 10); strcat(Buffer, "-"); strcat(Buffer, TempBuffer); break; case SINGLE_VALUE: _itoa(PortStart, Buffer, 10); break; default: strcpy(Buffer, "???"); break; } return Buffer; } void ParseSPPort( char *EntryString, unsigned short *PortStart, unsigned short *PortEnd, unsigned int *PortField) { char *RangeEntry; RangeEntry = strchr(EntryString, '-'); if (RangeEntry == NULL) { // // Should be a wildcard, or a single value. // if (!strcmp(EntryString, "*")) { *PortField = WILDCARD_VALUE; *PortStart = NONE; } else { *PortField = SINGLE_VALUE; *PortStart = (unsigned short)atoi(EntryString); } *PortEnd = NONE; } else { // // We were given a range. // Break entry string into two and parse separately. // *RangeEntry++ = '\0'; *PortStart = (unsigned short)atoi(EntryString); *PortEnd = (unsigned short)atoi(RangeEntry); *PortField = RANGE_VALUE; } } unsigned char * FormatSelector(unsigned int Selector) { char *Buffer; switch (Selector) { case PACKET_SELECTOR: Buffer = "+"; break; case POLICY_SELECTOR: Buffer = "-"; break; default: Buffer = "?"; break; } return Buffer; } unsigned int ParseSelector(char *Selector) { unsigned int Result; if (!strcmp(Selector, "+")) { Result = PACKET_SELECTOR; } else if (!strcmp(Selector, "-")) { Result = POLICY_SELECTOR; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_19); // printf("Bad value for one of the selector types.\n"); exit(1); } return Result; } char * FormatIndex(unsigned long Index) { static char Buffer[11]; switch (Index) { case NONE: strcpy(Buffer, "NONE"); break; default: _itoa(Index, Buffer, 10); break; } return Buffer; } unsigned long ParseIndex(char *Index) { unsigned long Result; if (!strcmp(Index, "NONE")) { Result = NONE; } else { Result = atoi(Index); } return Result; } char * FormatDirection(unsigned int Direction) { char *Buffer; switch (Direction) { case INBOUND: Buffer = "INBOUND"; break; case OUTBOUND: Buffer = "OUTBOUND"; break; case BIDIRECTIONAL: Buffer = "BIDIRECT"; break; default: Buffer = "???"; break; } return Buffer; } unsigned int ParseDirection(char *Direction) { unsigned int Result; if (!strcmp(Direction, "INBOUND")) { Result = INBOUND; } else if (!strcmp(Direction, "OUTBOUND")) { Result = OUTBOUND; } else if (!strcmp(Direction, "BIDIRECT")) { Result = BIDIRECTIONAL; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_20, Direction); // printf("Bad Direction Value Entry %s.\n", Direction); exit(1); } return Result; } char * FormatIPSecAction(unsigned int PolicyFlag) { char *Result; switch (PolicyFlag) { case IPSEC_BYPASS: Result = "BYPASS"; break; case IPSEC_DISCARD: Result = "DISCARD"; break; case IPSEC_APPLY: Result = "APPLY"; break; case IPSEC_APPCHOICE: Result = "APPCHOICE"; break; default: Result = "???"; break; } return Result; } unsigned int ParseIPSecAction(char *Action) { unsigned int Result; if (!strcmp(Action, "BYPASS")) { Result = IPSEC_BYPASS; } else if (!strcmp(Action, "DISCARD")) { Result = IPSEC_DISCARD; } else if (!strcmp(Action, "APPLY")) { Result = IPSEC_APPLY; } else if (!strcmp(Action, "APPCHOICE")) { Result = IPSEC_APPCHOICE; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_21, Action); // printf("Bad IPSec Action Value Entry %s.\n", Action); exit(1); } return Result; } char * FormatAuthAlg(unsigned int AlgorithmId) { char *Result; switch (AlgorithmId) { case ALGORITHM_NULL: Result = "NULL"; break; case ALGORITHM_HMAC_MD5: Result = "HMAC-MD5"; break; case ALGORITHM_HMAC_MD5_96: Result = "HMAC-MD5-96"; break; case ALGORITHM_HMAC_SHA1: Result = "HMAC-SHA1"; break; case ALGORITHM_HMAC_SHA1_96: Result = "HMAC-SHA1-96"; break; default: Result = "???"; break; } return Result; } unsigned int ParseAuthAlg(char *AuthAlg) { if (!strcmp(AuthAlg, "NULL")) { return ALGORITHM_NULL; } if (!strcmp(AuthAlg, "HMAC-MD5")) { return ALGORITHM_HMAC_MD5; } if (!strcmp(AuthAlg, "HMAC-MD5-96")) { return ALGORITHM_HMAC_MD5_96; } if (!strcmp(AuthAlg, "HMAC-SHA1")) { return ALGORITHM_HMAC_SHA1; } if (!strcmp(AuthAlg, "HMAC-SHA1-96")) { return ALGORITHM_HMAC_SHA1_96; } NlsPutMsg(STDOUT, IPSEC_MESSAGE_22, AuthAlg); // printf("Bad Authentication Algorithm Value Entry %s.\n", AuthAlg); exit(1); } unsigned int ReadKeyFile( char *FileName, unsigned char *Key) { FILE *KeyFile; unsigned int KeySize; if (!strcmp(FileName, "NONE")) { // This is for NULL algorithm. strcpy(Key, "NO KEY"); KeySize = strlen(Key); } else { if ((KeyFile = fopen(FileName, "r")) == NULL) { return 0; } KeySize = fread(Key, sizeof(unsigned char), MAX_KEY_SIZE, KeyFile); fclose(KeyFile); } return KeySize; } //* PrintSecurityPolicyEntry // // Print out the security policy entry, "nicely"? formatted, // to the given file. // PrintSecurityPolicyEntry( FILE *File, IPV6_INFO_SECURITY_POLICY_LIST *SPEntry) { fprintf(File, "%-10lu", SPEntry->SPIndex); fprintf(File, "%-2s", FormatSelector(SPEntry->RemoteAddrSelector)); fprintf(File, "%-45s", FormatSPAddressEntry(&(SPEntry->RemoteAddr), &(SPEntry->RemoteAddrData), SPEntry->RemoteAddrField)); fprintf(File, "%-2s", FormatSelector(SPEntry->LocalAddrSelector)); fprintf(File, "%-45s", FormatSPAddressEntry(&(SPEntry->LocalAddr), &(SPEntry->LocalAddrData), SPEntry->LocalAddrField)); fprintf(File, "%-2s", FormatSelector(SPEntry->TransportProtoSelector)); fprintf(File, "%-12s", FormatSPTransportProto(SPEntry->TransportProto)); fprintf(File, "%-2s", FormatSelector(SPEntry->RemotePortSelector)); fprintf(File, "%-12s", FormatSPPort(SPEntry->RemotePort, SPEntry->RemotePortData, SPEntry->RemotePortField)); fprintf(File, "%-2s", FormatSelector(SPEntry->LocalPortSelector)); fprintf(File, "%-12s", FormatSPPort(SPEntry->LocalPort, SPEntry->LocalPortData, SPEntry->LocalPortField)); fprintf(File, "%-15s", FormatIPSecProto(SPEntry->IPSecProtocol)); fprintf(File, "%-12s", FormatIPSecMode(SPEntry->IPSecMode)); fprintf(File, "%-45s", FormatRemoteGW(SPEntry->IPSecMode, &(SPEntry->RemoteSecurityGWAddr))); fprintf(File, "%-15s", FormatIndex(SPEntry->SABundleIndex)); fprintf(File, "%-12s", FormatDirection(SPEntry->Direction)); fprintf(File, "%-12s", FormatIPSecAction(SPEntry->IPSecAction)); fprintf(File, "%-15u", SPEntry->SPInterface); fprintf(File, ";\n"); } //* PrintSecurityPolicyHeader // // Print out the security policy header fields to the given file. // PrintSecurityPolicyHeader( FILE *File) { int Loop; fprintf(File, "%-10s", "Policy"); fprintf(File, "%-2s", " "); fprintf(File, "%-45s", "RemoteIPAddr"); fprintf(File, "%-2s", " "); fprintf(File, "%-45s", "LocalIPAddr"); fprintf(File, "%-2s", " "); fprintf(File, "%-12s", "Protocol"); fprintf(File, "%-2s", " "); fprintf(File, "%-12s", "RemotePort"); fprintf(File, "%-2s", " "); fprintf(File, "%-12s", "LocalPort"); fprintf(File, "%-15s", "IPSecProtocol"); fprintf(File, "%-12s", "IPSecMode"); fprintf(File, "%-45s", "RemoteGWIPAddr"); fprintf(File, "%-15s", "SABundleIndex"); fprintf(File, "%-12s", "Direction"); fprintf(File, "%-12s", "Action"); fprintf(File, "%-15s", "InterfaceIndex"); fprintf(File, "\n"); for (Loop = 0; Loop < SP_FILE_BORDER; Loop++) { fprintf(File, "_"); } fprintf(File, "\n"); } //* PrintSecurityPolicyFooter // // Print out the security policy footer to the given file. // PrintSecurityPolicyFooter( FILE *File) { int Loop; for (Loop = 0; Loop < SP_FILE_BORDER; Loop++) { fprintf(File, "_"); } fprintf(File, "\n\n"); fprintf(File, "- = Take selector from policy.\n"); fprintf(File, "+ = Take selector from packet.\n"); } //* PrintSecurityAssociationEntry // // Print out the security association entry, "nicely"? formatted, // to the given file. // PrintSecurityAssociationEntry( FILE *File, IPV6_INFO_SECURITY_ASSOCIATION_LIST *SAEntry) { fprintf(File, "%-10lu", SAEntry->SAIndex); fprintf(File, "%-15lu", SAEntry->SPI); fprintf(File, "%-45s", FormatIPv6Address(&(SAEntry->SADestAddr))); fprintf(File, "%-45s", FormatIPv6Address(&(SAEntry->DestAddr))); fprintf(File, "%-45s", FormatIPv6Address(&(SAEntry->SrcAddr))); fprintf(File, "%-12s", FormatSATransportProto(SAEntry->TransportProto)); fprintf(File, "%-12s", FormatSAPort(SAEntry->DestPort)); fprintf(File, "%-12s", FormatSAPort(SAEntry->SrcPort)); fprintf(File, "%-12s", FormatAuthAlg(SAEntry->AlgorithmId)); fprintf(File, "%-15s", " "); fprintf(File, "%-12s", FormatDirection(SAEntry->Direction)); fprintf(File, "%-15lu", SAEntry->SecPolicyIndex); fprintf(File, "%-1;"); fprintf(File, "\n"); } //* PrintSecurityAssociationHeader // // Print out the security association header fields to the given file. // PrintSecurityAssociationHeader( FILE *File) { int Loop; fprintf(File, "Security Association List\n\n"); fprintf(File, "%-10s", "SAEntry"); fprintf(File, "%-15s", "SPI"); fprintf(File, "%-45s", "SADestIPAddr"); fprintf(File, "%-45s", "DestIPAddr"); fprintf(File, "%-45s", "SrcIPAddr"); fprintf(File, "%-12s", "Protocol"); fprintf(File, "%-12s", "DestPort"); fprintf(File, "%-12s", "SrcPort"); fprintf(File, "%-12s", "AuthAlg"); fprintf(File, "%-15s", "KeyFile"); fprintf(File, "%-12s", "Direction"); fprintf(File, "%-15s", "SecPolicyIndex"); fprintf(File, "\n"); for (Loop = 0; Loop < SA_FILE_BORDER; Loop++) { fprintf(File, "_"); } fprintf(File, "\n"); } //* PrintSecurityAssociationFooter // // Print out the security association footer to the given file. // PrintSecurityAssociationFooter( FILE *File) { int Loop; for (Loop = 0; Loop < SA_FILE_BORDER; Loop++) { fprintf(File, "_"); } fprintf(File, "\n"); } void CreateSecurityPolicyFile(char *BaseName) { IPV6_INFO_SECURITY_POLICY_LIST Info; char FileName[MAX_PATH + 1]; FILE *File; unsigned long Index; DWORD Error; // // Copy the filename from the command line to our own buffer so we can // append an extension to it. We reserve at least 4 characters for the // extension. The strncpy function will zero fill up to the limit of // the copy, thus the character at the limit will be NULL unless the // command line field was too long to fit. // strncpy(FileName, BaseName, MAX_PATH - 3); if (FileName[MAX_PATH - 4] != 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_23); // printf("\nFilename length is too long.\n"); exit(1); } strcat(FileName, ".spd"); if ((File = fopen(FileName, "w+")) == NULL) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_24, FileName); // printf("\nFile %s could not be opened.\n", FileName); exit(1); } // // Find index of first policy on the in-kernel list. // Error = GetSecurityPolicyEntry(0, 0, &Info); switch (Error) { case ERROR_SUCCESS: Index = Info.SPIndex; // First entry. break; case ERROR_NO_MATCH: Index = 0; // No entries exist. break; default: NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error)); // printf("\nError %u reading Security Policies: %s.\n", // Error, strerror(Error)); Index = 0; break; } fprintf(File, "\nSecurity Policy List\n\n"); PrintSecurityPolicyHeader(File); // // Loop through all the policies on the list. // while (Index != 0) { Error = GetSecurityPolicyEntry(0, Index, &Info); if (Error != ERROR_SUCCESS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error)); // printf("\nError %u reading Security Policies: %s.\n", // Error, strerror(Error)); break; } PrintSecurityPolicyEntry(File, &Info); Index = Info.NextSPIndex; } PrintSecurityPolicyFooter(File); fclose(File); NlsPutMsg(STDOUT, IPSEC_MESSAGE_26, FileName); // printf("Security Policy Data -> %s\n", FileName); return; } void CreateSecurityAssociationFile(char *BaseName) { IPV6_INFO_SECURITY_ASSOCIATION_LIST Info; char FileName[MAX_PATH + 1]; FILE *File; unsigned long Index; DWORD Error; // // Copy the filename from the command line to our own buffer so we can // append an extension to it. We reserve at least 4 characters for the // extension. The strncpy function will zero fill up to the limit of // the copy, thus the character at the limit will be NULL unless the // command line field was too long to fit. // strncpy(FileName, BaseName, MAX_PATH - 3); if (FileName[MAX_PATH - 4] != 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_27); // printf("\nFilename length is too long.\n"); exit(1); } strcat(FileName, ".sad"); if ((File = fopen(FileName, "w+")) == NULL) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_28, FileName); // printf("\nFile %s could not be opened.\n", FileName); exit(1); } // // Find index of first association on the in-kernel list. // Error = GetSecurityAssociationEntry(0, &Info); switch (Error) { case ERROR_SUCCESS: Index = Info.SAIndex; // First entry. break; case ERROR_NO_MATCH: Index = 0; // No entries exist. break; default: NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error)); // printf("\nError %u reading Security Associations: %s.\n", // Error, strerror(Error)); Index = 0; break; } PrintSecurityAssociationHeader(File); // // Loop through all the associations on the list. // while (Index != 0) { Error = GetSecurityAssociationEntry(Index, &Info); if (Error != ERROR_SUCCESS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error)); // printf("\nError %u reading Security Associations: %s.\n", // Error, strerror(Error)); break; } PrintSecurityAssociationEntry(File, &Info); Index = Info.NextSAIndex; } PrintSecurityAssociationFooter(File); fclose(File); NlsPutMsg(STDOUT, IPSEC_MESSAGE_30, FileName); // printf("Security Association Data -> %s\n", FileName); return; } void DisplaySecurityPolicyList(unsigned int Interface) { IPV6_INFO_SECURITY_POLICY_LIST Info; unsigned long Index; DWORD Error; // // Find index of first policy on the in-kernel list. // Error = GetSecurityPolicyEntry(Interface, 0, &Info); switch (Error) { case ERROR_SUCCESS: Index = Info.SPIndex; // First entry. break; case ERROR_NOT_FOUND: NlsPutMsg(STDOUT, IPSEC_MESSAGE_31, Interface); // printf("Interface %u does not exist.\n", Interface); exit(1); case ERROR_NO_MATCH: NlsPutMsg(STDOUT, IPSEC_MESSAGE_32); // printf("No Security Policies exist"); if (Interface != 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_33, Interface); // printf(" for interface %d", Interface); } NlsPutMsg(STDOUT, IPSEC_MESSAGE_34); // printf(".\n"); exit(1); default: NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error)); // printf("\nError %u reading Security Policies: %s.\n", // Error, strerror(Error)); exit(1); } if (Interface == 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_35); // printf("\nAll Security Policies\n\n"); } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_36, Interface); // printf("\nSecurity Policy List for Interface %d\n\n", Interface); } PrintSecurityPolicyHeader(stdout); // // Loop through all the policies on the list. // while (Index != 0) { Error = GetSecurityPolicyEntry(Interface, Index, &Info); if (Error != ERROR_SUCCESS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_25, Error, GetErrorString(Error)); // printf("\nError %u reading Security Policies: %s.\n", // Error, strerror(Error)); exit(1); } PrintSecurityPolicyEntry(stdout, &Info); Index = Info.NextSPIndex; } PrintSecurityPolicyFooter(stdout); return; } void DisplaySecurityAssociationList(void) { IPV6_INFO_SECURITY_ASSOCIATION_LIST Info; unsigned long Index; DWORD Error; // // Find index of first association on the in-kernel list. // Error = GetSecurityAssociationEntry(0, &Info); switch (Error) { case ERROR_SUCCESS: Index = Info.SAIndex; // First entry. break; case ERROR_NO_MATCH: // There are no SA entries yet. NlsPutMsg(STDOUT, IPSEC_MESSAGE_37); // printf("No Security Associations exist.\n"); exit(1); default: NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error)); // printf("\nError %u reading Security Associations: %s.\n", // Error, strerror(Error)); exit(1); } NlsPutMsg(STDOUT, IPSEC_MESSAGE_38); // printf("\n"); PrintSecurityAssociationHeader(stdout); // // Loop through all the associations on the list. // while (Index != 0) { Error = GetSecurityAssociationEntry(Index, &Info); if (Error != ERROR_SUCCESS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_29, Error, GetErrorString(Error)); // printf("\nError %u reading Security Associations: %s.\n", // Error, strerror(Error)); exit(1); } PrintSecurityAssociationEntry(stdout, &Info); Index = Info.NextSAIndex; } PrintSecurityAssociationFooter(stdout); return; } int ParseSPLine( char *Line, // Line to parse. IPV6_CREATE_SECURITY_POLICY *SP) // Where to put the data. { char *Token; Token = strtok(Line, " "); if (Token == NULL) { return FALSE; } // Policy Number. SP->SPIndex = atol(Token); // RemoteIPAddr Selector. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->RemoteAddrSelector = ParseSelector(Token); // RemoteIPAddr. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSPAddressEntry(Token, &SP->RemoteAddr, &SP->RemoteAddrData, &SP->RemoteAddrField); // LocalIPAddr Selector. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->LocalAddrSelector = ParseSelector(Token); // LocalIPAddr. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSPAddressEntry(Token, &SP->LocalAddr, &SP->LocalAddrData, &SP->LocalAddrField); // Protocol Selector. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->TransportProtoSelector = ParseSelector(Token); // Protocol. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->TransportProto = ParseSPTransportProto(Token); // RemotePort Selector. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->RemotePortSelector = ParseSelector(Token); // RemotePort. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSPPort(Token, &SP->RemotePort, &SP->RemotePortData, &SP->RemotePortField); // LocalPort Selector. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->LocalPortSelector = ParseSelector(Token); // Local Port. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSPPort(Token, &SP->LocalPort, &SP->LocalPortData, &SP->LocalPortField); // IPSecProtocol. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->IPSecProtocol = ParseIPSecProto(Token); // IPSecMode. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->IPSecMode = ParseIPSecMode(Token); // RemoteGWIPAddr. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseRemoteGW(Token, &SP->RemoteSecurityGWAddr, SP->IPSecMode); // SABundleIndex. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->SABundleIndex = ParseIndex(Token); // Direction. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->Direction = ParseDirection(Token); // Action. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->IPSecAction = ParseIPSecAction(Token); // Interface SP. if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SP->SPInterface = atol(Token); // End of current policy. // REVIEW: Insist that nothing follows final valid field on the line? // if ((Token = strtok(NULL, " ")) != NULL) return FALSE; return TRUE; } int ParseSALine( char *Line, // Line to parse. IPV6_CREATE_SA_AND_KEY *SAAndKey) // Where to put the data. { char *Token; IPV6_CREATE_SECURITY_ASSOCIATION *SA = &(SAAndKey->SA); Token = strtok(Line, " "); if (Token == NULL) { return FALSE; } // Security Association Entry Number. SA->SAIndex = atol(Token); // SPI if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->SPI = atol(Token); // SADestAddr if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSAAdressEntry(Token, &SA->SADestAddr); // DestIPAddr if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSAAdressEntry(Token, &SA->DestAddr); // SrcIPAddr if ((Token = strtok(NULL, " ")) == NULL) return FALSE; ParseSAAdressEntry(Token, &SA->SrcAddr); // Protocol if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->TransportProto = ParseSATransportProto(Token); // DestPort if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->DestPort = (unsigned short)ParseSAPort(Token); // SrcPort if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->SrcPort = (unsigned short)ParseSAPort(Token); // AuthAlg if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->AlgorithmId = ParseAuthAlg(Token); // KeyFile if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->RawKeySize = ReadKeyFile(Token, SAAndKey->Key); if (SA->RawKeySize == 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_39, Token); // printf("Error reading key file %s\n", Token); return FALSE; } // Direction if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->Direction = ParseDirection(Token); // SecPolicyIndex if ((Token = strtok(NULL, " ")) == NULL) return FALSE; SA->SecPolicyIndex = atol(Token); // End of current association. // REVIEW: Insist that nothing follows final valid field on the line? // if ((Token = strtok(NULL, " ")) != NULL) return FALSE; return TRUE; } void ReadConfigurationFile(char *BaseName, int Type) { char Buffer[SP_FILE_BORDER + 2]; // Note: SP_FILE_BORDER > SA_FILE_BORDER char FileName[MAX_PATH + 1]; unsigned int MaxLineLengthPlusOne, LineLength, Line; FILE *File; int ParseIt = 0; IPV6_CREATE_SECURITY_POLICY SPEntry; IPV6_CREATE_SA_AND_KEY SAEntry; int Policies = 0; int Associations = 0; DWORD Error; // // Copy the filename from the command line to our own buffer so we can // append an extension to it. We reserve at least 4 characters for the // extension. The strncpy function will zero fill up to the limit of // the copy, thus the character at the limit will be NULL unless the // command line field was too long to fit. // strncpy(FileName, BaseName, MAX_PATH - 3); if (FileName[MAX_PATH - 4] != 0) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_40); // printf("\nFilename length is too long.\n"); exit(1); } // // Add appropriate file extension. // Maximum line length is the size of the field entries // plus one for the newline character. Since we need to // fgets with a value one greater than the max that can // be read in, we add that onto the maximum line length // to get MaxLineLengthPlusOne. Saves us an add later. // if (Type == POLICY) { strcat(FileName, ".spd"); MaxLineLengthPlusOne = SP_FILE_BORDER + 2; } else { if (Type == ASSOCIATION) { strcat(FileName, ".sad"); MaxLineLengthPlusOne = SA_FILE_BORDER + 2; } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_41); // printf("\nReadConfigurationFile routine called incorrectly.\n"); exit(1); } } if ((File = fopen(FileName, "r")) == NULL) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_42, FileName); // printf("\nFile %s could not be opened.\n", FileName); exit(1); } for (Line = 1; !feof(File); Line++) { if (fgets(Buffer, MaxLineLengthPlusOne, File) == NULL) break; LineLength = strlen(Buffer); // printf("Line = %u, Length = %u: %s.\n", Line, LineLength, Buffer); if (Buffer[LineLength - 1] != '\n') { NlsPutMsg(STDOUT, IPSEC_MESSAGE_43, Line); // printf("Error on line %u, line too long.\n", Line); break; } else { Buffer[LineLength - 1] = '\0'; } if (ParseIt) { if (Buffer[0] == '_') break; if (Type == POLICY) { if (!ParseSPLine(Buffer, &SPEntry)) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_44, Line); // printf("Error parsing SP entry fields on line %u.\n", Line); break; } else { Error = CreateSecurityPolicyEntry(&SPEntry); if (Error == ERROR_ALREADY_EXISTS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_45, Line, SPEntry.SPIndex); // printf("Error on line %u: a policy with index %u " // "already exists.\n", Line, SPEntry.SPIndex); continue; } if (Error == ERROR_NOT_FOUND) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_46, Line, SPEntry.SPIndex); // printf("Error on line %u: policy %u specifies a " // "non-existent interface.\n", // Line, SPEntry.SPIndex); continue; } if (Error != ERROR_SUCCESS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_47, Error, Line, SPEntry.SPIndex, GetErrorString(Error)); // printf("Error %u on line %u, policy %u: %s.\n", // Error, Line, SPEntry.SPIndex, strerror(Error)); break; } Policies++; } } else { if (!ParseSALine(Buffer, &SAEntry)) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_48, Line); // printf("Error parsing SA entry fields on line %u.\n", Line); break; } else { Error = CreateSecurityAssociationEntry(&SAEntry); if (Error == ERROR_ALREADY_EXISTS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_49, Line, SAEntry.SA.SAIndex); // printf("Error on line %u: an association with index " // "%u already exists.\n", Line, // SAEntry.SA.SAIndex); continue; } if (Error != ERROR_SUCCESS) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_50, Error, SAEntry.SA.SAIndex, GetErrorString(Error)); // printf("Error %u adding association %u: %s.\n", // Error, SAEntry.SA.SAIndex, strerror(Error)); break; } Associations++; } } } if (Buffer[0] == '_') ParseIt = TRUE; } if (Type == POLICY) { if (Policies == 1) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_51, Policies); } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_59, Policies); } // printf("Added %d polic%s.\n", Policies, Policies == 1 ? "y" : "ies"); } else { if (Associations == 1) { NlsPutMsg(STDOUT, IPSEC_MESSAGE_52, Associations); } else { NlsPutMsg(STDOUT, IPSEC_MESSAGE_60, Associations); } // printf("Added %d association%s.\n", // Associations, Associations == 1 ? "" : "s"); } }