674 lines
15 KiB
C++
674 lines
15 KiB
C++
/**********************************************************************/
|
|
/** Microsoft Windows/NT **/
|
|
/** Copyright(c) Microsoft Corporation, 1997 - 2002 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
spdutil.cpp
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "winipsec.h"
|
|
#include "ipsec.h"
|
|
#include "spdutil.h"
|
|
#include "objplus.h"
|
|
#include "ipaddres.h"
|
|
#include "spddb.h"
|
|
#include "server.h"
|
|
|
|
#define MY_ENCODING_TYPE (X509_ASN_ENCODING)
|
|
|
|
extern CHashTable g_HashTable;
|
|
|
|
const DWORD IPSM_PROTOCOL_TCP = 6;
|
|
const DWORD IPSM_PROTOCOL_UDP = 17;
|
|
|
|
const TCHAR c_szSingleAddressMask[] = _T("255.255.255.255");
|
|
|
|
const ProtocolStringMap c_ProtocolStringMap[] =
|
|
{
|
|
{0, IDS_PROTOCOL_ANY},
|
|
{1, IDS_PROTOCOL_ICMP},
|
|
{3, IDS_PROTOCOL_GGP},
|
|
{6, IDS_PROTOCOL_TCP},
|
|
{8, IDS_PROTOCOL_EGP},
|
|
{12, IDS_PROTOCOL_PUP},
|
|
{17, IDS_PROTOCOL_UDP},
|
|
{20, IDS_PROTOCOL_HMP},
|
|
{22, IDS_PROTOCOL_XNS_IDP},
|
|
{27, IDS_PROTOCOL_RDP},
|
|
{66, IDS_PROTOCOL_RVD}
|
|
};
|
|
|
|
const int c_nProtocols = DimensionOf(c_ProtocolStringMap);
|
|
|
|
ULONG RevertDwordBytes(DWORD dw)
|
|
{
|
|
ULONG ulRet;
|
|
ulRet = dw >> 24;
|
|
ulRet += (dw & 0xFF0000) >> 8;
|
|
ulRet += (dw & 0x00FF00) << 8;
|
|
ulRet += (dw & 0x0000FF) << 24;
|
|
|
|
return ulRet;
|
|
}
|
|
|
|
void PortToString
|
|
(
|
|
PORT port,
|
|
CString * pst
|
|
)
|
|
{
|
|
if (0 == port.wPort)
|
|
{
|
|
pst->LoadString(IDS_PORT_ANY);
|
|
}
|
|
else
|
|
{
|
|
pst->Format(_T("%d"), port.wPort);
|
|
}
|
|
}
|
|
|
|
void FilterFlagToString
|
|
(
|
|
FILTER_ACTION FltrFlag,
|
|
CString * pst
|
|
)
|
|
{
|
|
pst->Empty();
|
|
switch(FltrFlag)
|
|
{
|
|
case PASS_THRU:
|
|
pst->LoadString(IDS_PASS_THROUGH);
|
|
break;
|
|
case BLOCKING:
|
|
pst->LoadString(IDS_BLOCKING);
|
|
break;
|
|
case NEGOTIATE_SECURITY:
|
|
pst->LoadString(IDS_NEG_SEC);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ProtocolToString
|
|
(
|
|
PROTOCOL protocol,
|
|
CString * pst
|
|
)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
for (int i = 0; i < DimensionOf(c_ProtocolStringMap); i++)
|
|
{
|
|
if (c_ProtocolStringMap[i].dwProtocol == protocol.dwProtocol)
|
|
{
|
|
pst->LoadString(c_ProtocolStringMap[i].nStringID);
|
|
fFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
pst->Format(IDS_OTHER_PROTO, protocol.dwProtocol);
|
|
}
|
|
}
|
|
|
|
void InterfaceTypeToString
|
|
(
|
|
IF_TYPE ifType,
|
|
CString * pst
|
|
)
|
|
{
|
|
switch (ifType)
|
|
{
|
|
case INTERFACE_TYPE_ALL:
|
|
pst->LoadString (IDS_IF_TYPE_ALL);
|
|
break;
|
|
|
|
case INTERFACE_TYPE_LAN:
|
|
pst->LoadString (IDS_IF_TYPE_LAN);
|
|
break;
|
|
|
|
case INTERFACE_TYPE_DIALUP:
|
|
pst->LoadString (IDS_IF_TYPE_RAS);
|
|
break;
|
|
|
|
default:
|
|
pst->LoadString (IDS_UNKNOWN);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void BoolToString
|
|
(
|
|
BOOL bl,
|
|
CString * pst
|
|
)
|
|
{
|
|
if (bl)
|
|
pst->LoadString (IDS_YES);
|
|
else
|
|
pst->LoadString (IDS_NO);
|
|
}
|
|
|
|
void DirectionToString
|
|
(
|
|
DWORD dwDir,
|
|
CString * pst
|
|
)
|
|
{
|
|
switch (dwDir)
|
|
{
|
|
case FILTER_DIRECTION_INBOUND:
|
|
pst->LoadString(IDS_FLTR_DIR_IN);
|
|
break;
|
|
case FILTER_DIRECTION_OUTBOUND:
|
|
pst->LoadString(IDS_FLTR_DIR_OUT);
|
|
break;
|
|
default:
|
|
pst->Empty();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DoiEspAlgorithmToString
|
|
(
|
|
IPSEC_MM_ALGO algo,
|
|
CString * pst
|
|
)
|
|
{
|
|
switch (algo.uAlgoIdentifier)
|
|
{
|
|
case CONF_ALGO_NONE:
|
|
pst->LoadString(IDS_DOI_ESP_NONE);
|
|
break;
|
|
case CONF_ALGO_DES:
|
|
pst->LoadString(IDS_DOI_ESP_DES);
|
|
break;
|
|
case CONF_ALGO_3_DES:
|
|
pst->LoadString(IDS_DOI_ESP_3_DES);
|
|
break;
|
|
default:
|
|
pst->Empty();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DoiAuthAlgorithmToString
|
|
(
|
|
IPSEC_MM_ALGO algo,
|
|
CString * pst
|
|
)
|
|
{
|
|
switch(algo.uAlgoIdentifier)
|
|
{
|
|
case AUTH_ALGO_NONE:
|
|
pst->LoadString(IDS_DOI_AH_NONE);
|
|
break;
|
|
case AUTH_ALGO_MD5:
|
|
pst->LoadString(IDS_DOI_AH_MD5);
|
|
break;
|
|
case AUTH_ALGO_SHA1:
|
|
pst->LoadString(IDS_DOI_AH_SHA);
|
|
break;
|
|
default:
|
|
pst->Empty();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DhGroupToString(DWORD dwGp, CString * pst)
|
|
{
|
|
switch(dwGp)
|
|
{
|
|
case DH_GROUP_1:
|
|
pst->LoadString(IDS_DHGROUP_LOW);
|
|
break;
|
|
case DH_GROUP_2:
|
|
pst->LoadString(IDS_DHGROUP_MEDIUM);
|
|
break;
|
|
case DH_GROUP_2048:
|
|
pst->LoadString(IDS_DHGROUP_HIGH);
|
|
break;
|
|
default:
|
|
pst->Format(_T("%d"), dwGp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MmAuthToString(MM_AUTH_ENUM auth, CString * pst)
|
|
{
|
|
switch(auth)
|
|
{
|
|
case IKE_PRESHARED_KEY:
|
|
pst->LoadString(IDS_IKE_PRESHARED_KEY);
|
|
break;
|
|
case IKE_DSS_SIGNATURE:
|
|
pst->LoadString(IDS_IKE_DSS_SIGNATURE);
|
|
break;
|
|
case IKE_RSA_SIGNATURE:
|
|
pst->LoadString(IDS_IKE_RSA_SIGNATURE);
|
|
break;
|
|
case IKE_RSA_ENCRYPTION:
|
|
pst->LoadString(IDS_IKE_RSA_ENCRYPTION);
|
|
break;
|
|
case IKE_SSPI:
|
|
pst->LoadString(IDS_IKE_SSPI);
|
|
break;
|
|
default:
|
|
pst->Empty();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void KeyLifetimeToString(KEY_LIFETIME lifetime, CString * pst)
|
|
{
|
|
pst->Format(IDS_KEY_LIFE_TIME, lifetime.uKeyExpirationKBytes, lifetime.uKeyExpirationTime);
|
|
}
|
|
|
|
void IpToString(ULONG ulIp, CString *pst)
|
|
{
|
|
ULONG ul;
|
|
CIpAddress ipAddr;
|
|
ul = RevertDwordBytes(ulIp);
|
|
ipAddr = ul;
|
|
*pst = (CString) ipAddr;
|
|
}
|
|
|
|
void AddressToString(ADDR addr, CString * pst, BOOL * pfIsDnsName)
|
|
{
|
|
Assert(pst);
|
|
if (NULL == pst)
|
|
return;
|
|
|
|
if (pfIsDnsName)
|
|
{
|
|
*pfIsDnsName = FALSE;
|
|
}
|
|
|
|
|
|
ULONG ul;
|
|
CIpAddress ipAddr;
|
|
|
|
pst->Empty();
|
|
|
|
switch (addr.AddrType)
|
|
{
|
|
case IP_ADDR_UNIQUE:
|
|
if (IP_ADDRESS_ME == addr.uIpAddr)
|
|
{
|
|
pst->LoadString(IDS_ADDR_ME);
|
|
}
|
|
else
|
|
{
|
|
HashEntry *pHashEntry=NULL;
|
|
|
|
if (g_HashTable.GetObject(&pHashEntry,*(in_addr*)&addr.uIpAddr) != ERROR_SUCCESS) {
|
|
ul = RevertDwordBytes(addr.uIpAddr);
|
|
ipAddr = ul;
|
|
*pst = (CString) ipAddr;
|
|
}
|
|
else
|
|
{
|
|
*pst=pHashEntry->HostName;
|
|
if (pfIsDnsName)
|
|
{
|
|
*pfIsDnsName = TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IP_ADDR_SUBNET:
|
|
if (SUBNET_ADDRESS_ANY == addr.uSubNetMask)
|
|
{
|
|
pst->LoadString(IDS_ADDR_ANY);
|
|
}
|
|
else
|
|
{
|
|
ul = RevertDwordBytes(addr.uIpAddr);
|
|
ipAddr = ul;
|
|
*pst = (CString) ipAddr;
|
|
*pst += _T("(");
|
|
ul = RevertDwordBytes(addr.uSubNetMask);
|
|
ipAddr = ul;
|
|
*pst += (CString) ipAddr;
|
|
*pst += _T(")");
|
|
}
|
|
break;
|
|
case IP_ADDR_DNS_SERVER:
|
|
pst->LoadString(IDS_FILTER_EXT_DNS_SERVER);
|
|
break;
|
|
case IP_ADDR_WINS_SERVER:
|
|
pst->LoadString(IDS_FILTER_EXT_WINS_SERVER);
|
|
break;
|
|
case IP_ADDR_DHCP_SERVER:
|
|
pst->LoadString(IDS_FILTER_EXT_DHCP_SERVER);
|
|
break;
|
|
case IP_ADDR_DEFAULT_GATEWAY:
|
|
pst->LoadString(IDS_FILTER_EXT_DEF_GATEWAY);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IpsecByteBlobToString(const IPSEC_BYTE_BLOB& blob, CString * pst)
|
|
{
|
|
Assert(pst);
|
|
if (NULL == pst)
|
|
return;
|
|
|
|
pst->Empty();
|
|
//TODO to translate the blob info to readable strings
|
|
}
|
|
|
|
void QmAlgorithmToString
|
|
(
|
|
QM_ALGO_TYPE type,
|
|
CQmOffer * pOffer,
|
|
CString * pst
|
|
)
|
|
{
|
|
Assert(pst);
|
|
Assert(pOffer);
|
|
|
|
if (NULL == pst || NULL == pOffer)
|
|
return;
|
|
|
|
pst->LoadString(IDS_ALGO_NONE);
|
|
|
|
for (DWORD i = 0; i < pOffer->m_dwNumAlgos; i++)
|
|
{
|
|
switch(type)
|
|
{
|
|
case QM_ALGO_AUTH:
|
|
if (AUTHENTICATION == pOffer->m_arrAlgos[i].m_Operation)
|
|
{
|
|
switch(pOffer->m_arrAlgos[i].m_ulAlgo)
|
|
{
|
|
case AUTH_ALGO_MD5:
|
|
pst->LoadString(IDS_DOI_AH_MD5);
|
|
break;
|
|
case AUTH_ALGO_SHA1:
|
|
pst->LoadString(IDS_DOI_AH_SHA);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case QM_ALGO_ESP_CONF:
|
|
if (ENCRYPTION == pOffer->m_arrAlgos[i].m_Operation)
|
|
{
|
|
switch(pOffer->m_arrAlgos[i].m_ulAlgo)
|
|
{
|
|
case CONF_ALGO_DES:
|
|
pst->LoadString(IDS_DOI_ESP_DES);
|
|
break;
|
|
case CONF_ALGO_3_DES:
|
|
pst->LoadString(IDS_DOI_ESP_3_DES);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case QM_ALGO_ESP_INTEG:
|
|
if (ENCRYPTION == pOffer->m_arrAlgos[i].m_Operation)
|
|
{
|
|
switch(pOffer->m_arrAlgos[i].m_SecAlgo)
|
|
{
|
|
case HMAC_AUTH_ALGO_MD5:
|
|
pst->LoadString(IDS_HMAC_AH_MD5);
|
|
break;
|
|
case HMAC_AUTH_ALGO_SHA1:
|
|
pst->LoadString(IDS_HMAC_AH_SHA);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TnlEpToString
|
|
(
|
|
QM_FILTER_TYPE FltrType,
|
|
ADDR TnlEp,
|
|
CString * pst
|
|
)
|
|
{
|
|
Assert(pst);
|
|
|
|
if (NULL == pst)
|
|
return;
|
|
|
|
if (QM_TUNNEL_FILTER == FltrType)
|
|
{
|
|
AddressToString(TnlEp, pst);
|
|
}
|
|
else
|
|
{
|
|
pst->LoadString(IDS_NOT_AVAILABLE);
|
|
}
|
|
}
|
|
|
|
void TnlEpToString
|
|
(
|
|
FILTER_TYPE FltrType,
|
|
ADDR TnlEp,
|
|
CString * pst
|
|
)
|
|
{
|
|
Assert(pst);
|
|
|
|
if (NULL == pst)
|
|
return;
|
|
|
|
if (FILTER_TYPE_TUNNEL == FltrType)
|
|
{
|
|
AddressToString(TnlEp, pst);
|
|
}
|
|
else
|
|
{
|
|
pst->LoadString(IDS_NOT_AVAILABLE);
|
|
}
|
|
}
|
|
|
|
void IpsecByteBlobToString1(const IPSEC_BYTE_BLOB& blob, CString * pst)
|
|
{
|
|
Assert(pst);
|
|
if (NULL == pst)
|
|
return;
|
|
|
|
pst->Empty();
|
|
|
|
WCHAR *pszTemp = NULL;
|
|
|
|
pszTemp = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,blob.dwSize + sizeof(WCHAR));
|
|
|
|
memcpy((LPBYTE)pszTemp, blob.pBlob, blob.dwSize);
|
|
|
|
*pst = pszTemp;
|
|
|
|
//bug bug
|
|
LocalFree(pszTemp);
|
|
}
|
|
|
|
BOOL
|
|
GetNameAudit(
|
|
IN CRYPT_DATA_BLOB *NameBlob,
|
|
IN OUT LPTSTR Name,
|
|
IN DWORD NameBufferSize
|
|
)
|
|
{
|
|
DWORD dwCount=0;
|
|
DWORD dwSize = 0;
|
|
BOOL bRet = TRUE;
|
|
|
|
dwSize = CertNameToStr(
|
|
MY_ENCODING_TYPE, // Encoding type
|
|
NameBlob, // CRYPT_DATA_BLOB
|
|
CERT_X500_NAME_STR, // Type
|
|
Name, // Place to return string
|
|
NameBufferSize); // Size of string (chars)
|
|
if(dwSize <= 1)
|
|
{
|
|
dwCount = _tcslen(_TEXT(""))+1;
|
|
_tcsncpy(Name, _TEXT(""), dwCount);
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
VOID
|
|
GetCertId(
|
|
IN PIPSEC_BYTE_BLOB pCertificateChain,
|
|
CString * pstCertId
|
|
)
|
|
{
|
|
CRYPT_DATA_BLOB pkcsMsg;
|
|
HANDLE hCertStore = NULL;
|
|
PCCERT_CONTEXT pPrevCertContext = NULL;
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
_TCHAR pszSubjectName[1024] = {0};
|
|
CRYPT_DATA_BLOB NameBlob;
|
|
BOOL bRet;
|
|
|
|
pkcsMsg.pbData=pCertificateChain->pBlob;
|
|
pkcsMsg.cbData=pCertificateChain->dwSize;
|
|
|
|
hCertStore = CertOpenStore( CERT_STORE_PROV_PKCS7,
|
|
MY_ENCODING_TYPE | PKCS_7_ASN_ENCODING,
|
|
NULL,
|
|
CERT_STORE_READONLY_FLAG,
|
|
&pkcsMsg);
|
|
|
|
if ( NULL == hCertStore )
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
pCertContext = CertEnumCertificatesInStore( hCertStore,
|
|
pPrevCertContext);
|
|
if ( NULL == pCertContext )
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
NameBlob = pCertContext->pCertInfo->Subject;
|
|
|
|
*pstCertId = _T("\0");
|
|
|
|
DWORD dwRet = CertGetNameString(
|
|
pCertContext,
|
|
CERT_NAME_FRIENDLY_DISPLAY_TYPE,
|
|
0,
|
|
NULL,
|
|
pszSubjectName,
|
|
sizeof(pszSubjectName)/sizeof(pszSubjectName[0])
|
|
);
|
|
|
|
*pstCertId = _T("");
|
|
|
|
if ( dwRet > 1 )
|
|
{
|
|
*pstCertId = pszSubjectName;
|
|
}
|
|
|
|
error:
|
|
if ( hCertStore )
|
|
{
|
|
CertCloseStore(hCertStore, 0 );
|
|
}
|
|
}
|
|
|
|
void PFSGroupToString(
|
|
DWORD dwPFSGroup,
|
|
CString * pst
|
|
)
|
|
{
|
|
switch(dwPFSGroup)
|
|
{
|
|
case 1:
|
|
pst->LoadString(IDS_DHGROUP_LOW);
|
|
break;
|
|
case 2:
|
|
pst->LoadString(IDS_DHGROUP_MEDIUM);
|
|
break;
|
|
case PFS_GROUP_2048:
|
|
pst->LoadString(IDS_DHGROUP_HIGH);
|
|
break;
|
|
case PFS_GROUP_MM:
|
|
pst->LoadString(IDS_PFS_GROUP_DERIVED);
|
|
break;
|
|
case 0:
|
|
pst->LoadString(IDS_DHGROUP_UNASSIGNED);
|
|
break;
|
|
default:
|
|
pst->Format(_T("%d"), dwPFSGroup);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void GetAuthId(PIPSEC_MM_SA pSa, CString * pstAuthId, BOOL bPeer)
|
|
{
|
|
PIPSEC_BYTE_BLOB pAuthIdBlob = NULL;
|
|
PIPSEC_BYTE_BLOB pCertChainBlob = NULL;
|
|
|
|
//assign to NULL
|
|
*pstAuthId = _T("");
|
|
|
|
if ( bPeer )
|
|
{
|
|
pAuthIdBlob = (PIPSEC_BYTE_BLOB ) &(pSa->PeerId);
|
|
pCertChainBlob = (PIPSEC_BYTE_BLOB) &(pSa->PeerCertificateChain);
|
|
}
|
|
else
|
|
{
|
|
pAuthIdBlob = (PIPSEC_BYTE_BLOB) &(pSa->MyId);
|
|
pCertChainBlob = (PIPSEC_BYTE_BLOB) &(pSa->MyCertificateChain);
|
|
}
|
|
|
|
if ( (pAuthIdBlob->dwSize > 0) && (pAuthIdBlob->pBlob) )
|
|
{
|
|
IpsecByteBlobToString1( *pAuthIdBlob, pstAuthId );
|
|
return;
|
|
}
|
|
|
|
switch(pSa->MMAuthEnum)
|
|
{
|
|
case IKE_PRESHARED_KEY:
|
|
{
|
|
ADDR *pAddr;
|
|
ULONG ul;
|
|
CIpAddress ipAddr;
|
|
//should be just a IP address
|
|
if ( bPeer )
|
|
{
|
|
pAddr = &(pSa->Peer);
|
|
}
|
|
else
|
|
{
|
|
pAddr = &(pSa->Me);
|
|
}
|
|
|
|
ul = RevertDwordBytes(pAddr->uIpAddr);
|
|
ipAddr = ul;
|
|
*pstAuthId = (CString) ipAddr;
|
|
}
|
|
break;
|
|
case IKE_DSS_SIGNATURE:
|
|
case IKE_RSA_SIGNATURE:
|
|
case IKE_RSA_ENCRYPTION:
|
|
//get the id from the cert chain
|
|
GetCertId( pCertChainBlob, pstAuthId );
|
|
break;
|
|
case IKE_SSPI:
|
|
//dns name
|
|
//not needed to do anything as spd gives the correct id for SSPI case
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} |