#include "ipseccmd.h" #ifdef __cplusplus extern "C" { #endif IPSECPolicyToStorage::IPSECPolicyToStorage(): myPolicyStorage(NULL), myIPSECPolicy(NULL), mybIsOpen(false), mybPolicyExists(false) { } IPSECPolicyToStorage::~IPSECPolicyToStorage() { // if (myIPSECPolicy) IPSecFreePolicyData(myIPSECPolicy); // polstore AVs if something inside the policy is missing if (myPolicyStorage) { IPSecClosePolicyStore(myPolicyStorage); } } // this small function will attempt to CreateIpsecPolicyData, and if it succeeds, it'll mark that object is created in the storage // so that next time we'll use Set routine, not Create void IPSECPolicyToStorage::TryToCreatePolicy() { if (IPSecCreatePolicyData(myPolicyStorage, myIPSECPolicy) == ERROR_SUCCESS) { mybPolicyExists = true; } } // opens storage an initializes policy // pass name as NULL for local storage or if you want // the DS to be located // szPolicyName is required // szDescription is optional HRESULT IPSECPolicyToStorage::Open( IN DWORD location, IN LPTSTR name, IN LPTSTR szPolicyName, IN LPTSTR szDescription, IN time_t tPollingInterval, IN bool bUseExisting) { HRESULT hrReturnCode = S_OK; RPC_STATUS RpcStat; // need to do error checking if (!szPolicyName || (szPolicyName[0] == TEXT('\0')) ) { hrReturnCode = P2STORE_MISSING_NAME; } else { if (myPolicyStorage) { IPSecClosePolicyStore(myPolicyStorage); myPolicyStorage = NULL; } hrReturnCode = IPSecOpenPolicyStore(name, location, NULL, &myPolicyStorage); if (hrReturnCode == ERROR_SUCCESS) { mybIsOpen = true; if (myIPSECPolicy) { IPSecFreePolicyData(myIPSECPolicy); myIPSECPolicy = NULL; } if (bUseExisting) { // try to find existing policy cause user requested us to // myIPSECPolicy will be NULL if we haven't found it PIPSEC_POLICY_DATA *ppPolicyEnum = NULL; DWORD dwNumPolicies = 0; hrReturnCode = IPSecEnumPolicyData(myPolicyStorage, &ppPolicyEnum, &dwNumPolicies); if (hrReturnCode == ERROR_SUCCESS && dwNumPolicies > 0 && ppPolicyEnum != NULL) { // we have something in the storage, let's go through it int i; for (i = 0; i < (int) dwNumPolicies; i++) { if (wcscmp(ppPolicyEnum[i]->pszIpsecName, szPolicyName) == 0) { // we found it // make a copy in myIPSECPolicy and update description and polling interval hrReturnCode = IPSecCopyPolicyData(ppPolicyEnum[i], &myIPSECPolicy); mybPolicyExists = true; if (hrReturnCode == ERROR_SUCCESS) { hrReturnCode = IPSecEnumNFAData(myPolicyStorage, myIPSECPolicy->PolicyIdentifier , &(myIPSECPolicy->ppIpsecNFAData), &(myIPSECPolicy->dwNumNFACount)); } if (hrReturnCode == ERROR_SUCCESS) { int i; // also get other parts of the policy, no error checks here IPSecGetISAKMPData(myPolicyStorage, myIPSECPolicy->ISAKMPIdentifier, &(myIPSECPolicy->pIpsecISAKMPData)); for (i = 0; i < (int) myIPSECPolicy->dwNumNFACount; i++) { if (!UuidIsNil(&(myIPSECPolicy->ppIpsecNFAData[i]->NegPolIdentifier), &RpcStat)) { IPSecGetNegPolData(myPolicyStorage, myIPSECPolicy->ppIpsecNFAData[i]->NegPolIdentifier, &(myIPSECPolicy->ppIpsecNFAData[i]->pIpsecNegPolData)); } if (!UuidIsNil(&(myIPSECPolicy->ppIpsecNFAData[i]->FilterIdentifier), &RpcStat)) { IPSecGetFilterData(myPolicyStorage, myIPSECPolicy->ppIpsecNFAData[i]->FilterIdentifier, &(myIPSECPolicy->ppIpsecNFAData[i]->pIpsecFilterData)); } } if (myIPSECPolicy->pszDescription == NULL && szDescription != NULL) { // we've got description to set myIPSECPolicy->pszDescription = IPSecAllocPolStr(szDescription); } // set Polling Interval if (tPollingInterval >= 0) { myIPSECPolicy->dwPollingInterval = (DWORD) tPollingInterval; } // commit hrReturnCode = IPSecSetPolicyData(myPolicyStorage, myIPSECPolicy); } } } } else { hrReturnCode = ERROR_SUCCESS; } // clean it up if (dwNumPolicies > 0 && ppPolicyEnum != NULL) { IPSecFreeMulPolicyData(ppPolicyEnum, dwNumPolicies); } } // this is executed only when no bUseExisting was specified or existing policy wasn't found if (!bUseExisting || myIPSECPolicy == NULL) { // create mybPolicyExists = false; myIPSECPolicy = (PIPSEC_POLICY_DATA) IPSecAllocPolMem(sizeof(IPSEC_POLICY_DATA)); if (myIPSECPolicy == NULL) { hrReturnCode = GetLastError(); } else { myIPSECPolicy->pszIpsecName = IPSecAllocPolStr(szPolicyName); if (szDescription) { myIPSECPolicy->pszDescription = IPSecAllocPolStr(szDescription); } else { myIPSECPolicy->pszDescription = NULL; } myIPSECPolicy->dwPollingInterval = (DWORD) tPollingInterval; RpcStat = UuidCreate(&(myIPSECPolicy->PolicyIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); // now init other stuff somehow myIPSECPolicy->pIpsecISAKMPData = NULL; myIPSECPolicy->ppIpsecNFAData = NULL; myIPSECPolicy->dwNumNFACount = 0; myIPSECPolicy->dwWhenChanged = 0; UuidCreateNil(&(myIPSECPolicy->ISAKMPIdentifier)); // TryToCreatePolicy(); } } } } return hrReturnCode; } HRESULT IPSECPolicyToStorage::AddRule( IN IPSEC_IKE_POLICY IpsecIkePol, PSTORAGE_INFO pStorageInfo) { HRESULT hrReturn = S_OK; PIPSEC_NFA_DATA pRule = MakeRule(IpsecIkePol, pStorageInfo); int i; if (!IsOpen()) { return ERROR_ACCESS_DENIED; } // form policy data structures myIPSECPolicy->dwNumNFACount++; myIPSECPolicy->ppIpsecNFAData = (PIPSEC_NFA_DATA *) ReallocPolMem(myIPSECPolicy->ppIpsecNFAData , (myIPSECPolicy->dwNumNFACount-1)*sizeof(PIPSEC_NFA_DATA) , (myIPSECPolicy->dwNumNFACount)*sizeof(PIPSEC_NFA_DATA)); myIPSECPolicy->ppIpsecNFAData[myIPSECPolicy->dwNumNFACount-1] = pRule; // commit everything // start from qm policy if (!pRule->pIpsecFilterData) { // fix up neg pol pRule->pIpsecNegPolData->NegPolType = GUID_NEGOTIATION_TYPE_DEFAULT; } hrReturn = IPSecCreateNegPolData(myPolicyStorage, pRule->pIpsecNegPolData); if (hrReturn != ERROR_SUCCESS) { return hrReturn; } // filter if (pRule->pIpsecFilterData) { hrReturn = IPSecCreateFilterData(myPolicyStorage, pRule->pIpsecFilterData); if (hrReturn != ERROR_SUCCESS) { return hrReturn; } } // NFA IPSecCreateNFAData(myPolicyStorage, myIPSECPolicy->PolicyIdentifier, pRule); // policy if (IsPolicyInStorage()) { IPSecSetPolicyData(myPolicyStorage, myIPSECPolicy); } else { TryToCreatePolicy(); } return hrReturn; } // Add default response rule to the policy HRESULT IPSECPolicyToStorage::AddDefaultResponseRule ( ) { HRESULT hrReturn = S_OK; PIPSEC_NFA_DATA pRule = MakeDefaultResponseRule(); int i; if (!IsOpen()) { return ERROR_ACCESS_DENIED; } // form policy data structures myIPSECPolicy->dwNumNFACount++; myIPSECPolicy->ppIpsecNFAData = (PIPSEC_NFA_DATA *) ReallocPolMem(myIPSECPolicy->ppIpsecNFAData , (myIPSECPolicy->dwNumNFACount-1)*sizeof(PIPSEC_NFA_DATA) , (myIPSECPolicy->dwNumNFACount)*sizeof(PIPSEC_NFA_DATA)); myIPSECPolicy->ppIpsecNFAData[myIPSECPolicy->dwNumNFACount-1] = pRule; // commit everything // start from qm policy // fix up neg pol pRule->pIpsecNegPolData->NegPolType = GUID_NEGOTIATION_TYPE_DEFAULT; hrReturn = IPSecCreateNegPolData(myPolicyStorage, pRule->pIpsecNegPolData); if (hrReturn != ERROR_SUCCESS) { return hrReturn; } // NFA IPSecCreateNFAData(myPolicyStorage, myIPSECPolicy->PolicyIdentifier, pRule); // policy if (IsPolicyInStorage()) { IPSecSetPolicyData(myPolicyStorage, myIPSECPolicy); } else { TryToCreatePolicy(); } return hrReturn; } // this will update a rule: // if there are filters, all the filters from the current NFA // are removed and the ones passed in are added // same thing goes for negotiation policies and authinfos HRESULT IPSECPolicyToStorage::UpdateRule( IN PIPSEC_NFA_DATA pRule, IN IPSEC_IKE_POLICY IpsecIkePol, IN PSTORAGE_INFO pStorageInfo) { RPC_STATUS RpcStat; T2P_FILTER *pFilterList; IF_TYPE Interface; WCHAR wszRuleName[POTF_MAX_STRLEN]; HRESULT hrReturn = S_OK; int i; GUID oldFilter, oldNegPol; if (pRule == NULL || !IsOpen()) { return ERROR_ACCESS_DENIED; } // first, remove filter and policy data oldFilter = pRule->FilterIdentifier; if (pRule->pIpsecFilterData) { IPSecFreeFilterData(pRule->pIpsecFilterData); } oldNegPol = pRule->NegPolIdentifier; if (pRule->pIpsecNegPolData) { IPSecFreeNegPolData(pRule->pIpsecNegPolData); } // free auth methods if (pRule->ppAuthMethods) { for (i = 0; i < (int) pRule->dwAuthMethodCount; i++) { if (pRule->ppAuthMethods[i]->pszAuthMethod) { IPSecFreePolMem(pRule->ppAuthMethods[i]->pszAuthMethod); } if (pRule->ppAuthMethods[i]->dwAltAuthLen && pRule->ppAuthMethods[i]->pAltAuthMethod) { IPSecFreePolMem(pRule->ppAuthMethods[i]->pAltAuthMethod); } IPSecFreePolMem(pRule->ppAuthMethods[i]); } } IPSecFreePolMem(pRule->ppAuthMethods); // free strings if (pRule->pszIpsecName) { IPSecFreePolStr(pRule->pszIpsecName); } if (pRule->pszInterfaceName) { IPSecFreePolStr(pRule->pszInterfaceName); } if (pRule->pszEndPointName) { IPSecFreePolStr(pRule->pszEndPointName); } if (pRule->pszDescription) { IPSecFreePolStr(pRule->pszDescription); } // now make a rule pRule->pszIpsecName = pRule->pszDescription = pRule->pszInterfaceName = pRule->pszEndPointName = NULL; if (pStorageInfo) { pRule->pszIpsecName = IPSecAllocPolStr(pStorageInfo->szRuleName); } pRule->dwWhenChanged = 0; // filters if (IpsecIkePol.QMFilterType == QM_TRANSPORT_FILTER && IpsecIkePol.pTransportFilters[0].SrcAddr.AddrType == IP_ADDR_UNIQUE && IpsecIkePol.pTransportFilters[0].SrcAddr.uIpAddr == IP_ADDRESS_ME && IpsecIkePol.pTransportFilters[0].DesAddr.AddrType == IP_ADDR_UNIQUE && IpsecIkePol.pTransportFilters[0].DesAddr.uIpAddr == IP_ADDRESS_ME && IpsecIkePol.pTransportFilters[0].InboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG && IpsecIkePol.pTransportFilters[0].OutboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG) { pRule->pIpsecFilterData = NULL; UuidCreateNil(&(pRule->FilterIdentifier)); } else { pFilterList = new T2P_FILTER[IpsecIkePol.dwNumFilters]; for (i = 0; i < (int) IpsecIkePol.dwNumFilters; i++) { if (IpsecIkePol.QMFilterType == QM_TRANSPORT_FILTER) { pFilterList[i].QMFilterType = QM_TRANSPORT_FILTER; pFilterList[i].TransportFilter = IpsecIkePol.pTransportFilters[i]; } else { // tunnel pFilterList[i].QMFilterType = QM_TUNNEL_FILTER; pFilterList[i].TunnelFilter = IpsecIkePol.pTunnelFilters[i]; } } if (pStorageInfo) { pRule->pIpsecFilterData = MakeFilters(pFilterList, IpsecIkePol.dwNumFilters, pStorageInfo->szRuleName); } else { pRule->pIpsecFilterData = MakeFilters(pFilterList, IpsecIkePol.dwNumFilters, L""); } pRule->FilterIdentifier = pRule->pIpsecFilterData->FilterIdentifier; delete[] pFilterList; } // filter action if (pStorageInfo) { pRule->pIpsecNegPolData = MakeNegotiationPolicy(IpsecIkePol.IpsPol, pStorageInfo->szRuleName); } else { pRule->pIpsecNegPolData = MakeNegotiationPolicy(IpsecIkePol.IpsPol, L""); } pRule->NegPolIdentifier = pRule->pIpsecNegPolData->NegPolIdentifier; if (pStorageInfo && pStorageInfo->guidNegPolAction != GUID_NEGOTIATION_ACTION_NORMAL_IPSEC) { pRule->pIpsecNegPolData->NegPolAction = pStorageInfo->guidNegPolAction; } // tunnel address pRule->dwTunnelFlags = 0; if (IpsecIkePol.QMFilterType == QM_TUNNEL_FILTER) { pRule->dwTunnelFlags = 1; pRule->dwTunnelIpAddr = IpsecIkePol.pTunnelFilters[0].DesTunnelAddr.uIpAddr; } // interface type Interface = (IpsecIkePol.QMFilterType == QM_TRANSPORT_FILTER) ? IpsecIkePol.pTransportFilters[0].InterfaceType : IpsecIkePol.pTunnelFilters[0].InterfaceType; if (Interface == INTERFACE_TYPE_ALL) { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_ALL; } else if (Interface == INTERFACE_TYPE_LAN) { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_LAN; } else if (Interface == INTERFACE_TYPE_DIALUP) { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_DIALUP; } else { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_NONE; } // active flag pRule->dwActiveFlag = TRUE; // auth methods pRule->dwAuthMethodCount = IpsecIkePol.AuthInfos.dwNumAuthInfos; pRule->ppAuthMethods = (PIPSEC_AUTH_METHOD *) IPSecAllocPolMem(pRule->dwAuthMethodCount * sizeof(PIPSEC_AUTH_METHOD)); for (i = 0; i < (int) pRule->dwAuthMethodCount; i++) { pRule->ppAuthMethods[i] = (PIPSEC_AUTH_METHOD) IPSecAllocPolMem(sizeof(IPSEC_AUTH_METHOD)); pRule->ppAuthMethods[i]->dwAuthType = IpsecIkePol.AuthInfos.pAuthenticationInfo[i].AuthMethod; if (pRule->ppAuthMethods[i]->dwAuthType == IKE_SSPI) { pRule->ppAuthMethods[i]->dwAuthLen = 0; pRule->ppAuthMethods[i]->pszAuthMethod = NULL; pRule->ppAuthMethods[i]->dwAltAuthLen = 0; pRule->ppAuthMethods[i]->pAltAuthMethod = 0; } else if (pRule->ppAuthMethods[i]->dwAuthType == IKE_RSA_SIGNATURE) { LPTSTR pTemp = NULL; pRule->ppAuthMethods[i]->dwAltAuthLen = IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize; pRule->ppAuthMethods[i]->pAltAuthMethod = (PBYTE) IPSecAllocPolMem(IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize); memcpy(pRule->ppAuthMethods[i]->pAltAuthMethod, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].pAuthInfo, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize); hrReturn = CM_DecodeName(pRule->ppAuthMethods[i]->pAltAuthMethod, pRule->ppAuthMethods[i]->dwAltAuthLen, &pTemp); assert(hrReturn == ERROR_SUCCESS); pRule->ppAuthMethods[i]->pszAuthMethod = IPSecAllocPolStr(pTemp); pRule->ppAuthMethods[i]->dwAuthLen = wcslen(pRule->ppAuthMethods[i]->pszAuthMethod); delete[] pTemp; } else { pRule->ppAuthMethods[i]->dwAuthLen = IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize / sizeof(WCHAR); pRule->ppAuthMethods[i]->pszAuthMethod = (LPWSTR) IPSecAllocPolMem(IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize + sizeof(WCHAR)); memcpy(pRule->ppAuthMethods[i]->pszAuthMethod, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].pAuthInfo, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize); // add trailing '\0' - this is requirement for the polstore pRule->ppAuthMethods[i]->pszAuthMethod[pRule->ppAuthMethods[i]->dwAuthLen] = 0; pRule->ppAuthMethods[i]->dwAltAuthLen = 0; pRule->ppAuthMethods[i]->pAltAuthMethod = 0; } } // plumb it if (!pRule->pIpsecFilterData) { // fix up neg pol pRule->pIpsecNegPolData->NegPolType = GUID_NEGOTIATION_TYPE_DEFAULT; } hrReturn = IPSecCreateNegPolData(myPolicyStorage, pRule->pIpsecNegPolData); if (hrReturn != ERROR_SUCCESS) { return hrReturn; } // filter if (pRule->pIpsecFilterData) { hrReturn = IPSecCreateFilterData(myPolicyStorage, pRule->pIpsecFilterData); if (hrReturn != ERROR_SUCCESS) { return hrReturn; } } // NFA IPSecSetNFAData(myPolicyStorage, myIPSECPolicy->PolicyIdentifier, pRule); // policy if (IsPolicyInStorage()) { IPSecSetPolicyData(myPolicyStorage, myIPSECPolicy); } else { TryToCreatePolicy(); } if (!UuidIsNil(&oldFilter, &RpcStat)) { IPSecDeleteFilterData(myPolicyStorage, oldFilter); } IPSecDeleteNegPolData(myPolicyStorage, oldNegPol); return hrReturn; } // forms a rule but doesn't commit it PIPSEC_NFA_DATA IPSECPolicyToStorage::MakeRule(IN IPSEC_IKE_POLICY IpsecIkePol, IN PSTORAGE_INFO pStorageInfo) { RPC_STATUS RpcStat; T2P_FILTER *pFilterList; IF_TYPE Interface; int i; WCHAR wszRuleName[POTF_MAX_STRLEN]; PIPSEC_NFA_DATA pRule = (PIPSEC_NFA_DATA) IPSecAllocPolMem(sizeof(IPSEC_NFA_DATA)); HRESULT hrReturn = S_OK; assert(pRule); pRule->pszIpsecName = pRule->pszDescription = pRule->pszInterfaceName = pRule->pszEndPointName = NULL; if (pStorageInfo) { pRule->pszIpsecName = IPSecAllocPolStr(pStorageInfo->szRuleName); } RpcStat = UuidCreate(&(pRule->NFAIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); pRule->dwWhenChanged = 0; // filters if (IpsecIkePol.QMFilterType == QM_TRANSPORT_FILTER && IpsecIkePol.pTransportFilters[0].SrcAddr.AddrType == IP_ADDR_UNIQUE && IpsecIkePol.pTransportFilters[0].SrcAddr.uIpAddr == IP_ADDRESS_ME && IpsecIkePol.pTransportFilters[0].DesAddr.AddrType == IP_ADDR_UNIQUE && IpsecIkePol.pTransportFilters[0].DesAddr.uIpAddr == IP_ADDRESS_ME && IpsecIkePol.pTransportFilters[0].InboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG && IpsecIkePol.pTransportFilters[0].OutboundFilterFlag == (FILTER_FLAG) POTF_DEFAULT_RESPONSE_FLAG) { pRule->pIpsecFilterData = NULL; UuidCreateNil(&(pRule->FilterIdentifier)); } else { pFilterList = new T2P_FILTER[IpsecIkePol.dwNumFilters]; for (i = 0; i < (int) IpsecIkePol.dwNumFilters; i++) { if (IpsecIkePol.QMFilterType == QM_TRANSPORT_FILTER) { pFilterList[i].QMFilterType = QM_TRANSPORT_FILTER; pFilterList[i].TransportFilter = IpsecIkePol.pTransportFilters[i]; } else { // tunnel pFilterList[i].QMFilterType = QM_TUNNEL_FILTER; pFilterList[i].TunnelFilter = IpsecIkePol.pTunnelFilters[i]; } } if (pStorageInfo) { pRule->pIpsecFilterData = MakeFilters(pFilterList, IpsecIkePol.dwNumFilters, pStorageInfo->szRuleName); } else { pRule->pIpsecFilterData = MakeFilters(pFilterList, IpsecIkePol.dwNumFilters, L""); } pRule->FilterIdentifier = pRule->pIpsecFilterData->FilterIdentifier; delete[] pFilterList; } // filter action if (pStorageInfo) { pRule->pIpsecNegPolData = MakeNegotiationPolicy(IpsecIkePol.IpsPol, pStorageInfo->szRuleName); } else { pRule->pIpsecNegPolData = MakeNegotiationPolicy(IpsecIkePol.IpsPol, L""); } pRule->NegPolIdentifier = pRule->pIpsecNegPolData->NegPolIdentifier; if (pStorageInfo && pStorageInfo->guidNegPolAction != GUID_NEGOTIATION_ACTION_NORMAL_IPSEC) { pRule->pIpsecNegPolData->NegPolAction = pStorageInfo->guidNegPolAction; } // tunnel address pRule->dwTunnelFlags = 0; if (IpsecIkePol.QMFilterType == QM_TUNNEL_FILTER) { pRule->dwTunnelFlags = 1; pRule->dwTunnelIpAddr = IpsecIkePol.pTunnelFilters[0].DesTunnelAddr.uIpAddr; } // interface type Interface = (IpsecIkePol.QMFilterType == QM_TRANSPORT_FILTER) ? IpsecIkePol.pTransportFilters[0].InterfaceType : IpsecIkePol.pTunnelFilters[0].InterfaceType; if (Interface == INTERFACE_TYPE_ALL) { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_ALL; } else if (Interface == INTERFACE_TYPE_LAN) { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_LAN; } else if (Interface == INTERFACE_TYPE_DIALUP) { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_DIALUP; } else { pRule->dwInterfaceType = PAS_INTERFACE_TYPE_NONE; } // active flag pRule->dwActiveFlag = TRUE; // auth methods pRule->dwAuthMethodCount = IpsecIkePol.AuthInfos.dwNumAuthInfos; pRule->ppAuthMethods = (PIPSEC_AUTH_METHOD *) IPSecAllocPolMem(pRule->dwAuthMethodCount * sizeof(PIPSEC_AUTH_METHOD)); for (i = 0; i < (int) pRule->dwAuthMethodCount; i++) { pRule->ppAuthMethods[i] = (PIPSEC_AUTH_METHOD) IPSecAllocPolMem(sizeof(IPSEC_AUTH_METHOD)); pRule->ppAuthMethods[i]->dwAuthType = IpsecIkePol.AuthInfos.pAuthenticationInfo[i].AuthMethod; if (pRule->ppAuthMethods[i]->dwAuthType == IKE_SSPI) { pRule->ppAuthMethods[i]->dwAuthLen = 0; pRule->ppAuthMethods[i]->pszAuthMethod = NULL; pRule->ppAuthMethods[i]->dwAltAuthLen = 0; pRule->ppAuthMethods[i]->pAltAuthMethod = 0; } else if (pRule->ppAuthMethods[i]->dwAuthType == IKE_RSA_SIGNATURE) { LPTSTR pTemp = NULL; pRule->ppAuthMethods[i]->dwAltAuthLen = IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize; pRule->ppAuthMethods[i]->pAltAuthMethod = (PBYTE) IPSecAllocPolMem(IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize); memcpy(pRule->ppAuthMethods[i]->pAltAuthMethod, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].pAuthInfo, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize); hrReturn = CM_DecodeName(pRule->ppAuthMethods[i]->pAltAuthMethod, pRule->ppAuthMethods[i]->dwAltAuthLen, &pTemp); assert(hrReturn == ERROR_SUCCESS); pRule->ppAuthMethods[i]->pszAuthMethod = IPSecAllocPolStr(pTemp); pRule->ppAuthMethods[i]->dwAuthLen = wcslen(pRule->ppAuthMethods[i]->pszAuthMethod); delete[] pTemp; } else { pRule->ppAuthMethods[i]->dwAuthLen = IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize / sizeof(WCHAR); pRule->ppAuthMethods[i]->pszAuthMethod = (LPWSTR) IPSecAllocPolMem(IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize + sizeof(WCHAR)); memcpy(pRule->ppAuthMethods[i]->pszAuthMethod, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].pAuthInfo, IpsecIkePol.AuthInfos.pAuthenticationInfo[i].dwAuthInfoSize); // add trailing '\0' - this is requirement for the polstore pRule->ppAuthMethods[i]->pszAuthMethod[pRule->ppAuthMethods[i]->dwAuthLen] = 0; pRule->ppAuthMethods[i]->dwAltAuthLen = 0; pRule->ppAuthMethods[i]->pAltAuthMethod = 0; } } return pRule; } // does not commit it to the storage // it is assumed that action is NEGOTIATE_SECURITY. If that's not true, it'll be corrected in MakeRule call // Soft SA flag is handled here PIPSEC_NEGPOL_DATA IPSECPolicyToStorage::MakeNegotiationPolicy(IPSEC_QM_POLICY IpsPol, LPWSTR Name) { RPC_STATUS RpcStat; int i; PIPSEC_NEGPOL_DATA pNegPol = (PIPSEC_NEGPOL_DATA) IPSecAllocPolMem(sizeof(IPSEC_NEGPOL_DATA)); BOOL bPFS = FALSE; WCHAR pFAName[POTF_MAX_STRLEN]; RpcStat = UuidCreate(&(pNegPol->NegPolIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); pNegPol->NegPolAction = GUID_NEGOTIATION_ACTION_NORMAL_IPSEC; pNegPol->NegPolType = GUID_NEGOTIATION_TYPE_STANDARD; pNegPol->dwSecurityMethodCount = IpsPol.dwOfferCount; if (IpsPol.dwFlags & IPSEC_QM_POLICY_ALLOW_SOFT) { // we need to add one more offer with no security algorithms pNegPol->dwSecurityMethodCount++; } // allocate sec.methods pNegPol->pIpsecSecurityMethods = (IPSEC_SECURITY_METHOD *) IPSecAllocPolMem(pNegPol->dwSecurityMethodCount * sizeof(IPSEC_SECURITY_METHOD)); // fix up PFS, in storage it is the property of the filter action, not individual offer for (i = 0; i < (int) IpsPol.dwOfferCount; i++) { if (IpsPol.pOffers[i].bPFSRequired) { bPFS = TRUE; } } // handle sec.methods for (i = 0; i < (int) IpsPol.dwOfferCount; i++) { int j; pNegPol->pIpsecSecurityMethods[i].Lifetime.KeyExpirationBytes = IpsPol.pOffers[i].Lifetime.uKeyExpirationKBytes; pNegPol->pIpsecSecurityMethods[i].Lifetime.KeyExpirationTime = IpsPol.pOffers[i].Lifetime.uKeyExpirationTime; pNegPol->pIpsecSecurityMethods[i].Flags = 0; pNegPol->pIpsecSecurityMethods[i].PfsQMRequired = bPFS; pNegPol->pIpsecSecurityMethods[i].Count = IpsPol.pOffers[i].dwNumAlgos; for (j = 0; j < (int) pNegPol->pIpsecSecurityMethods[i].Count && j < QM_MAX_ALGOS; j++) { pNegPol->pIpsecSecurityMethods[i].Algos[j].algoIdentifier = IpsPol.pOffers[i].Algos[j].uAlgoIdentifier; pNegPol->pIpsecSecurityMethods[i].Algos[j].secondaryAlgoIdentifier = IpsPol.pOffers[i].Algos[j].uSecAlgoIdentifier; pNegPol->pIpsecSecurityMethods[i].Algos[j].algoKeylen = IpsPol.pOffers[i].Algos[j].uAlgoKeyLen; pNegPol->pIpsecSecurityMethods[i].Algos[j].algoRounds = IpsPol.pOffers[i].Algos[j].uAlgoRounds; switch (IpsPol.pOffers[i].Algos[j].Operation) { case AUTHENTICATION: pNegPol->pIpsecSecurityMethods[i].Algos[j].operation = Auth; break; case ENCRYPTION: pNegPol->pIpsecSecurityMethods[i].Algos[j].operation = Encrypt; break; default: pNegPol->pIpsecSecurityMethods[i].Algos[j].operation = None; } } } // add soft if (IpsPol.dwFlags & IPSEC_QM_POLICY_ALLOW_SOFT) { // set Count (and everything) to 0 memset(&(pNegPol->pIpsecSecurityMethods[pNegPol->dwSecurityMethodCount - 1]), 0, sizeof(IPSEC_SECURITY_METHOD)); } // name swprintf(pFAName, TEXT("%s filter action"), Name); pNegPol->pszIpsecName = IPSecAllocPolStr(pFAName); pNegPol->pszDescription = NULL; return pNegPol; } PIPSEC_FILTER_DATA IPSECPolicyToStorage::MakeFilters( T2P_FILTER *Filters, UINT NumFilters, LPWSTR Name) { RPC_STATUS RpcStat; PIPSEC_FILTER_DATA pFilter = (PIPSEC_FILTER_DATA) IPSecAllocPolMem(sizeof(IPSEC_FILTER_DATA)); int i; WCHAR pFLName[POTF_MAX_STRLEN]; RpcStat = UuidCreate(&(pFilter->FilterIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); pFilter->dwNumFilterSpecs = NumFilters; pFilter->ppFilterSpecs = (PIPSEC_FILTER_SPEC *) IPSecAllocPolMem(NumFilters*sizeof(PIPSEC_FILTER_SPEC)); assert(pFilter->ppFilterSpecs); for (i = 0; i < (int) NumFilters; i++) { pFilter->ppFilterSpecs[i] = (PIPSEC_FILTER_SPEC) IPSecAllocPolMem(sizeof(IPSEC_FILTER_SPEC)); assert(pFilter->ppFilterSpecs[i]); ConvertFilter(Filters[i], *(pFilter->ppFilterSpecs[i])); } pFilter->dwWhenChanged = 0; swprintf(pFLName, TEXT("%s filter list"), Name); pFilter->pszIpsecName = IPSecAllocPolStr(pFLName); pFilter->pszDescription = NULL; return pFilter; } HRESULT IPSECPolicyToStorage::SetISAKMPPolicy(IPSEC_MM_POLICY IkePol) { HRESULT hrReturn = S_OK; RPC_STATUS RpcStat; GUID oldISAKMP; int i; if (!IsOpen()) { return ERROR_ACCESS_DENIED; } oldISAKMP = myIPSECPolicy->ISAKMPIdentifier; if (myIPSECPolicy->pIpsecISAKMPData) { IPSecFreeISAKMPData(myIPSECPolicy->pIpsecISAKMPData); } RpcStat = UuidCreate(&(myIPSECPolicy->ISAKMPIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); myIPSECPolicy->pIpsecISAKMPData = (PIPSEC_ISAKMP_DATA) IPSecAllocPolMem(sizeof(IPSEC_ISAKMP_DATA)); myIPSECPolicy->pIpsecISAKMPData->ISAKMPIdentifier = myIPSECPolicy->ISAKMPIdentifier; myIPSECPolicy->pIpsecISAKMPData->dwWhenChanged = 0; // sec methods stuff myIPSECPolicy->pIpsecISAKMPData->dwNumISAKMPSecurityMethods = IkePol.dwOfferCount; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods = (PCRYPTO_BUNDLE) IPSecAllocPolMem(sizeof(CRYPTO_BUNDLE)*IkePol.dwOfferCount); for (i = 0; i < (int) IkePol.dwOfferCount; i++) { myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].MajorVersion = 0; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].MinorVersion = 0; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].AuthenticationMethod = 0; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].PseudoRandomFunction.AlgorithmIdentifier = 0; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].PseudoRandomFunction.KeySize = 0; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].PseudoRandomFunction.Rounds = 0; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].PfsIdentityRequired = (IkePol.pOffers[i].dwQuickModeLimit == 1); myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].EncryptionAlgorithm.AlgorithmIdentifier = IkePol.pOffers[i].EncryptionAlgorithm.uAlgoIdentifier; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].EncryptionAlgorithm.KeySize = IkePol.pOffers[i].EncryptionAlgorithm.uAlgoKeyLen; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].EncryptionAlgorithm.Rounds = IkePol.pOffers[i].EncryptionAlgorithm.uAlgoRounds; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].HashAlgorithm.AlgorithmIdentifier = IkePol.pOffers[i].HashingAlgorithm.uAlgoIdentifier; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].HashAlgorithm.KeySize = IkePol.pOffers[i].HashingAlgorithm.uAlgoKeyLen; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].HashAlgorithm.Rounds = IkePol.pOffers[i].HashingAlgorithm.uAlgoRounds; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].OakleyGroup = IkePol.pOffers[i].dwDHGroup; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].QuickModeLimit = IkePol.pOffers[i].dwQuickModeLimit; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].Lifetime.KBytes = IkePol.pOffers[i].Lifetime.uKeyExpirationKBytes; myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[i].Lifetime.Seconds = IkePol.pOffers[i].Lifetime.uKeyExpirationTime; } // now for other stuff - ISAKMPPolicy myIPSECPolicy->pIpsecISAKMPData->ISAKMPPolicy.PolicyId = myIPSECPolicy->ISAKMPIdentifier; myIPSECPolicy->pIpsecISAKMPData->ISAKMPPolicy.IdentityProtectionRequired = 0; myIPSECPolicy->pIpsecISAKMPData->ISAKMPPolicy.PfsIdentityRequired = myIPSECPolicy->pIpsecISAKMPData->pSecurityMethods[0].PfsIdentityRequired; // save it hrReturn = IPSecCreateISAKMPData(myPolicyStorage, myIPSECPolicy->pIpsecISAKMPData); if (hrReturn != ERROR_SUCCESS) { return hrReturn; } if (IsPolicyInStorage()) { IPSecSetPolicyData(myPolicyStorage, myIPSECPolicy); } else { TryToCreatePolicy(); } IPSecDeleteISAKMPData(myPolicyStorage, oldISAKMP); return ERROR_SUCCESS; } LPVOID IPSECPolicyToStorage::ReallocPolMem( LPVOID pOldMem, DWORD cbOld, DWORD cbNew ) { LPVOID pNewMem; pNewMem=IPSecAllocPolMem(cbNew); if (pOldMem && pNewMem) { memcpy(pNewMem, pOldMem, min(cbNew, cbOld)); IPSecFreePolMem(pOldMem); } return pNewMem; } // forms a rule but doesn't commit it // forms default response rule PIPSEC_NFA_DATA IPSECPolicyToStorage::MakeDefaultResponseRule () { RPC_STATUS RpcStat; PIPSEC_NFA_DATA pRule = (PIPSEC_NFA_DATA) IPSecAllocPolMem(sizeof(IPSEC_NFA_DATA)); assert(pRule); pRule->pszIpsecName = pRule->pszDescription = pRule->pszInterfaceName = pRule->pszEndPointName = NULL; RpcStat = UuidCreate(&(pRule->NFAIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); pRule->dwWhenChanged = 0; // filter list pRule->pIpsecFilterData = NULL; UuidCreateNil(&(pRule->FilterIdentifier)); // filter action pRule->pIpsecNegPolData = MakeDefaultResponseNegotiationPolicy (); pRule->NegPolIdentifier = pRule->pIpsecNegPolData->NegPolIdentifier; // tunnel address pRule->dwTunnelFlags = 0; // interface type pRule->dwInterfaceType = PAS_INTERFACE_TYPE_ALL; // active flag pRule->dwActiveFlag = FALSE; // auth methods pRule->dwAuthMethodCount = 1; pRule->ppAuthMethods = (PIPSEC_AUTH_METHOD *) IPSecAllocPolMem(pRule->dwAuthMethodCount * sizeof(PIPSEC_AUTH_METHOD)); assert(pRule->ppAuthMethods); pRule->ppAuthMethods[0] = (PIPSEC_AUTH_METHOD) IPSecAllocPolMem(sizeof(IPSEC_AUTH_METHOD)); pRule->ppAuthMethods[0]->dwAuthType = IKE_SSPI; pRule->ppAuthMethods[0]->dwAuthLen = 0; pRule->ppAuthMethods[0]->pszAuthMethod = NULL; return pRule; } // does not commit it to the storage PIPSEC_NEGPOL_DATA IPSECPolicyToStorage::MakeDefaultResponseNegotiationPolicy ( ) { RPC_STATUS RpcStat; int i; PIPSEC_NEGPOL_DATA pNegPol = (PIPSEC_NEGPOL_DATA) IPSecAllocPolMem(sizeof(IPSEC_NEGPOL_DATA)); WCHAR pFAName[POTF_MAX_STRLEN]; RpcStat = UuidCreate(&(pNegPol->NegPolIdentifier)); assert(RpcStat == RPC_S_OK || RpcStat == RPC_S_UUID_LOCAL_ONLY); pNegPol->NegPolAction = GUID_NEGOTIATION_ACTION_NORMAL_IPSEC; pNegPol->NegPolType = GUID_NEGOTIATION_TYPE_DEFAULT; pNegPol->dwSecurityMethodCount = 6; // allocate sec.methods pNegPol->pIpsecSecurityMethods = (IPSEC_SECURITY_METHOD *) IPSecAllocPolMem(pNegPol->dwSecurityMethodCount * sizeof(IPSEC_SECURITY_METHOD)); // method 0 - ESP[3DES, SHA1] pNegPol->pIpsecSecurityMethods[0].Lifetime.KeyExpirationBytes = 0; pNegPol->pIpsecSecurityMethods[0].Lifetime.KeyExpirationTime = 0; pNegPol->pIpsecSecurityMethods[0].Flags = 0; pNegPol->pIpsecSecurityMethods[0].PfsQMRequired = FALSE; pNegPol->pIpsecSecurityMethods[0].Count = 1; pNegPol->pIpsecSecurityMethods[0].Algos[0].algoIdentifier = IPSEC_DOI_ESP_3_DES; pNegPol->pIpsecSecurityMethods[0].Algos[0].secondaryAlgoIdentifier = IPSEC_DOI_AH_SHA1; pNegPol->pIpsecSecurityMethods[0].Algos[0].algoKeylen = 0; pNegPol->pIpsecSecurityMethods[0].Algos[0].algoRounds = 0; pNegPol->pIpsecSecurityMethods[0].Algos[0].operation = Encrypt; // method 1 - ESP[3DES, MD5] pNegPol->pIpsecSecurityMethods[1].Lifetime.KeyExpirationBytes = 0; pNegPol->pIpsecSecurityMethods[1].Lifetime.KeyExpirationTime = 0; pNegPol->pIpsecSecurityMethods[1].Flags = 0; pNegPol->pIpsecSecurityMethods[1].PfsQMRequired = FALSE; pNegPol->pIpsecSecurityMethods[1].Count = 1; pNegPol->pIpsecSecurityMethods[1].Algos[0].algoIdentifier = IPSEC_DOI_ESP_3_DES; pNegPol->pIpsecSecurityMethods[1].Algos[0].secondaryAlgoIdentifier = IPSEC_DOI_AH_MD5; pNegPol->pIpsecSecurityMethods[1].Algos[0].algoKeylen = 0; pNegPol->pIpsecSecurityMethods[1].Algos[0].algoRounds = 0; pNegPol->pIpsecSecurityMethods[1].Algos[0].operation = Encrypt; // method 2 - ESP[DES, SHA1] pNegPol->pIpsecSecurityMethods[2].Lifetime.KeyExpirationBytes = 0; pNegPol->pIpsecSecurityMethods[2].Lifetime.KeyExpirationTime = 0; pNegPol->pIpsecSecurityMethods[2].Flags = 0; pNegPol->pIpsecSecurityMethods[2].PfsQMRequired = FALSE; pNegPol->pIpsecSecurityMethods[2].Count = 1; pNegPol->pIpsecSecurityMethods[2].Algos[0].algoIdentifier = IPSEC_DOI_ESP_DES; pNegPol->pIpsecSecurityMethods[2].Algos[0].secondaryAlgoIdentifier = IPSEC_DOI_AH_SHA1; pNegPol->pIpsecSecurityMethods[2].Algos[0].algoKeylen = 0; pNegPol->pIpsecSecurityMethods[2].Algos[0].algoRounds = 0; pNegPol->pIpsecSecurityMethods[2].Algos[0].operation = Encrypt; // method 3 - ESP[DES, MD5] pNegPol->pIpsecSecurityMethods[3].Lifetime.KeyExpirationBytes = 0; pNegPol->pIpsecSecurityMethods[3].Lifetime.KeyExpirationTime = 0; pNegPol->pIpsecSecurityMethods[3].Flags = 0; pNegPol->pIpsecSecurityMethods[3].PfsQMRequired = FALSE; pNegPol->pIpsecSecurityMethods[3].Count = 1; pNegPol->pIpsecSecurityMethods[3].Algos[0].algoIdentifier = IPSEC_DOI_ESP_DES; pNegPol->pIpsecSecurityMethods[3].Algos[0].secondaryAlgoIdentifier = IPSEC_DOI_AH_MD5; pNegPol->pIpsecSecurityMethods[3].Algos[0].algoKeylen = 0; pNegPol->pIpsecSecurityMethods[3].Algos[0].algoRounds = 0; pNegPol->pIpsecSecurityMethods[3].Algos[0].operation = Encrypt; // method 4 - AH[SHA1] pNegPol->pIpsecSecurityMethods[4].Lifetime.KeyExpirationBytes = 0; pNegPol->pIpsecSecurityMethods[4].Lifetime.KeyExpirationTime = 0; pNegPol->pIpsecSecurityMethods[4].Flags = 0; pNegPol->pIpsecSecurityMethods[4].PfsQMRequired = FALSE; pNegPol->pIpsecSecurityMethods[4].Count = 1; pNegPol->pIpsecSecurityMethods[4].Algos[0].algoIdentifier = IPSEC_DOI_AH_SHA1; pNegPol->pIpsecSecurityMethods[4].Algos[0].secondaryAlgoIdentifier = IPSEC_DOI_AH_NONE; pNegPol->pIpsecSecurityMethods[4].Algos[0].algoKeylen = 0; pNegPol->pIpsecSecurityMethods[4].Algos[0].algoRounds = 0; pNegPol->pIpsecSecurityMethods[4].Algos[0].operation = Auth; // method 5 - AH[MD5] pNegPol->pIpsecSecurityMethods[5].Lifetime.KeyExpirationBytes = 0; pNegPol->pIpsecSecurityMethods[5].Lifetime.KeyExpirationTime = 0; pNegPol->pIpsecSecurityMethods[5].Flags = 0; pNegPol->pIpsecSecurityMethods[5].PfsQMRequired = FALSE; pNegPol->pIpsecSecurityMethods[5].Count = 1; pNegPol->pIpsecSecurityMethods[5].Algos[0].algoIdentifier = IPSEC_DOI_AH_MD5; pNegPol->pIpsecSecurityMethods[5].Algos[0].secondaryAlgoIdentifier = IPSEC_DOI_AH_NONE; pNegPol->pIpsecSecurityMethods[5].Algos[0].algoKeylen = 0; pNegPol->pIpsecSecurityMethods[5].Algos[0].algoRounds = 0; pNegPol->pIpsecSecurityMethods[5].Algos[0].operation = Auth; // name swprintf(pFAName, TEXT("")); pNegPol->pszIpsecName = IPSecAllocPolStr(pFAName); pNegPol->pszDescription = NULL; return pNegPol; } #ifdef __cplusplus } #endif