1307 lines
38 KiB
C++
1307 lines
38 KiB
C++
|
/////////////////////////////////////////////////////////////
|
|||
|
// Copyright(c) 2000-2001, Microsoft Corporation
|
|||
|
//
|
|||
|
// text2spd.cpp
|
|||
|
//
|
|||
|
// Created on 2/15/00 by DKalin
|
|||
|
// Revisions:
|
|||
|
// Split into text2spd.cpp and spdutil.cpp 3/27/01 DKalin
|
|||
|
//
|
|||
|
// Moved the routines to this module from text2pol.cpp 2/15/00 DKalin
|
|||
|
//
|
|||
|
// Implementation for the text to policy conversion routines that deal directly with SPD structures
|
|||
|
//
|
|||
|
// Separated from generic routines in text2pol.cpp
|
|||
|
//
|
|||
|
/////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include "ipseccmd.h"
|
|||
|
|
|||
|
|
|||
|
// if szSrc and/or szDst are passed in,
|
|||
|
// caller must provide adequate space
|
|||
|
|
|||
|
DWORD TextToFilter(IN char *szText, IN OUT T2P_FILTER &Filter, char *szSrc, char *szDst)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK; // return code of this function
|
|||
|
char *pToken = NULL, *pTmp = NULL;
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
char *pPortTok = NULL,
|
|||
|
*pProtTok = NULL;
|
|||
|
BOOL bMirror = false;
|
|||
|
|
|||
|
if (szText != NULL) // do not assume that caller is smart
|
|||
|
{
|
|||
|
// We copy szText to szTmp so we can muck with it
|
|||
|
// in the process, we
|
|||
|
// determine passthru or drop filter
|
|||
|
|
|||
|
// but first we set this filter to negotiate security and to be not mirrored
|
|||
|
// we also set protocol field
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
|
|||
|
// the very first thing we do is check for default response rule specified
|
|||
|
// then we set both Inbound and Outbound filter flags to POTF_DEFAULT_RESPONSE_FLAG
|
|||
|
// and substitute "DEFAULT" string with "0+0" (Me-to-Me)
|
|||
|
if (_stricmp(POTF_FILTER_DEFAULT, szText) == 0)
|
|||
|
{
|
|||
|
Filter.TransportFilter.InboundFilterFlag = (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG;
|
|||
|
Filter.TransportFilter.OutboundFilterFlag = (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG;
|
|||
|
szText[0] = '0';
|
|||
|
szText[1] = '+';
|
|||
|
szText[2] = '0';
|
|||
|
szText[3] = '\0';
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Filter.TransportFilter.InboundFilterFlag = NEGOTIATE_SECURITY;
|
|||
|
Filter.TransportFilter.OutboundFilterFlag = NEGOTIATE_SECURITY;
|
|||
|
}
|
|||
|
|
|||
|
Filter.TransportFilter.bCreateMirror = FALSE;
|
|||
|
Filter.TransportFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
|
|||
|
Filter.TransportFilter.Protocol.dwProtocol = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
Filter.TunnelFilter.InboundFilterFlag = NEGOTIATE_SECURITY;
|
|||
|
Filter.TunnelFilter.OutboundFilterFlag = NEGOTIATE_SECURITY;
|
|||
|
Filter.TunnelFilter.bCreateMirror = FALSE;
|
|||
|
Filter.TunnelFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
|
|||
|
Filter.TunnelFilter.Protocol.dwProtocol = 0;
|
|||
|
UuidCreateNil(&(Filter.TunnelFilter.SrcTunnelAddr.gInterfaceID));
|
|||
|
UuidCreateNil(&(Filter.TunnelFilter.DesTunnelAddr.gInterfaceID));
|
|||
|
}
|
|||
|
|
|||
|
pToken = strchr(szText, POTF_PASSTHRU_OPEN_TOKEN);
|
|||
|
if (pToken != NULL)
|
|||
|
{
|
|||
|
if (strrchr(szText, POTF_PASSTHRU_CLOSE_TOKEN) == NULL)
|
|||
|
{
|
|||
|
dwReturn = T2P_PASSTHRU_NOT_CLOSED;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
strcpy(szTmp, szText + 1);
|
|||
|
szTmp[strlen(szTmp) - 1] = '\0';
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
Filter.TransportFilter.InboundFilterFlag = PASS_THRU;
|
|||
|
Filter.TransportFilter.OutboundFilterFlag = PASS_THRU;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
Filter.TunnelFilter.InboundFilterFlag = PASS_THRU;
|
|||
|
Filter.TunnelFilter.OutboundFilterFlag = PASS_THRU;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( (pToken = strchr(szText, POTF_DROP_OPEN_TOKEN)) != NULL )
|
|||
|
{
|
|||
|
if (strrchr(szText, POTF_DROP_CLOSE_TOKEN) == NULL)
|
|||
|
{
|
|||
|
dwReturn = T2P_DROP_NOT_CLOSED;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
strcpy(szTmp, szText + 1);
|
|||
|
szTmp[strlen(szTmp) - 1] = '\0';
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
Filter.TransportFilter.dwFlags |= FILTER_NATURE_BLOCKING;
|
|||
|
Filter.TransportFilter.InboundFilterFlag = BLOCKING;
|
|||
|
Filter.TransportFilter.OutboundFilterFlag = BLOCKING;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
Filter.TunnelFilter.dwFlags |= FILTER_NATURE_BLOCKING;
|
|||
|
Filter.TunnelFilter.InboundFilterFlag = BLOCKING;
|
|||
|
Filter.TunnelFilter.OutboundFilterFlag = BLOCKING;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
strcpy(szTmp, szText);
|
|||
|
|
|||
|
// parse into source and dest strings
|
|||
|
for (pToken = szText; *pToken != POTF_FILTER_TOKEN &&
|
|||
|
*pToken != POTF_FILTER_MIRTOKEN &&
|
|||
|
*pToken != '\0'; ++pToken)
|
|||
|
;
|
|||
|
if (*pToken == '\0')
|
|||
|
{
|
|||
|
dwReturn = T2P_NOSRCDEST_TOKEN;
|
|||
|
}
|
|||
|
else if ( *(pToken + 1) == '\0' )
|
|||
|
{
|
|||
|
dwReturn = T2P_NO_DESTADDR;
|
|||
|
}
|
|||
|
else if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
if (*pToken == POTF_FILTER_MIRTOKEN)
|
|||
|
{
|
|||
|
bMirror = TRUE;
|
|||
|
// set Mirrored = true
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
Filter.TransportFilter.bCreateMirror = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
Filter.TunnelFilter.bCreateMirror = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!bMirror)
|
|||
|
pToken = strchr(szTmp, POTF_FILTER_TOKEN);
|
|||
|
else
|
|||
|
pToken = strchr(szTmp, POTF_FILTER_MIRTOKEN);
|
|||
|
|
|||
|
*pToken = '\0';
|
|||
|
|
|||
|
// do the src address
|
|||
|
dwReturn = TextToFiltAddr(szTmp, Filter, szSrc);
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
// do the dest address
|
|||
|
pPortTok = strchr(pToken + 1, POTF_PT_TOKEN);
|
|||
|
|
|||
|
if (pPortTok == NULL) // no port/prot specified
|
|||
|
dwReturn = TextToFiltAddr(pToken + 1, Filter, szDst, true);
|
|||
|
else if ( (pProtTok = strchr(pPortTok + 1, POTF_PT_TOKEN)) == NULL )
|
|||
|
{
|
|||
|
// there is a port but not a protocol specified
|
|||
|
// this is illegal (bug 285266)
|
|||
|
dwReturn = T2P_INVALID_ADDR;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// there is both port and protocol specified
|
|||
|
*pProtTok = '\0';
|
|||
|
dwReturn = TextToFiltAddr(pToken + 1, Filter, szDst, true);
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
Filter.TransportFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
|
|||
|
dwReturn = TextToProtocol(pProtTok + 1, Filter.TransportFilter.Protocol.dwProtocol);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
Filter.TunnelFilter.Protocol.ProtocolType = PROTOCOL_UNIQUE;
|
|||
|
dwReturn = TextToProtocol(pProtTok + 1, Filter.TunnelFilter.Protocol.dwProtocol);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// we're done, do any fixing up of Filter
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
// set the GUID
|
|||
|
RPC_STATUS RpcStat = UuidCreate(&Filter.TransportFilter.gFilterID);
|
|||
|
if (RpcStat != RPC_S_OK && RpcStat != RPC_S_UUID_LOCAL_ONLY)
|
|||
|
{
|
|||
|
dwReturn = RpcStat;
|
|||
|
}
|
|||
|
|
|||
|
// set the name to be equal to the "text2pol " + GUID
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
WCHAR StringTxt[POTF_MAX_STRLEN];
|
|||
|
int iReturn;
|
|||
|
|
|||
|
wcscpy(StringTxt, L"text2pol ");
|
|||
|
iReturn = StringFromGUID2(Filter.TransportFilter.gFilterID, StringTxt+wcslen(StringTxt), POTF_MAX_STRLEN-wcslen(StringTxt));
|
|||
|
assert(iReturn != 0);
|
|||
|
Filter.TransportFilter.pszFilterName = new WCHAR[wcslen(StringTxt)+1];
|
|||
|
assert(Filter.TransportFilter.pszFilterName != NULL);
|
|||
|
wcscpy(Filter.TransportFilter.pszFilterName, StringTxt);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
// set the GUID
|
|||
|
RPC_STATUS RpcStat = UuidCreate(&Filter.TunnelFilter.gFilterID);
|
|||
|
if (RpcStat != RPC_S_OK && RpcStat != RPC_S_UUID_LOCAL_ONLY)
|
|||
|
{
|
|||
|
dwReturn = RpcStat;
|
|||
|
}
|
|||
|
|
|||
|
// set the name to be equal to the "text2pol " + GUID
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
WCHAR StringTxt[POTF_MAX_STRLEN];
|
|||
|
int iReturn;
|
|||
|
|
|||
|
wcscpy(StringTxt, L"text2pol ");
|
|||
|
iReturn = StringFromGUID2(Filter.TunnelFilter.gFilterID, StringTxt+wcslen(StringTxt), POTF_MAX_STRLEN-wcslen(StringTxt));
|
|||
|
assert(iReturn != 0);
|
|||
|
Filter.TunnelFilter.pszFilterName = new WCHAR[wcslen(StringTxt)+1];
|
|||
|
assert(Filter.TunnelFilter.pszFilterName != NULL);
|
|||
|
wcscpy(Filter.TunnelFilter.pszFilterName, StringTxt);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // szText is NULL
|
|||
|
dwReturn = T2P_NULL_STRING;
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD TextToFiltAddr(IN char *szAddr, IN OUT T2P_FILTER & Filter,
|
|||
|
OUT char *szName,
|
|||
|
IN bool bDest) // bDest is false
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
|
|||
|
IPAddr Address = INADDR_NONE;
|
|||
|
IPMask Mask = INADDR_NONE;
|
|||
|
WORD Port = 0;
|
|||
|
char *pMask = NULL,
|
|||
|
*pPort = NULL,
|
|||
|
*pPeek = NULL;
|
|||
|
bool bInterface = false;
|
|||
|
GUID gInterfaceId;
|
|||
|
|
|||
|
struct hostent *pHostEnt;
|
|||
|
|
|||
|
|
|||
|
if (szAddr != NULL)
|
|||
|
{
|
|||
|
// copy szAddr so we can muck with it
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
strcpy(szTmp, szAddr);
|
|||
|
|
|||
|
// let's see what we have here
|
|||
|
if ( (pPort = strrchr(szTmp, POTF_PT_TOKEN)) != NULL )
|
|||
|
{
|
|||
|
*pPort = '\0';
|
|||
|
++pPort;
|
|||
|
}
|
|||
|
if ( (pMask = strrchr(szTmp, POTF_MASK_TOKEN)) != NULL )
|
|||
|
{
|
|||
|
*pMask = '\0';
|
|||
|
++pMask;
|
|||
|
}
|
|||
|
|
|||
|
// first, the easy cases
|
|||
|
// To specify ME, use 0 for the address and -1 for the mask
|
|||
|
// To specify ANY use 0 for the address and 0 for the mask.
|
|||
|
if (szTmp[0] == POTF_ANYADDR_TOKEN)
|
|||
|
{
|
|||
|
Address = SUBNET_ADDRESS_ANY;
|
|||
|
Mask = SUBNET_MASK_ANY;
|
|||
|
}
|
|||
|
else if (szTmp[0] == POTF_ME_TOKEN)
|
|||
|
{
|
|||
|
Address = IP_ADDRESS_ME;
|
|||
|
Mask = IP_ADDRESS_MASK_NONE;
|
|||
|
}
|
|||
|
else if (szTmp[0] == POTF_GUID_TOKEN)
|
|||
|
{ // interface-specific filter
|
|||
|
char *pGUIDEnd = NULL;
|
|||
|
if ( (pGUIDEnd = strrchr(szTmp, POTF_GUID_END_TOKEN)) != NULL )
|
|||
|
{
|
|||
|
*pGUIDEnd = '\0';
|
|||
|
}
|
|||
|
if (pGUIDEnd && UuidFromStringA((unsigned char *)(szTmp+1), &gInterfaceId) == RPC_S_OK)
|
|||
|
{
|
|||
|
bInterface = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_ADDR;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (isdnsname(szTmp)) // DNS name
|
|||
|
{
|
|||
|
pHostEnt = gethostbyname(szTmp);
|
|||
|
if (pHostEnt != NULL)
|
|||
|
{
|
|||
|
Address = *(IPAddr *)pHostEnt->h_addr;
|
|||
|
// should check for more here, but not now
|
|||
|
|
|||
|
// specific host, Mask is 255.255.255.255
|
|||
|
Mask = IP_ADDRESS_MASK_NONE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_DNSLOOKUP_FAILED;
|
|||
|
}
|
|||
|
|
|||
|
if ( szName )
|
|||
|
strcpy(szName, szTmp);
|
|||
|
}
|
|||
|
else // good old dotted notation
|
|||
|
{
|
|||
|
// process the * shortcut for subnetting
|
|||
|
if (strchr(szTmp, POTF_STAR_TOKEN) != NULL)
|
|||
|
{
|
|||
|
Mask = 0x000000FF;
|
|||
|
for (pPeek = szTmp; *pPeek != '\0'; ++pPeek)
|
|||
|
{
|
|||
|
if ((*pPeek == '.') && (*(pPeek + 1) != POTF_STAR_TOKEN))
|
|||
|
Mask |= (Mask << 8);
|
|||
|
else if ((*pPeek == '.') && (*(pPeek + 1) != '\0'))
|
|||
|
*(pPeek + 1) = '0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Address = inet_addr(szTmp);
|
|||
|
if (Address == INADDR_NONE)
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_ADDR;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (pMask != NULL)
|
|||
|
{
|
|||
|
Mask = inet_addr(pMask);
|
|||
|
}
|
|||
|
else if (pPeek == NULL)
|
|||
|
Mask = IP_ADDRESS_MASK_NONE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// now for the port and fill the Filter out
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
if (pPort != NULL)
|
|||
|
{
|
|||
|
Port = (SHORT)atoi(pPort);
|
|||
|
}
|
|||
|
|
|||
|
if (Filter.QMFilterType != QM_TUNNEL_FILTER)
|
|||
|
{
|
|||
|
// transport filter
|
|||
|
if (bDest) // we converted the dest addr
|
|||
|
{
|
|||
|
if (!bInterface)
|
|||
|
{
|
|||
|
Filter.TransportFilter.DesAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
|
|||
|
Filter.TransportFilter.DesAddr.uIpAddr = Address;
|
|||
|
Filter.TransportFilter.DesAddr.uSubNetMask = Mask;
|
|||
|
Filter.TransportFilter.DesPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TransportFilter.DesPort.wPort = Port;
|
|||
|
UuidCreateNil(&(Filter.TransportFilter.DesAddr.gInterfaceID));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Filter.TransportFilter.DesAddr.AddrType = IP_ADDR_INTERFACE;
|
|||
|
Filter.TransportFilter.DesAddr.uIpAddr = IP_ADDRESS_ME;
|
|||
|
Filter.TransportFilter.DesAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
|
|||
|
Filter.TransportFilter.DesPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TransportFilter.DesPort.wPort = Port;
|
|||
|
Filter.TransportFilter.DesAddr.gInterfaceID = gInterfaceId;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (!bInterface)
|
|||
|
{
|
|||
|
Filter.TransportFilter.SrcAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
|
|||
|
Filter.TransportFilter.SrcAddr.uIpAddr = Address;
|
|||
|
Filter.TransportFilter.SrcAddr.uSubNetMask = Mask;
|
|||
|
Filter.TransportFilter.SrcPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TransportFilter.SrcPort.wPort = Port;
|
|||
|
UuidCreateNil(&(Filter.TransportFilter.SrcAddr.gInterfaceID));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Filter.TransportFilter.SrcAddr.AddrType = IP_ADDR_INTERFACE;
|
|||
|
Filter.TransportFilter.SrcAddr.uIpAddr = IP_ADDRESS_ME;
|
|||
|
Filter.TransportFilter.SrcAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
|
|||
|
Filter.TransportFilter.SrcPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TransportFilter.SrcPort.wPort = Port;
|
|||
|
Filter.TransportFilter.SrcAddr.gInterfaceID = gInterfaceId;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// tunnel filter
|
|||
|
if (bDest) // we converted the dest addr
|
|||
|
{
|
|||
|
if (!bInterface)
|
|||
|
{
|
|||
|
Filter.TunnelFilter.DesAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
|
|||
|
Filter.TunnelFilter.DesAddr.uIpAddr = Address;
|
|||
|
Filter.TunnelFilter.DesAddr.uSubNetMask = Mask;
|
|||
|
Filter.TunnelFilter.DesPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TunnelFilter.DesPort.wPort = Port;
|
|||
|
UuidCreateNil(&(Filter.TunnelFilter.DesAddr.gInterfaceID));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Filter.TunnelFilter.DesAddr.AddrType = IP_ADDR_INTERFACE;
|
|||
|
Filter.TunnelFilter.DesAddr.uIpAddr = IP_ADDRESS_ME;
|
|||
|
Filter.TunnelFilter.DesAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
|
|||
|
Filter.TunnelFilter.DesPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TunnelFilter.DesPort.wPort = Port;
|
|||
|
Filter.TunnelFilter.DesAddr.gInterfaceID = gInterfaceId;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (!bInterface)
|
|||
|
{
|
|||
|
Filter.TunnelFilter.SrcAddr.AddrType = (Mask == IP_ADDRESS_MASK_NONE) ? IP_ADDR_UNIQUE : IP_ADDR_SUBNET;
|
|||
|
Filter.TunnelFilter.SrcAddr.uIpAddr = Address;
|
|||
|
Filter.TunnelFilter.SrcAddr.uSubNetMask = Mask;
|
|||
|
Filter.TunnelFilter.SrcPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TunnelFilter.SrcPort.wPort = Port;
|
|||
|
UuidCreateNil(&(Filter.TunnelFilter.SrcAddr.gInterfaceID));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Filter.TunnelFilter.SrcAddr.AddrType = IP_ADDR_INTERFACE;
|
|||
|
Filter.TunnelFilter.SrcAddr.uIpAddr = IP_ADDRESS_ME;
|
|||
|
Filter.TunnelFilter.SrcAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
|
|||
|
Filter.TunnelFilter.SrcPort.PortType = PORT_UNIQUE;
|
|||
|
Filter.TunnelFilter.SrcPort.wPort = Port;
|
|||
|
Filter.TunnelFilter.SrcAddr.gInterfaceID = gInterfaceId;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
dwReturn = T2P_NULL_STRING;
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD TextToProtocol(IN char *szProt, OUT DWORD & dwProtocol)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
|
|||
|
if (szProt != NULL)
|
|||
|
{
|
|||
|
// is it special string
|
|||
|
if (isalpha(szProt[0]))
|
|||
|
{
|
|||
|
if (_stricmp(szProt, POTF_TCP_STR) == 0)
|
|||
|
dwProtocol = (POTF_TCP_PROTNUM);
|
|||
|
else if (_stricmp(szProt, POTF_UDP_STR) == 0)
|
|||
|
dwProtocol = (POTF_UDP_PROTNUM);
|
|||
|
else if (_stricmp(szProt, POTF_ICMP_STR) == 0)
|
|||
|
dwProtocol = (POTF_ICMP_PROTNUM);
|
|||
|
else if (_stricmp(szProt, POTF_RAW_STR) == 0)
|
|||
|
dwProtocol = (POTF_RAW_PROTNUM);
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_PROTOCOL;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwProtocol = ((DWORD)atol(szProt));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD TextToOffer(IN char *szText, IN OUT IPSEC_QM_OFFER & Offer)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
char *pAnd = NULL,
|
|||
|
*pOptions = NULL,
|
|||
|
*pString = NULL;
|
|||
|
|
|||
|
if (szText != NULL)
|
|||
|
{
|
|||
|
// we will for sure overwrite the Count and Algos
|
|||
|
// since they are required for valid conversion
|
|||
|
Offer.dwNumAlgos = 0;
|
|||
|
Offer.dwPFSGroup = 0;
|
|||
|
|
|||
|
// copy szText so we can muck it up
|
|||
|
strcpy(szTmp, szText);
|
|||
|
|
|||
|
// process Rekey and PFS first
|
|||
|
pOptions = strrchr(szTmp, POTF_NEGPOL_CLOSE);
|
|||
|
if ((pOptions != NULL) && *(pOptions + 1) != '\0')
|
|||
|
{
|
|||
|
++pOptions; // we have options
|
|||
|
|
|||
|
pString = strchr(pOptions, POTF_NEGPOL_PFS);
|
|||
|
if (pString != NULL)
|
|||
|
{
|
|||
|
char *pStr;
|
|||
|
Offer.bPFSRequired = TRUE;
|
|||
|
Offer.dwPFSGroup = PFS_GROUP_MM;
|
|||
|
pStr = strchr(pString, '1');
|
|||
|
if (pStr)
|
|||
|
{
|
|||
|
Offer.dwPFSGroup = PFS_GROUP_1;
|
|||
|
}
|
|||
|
pStr = strchr(pString, '2');
|
|||
|
if (pStr)
|
|||
|
{
|
|||
|
Offer.dwPFSGroup = PFS_GROUP_2;
|
|||
|
}
|
|||
|
*pString = '\0';
|
|||
|
}
|
|||
|
|
|||
|
if (pString != pOptions) // user could have specified just PFS
|
|||
|
{
|
|||
|
// process key lifetime
|
|||
|
|
|||
|
// two params specified?
|
|||
|
pString = strchr(pOptions, POTF_REKEY_TOKEN);
|
|||
|
if (pString != NULL)
|
|||
|
{
|
|||
|
*pString = '\0';
|
|||
|
++pString;
|
|||
|
|
|||
|
switch (pString[strlen(pString) - 1])
|
|||
|
{
|
|||
|
case 'k':
|
|||
|
case 'K':
|
|||
|
pString[strlen(pString) - 1] = '\0';
|
|||
|
Offer.Lifetime.uKeyExpirationKBytes = atol(pString);
|
|||
|
|
|||
|
if ( Offer.Lifetime.uKeyExpirationKBytes < POTF_MIN_P2LIFE_BYTES )
|
|||
|
{
|
|||
|
dwReturn = T2P_P2REKEY_TOO_LOW;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
case 's':
|
|||
|
case 'S':
|
|||
|
pString[strlen(pString) - 1] = '\0';
|
|||
|
Offer.Lifetime.uKeyExpirationTime = atol(pString);
|
|||
|
|
|||
|
if ( Offer.Lifetime.uKeyExpirationTime < POTF_MIN_P2LIFE_TIME )
|
|||
|
{
|
|||
|
dwReturn = T2P_P2REKEY_TOO_LOW;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
default:
|
|||
|
dwReturn = T2P_INVALID_P2REKEY_UNIT;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
switch (pOptions[strlen(pOptions) - 1])
|
|||
|
{
|
|||
|
case 'k':
|
|||
|
case 'K':
|
|||
|
pOptions[strlen(pOptions) - 1] = '\0';
|
|||
|
Offer.Lifetime.uKeyExpirationKBytes = atol(pOptions);
|
|||
|
|
|||
|
if ( Offer.Lifetime.uKeyExpirationKBytes < POTF_MIN_P2LIFE_BYTES )
|
|||
|
{
|
|||
|
dwReturn = T2P_P2REKEY_TOO_LOW;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
case 's':
|
|||
|
case 'S':
|
|||
|
pOptions[strlen(pOptions) - 1] = '\0';
|
|||
|
Offer.Lifetime.uKeyExpirationTime = atol(pOptions);
|
|||
|
|
|||
|
if ( Offer.Lifetime.uKeyExpirationTime < POTF_MIN_P2LIFE_TIME )
|
|||
|
{
|
|||
|
dwReturn = T2P_P2REKEY_TOO_LOW;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
default:
|
|||
|
dwReturn = T2P_INVALID_P2REKEY_UNIT;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// important: we have to do this here so the alginfo
|
|||
|
// gets processed ok:
|
|||
|
*pOptions = '\0';
|
|||
|
}
|
|||
|
|
|||
|
if ( T2P_SUCCESS(dwReturn) )
|
|||
|
{
|
|||
|
// now process the ipsec protocol spec AH, ESP
|
|||
|
|
|||
|
pAnd = strchr(szTmp, POTF_NEGPOL_AND);
|
|||
|
|
|||
|
if ( pAnd != NULL )
|
|||
|
{
|
|||
|
// we have an AND proposal
|
|||
|
*pAnd = '\0';
|
|||
|
++pAnd;
|
|||
|
|
|||
|
dwReturn = TextToAlgoInfo(szTmp, Offer.Algos[Offer.dwNumAlgos]);
|
|||
|
++Offer.dwNumAlgos;
|
|||
|
if ( T2P_SUCCESS(dwReturn) )
|
|||
|
{
|
|||
|
|
|||
|
dwReturn = TextToAlgoInfo(pAnd, Offer.Algos[Offer.dwNumAlgos]);
|
|||
|
++Offer.dwNumAlgos;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = TextToAlgoInfo(szTmp, Offer.Algos[Offer.dwNumAlgos]);
|
|||
|
++Offer.dwNumAlgos;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
dwReturn = T2P_NULL_STRING;
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD TextToAlgoInfo(IN char *szText, OUT IPSEC_QM_ALGO & algoInfo)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
char *pOpen = NULL,
|
|||
|
*pClose = NULL,
|
|||
|
*pString = NULL;
|
|||
|
|
|||
|
// these are used for processing AND to default to NONE
|
|||
|
bool bEncryption = false, bAuthentication= false;
|
|||
|
|
|||
|
if (szText == NULL)
|
|||
|
return T2P_NULL_STRING;
|
|||
|
|
|||
|
// muck with the string so we can copy it ;)
|
|||
|
strcpy(szTmp, szText);
|
|||
|
|
|||
|
algoInfo.uAlgoKeyLen = algoInfo.uAlgoRounds = 0;
|
|||
|
|
|||
|
pOpen = strchr(szTmp, POTF_NEGPOL_OPEN);
|
|||
|
pClose = strrchr(szTmp, POTF_NEGPOL_CLOSE);
|
|||
|
|
|||
|
if ((pOpen != NULL) && (pClose != NULL) && (*(pClose + 1) == '\0')) // defense
|
|||
|
{
|
|||
|
*pOpen = '\0';
|
|||
|
*pClose = '\0';
|
|||
|
++pOpen;
|
|||
|
|
|||
|
if (_stricmp(szTmp, POTF_NEGPOL_AH) == 0)
|
|||
|
{
|
|||
|
if (_stricmp(pOpen, POTF_NEGPOL_MD5) == 0)
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_AH_MD5;
|
|||
|
else if (_stricmp(pOpen, POTF_NEGPOL_SHA) == 0 || _stricmp(pOpen, POTF_NEGPOL_SHA1) == 0)
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_HASH_ALG;
|
|||
|
}
|
|||
|
|
|||
|
algoInfo.Operation = AUTHENTICATION;
|
|||
|
}
|
|||
|
else if (_stricmp(szTmp, POTF_NEGPOL_ESP) == 0)
|
|||
|
{
|
|||
|
algoInfo.Operation = ENCRYPTION;
|
|||
|
|
|||
|
pString = strchr(pOpen, POTF_ESPTRANS_TOKEN);
|
|||
|
|
|||
|
if (pString != NULL)
|
|||
|
{
|
|||
|
*pString = '\0';
|
|||
|
++pString;
|
|||
|
|
|||
|
// we allow the hash and encryption to be specified in either
|
|||
|
// the first or second field-- hence the long conditionals
|
|||
|
if (_stricmp(pOpen, POTF_NEGPOL_DES) == 0)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
|
|||
|
}
|
|||
|
else if (_stricmp(pOpen, POTF_NEGPOL_3DES) == 0)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
|
|||
|
}
|
|||
|
else if (_stricmp(pOpen, POTF_NEGPOL_MD5) == 0)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
algoInfo.uSecAlgoIdentifier = HMAC_AH_MD5;
|
|||
|
}
|
|||
|
else if (_stricmp(pOpen, POTF_NEGPOL_SHA) == 0 || _stricmp(pOpen, POTF_NEGPOL_SHA1) == 0)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
algoInfo.uSecAlgoIdentifier = HMAC_AH_SHA1;
|
|||
|
}
|
|||
|
else if (_stricmp(pOpen, POTF_NEGPOL_NONE) != 0) // parse error
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
// now the second one
|
|||
|
|
|||
|
if (_stricmp(pString, POTF_NEGPOL_DES) == 0 && !bEncryption)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
|
|||
|
}
|
|||
|
else if (_stricmp(pString, POTF_NEGPOL_3DES) == 0 && !bEncryption)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
|
|||
|
}
|
|||
|
else if (_stricmp(pString, POTF_NEGPOL_MD5) == 0 && !bAuthentication)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
algoInfo.uSecAlgoIdentifier = HMAC_AH_MD5;
|
|||
|
}
|
|||
|
else if ((_stricmp(pString, POTF_NEGPOL_SHA) == 0 || _stricmp(pString, POTF_NEGPOL_SHA1) == 0) && !bAuthentication)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
algoInfo.uSecAlgoIdentifier = HMAC_AH_SHA1;
|
|||
|
}
|
|||
|
else if (_stricmp(pString, POTF_NEGPOL_NONE) != 0) // parse error
|
|||
|
{
|
|||
|
dwReturn = T2P_DUP_ALGS;
|
|||
|
}
|
|||
|
|
|||
|
// now, fill in the NONE policies or detect NONE, NONE
|
|||
|
if (!bAuthentication && !bEncryption)
|
|||
|
{
|
|||
|
dwReturn = T2P_NONE_NONE;
|
|||
|
}
|
|||
|
else if (!bAuthentication)
|
|||
|
{
|
|||
|
algoInfo.uSecAlgoIdentifier = HMAC_AH_NONE;
|
|||
|
}
|
|||
|
else if (!bEncryption)
|
|||
|
{
|
|||
|
algoInfo.uAlgoIdentifier = IPSEC_DOI_ESP_NONE;
|
|||
|
}
|
|||
|
}
|
|||
|
else // error
|
|||
|
{
|
|||
|
dwReturn = T2P_INCOMPLETE_ESPALGS;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_IPSECPROT;
|
|||
|
}
|
|||
|
}
|
|||
|
else // error
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD TextToOakleyAuth(IN char *szText, OUT IPSEC_MM_AUTH_INFO & AuthInfo)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
char *pString = NULL,
|
|||
|
*pTmp = NULL;
|
|||
|
char *szTmp = NULL;
|
|||
|
char *Info = NULL;
|
|||
|
|
|||
|
if (szText != NULL)
|
|||
|
{
|
|||
|
// copy szText so we can muck with it
|
|||
|
szTmp = new char[strlen(szText)+1];
|
|||
|
assert(szTmp != 0);
|
|||
|
strcpy(szTmp, szText);
|
|||
|
|
|||
|
// parse string
|
|||
|
if ( (pString = strchr(szTmp, POTF_OAKAUTH_TOKEN)) != NULL )
|
|||
|
*pString = '\0';
|
|||
|
|
|||
|
// not UNICODE compliant
|
|||
|
if (tolower(szTmp[0]) == tolower(POTF_OAKAUTH_PRESHARE[0]))
|
|||
|
{
|
|||
|
if ((pString != NULL) && (strlen(pString + 1) > 0) )
|
|||
|
{
|
|||
|
++pString; // now pointing at string
|
|||
|
|
|||
|
AuthInfo.AuthMethod = IKE_PRESHARED_KEY;
|
|||
|
|
|||
|
if (*pString == '"') // fix up if the user included quotes
|
|||
|
{
|
|||
|
++pString;
|
|||
|
pTmp = strrchr(pString, '"');
|
|||
|
if (pTmp != NULL)
|
|||
|
{
|
|||
|
*pTmp = '\0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// convert to wide and fill in
|
|||
|
Info = new char[strlen(pString) + 1];
|
|||
|
assert(Info != NULL);
|
|||
|
strcpy(Info, pString);
|
|||
|
}
|
|||
|
else // no key provided
|
|||
|
{
|
|||
|
dwReturn = T2P_NO_PRESHARED_KEY;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (tolower(szTmp[0]) == tolower(POTF_OAKAUTH_KERBEROS[0]))
|
|||
|
{
|
|||
|
AuthInfo.AuthMethod = IKE_SSPI;
|
|||
|
}
|
|||
|
else if (tolower(szTmp[0]) == tolower(POTF_OAKAUTH_CERT[0]))
|
|||
|
{
|
|||
|
AuthInfo.AuthMethod = IKE_RSA_SIGNATURE;
|
|||
|
|
|||
|
if ((pString != NULL) && (strlen(pString + 1) > 0) )
|
|||
|
{
|
|||
|
// CA is indicated
|
|||
|
|
|||
|
++pString; // now pointing at string
|
|||
|
|
|||
|
Info = new char[strlen(pString) + 1];
|
|||
|
assert(Info != NULL);
|
|||
|
|
|||
|
if (*pString == '"') // fix up if the user included quotes
|
|||
|
{
|
|||
|
++pString;
|
|||
|
pTmp = strrchr(pString, '"');
|
|||
|
if (pTmp != NULL)
|
|||
|
{
|
|||
|
*pTmp = '\0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
strcpy(Info, pString);
|
|||
|
}
|
|||
|
|
|||
|
// else the CA will be negotiated
|
|||
|
|
|||
|
}
|
|||
|
else // invalid option
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_AUTH_METHOD;
|
|||
|
}
|
|||
|
|
|||
|
// now convert the ascii to wide char
|
|||
|
// authinfo needs to be wide
|
|||
|
if (Info != NULL && T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
AuthInfo.pAuthInfo = NULL;
|
|||
|
AuthInfo.dwAuthInfoSize = 0;
|
|||
|
|
|||
|
AuthInfo.dwAuthInfoSize = MultiByteToWideChar(CP_THREAD_ACP, 0, Info, -1,
|
|||
|
(WCHAR *) AuthInfo.pAuthInfo, 0);
|
|||
|
if (AuthInfo.dwAuthInfoSize == 0) // failure
|
|||
|
{
|
|||
|
dwReturn = T2P_MB2WC_FAILED;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
AuthInfo.pAuthInfo = (LPBYTE) new WCHAR[AuthInfo.dwAuthInfoSize];
|
|||
|
assert(AuthInfo.pAuthInfo != NULL);
|
|||
|
AuthInfo.dwAuthInfoSize = MultiByteToWideChar(CP_THREAD_ACP, 0, Info, -1,
|
|||
|
(WCHAR *) AuthInfo.pAuthInfo, AuthInfo.dwAuthInfoSize);
|
|||
|
AuthInfo.dwAuthInfoSize--;
|
|||
|
AuthInfo.dwAuthInfoSize *= sizeof(WCHAR);
|
|||
|
}
|
|||
|
|
|||
|
if (AuthInfo.dwAuthInfoSize == 0) // failure
|
|||
|
{
|
|||
|
delete [] AuthInfo.pAuthInfo;
|
|||
|
dwReturn = T2P_MB2WC_FAILED;
|
|||
|
}
|
|||
|
|
|||
|
// now do additional conversion if this is cert
|
|||
|
if (T2P_SUCCESS(dwReturn) && AuthInfo.AuthMethod == IKE_RSA_SIGNATURE)
|
|||
|
{
|
|||
|
LPBYTE asnCert;
|
|||
|
dwReturn = CM_EncodeName((LPWSTR) AuthInfo.pAuthInfo, &asnCert, &AuthInfo.dwAuthInfoSize);
|
|||
|
delete [] AuthInfo.pAuthInfo;
|
|||
|
if (dwReturn != ERROR_SUCCESS)
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_AUTH_METHOD;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AuthInfo.pAuthInfo = asnCert;
|
|||
|
dwReturn = T2P_OK;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
dwReturn = T2P_NULL_STRING;
|
|||
|
|
|||
|
if (Info) delete Info;
|
|||
|
if (szTmp) delete szTmp;
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD TextToSecMethod(IN char *szText, IN OUT IPSEC_MM_OFFER & SecMethod)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
char *pString1 = NULL,
|
|||
|
*pString2 = NULL;
|
|||
|
bool bEncryption = false,
|
|||
|
bAuthentication = false;
|
|||
|
|
|||
|
if (szText == NULL)
|
|||
|
return T2P_NULL_STRING;
|
|||
|
|
|||
|
// copy szText so we can muck it up
|
|||
|
strcpy(szTmp, szText);
|
|||
|
pString1 = strchr(szTmp, POTF_P1_TOKEN);
|
|||
|
pString2 = strrchr(szTmp, POTF_P1_TOKEN);
|
|||
|
|
|||
|
if ((pString1 != NULL) && (pString2 != NULL) && (pString1 != pString2))
|
|||
|
{
|
|||
|
// string parsed ok so far
|
|||
|
*pString1 = '\0';
|
|||
|
*pString2 = '\0';
|
|||
|
++pString1;
|
|||
|
++pString2;
|
|||
|
|
|||
|
// we allow the hash and encryption to be specified in either
|
|||
|
// the first or second field-- hence the long conditionals
|
|||
|
if (_stricmp(szTmp, POTF_P1_DES) == 0)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else if (_stricmp(szTmp, POTF_P1_3DES) == 0)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else if (_stricmp(szTmp, POTF_P1_MD5) == 0)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_MD5;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else if (_stricmp(szTmp, POTF_P1_SHA) == 0)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else // parse error
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
if (_stricmp(pString1, POTF_P1_DES) == 0 && !bEncryption)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_DES;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else if (_stricmp(pString1, POTF_P1_3DES) == 0 && !bEncryption)
|
|||
|
{
|
|||
|
bEncryption = true;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
|
|||
|
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else if (_stricmp(pString1, POTF_P1_MD5) == 0 && !bAuthentication)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_MD5;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else if (_stricmp(pString1, POTF_P1_SHA) == 0 && !bAuthentication)
|
|||
|
{
|
|||
|
bAuthentication = true;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
|
|||
|
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
|
|||
|
}
|
|||
|
else // parse error
|
|||
|
{
|
|||
|
dwReturn = T2P_DUP_ALGS;
|
|||
|
}
|
|||
|
|
|||
|
// now for the group
|
|||
|
if (isdigit(pString2[0]))
|
|||
|
{
|
|||
|
switch (pString2[0])
|
|||
|
{
|
|||
|
case '1':
|
|||
|
SecMethod.dwDHGroup = POTF_OAKLEY_GROUP1;
|
|||
|
break;
|
|||
|
case '2':
|
|||
|
SecMethod.dwDHGroup = POTF_OAKLEY_GROUP2;
|
|||
|
break;
|
|||
|
default:
|
|||
|
dwReturn = T2P_INVALID_P1GROUP;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_P1GROUP_MISSING;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else // parse error
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD TextToP1Rekey(IN char *szText, IN OUT KEY_LIFETIME & LifeTime, OUT DWORD & QMLim)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
char *pString = NULL;
|
|||
|
|
|||
|
if (!szText)
|
|||
|
return T2P_NULL_STRING;
|
|||
|
|
|||
|
// copy szText so we can muck it up
|
|||
|
strcpy(szTmp, szText);
|
|||
|
|
|||
|
// two params specified?
|
|||
|
pString = strchr(szTmp, POTF_QM_TOKEN);
|
|||
|
if (pString != NULL)
|
|||
|
{
|
|||
|
*pString = '\0';
|
|||
|
++pString;
|
|||
|
|
|||
|
switch (pString[strlen(pString) - 1])
|
|||
|
{
|
|||
|
case 'q':
|
|||
|
case 'Q':
|
|||
|
pString[strlen(pString) - 1] = '\0';
|
|||
|
QMLim = atol(pString);
|
|||
|
break;
|
|||
|
case 's':
|
|||
|
case 'S':
|
|||
|
pString[strlen(pString) - 1] = '\0';
|
|||
|
LifeTime.uKeyExpirationTime = atol(pString);
|
|||
|
break;
|
|||
|
default:
|
|||
|
dwReturn = T2P_INVALID_P1REKEY_UNIT;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
switch (szTmp[strlen(szTmp) - 1])
|
|||
|
{
|
|||
|
case 'q':
|
|||
|
case 'Q':
|
|||
|
szTmp[strlen(szTmp) - 1] = '\0';
|
|||
|
QMLim = atol(szTmp);
|
|||
|
break;
|
|||
|
case 's':
|
|||
|
case 'S':
|
|||
|
szTmp[strlen(szTmp) - 1] = '\0';
|
|||
|
LifeTime.uKeyExpirationTime = atol(szTmp);
|
|||
|
break;
|
|||
|
default:
|
|||
|
dwReturn = T2P_INVALID_P1REKEY_UNIT;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
// caveat, won't go deep into DNS
|
|||
|
DWORD TextToIPAddr(IN char *szText, IN OUT IPAddr & Address)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK;
|
|||
|
struct hostent *pHostEnt;
|
|||
|
|
|||
|
if (szText != NULL)
|
|||
|
{
|
|||
|
|
|||
|
if (!strcmp(szText, POTF_ME_TUNNEL))
|
|||
|
{
|
|||
|
Address = 0;
|
|||
|
}
|
|||
|
else if (isdnsname(szText)) // DNS name
|
|||
|
{
|
|||
|
pHostEnt = gethostbyname(szText);
|
|||
|
if (pHostEnt != NULL)
|
|||
|
{
|
|||
|
Address = *(IPAddr *)pHostEnt->h_addr;
|
|||
|
// should check for more here, but not now
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_DNSLOOKUP_FAILED;
|
|||
|
}
|
|||
|
}
|
|||
|
else // good old dotted notation
|
|||
|
{
|
|||
|
Address = inet_addr(szText);
|
|||
|
if (Address == INADDR_NONE)
|
|||
|
{
|
|||
|
dwReturn = T2P_INVALID_ADDR;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dwReturn = T2P_NULL_STRING;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
// if szSrc and/or szDst are passed in,
|
|||
|
// caller must provide adequate space
|
|||
|
|
|||
|
DWORD TextToMMFilter(IN char *szText, IN OUT MM_FILTER &Filter, char *szSrc, char *szDst)
|
|||
|
{
|
|||
|
DWORD dwReturn = T2P_OK; // return code of this function
|
|||
|
char *pToken = NULL, *pTmp = NULL;
|
|||
|
char szTmp[POTF_MAX_STRLEN];
|
|||
|
char *pPortTok = NULL,
|
|||
|
*pProtTok = NULL;
|
|||
|
BOOL bMirror = false;
|
|||
|
T2P_FILTER t2pFilter; // for TextToFilterAddr calls
|
|||
|
|
|||
|
if (szText != NULL) // do not assume that caller is smart
|
|||
|
{
|
|||
|
// We copy szText to szTmp so we can muck with it
|
|||
|
// in the process, we
|
|||
|
// determine passthru or drop filter
|
|||
|
|
|||
|
// but first we set this filter to negotiate security and to be not mirrored
|
|||
|
// we also set protocol field
|
|||
|
Filter.bCreateMirror = FALSE;
|
|||
|
|
|||
|
// set up T2P_FILTER
|
|||
|
t2pFilter.QMFilterType = QM_TRANSPORT_FILTER;
|
|||
|
memset(&t2pFilter.TransportFilter, 0, sizeof(TRANSPORT_FILTER));
|
|||
|
|
|||
|
pToken = strchr(szText, POTF_PASSTHRU_OPEN_TOKEN);
|
|||
|
if (pToken != NULL)
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
else if ( (pToken = strchr(szText, POTF_DROP_OPEN_TOKEN)) != NULL )
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
else
|
|||
|
strcpy(szTmp, szText);
|
|||
|
|
|||
|
// parse into source and dest strings
|
|||
|
for (pToken = szText; *pToken != POTF_FILTER_TOKEN &&
|
|||
|
*pToken != POTF_FILTER_MIRTOKEN &&
|
|||
|
*pToken != '\0'; ++pToken)
|
|||
|
;
|
|||
|
if (*pToken == '\0')
|
|||
|
{
|
|||
|
dwReturn = T2P_NOSRCDEST_TOKEN;
|
|||
|
}
|
|||
|
else if ( *(pToken + 1) == '\0' )
|
|||
|
{
|
|||
|
dwReturn = T2P_NO_DESTADDR;
|
|||
|
}
|
|||
|
else if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
if (*pToken == POTF_FILTER_MIRTOKEN)
|
|||
|
{
|
|||
|
bMirror = TRUE;
|
|||
|
// set Mirrored = true
|
|||
|
Filter.bCreateMirror = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if (!bMirror)
|
|||
|
pToken = strchr(szTmp, POTF_FILTER_TOKEN);
|
|||
|
else
|
|||
|
pToken = strchr(szTmp, POTF_FILTER_MIRTOKEN);
|
|||
|
|
|||
|
*pToken = '\0';
|
|||
|
|
|||
|
// check for port presence
|
|||
|
pPortTok = strchr(szTmp, POTF_PT_TOKEN);
|
|||
|
if (pPortTok != NULL)
|
|||
|
{
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// do the src address
|
|||
|
dwReturn = TextToFiltAddr(szTmp, t2pFilter, szSrc);
|
|||
|
// copy src address
|
|||
|
Filter.SrcAddr = t2pFilter.TransportFilter.SrcAddr;
|
|||
|
}
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
// do the dest address
|
|||
|
pPortTok = strchr(pToken + 1, POTF_PT_TOKEN);
|
|||
|
|
|||
|
if (pPortTok == NULL) // no port/prot specified
|
|||
|
{
|
|||
|
dwReturn = TextToFiltAddr(pToken + 1, t2pFilter, szDst, true);
|
|||
|
// copy dest address
|
|||
|
Filter.DesAddr = t2pFilter.TransportFilter.DesAddr;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// error
|
|||
|
dwReturn = T2P_GENERAL_PARSE_ERROR;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// we're done, do any fixing up of Filter
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
// set the GUID
|
|||
|
RPC_STATUS RpcStat = UuidCreate(&Filter.gFilterID);
|
|||
|
if (RpcStat != RPC_S_OK && RpcStat != RPC_S_UUID_LOCAL_ONLY)
|
|||
|
{
|
|||
|
dwReturn = RpcStat;
|
|||
|
}
|
|||
|
|
|||
|
// set the name to be equal to the "text2pol " + GUID
|
|||
|
if (T2P_SUCCESS(dwReturn))
|
|||
|
{
|
|||
|
WCHAR StringTxt[POTF_MAX_STRLEN];
|
|||
|
int iReturn;
|
|||
|
|
|||
|
wcscpy(StringTxt, L"text2pol ");
|
|||
|
iReturn = StringFromGUID2(Filter.gFilterID, StringTxt+wcslen(StringTxt), POTF_MAX_STRLEN-wcslen(StringTxt));
|
|||
|
assert(iReturn != 0);
|
|||
|
Filter.pszFilterName = new WCHAR[wcslen(StringTxt)+1];
|
|||
|
assert(Filter.pszFilterName != NULL);
|
|||
|
wcscpy(Filter.pszFilterName, StringTxt);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // szText is NULL
|
|||
|
dwReturn = T2P_NULL_STRING;
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|