|
|
/////////////////////////////////////////////////////////////
// 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;
}
|