Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1300 lines
42 KiB

/////////////////////////////////////////////////////////////
// Copyright(c) 1998-2000, Microsoft Corporation
//
// text2pol.cpp
//
// Created on 4/5/98 by Randyram
// Revisions:
// Moved the routines to this module 8/25/98
//
// Split into text2pol.cpp, text2spd.h and text2spd.cpp 2/15/00 DKalin
//
// Implementation for the text to policy conversion routines (generic ones)
// (See more in the text2spd.cpp)
//
/////////////////////////////////////////////////////////////
#include "ipseccmd.h"
// CFilter storage version
DWORD ConvertFilter(IN T2P_FILTER &Filter,
IN OUT IPSEC_FILTER_SPEC &PolstoreFilter)
{
DWORD dwReturn = T2P_OK; // return code of this function
PolstoreFilter.pszSrcDNSName = PolstoreFilter.pszDestDNSName = 0;
if (Filter.QMFilterType == QM_TRANSPORT_FILTER)
{
PolstoreFilter.FilterSpecGUID = Filter.TransportFilter.gFilterID;
PolstoreFilter.pszDescription = IPSecAllocPolStr(Filter.TransportFilter.pszFilterName);
PolstoreFilter.dwMirrorFlag = Filter.TransportFilter.bCreateMirror;
PolstoreFilter.Filter.SrcAddr = Filter.TransportFilter.SrcAddr.uIpAddr;
PolstoreFilter.Filter.SrcMask = Filter.TransportFilter.SrcAddr.uSubNetMask;
PolstoreFilter.Filter.DestAddr = Filter.TransportFilter.DesAddr.uIpAddr;
PolstoreFilter.Filter.DestMask = Filter.TransportFilter.DesAddr.uSubNetMask;
PolstoreFilter.Filter.TunnelAddr = 0;
PolstoreFilter.Filter.Protocol = Filter.TransportFilter.Protocol.dwProtocol;
PolstoreFilter.Filter.SrcPort = Filter.TransportFilter.SrcPort.wPort;
PolstoreFilter.Filter.DestPort = Filter.TransportFilter.DesPort.wPort;
PolstoreFilter.Filter.TunnelFilter = FALSE;
}
else
{
// tunnel filter
PolstoreFilter.FilterSpecGUID = Filter.TunnelFilter.gFilterID;
PolstoreFilter.pszDescription = IPSecAllocPolStr(Filter.TunnelFilter.pszFilterName);
PolstoreFilter.dwMirrorFlag = FALSE;
PolstoreFilter.Filter.SrcAddr = Filter.TunnelFilter.SrcAddr.uIpAddr;
PolstoreFilter.Filter.SrcMask = Filter.TunnelFilter.SrcAddr.uSubNetMask;
PolstoreFilter.Filter.DestAddr = Filter.TunnelFilter.DesAddr.uIpAddr;
PolstoreFilter.Filter.DestMask = Filter.TunnelFilter.DesAddr.uSubNetMask;
PolstoreFilter.Filter.TunnelAddr = Filter.TunnelFilter.DesTunnelAddr.uIpAddr;
PolstoreFilter.Filter.Protocol = Filter.TunnelFilter.Protocol.dwProtocol;
PolstoreFilter.Filter.SrcPort = Filter.TunnelFilter.SrcPort.wPort;
PolstoreFilter.Filter.DestPort = Filter.TunnelFilter.DesPort.wPort;
PolstoreFilter.Filter.TunnelFilter = TRUE;
}
return dwReturn;
}
DWORD TextToStorageLocation(IN char *szText, OUT STORAGE_INFO & StoreInfo)
{
DWORD dwReturn = T2P_OK;
WCHAR *pString = NULL,
*pTmp = NULL;
WCHAR szTmp[POTF_MAX_STRLEN];
WCHAR *Info = NULL;
if (szText != NULL)
{
// copy szText so we can muck with it
_stprintf(szTmp, TEXT("%S"), szText);
// parse string
if ( (pString = wcschr(szTmp, POTF_STORAGE_TOKEN)) != NULL )
*pString = L'\0';
if (towlower(szTmp[0]) == tolower(POTF_STORAGE_DS[0]))
{
StoreInfo.Type = STORAGE_TYPE_DS;
if ((pString != NULL) && (wcslen(pString + 1) > 0) )
{
++pString; // now pointing at string
wcscpy(StoreInfo.szLocationName, pString);
}
// else no domain provided
}
else if (towlower(szTmp[0]) == tolower(POTF_STORAGE_REG[0]))
{
StoreInfo.Type = STORAGE_TYPE_REGISTRY;
}
else if (towlower(szTmp[0]) == tolower(POTF_STORAGE_CACHE[0]))
{
StoreInfo.Type = STORAGE_TYPE_CACHE;
}
else // invalid option
{
dwReturn = T2P_INVALID_STORAGE_INFO;
}
}
else
dwReturn = T2P_NULL_STRING;
return dwReturn;
}
// the whole reason to have this is to extract the polling interval
// if specified
DWORD TextToPolicyName(IN char *szText, OUT STORAGE_INFO & StoreInfo)
{
DWORD dwReturn = T2P_OK;
WCHAR *pString = NULL,
*pTmp = NULL;
WCHAR szTmp[POTF_MAX_STRLEN];
WCHAR *Info = NULL;
if (szText != NULL)
{
// copy szText so we can muck with it
_stprintf(szTmp, TEXT("%S"), szText);
// parse string
if ( (pString = wcschr(szTmp, POTF_STORAGE_TOKEN)) != NULL )
*pString = '\0';
wcscpy(StoreInfo.szPolicyName, szTmp);
if ((pString != NULL) && (wcslen(pString + 1) > 0) )
{
++pString; // now pointing at polling interval
// XX could be checked more stringently
// do the converstion to minutes here
StoreInfo.tPollingInterval = 60 * (wcstol(pString, NULL, 10));
}
}
else
dwReturn = T2P_NULL_STRING;
return dwReturn;
}
bool InStorageMode(IN UINT uArgCount, IN char *strArgs[])
{
for (UINT i = 0; i < uArgCount; ++i)
if ( strArgs[i][1] == POTF_STORAGE_FLAG )
return true;
return false;
}
// CmdLineToPolicy
// pStorageInfo has NULL as default
// Returns False if there is any kind of failure
DWORD CmdLineToPolicy(IN UINT uArgCount, IN char *strArgs[],
OUT IPSEC_IKE_POLICY & IpsecIkePol,
OUT bool & bConfirm
,OUT PSTORAGE_INFO pStorageInfo)
{
DWORD dwReturn = T2P_OK;
IPSEC_QM_POLICY IpsPol;
IPSEC_MM_POLICY IkePol;
MM_AUTH_METHODS AuthInfos;
MM_FILTER* pMMFilters;
DWORD dwNumMMFilters;
QM_FILTER_TYPE QMFilterType;
DWORD dwNumFilters;
TRANSPORT_FILTER* pTransportFilters;
TUNNEL_FILTER* pTunnelFilters;
memcpy(&IpsPol, &IpsecIkePol.IpsPol, sizeof(IpsPol));
memcpy(&IkePol, &IpsecIkePol.IkePol, sizeof(IkePol));
memcpy(&AuthInfos, &IpsecIkePol.AuthInfos, sizeof(AuthInfos));
pMMFilters = IpsecIkePol.pMMFilters;
dwNumMMFilters = IpsecIkePol.dwNumMMFilters;
QMFilterType = IpsecIkePol.QMFilterType;
dwNumFilters = IpsecIkePol.dwNumFilters;
pTransportFilters = IpsecIkePol.pTransportFilters;
pTunnelFilters = IpsecIkePol.pTunnelFilters;
// used when finding out how much mem to alloc
UINT uFiltAlloc = 0,
uMMFiltAlloc = 0,
uSecMetAlloc = 0,
uOfferAlloc = 0,
uAuthAlloc = 0;
UINT i = 0; // loop cntr
bool bIsMirrorFilt = false,
bMirrorFiltRC = true; // since MirrorFilt is not a T2P mod
T2P_FILTER Filter; // for TextToFilter calls
memset(&Filter, 0, sizeof(Filter));
Filter.QMFilterType = QM_TRANSPORT_FILTER; // by default it's transport
bConfirm = false;
// for post-processing Ike policy
bool bP1RekeyUsed = false;
KEY_LIFETIME OakLife;
DWORD QMLimit = POTF_DEFAULT_P1REKEY_QMS;
OakLife.uKeyExpirationTime = POTF_DEFAULT_P1REKEY_TIME;
OakLife.uKeyExpirationKBytes = 0; // not used
IF_TYPE Interface = INTERFACE_TYPE_ALL;
IPAddr DesTunnelAddr = 0;
IPAddr SrcTunnelAddr = 0;
// We do some things differently in storage mode:
// * process negotiation policy actions
// * use a different filter list
//
// This could all be much cleaner, but until the cmd line
// parsing is actually separated from the policy processing
// we're pretty much stuck with this unless we want to duplicated
// alot of code. eg. 2 cmdlinetopolicy, one dynamic, one storage
//
bool bStorageMode = InStorageMode(uArgCount, strArgs);
if ( bStorageMode && !pStorageInfo )
return T2P_NO_STORAGE_INFO;
//
// we'll allow the cmd line to specify
// storage options. Use a temp structure to hold those
// options-- then we'll copy it at the end if pStorageInfo != NULL
//
STORAGE_INFO tmpStorageInfo;
memset(&tmpStorageInfo, 0, sizeof(tmpStorageInfo));
tmpStorageInfo.guidNegPolAction = GUID_NEGOTIATION_ACTION_NORMAL_IPSEC;
// init OUT params (free them if necessary)
if (IkePol.pOffers != NULL)
{
free(IkePol.pOffers);
}
IkePol.pOffers = NULL;
IkePol.dwOfferCount = 0;
if (IpsPol.pOffers != NULL)
{
free(IpsPol.pOffers);
}
IpsPol.pOffers = NULL;
IpsPol.dwOfferCount = 0;
if (AuthInfos.pAuthenticationInfo != NULL)
{
for (i = 0; i < (UINT) AuthInfos.dwNumAuthInfos; i++)
{
if (AuthInfos.pAuthenticationInfo[i].pAuthInfo != NULL)
free(AuthInfos.pAuthenticationInfo[i].pAuthInfo);
}
free(AuthInfos.pAuthenticationInfo);
}
AuthInfos.pAuthenticationInfo = NULL;
AuthInfos.dwNumAuthInfos = NULL;
// cleanup filters
if (pTransportFilters != NULL)
{
for (i = 0; i < (UINT) dwNumFilters; i++)
{
if (pTransportFilters[i].pszFilterName != NULL)
free(pTransportFilters[i].pszFilterName);
}
free(pTransportFilters);
}
pTransportFilters = NULL;
if (pTunnelFilters != NULL)
{
for (i = 0; i < (UINT) dwNumFilters; i++)
{
if (pTunnelFilters[i].pszFilterName != NULL)
free(pTunnelFilters[i].pszFilterName);
}
free(pTunnelFilters);
}
pTunnelFilters = NULL;
QMFilterType = Filter.QMFilterType;
dwNumFilters = 0;
// mm filters
if (pMMFilters != NULL)
{
for (i = 0; i < (UINT) dwNumMMFilters; i++)
{
if (pMMFilters[i].pszFilterName != NULL)
free(pMMFilters[i].pszFilterName);
}
free(pMMFilters);
}
pMMFilters = NULL;
dwNumMMFilters = 0;
// we assume uArgCount and strArgs are OK
// but defend against ######### here
if (uArgCount > 0 && strArgs != NULL)
{
// find out how much memory we're going to need
// we do this here because I allow multiple flags of same type
for (i = 1; i < uArgCount; )
{
if ( strchr(POTF_FLAG_TOKENS, strArgs[i][0]) != NULL )
{
if (strArgs[i][1] == POTF_FILTER_FLAG)
{
if (strArgs[i][2] != '\0') // user omitted space
{
++uFiltAlloc;
}
++i;
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
++uFiltAlloc;
++i;
}
}
else if (strArgs[i][1] == POTF_NEGPOL_FLAG)
{
if (strArgs[i][2] != '\0') // user omitted space
++uOfferAlloc;
++i;
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
++uOfferAlloc;
++i;
}
}
else if (strArgs[i][1] == POTF_AUTH_FLAG)
{
if (strArgs[i][2] != '\0') // user omitted space
++uAuthAlloc;
++i;
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
++uAuthAlloc;
++i;
}
}
else if ( strncmp(&strArgs[i][1], POTF_SECMETHOD_FLAG,
strlen(POTF_SECMETHOD_FLAG)) == 0 )
{
if (strArgs[i][3] != '\0') // user omitted space
++uSecMetAlloc;
++i;
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
++uSecMetAlloc;
++i;
}
}
else if ( strncmp(&strArgs[i][1], POTF_MMFILTER_FLAG,
strlen(POTF_MMFILTER_FLAG)) == 0 )
{
if (strArgs[i][3] != '\0') // user omitted space
++uMMFiltAlloc;
++i;
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
++uMMFiltAlloc;
++i;
}
}
else if (strArgs[i][1] == POTF_TUNNEL_FLAG)
{
// switch to tunnel mode
QMFilterType = Filter.QMFilterType = QM_TUNNEL_FILTER;
i++;
}
else
++i;
}
else
++i;
}
// now allocate the memory
if (uFiltAlloc)
{
// we allocate both transport and tunnel filter storage because of RPC reasons
pTransportFilters = new TRANSPORT_FILTER[uFiltAlloc + 1];
assert(pTransportFilters != NULL);
// init these
for (i = 0; i <= uFiltAlloc; ++i)
memset(&pTransportFilters[i], 0, sizeof(TRANSPORT_FILTER));
memset(&Filter.TransportFilter, 0, sizeof(TRANSPORT_FILTER));
// tunnel mode
pTunnelFilters = new TUNNEL_FILTER[uFiltAlloc + 1];
assert(pTunnelFilters != NULL);
// init these
for (i = 0; i <= uFiltAlloc; ++i)
memset(&pTunnelFilters[i], 0, sizeof(TUNNEL_FILTER));
memset(&Filter.TunnelFilter, 0, sizeof(TUNNEL_FILTER));
if (!uMMFiltAlloc)
{
// allocate main mode filters for auto-generation
pMMFilters = new MM_FILTER[uFiltAlloc + 1];
assert(pMMFilters != NULL);
// init these
for (i = 0; i <= uFiltAlloc; ++i)
memset(&pMMFilters[i], 0, sizeof(MM_FILTER));
}
}
if (uMMFiltAlloc)
{
// allocate main mode filters
pMMFilters = new MM_FILTER[uMMFiltAlloc + 1];
assert(pMMFilters != NULL);
// init these
for (i = 0; i <= uMMFiltAlloc; ++i)
memset(&pMMFilters[i], 0, sizeof(MM_FILTER));
}
if (uAuthAlloc)
{
AuthInfos.pAuthenticationInfo = new IPSEC_MM_AUTH_INFO[uAuthAlloc + 1];
assert(AuthInfos.pAuthenticationInfo != NULL);
// init these
for (i = 0; i <= uAuthAlloc; ++i)
memset(&AuthInfos.pAuthenticationInfo[i], 0, sizeof(IPSEC_MM_AUTH_INFO));
}
if (uOfferAlloc)
{
IpsPol.pOffers = new IPSEC_QM_OFFER[uOfferAlloc + 1];
assert(IpsPol.pOffers != NULL);
// init these
for (i = 0; i <= uOfferAlloc; ++i)
{
memset(&IpsPol.pOffers[i], 0, sizeof(IPSEC_QM_OFFER));
}
}
if (uSecMetAlloc)
{
IkePol.pOffers = new IPSEC_MM_OFFER[uSecMetAlloc + 1];
assert(IkePol.pOffers != NULL);
// init these
for (i = 0; i <= uSecMetAlloc; ++i)
{
memset(&IkePol.pOffers[i], 0, sizeof(IPSEC_MM_OFFER));
}
}
// Main processing loop ////////////////////////////////////////////////////////
// invariants;
// 1. use dwReturn when calling util functions, if returns false
// break out of for loop and let cleanup code take over
// 2. advance i each time you process a param
for (i = 1; i < uArgCount && T2P_SUCCESS(dwReturn); ) // we'll advance i below
{
// make sure there is actually a flag, else we have parse error
if ( strchr(POTF_FLAG_TOKENS, strArgs[i][0]) != NULL )
{
if (strArgs[i][1] == POTF_FILTER_FLAG) // filter list
{
// first filter is special case because user may
// omit space after flag
if ((strArgs[i][2] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][2]) == NULL))
{
//
// Even if we're in storage mode, we use these
// filters.
//
dwReturn = TextToFilter(&strArgs[i][2], Filter);
if (QMFilterType == QM_TRANSPORT_FILTER)
{
memcpy(&pTransportFilters[dwNumFilters], &Filter.TransportFilter, sizeof(TRANSPORT_FILTER));
}
else
{
// tunnel
memcpy(&pTunnelFilters[dwNumFilters], &Filter.TunnelFilter, sizeof(TUNNEL_FILTER));
}
if (!T2P_SUCCESS(dwReturn))
break;
else
{
++dwNumFilters;
}
}
else if (strArgs[i][2] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
++i; // advance to next arg
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
//
// Even if we're in storage mode, we fill these in
//
dwReturn = TextToFilter(&strArgs[i][0], Filter);
if (QMFilterType == QM_TRANSPORT_FILTER)
{
memcpy(&pTransportFilters[dwNumFilters], &Filter.TransportFilter, sizeof(TRANSPORT_FILTER));
}
else
{
// tunnel
memcpy(&pTunnelFilters[dwNumFilters], &Filter.TunnelFilter, sizeof(TUNNEL_FILTER));
}
if (!T2P_SUCCESS(dwReturn))
break;
else
{
++dwNumFilters;
}
++i; // advance to next arg
}
}
else if (strArgs[i][1] == POTF_NEGPOL_FLAG)
{
// first offer is special case because user may
// omit space after flag
if ((strArgs[i][2] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][2]) == NULL))
{
if ( !strcmp(&strArgs[i][2], POTF_PASSTHRU) )
{
tmpStorageInfo.guidNegPolAction
= GUID_NEGOTIATION_ACTION_NO_IPSEC;
}
else if ( !strcmp(&strArgs[i][2], POTF_INBOUND_PASSTHRU) )
{
tmpStorageInfo.guidNegPolAction =
GUID_NEGOTIATION_ACTION_INBOUND_PASSTHRU;
}
else if ( !strcmp(&strArgs[i][2], POTF_BLOCK) )
{
tmpStorageInfo.guidNegPolAction =
GUID_NEGOTIATION_ACTION_BLOCK;
}
else
{
dwReturn = TextToOffer(&strArgs[i][2], IpsPol.pOffers[IpsPol.dwOfferCount]);
if (!T2P_SUCCESS(dwReturn)) break;
else ++IpsPol.dwOfferCount;
}
}
else if (strArgs[i][2] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
++i; // advance to next arg
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
if ( !strcmp(&strArgs[i][0], POTF_PASSTHRU) )
{
tmpStorageInfo.guidNegPolAction
= GUID_NEGOTIATION_ACTION_NO_IPSEC;
}
else if ( !strcmp(&strArgs[i][0], POTF_INBOUND_PASSTHRU) )
{
tmpStorageInfo.guidNegPolAction =
GUID_NEGOTIATION_ACTION_INBOUND_PASSTHRU;
}
else if ( !strcmp(&strArgs[i][0], POTF_BLOCK) )
{
tmpStorageInfo.guidNegPolAction =
GUID_NEGOTIATION_ACTION_BLOCK;
}
else
{
dwReturn = TextToOffer(&strArgs[i][0], IpsPol.pOffers[IpsPol.dwOfferCount]);
if (!T2P_SUCCESS(dwReturn)) goto error_occured;
else ++IpsPol.dwOfferCount;
}
++i; // advance to next arg
}
}
else if (strArgs[i][1] == POTF_TUNNEL_FLAG)
{
if (strArgs[i][2] != '\0') // no space after flag
{
TextToIPAddr(&strArgs[i][2], DesTunnelAddr);
}
else
{
++i;
TextToIPAddr(&strArgs[i][0], DesTunnelAddr);
}
++i;
// now check for second tunnel address
if (i < uArgCount && strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL)
{
// not an option, tunnel address
SrcTunnelAddr = DesTunnelAddr;
TextToIPAddr(&strArgs[i][0], DesTunnelAddr);
++i;
}
}
else if (strArgs[i][1] == POTF_AUTH_FLAG)
{
// first offer is special case because user may
// omit space after flag
if ((strArgs[i][2] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][2]) == NULL))
{
dwReturn = TextToOakleyAuth(&strArgs[i][2], AuthInfos.pAuthenticationInfo[AuthInfos.dwNumAuthInfos]);
if (!T2P_SUCCESS(dwReturn)) break;
else ++AuthInfos.dwNumAuthInfos;
}
else if (strArgs[i][2] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
++i; // advance to next arg
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
dwReturn = TextToOakleyAuth(&strArgs[i][0], AuthInfos.pAuthenticationInfo[AuthInfos.dwNumAuthInfos]);
if (!T2P_SUCCESS(dwReturn)) goto error_occured;
else ++AuthInfos.dwNumAuthInfos;
++i; // advance to next arg
}
}
else if (strArgs[i][1] == POTF_STORAGE_FLAG)
{
if ((strArgs[i][2] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][2]) == NULL))
{
dwReturn = TextToStorageLocation(&strArgs[i][2], tmpStorageInfo);
if (!T2P_SUCCESS(dwReturn)) break;
}
else if (strArgs[i][2] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
else // storage info must be in next param
{
++i; // advance to next arg
if ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
dwReturn = TextToStorageLocation(&strArgs[i][0], tmpStorageInfo);
if (!T2P_SUCCESS(dwReturn)) goto error_occured;
++i; // advance to next arg
}
else
{
sprintf(STRLASTERR,
"You must specify storage info: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
}
}
else if (strArgs[i][1] == POTF_POLNAME_FLAG)
{
if ((strArgs[i][2] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][2]) == NULL))
{
dwReturn = TextToPolicyName(&strArgs[i][2], tmpStorageInfo);
if (!T2P_SUCCESS(dwReturn)) break;
}
else if (strArgs[i][2] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
else // policy name must be in next param
{
++i; // advance to next arg
if ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
dwReturn = TextToPolicyName(&strArgs[i][0], tmpStorageInfo);
if (!T2P_SUCCESS(dwReturn)) goto error_occured;
++i; // advance to next arg
}
else
{
sprintf(STRLASTERR,
"You must specify policy name: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
}
}
else if (strArgs[i][1] == POTF_RULENAME_FLAG)
{
// first offer is special case because user may
// omit space after flag
if ((strArgs[i][2] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][2]) == NULL))
{
_stprintf(tmpStorageInfo.szRuleName, TEXT("%S"), &strArgs[i][2]);
}
else if (strArgs[i][2] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
else // policy name must be in next param
{
++i; // advance to next arg
if ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
_stprintf(tmpStorageInfo.szRuleName, TEXT("%S"), &strArgs[i][0]);
++i; // advance to next arg
}
else
{
sprintf(STRLASTERR,
"You must specify rule name: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
}
}
else if (strArgs[i][1] == POTF_SETACTIVE_FLAG)
{
tmpStorageInfo.bSetActive = TRUE;
++i;
}
else if (strArgs[i][1] == POTF_SETINACTIVE_FLAG)
{
tmpStorageInfo.bSetInActive = TRUE;
++i;
}
else if (strArgs[i][1] == POTF_CONFIRM_FLAG)
{
bConfirm = true;
++i;
}
else if (strArgs[i][1] == POTF_DELETEPOLICY_FLAG)
{
tmpStorageInfo.bDeletePolicy = true;
++i;
}
else if ( strncmp(&strArgs[i][1], POTF_DIALUP_FLAG,
strlen(POTF_DIALUP_FLAG)) == 0 )
{
Interface = INTERFACE_TYPE_DIALUP;
++i;
}
else if (strArgs[i][1] == POTF_DEACTIVATE_FLAG)
{
// deactivate local registry policy right here
// this is left for backward compatibility with old text2pol
// directory policy assignment left intact
HANDLE hRegPolicyStore = NULL;
PIPSEC_POLICY_DATA pipspd = NULL;
DWORD dwRes = ERROR_SUCCESS;
dwRes = IPSecOpenPolicyStore(NULL, IPSEC_REGISTRY_PROVIDER, NULL, &hRegPolicyStore);
if (dwRes == ERROR_SUCCESS && hRegPolicyStore != NULL)
{
dwRes = IPSecGetAssignedPolicyData(hRegPolicyStore, &pipspd);
if (dwRes == ERROR_SUCCESS && pipspd != NULL)
{
dwRes = IPSecUnassignPolicy(hRegPolicyStore, pipspd[0].PolicyIdentifier);
IPSecFreePolicyData(pipspd);
}
IPSecClosePolicyStore(hRegPolicyStore);
}
if (dwRes != ERROR_SUCCESS)
{
sprintf(STRLASTERR,
"Polstore operation returned 0x%x!\n", dwRes);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
++i;
}
else if ( strncmp(&strArgs[i][1], POTF_MMFILTER_FLAG,
strlen(POTF_MMFILTER_FLAG)) == 0 )
{
// first filter is special case because user may
// omit space after flag
if ((strArgs[i][3] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][3]) == NULL))
{
dwReturn = TextToMMFilter(&strArgs[i][3], pMMFilters[dwNumMMFilters]);
if (!T2P_SUCCESS(dwReturn))
break;
else
{
++dwNumMMFilters;
}
}
else if (strArgs[i][3] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
break;
}
++i; // advance to next arg
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
dwReturn = TextToMMFilter(&strArgs[i][0], pMMFilters[dwNumMMFilters]);
if (!T2P_SUCCESS(dwReturn))
break;
else
{
++dwNumMMFilters;
}
++i; // advance to next arg
}
}
else if ( strncmp(&strArgs[i][1], POTF_SECMETHOD_FLAG,
strlen(POTF_SECMETHOD_FLAG)) == 0 )
{
// first method is special case because user may
// omit space after flag
if ((strArgs[i][3] != '\0')
&& (strchr(POTF_FLAG_TOKENS, strArgs[i][3]) == NULL))
{
dwReturn = TextToSecMethod(&strArgs[i][3], IkePol.pOffers[IkePol.dwOfferCount]);
if (!T2P_SUCCESS(dwReturn)) break;
else ++IkePol.dwOfferCount;
}
else if (strArgs[i][3] != '\0')
{
sprintf(STRLASTERR,
"Unexpected flag: %s. Check usage.\n", strArgs[i]);
PARSE_ERROR;
dwReturn = false;
break;
}
++i; // advance to next arg
while ( (i < uArgCount) && (strchr(POTF_FLAG_TOKENS, strArgs[i][0]) == NULL) )
{
dwReturn = TextToSecMethod(&strArgs[i][0], IkePol.pOffers[IkePol.dwOfferCount]);
if (!T2P_SUCCESS(dwReturn)) goto error_occured;
else ++IkePol.dwOfferCount;
++i; // advance to next arg
}
}
else if ( strncmp(&strArgs[i][1], POTF_P1PFS_FLAG,
strlen(POTF_P1PFS_FLAG)) == 0 )
{
QMLimit = 1;
bP1RekeyUsed = true; // will fixup all the P1 offers later
++i;
}
else if ( strncmp(&strArgs[i][1], POTF_SOFTSA_FLAG,
strlen(POTF_SOFTSA_FLAG)) == 0 )
{
IpsPol.dwFlags |= IPSEC_QM_POLICY_ALLOW_SOFT;
if (!IkePol.uSoftSAExpirationTime)
{
// set this time to default
IkePol.uSoftSAExpirationTime = POTF_DEF_P1SOFT_TIME;
}
++i;
}
else if ( strncmp(&strArgs[i][1], POTF_LAN_FLAG,
strlen(POTF_LAN_FLAG)) == 0 )
{
Interface = INTERFACE_TYPE_LAN;
++i;
}
else if ( strncmp(&strArgs[i][1], POTF_SOFTSAEXP_FLAG,
strlen(POTF_SOFTSAEXP_FLAG)) == 0 )
{
if (strArgs[i][3] != '\0')
{
// they may have omitted a space
IkePol.uSoftSAExpirationTime = atol(&strArgs[i][3]);
++i;
}
else
{
++i;
// process next arg
IkePol.uSoftSAExpirationTime = atol(&strArgs[i][0]);
++i;
}
}
else if ( strncmp(&strArgs[i][1], POTF_P1REKEY_FLAG,
strlen(POTF_P1REKEY_FLAG)) == 0 )
{
// special case because user may
// omit space after flag
if (strArgs[i][3] != '\0')
{
dwReturn = TextToP1Rekey(&strArgs[i][3], OakLife, QMLimit);
if (!T2P_SUCCESS(dwReturn)) break;
++i; // advance to next arg
}
else
{
++i; // advance to next arg
dwReturn = TextToP1Rekey(&strArgs[i][0], OakLife, QMLimit);
if (!T2P_SUCCESS(dwReturn)) break;
++i; // advance to next arg
}
bP1RekeyUsed = true;
}
else
{
sprintf(STRLASTERR,
"Unknown flag: %s\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
}
} // end if flag
else
{
sprintf(STRLASTERR,
"I don't understand:\n%s\n", strArgs[i]);
PARSE_ERROR;
dwReturn = POTF_FAILED;
}
} // end main processing loop
// now do some post-processing
// either cleanup for errors or fix up policy
if ( bP1RekeyUsed && T2P_SUCCESS(dwReturn) && (IkePol.pOffers == NULL))
{
LoadIkeDefaults(IkePol);
}
// filter post-processing
// apply interface type to transports and interface type + tunnel address to tunnels
if (QMFilterType == QM_TRANSPORT_FILTER)
{
for (i = 0; i < dwNumFilters; i++)
{
RPC_STATUS RpcStat = RPC_S_OK;
pTransportFilters[i].InterfaceType = Interface;
// apply guidNegPolAction so that PASS INPASS and BLOCK take effect here
if (UuidCompare(&(tmpStorageInfo.guidNegPolAction), (UUID *) &GUID_NEGOTIATION_ACTION_INBOUND_PASSTHRU, &RpcStat) == 0 && RpcStat == RPC_S_OK)
{
pTransportFilters[i].InboundFilterFlag = PASS_THRU;
pTransportFilters[i].OutboundFilterFlag = NEGOTIATE_SECURITY;
}
else if (UuidCompare(&(tmpStorageInfo.guidNegPolAction), (UUID *) &GUID_NEGOTIATION_ACTION_BLOCK, &RpcStat) == 0 && RpcStat == RPC_S_OK)
{
pTransportFilters[i].InboundFilterFlag = BLOCKING;
pTransportFilters[i].OutboundFilterFlag = BLOCKING;
}
else if (UuidCompare(&(tmpStorageInfo.guidNegPolAction), (UUID *) &GUID_NEGOTIATION_ACTION_NO_IPSEC, &RpcStat) == 0 && RpcStat == RPC_S_OK)
{
pTransportFilters[i].InboundFilterFlag = PASS_THRU;
pTransportFilters[i].OutboundFilterFlag = PASS_THRU;
}
}
}
else
{
// tunnel filter
for (i = 0; i < dwNumFilters; i++)
{
pTunnelFilters[i].InterfaceType = Interface;
if (SrcTunnelAddr == 0)
{
// SrcTunnelAddr is set to any
pTunnelFilters[i].SrcTunnelAddr.AddrType = IP_ADDR_SUBNET;
pTunnelFilters[i].SrcTunnelAddr.uIpAddr = SUBNET_ADDRESS_ANY;
pTunnelFilters[i].SrcTunnelAddr.uSubNetMask = SUBNET_MASK_ANY;
}
else
{
pTunnelFilters[i].SrcTunnelAddr.AddrType = IP_ADDR_UNIQUE;
pTunnelFilters[i].SrcTunnelAddr.uIpAddr = SrcTunnelAddr;
pTunnelFilters[i].SrcTunnelAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
}
// DesTunnelAddr is our tunnel address
pTunnelFilters[i].DesTunnelAddr.AddrType = IP_ADDR_UNIQUE;
pTunnelFilters[i].DesTunnelAddr.uIpAddr = DesTunnelAddr;
pTunnelFilters[i].DesTunnelAddr.uSubNetMask = IP_ADDRESS_MASK_NONE;
}
}
// if mainmode filters specified, apply interface type
if (uMMFiltAlloc)
{
for (i = 0; i < dwNumMMFilters; i++)
{
pMMFilters[i].InterfaceType = Interface;
}
}
if (!uMMFiltAlloc)
{
// generate mainmode filters - filter generation also depends on QMFilterType
if (QMFilterType == QM_TRANSPORT_FILTER)
{
// transport
Filter.QMFilterType = QM_TRANSPORT_FILTER;
for (i = 0; i < dwNumFilters; i++)
{
bool bSuccess;
bool bFound;
int j;
memcpy(&Filter.TransportFilter, &pTransportFilters[i], sizeof(TRANSPORT_FILTER));
if (Filter.TransportFilter.OutboundFilterFlag == NEGOTIATE_SECURITY
|| Filter.TransportFilter.InboundFilterFlag == NEGOTIATE_SECURITY)
{
bSuccess = GenerateMMFilter(Filter, pMMFilters[dwNumMMFilters]);
assert(bSuccess);
dwNumMMFilters++;
}
}
}
else
{
// tunnel - generate just one filter
bool bSuccess;
Filter.QMFilterType = QM_TUNNEL_FILTER;
memcpy(&Filter.TunnelFilter, &pTunnelFilters[0], sizeof(TUNNEL_FILTER));
bSuccess = GenerateMMFilter(Filter, pMMFilters[0]);
assert(bSuccess);
dwNumMMFilters++;
}
}
error_occured:
if (!T2P_SUCCESS(dwReturn))
{
// error occured, clean up
if (uFiltAlloc)
{
// clean up both transports and tunnels since we allocated both
for (i = 0; i <= uFiltAlloc; i++)
{
if (pTransportFilters[i].pszFilterName != NULL)
free(pTransportFilters[i].pszFilterName);
}
delete [] pTransportFilters;
pTransportFilters = NULL;
// tunnel filter
for (i = 0; i <= uFiltAlloc; i++)
{
if (pTunnelFilters[i].pszFilterName != NULL)
free(pTunnelFilters[i].pszFilterName);
}
delete [] pTunnelFilters;
pTunnelFilters = NULL;
dwNumFilters = 0;
if (!uMMFiltAlloc)
{
for (i = 0; i <= uMMFiltAlloc; i++)
{
if (pMMFilters[i].pszFilterName != NULL)
free(pMMFilters[i].pszFilterName);
}
delete [] pMMFilters;
pMMFilters = NULL;
dwNumMMFilters = 0;
}
}
if (uMMFiltAlloc)
{
for (i = 0; i <= uMMFiltAlloc; i++)
{
if (pMMFilters[i].pszFilterName != NULL)
free(pMMFilters[i].pszFilterName);
}
delete [] pMMFilters;
pMMFilters = NULL;
dwNumMMFilters = 0;
}
if (uOfferAlloc)
{
delete [] IpsPol.pOffers;
IpsPol.pOffers = NULL;
IpsPol.dwOfferCount = 0;
}
if (uSecMetAlloc)
{
delete [] IkePol.pOffers;
IkePol.pOffers = NULL;
IkePol.dwOfferCount = 0;
}
}
else // fix up policy as necessary
{
//
// if storage info requested, copy to caller
// only copy fields that were indicated, this gets
// passed in with caller specified items
//
if (bStorageMode)
{
T2P_FILTER tmpf;
tmpf.QMFilterType = QMFilterType;
tmpStorageInfo.FilterList = new IPSEC_FILTER_SPEC[dwNumFilters];
assert(tmpStorageInfo.FilterList != NULL);
// convert filters
for (i = 0; i < dwNumFilters; i++)
{
if (tmpf.QMFilterType == QM_TRANSPORT_FILTER)
{
memcpy(&(tmpf.TransportFilter), &(pTransportFilters[i]), sizeof(TRANSPORT_FILTER));
}
else
{
// tunnel
memcpy(&(tmpf.TunnelFilter), &(pTunnelFilters[i]), sizeof(TUNNEL_FILTER));
}
ConvertFilter(tmpf, tmpStorageInfo.FilterList[i]);
}
pStorageInfo->Type = tmpStorageInfo.Type;
if (tmpStorageInfo.szLocationName[0] != '\0')
wcscpy(pStorageInfo->szLocationName, tmpStorageInfo.szLocationName);
if (tmpStorageInfo.szPolicyName[0] != '\0')
wcscpy(pStorageInfo->szPolicyName, tmpStorageInfo.szPolicyName);
if (tmpStorageInfo.szRuleName[0] != '\0')
wcscpy(pStorageInfo->szRuleName, tmpStorageInfo.szRuleName);
if (tmpStorageInfo.tPollingInterval)
pStorageInfo->tPollingInterval = tmpStorageInfo.tPollingInterval;
pStorageInfo->guidNegPolAction = tmpStorageInfo.guidNegPolAction;
pStorageInfo->bSetActive = tmpStorageInfo.bSetActive;
pStorageInfo->bSetInActive = tmpStorageInfo.bSetInActive;
pStorageInfo->bDeleteRule = tmpStorageInfo.bDeleteRule;
pStorageInfo->bDeletePolicy = tmpStorageInfo.bDeletePolicy;
pStorageInfo->FilterList = tmpStorageInfo.FilterList;
pStorageInfo->uNumFilters = tmpStorageInfo.uNumFilters;
}
// fix up MM policy
if (bP1RekeyUsed)
{
// fix up Ike policy by filling each ike offer
// with the phase1 rekey
for (i = 0; i < IkePol.dwOfferCount; ++i)
{
IkePol.pOffers[i].Lifetime.uKeyExpirationKBytes = OakLife.uKeyExpirationKBytes;
IkePol.pOffers[i].Lifetime.uKeyExpirationTime = OakLife.uKeyExpirationTime;
IkePol.pOffers[i].dwQuickModeLimit = QMLimit;
}
}
else
{
// load defaults
for (i = 0; i < IkePol.dwOfferCount; ++i)
{
IkePol.pOffers[i].Lifetime.uKeyExpirationKBytes = 0; // not used
IkePol.pOffers[i].Lifetime.uKeyExpirationTime = POTF_DEFAULT_P1REKEY_TIME;
IkePol.pOffers[i].dwQuickModeLimit = POTF_DEFAULT_P1REKEY_QMS;
}
}
// if Kerberos is used, need to set AuthInfo string
// to dummy since RPC will choke otherwise
for (i = 0; i < AuthInfos.dwNumAuthInfos; ++i)
{
if (AuthInfos.pAuthenticationInfo[i].AuthMethod == IKE_SSPI ||
(AuthInfos.pAuthenticationInfo[i].AuthMethod == IKE_RSA_SIGNATURE &&
AuthInfos.pAuthenticationInfo[i].pAuthInfo == NULL)
)
{
AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize = 0;
AuthInfos.pAuthenticationInfo[i].pAuthInfo = (LPBYTE) new wchar_t[1];
AuthInfos.pAuthenticationInfo[i].pAuthInfo[0] = UNICODE_NULL;
}
}
}
} // end if args valid
else
{
fprintf(stderr, "Fatal error occured processing cmd line at line %d\n",
__LINE__ );
dwReturn = POTF_FAILED;
}
//
// OK, copy the info to the caller
//
memcpy(&IpsecIkePol.IpsPol, &IpsPol, sizeof(IpsPol));
memcpy(&IpsecIkePol.IkePol, &IkePol, sizeof(IkePol));
memcpy(&IpsecIkePol.AuthInfos, &AuthInfos, sizeof(AuthInfos));
IpsecIkePol.pMMFilters = pMMFilters;
IpsecIkePol.dwNumMMFilters = dwNumMMFilters;
IpsecIkePol.QMFilterType = QMFilterType;
IpsecIkePol.dwNumFilters = dwNumFilters;
IpsecIkePol.pTransportFilters = pTransportFilters;
IpsecIkePol.pTunnelFilters = pTunnelFilters;
// done
return dwReturn;
}