windows-nt/Source/XPSP1/NT/net/ipsec/spd/server/paqm-pol.c

831 lines
17 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "precomp.h"
DWORD
PAAddQMPolicies(
PIPSEC_NFA_DATA * ppIpsecNFAData,
DWORD dwNumNFACount
)
{
DWORD dwError = 0;
DWORD i = 0;
PIPSEC_NFA_DATA pIpsecNFAData = NULL;
PIPSEC_NEGPOL_DATA pIpsecNegPolData = NULL;
PQMPOLICYSTATE pQMPolicyState = NULL;
PIPSEC_QM_POLICY pSPDQMPolicy = NULL;
LPWSTR pServerName = NULL;
DWORD dwPersist = 0;
for (i = 0; i < dwNumNFACount; i++) {
pIpsecNFAData = *(ppIpsecNFAData + i);
pIpsecNegPolData = pIpsecNFAData->pIpsecNegPolData;
pQMPolicyState = FindQMPolicyState(
pIpsecNegPolData->NegPolIdentifier
);
if (pQMPolicyState) {
pQMPolicyState->cRef++;
continue;
}
dwError = PACreateQMPolicyState(
*(ppIpsecNFAData + i),
&pQMPolicyState
);
if (dwError) {
continue;
}
if (IsClearOnly(pQMPolicyState->gNegPolAction) ||
IsBlocking(pQMPolicyState->gNegPolAction)) {
pQMPolicyState->bInSPD = FALSE;
pQMPolicyState->dwErrorCode = 0;
pQMPolicyState->pNext = gpQMPolicyState;
gpQMPolicyState = pQMPolicyState;
continue;
}
dwError = PACreateQMPolicy(
*(ppIpsecNFAData + i),
pQMPolicyState,
&pSPDQMPolicy
);
if (dwError) {
pQMPolicyState->bInSPD = FALSE;
pQMPolicyState->dwErrorCode = dwError;
pQMPolicyState->pNext = gpQMPolicyState;
gpQMPolicyState = pQMPolicyState;
continue;
}
dwError = AddQMPolicy(
pServerName,
dwPersist,
pSPDQMPolicy
);
if (dwError) {
pQMPolicyState->bInSPD = FALSE;
pQMPolicyState->dwErrorCode = dwError;
}
else {
pQMPolicyState->bInSPD = TRUE;
pQMPolicyState->dwErrorCode = ERROR_SUCCESS;
}
pQMPolicyState->pNext = gpQMPolicyState;
gpQMPolicyState = pQMPolicyState;
PAFreeQMPolicy(pSPDQMPolicy);
}
return (dwError);
}
DWORD
PACreateQMPolicyState(
PIPSEC_NFA_DATA pIpsecNFAData,
PQMPOLICYSTATE * ppQMPolicyState
)
{
DWORD dwError = 0;
PQMPOLICYSTATE pQMPolicyState = NULL;
PIPSEC_NEGPOL_DATA pIpsecNegPolData = NULL;
WCHAR pszName[512];
dwError = AllocateSPDMemory(
sizeof(QMPOLICYSTATE),
&pQMPolicyState
);
BAIL_ON_WIN32_ERROR(dwError);
pIpsecNegPolData = pIpsecNFAData->pIpsecNegPolData;
memcpy(
&(pQMPolicyState->gPolicyID),
&(pIpsecNegPolData->NegPolIdentifier),
sizeof(GUID)
);
if (pIpsecNegPolData->pszIpsecName && *(pIpsecNegPolData->pszIpsecName)) {
dwError = AllocateSPDString(
pIpsecNegPolData->pszIpsecName,
&(pQMPolicyState->pszPolicyName)
);
BAIL_ON_WIN32_ERROR(dwError);
}
else {
wsprintf(pszName, L"%d", ++gdwQMPolicyCounter);
dwError = AllocateSPDString(
pszName,
&(pQMPolicyState->pszPolicyName)
);
BAIL_ON_WIN32_ERROR(dwError);
}
memcpy(
&(pQMPolicyState->gNegPolType),
&(pIpsecNegPolData->NegPolType),
sizeof(GUID)
);
memcpy(
&(pQMPolicyState->gNegPolAction),
&(pIpsecNegPolData->NegPolAction),
sizeof(GUID)
);
pQMPolicyState->bAllowsSoft = FALSE;
pQMPolicyState->cRef = 1;
pQMPolicyState->bInSPD = FALSE;
pQMPolicyState->dwErrorCode = 0;
pQMPolicyState->pNext = NULL;
*ppQMPolicyState = pQMPolicyState;
return (dwError);
error:
if (pQMPolicyState) {
PAFreeQMPolicyState(pQMPolicyState);
}
*ppQMPolicyState = NULL;
return (dwError);
}
VOID
PAFreeQMPolicyState(
PQMPOLICYSTATE pQMPolicyState
)
{
if (pQMPolicyState) {
if (pQMPolicyState->pszPolicyName) {
FreeSPDString(pQMPolicyState->pszPolicyName);
}
FreeSPDMemory(pQMPolicyState);
}
}
BOOL
IsClearOnly(
GUID gNegPolAction
)
{
if (!memcmp(
&gNegPolAction,
&(GUID_NEGOTIATION_ACTION_NO_IPSEC),
sizeof(GUID))) {
return (TRUE);
}
else {
return (FALSE);
}
}
BOOL
IsBlocking(
GUID gNegPolAction
)
{
if (!memcmp(
&gNegPolAction,
&(GUID_NEGOTIATION_ACTION_BLOCK),
sizeof(GUID))) {
return (TRUE);
}
else {
return (FALSE);
}
}
BOOL
IsInboundPassThru(
GUID gNegPolAction
)
{
if (!memcmp(
&gNegPolAction,
&(GUID_NEGOTIATION_ACTION_INBOUND_PASSTHRU),
sizeof(GUID))) {
return (TRUE);
}
else {
return (FALSE);
}
}
DWORD
PACreateQMPolicy(
PIPSEC_NFA_DATA pIpsecNFAData,
PQMPOLICYSTATE pQMPolicyState,
PIPSEC_QM_POLICY * ppSPDQMPolicy
)
{
DWORD dwError = 0;
PIPSEC_QM_POLICY pSPDQMPolicy = NULL;
PIPSEC_NEGPOL_DATA pIpsecNegPolData = NULL;
pIpsecNegPolData = pIpsecNFAData->pIpsecNegPolData;
dwError = AllocateSPDMemory(
sizeof(IPSEC_QM_POLICY),
&pSPDQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
memcpy(
&(pSPDQMPolicy->gPolicyID),
&(pIpsecNegPolData->NegPolIdentifier),
sizeof(GUID)
);
dwError = AllocateSPDString(
pQMPolicyState->pszPolicyName,
&(pSPDQMPolicy->pszPolicyName)
);
BAIL_ON_WIN32_ERROR(dwError);
dwError = PACreateQMOffers(
pIpsecNegPolData->dwSecurityMethodCount,
pIpsecNegPolData->pIpsecSecurityMethods,
pQMPolicyState,
&(pSPDQMPolicy->dwOfferCount),
&(pSPDQMPolicy->pOffers)
);
BAIL_ON_WIN32_ERROR(dwError);
pSPDQMPolicy->dwFlags = 0;
if (!memcmp(
&(pIpsecNegPolData->NegPolType),
&(GUID_NEGOTIATION_TYPE_DEFAULT),
sizeof(GUID))) {
pSPDQMPolicy->dwFlags |= IPSEC_QM_POLICY_DEFAULT_POLICY;
}
if (pIpsecNFAData->dwTunnelFlags) {
pSPDQMPolicy->dwFlags |= IPSEC_QM_POLICY_TUNNEL_MODE;
}
if (pQMPolicyState->bAllowsSoft) {
pSPDQMPolicy->dwFlags |= IPSEC_QM_POLICY_ALLOW_SOFT;
}
*ppSPDQMPolicy = pSPDQMPolicy;
return (dwError);
error:
if (pSPDQMPolicy) {
PAFreeQMPolicy(
pSPDQMPolicy
);
}
*ppSPDQMPolicy = NULL;
return (dwError);
}
DWORD
PACreateQMOffers(
DWORD dwSecurityMethodCount,
PIPSEC_SECURITY_METHOD pIpsecSecurityMethods,
PQMPOLICYSTATE pQMPolicyState,
PDWORD pdwOfferCount,
PIPSEC_QM_OFFER * ppOffers
)
{
DWORD dwError = 0;
DWORD dwTempOfferCount = 0;
PIPSEC_SECURITY_METHOD pTempMethod = NULL;
BOOL bAllowsSoft = FALSE;
DWORD i = 0;
DWORD dwOfferCount = 0;
PIPSEC_QM_OFFER pOffers = NULL;
PIPSEC_QM_OFFER pTempOffer = NULL;
if (!dwSecurityMethodCount || !pIpsecSecurityMethods) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if (dwSecurityMethodCount > IPSEC_MAX_QM_OFFERS) {
dwTempOfferCount = IPSEC_MAX_QM_OFFERS;
}
else {
dwTempOfferCount = dwSecurityMethodCount;
}
pTempMethod = pIpsecSecurityMethods;
for (i = 0; i < dwTempOfferCount; i++) {
if (pTempMethod->Count == 0) {
bAllowsSoft = TRUE;
}
else {
dwOfferCount++;
}
pTempMethod++;
}
if (!dwOfferCount) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
dwError = AllocateSPDMemory(
sizeof(IPSEC_QM_OFFER)*dwOfferCount,
&(pOffers)
);
BAIL_ON_WIN32_ERROR(dwError);
pTempOffer = pOffers;
pTempMethod = pIpsecSecurityMethods;
i = 0;
while (i < dwOfferCount) {
if (pTempMethod->Count) {
PACopyQMOffers(
pTempMethod,
pTempOffer
);
i++;
pTempOffer++;
}
pTempMethod++;
}
pQMPolicyState->bAllowsSoft = bAllowsSoft;
*pdwOfferCount = dwOfferCount;
*ppOffers = pOffers;
return (dwError);
error:
if (pOffers) {
PAFreeQMOffers(
i,
pOffers
);
}
*pdwOfferCount = 0;
*ppOffers = NULL;
return (dwError);
}
VOID
PACopyQMOffers(
PIPSEC_SECURITY_METHOD pMethod,
PIPSEC_QM_OFFER pOffer
)
{
DWORD i = 0;
DWORD j = 0;
DWORD k = 0;
pOffer->Lifetime.uKeyExpirationKBytes = pMethod->Lifetime.KeyExpirationBytes;
pOffer->Lifetime.uKeyExpirationTime = pMethod->Lifetime.KeyExpirationTime;
pOffer->dwFlags = pMethod->Flags;
pOffer->bPFSRequired = pMethod->PfsQMRequired;
if (pMethod->PfsQMRequired) {
pOffer->dwPFSGroup = PFS_GROUP_MM;
}
else {
pOffer->dwPFSGroup = PFS_GROUP_NONE;
}
i = 0;
for (j = 0; (j < pMethod->Count) && (i < QM_MAX_ALGOS) ; j++) {
switch (pMethod->Algos[j].operation) {
case Auth:
switch (pMethod->Algos[j].algoIdentifier) {
case IPSEC_AH_MD5:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_AH_MD5;
break;
case IPSEC_AH_SHA:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
break;
default:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_AH_NONE;
break;
}
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_NONE;
pOffer->Algos[i].Operation = AUTHENTICATION;
pOffer->Algos[i].uAlgoKeyLen = pMethod->Algos[j].algoKeylen;
pOffer->Algos[i].uAlgoRounds = pMethod->Algos[j].algoRounds;
pOffer->Algos[i].MySpi = 0;
pOffer->Algos[i].PeerSpi = 0;
i++;
break;
case Encrypt:
switch (pMethod->Algos[j].algoIdentifier) {
case IPSEC_ESP_DES:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_DES;
break;
case IPSEC_ESP_DES_40:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_DES;
break;
case IPSEC_ESP_3_DES:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
break;
default:
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_NONE;
break;
}
switch (pMethod->Algos[j].secondaryAlgoIdentifier) {
case IPSEC_AH_MD5:
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_MD5;
break;
case IPSEC_AH_SHA:
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_SHA1;
break;
default:
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_NONE;
break;
}
pOffer->Algos[i].Operation = ENCRYPTION;
pOffer->Algos[i].uAlgoKeyLen = pMethod->Algos[j].algoKeylen;
pOffer->Algos[i].uAlgoRounds = pMethod->Algos[j].algoRounds;
pOffer->Algos[i].MySpi = 0;
pOffer->Algos[i].PeerSpi = 0;
i++;
break;
case None:
case Compress:
default:
break;
}
}
for (k = i; k < QM_MAX_ALGOS; k++) {
memset(&(pOffer->Algos[k]), 0, sizeof(IPSEC_QM_ALGO));
}
pOffer->dwNumAlgos = i;
}
VOID
PAFreeQMPolicy(
PIPSEC_QM_POLICY pSPDQMPolicy
)
{
if (pSPDQMPolicy) {
if (pSPDQMPolicy->pszPolicyName) {
FreeSPDString(pSPDQMPolicy->pszPolicyName);
}
PAFreeQMOffers(
pSPDQMPolicy->dwOfferCount,
pSPDQMPolicy->pOffers
);
FreeSPDMemory(pSPDQMPolicy);
}
}
VOID
PAFreeQMOffers(
DWORD dwOfferCount,
PIPSEC_QM_OFFER pOffers
)
{
if (pOffers) {
FreeSPDMemory(pOffers);
}
}
DWORD
PADeleteAllQMPolicies(
)
{
DWORD dwError = 0;
PQMPOLICYSTATE pQMPolicyState = NULL;
LPWSTR pServerName = NULL;
PQMPOLICYSTATE pTemp = NULL;
PQMPOLICYSTATE pLeftQMPolicyState = NULL;
pQMPolicyState = gpQMPolicyState;
while (pQMPolicyState) {
if (pQMPolicyState->bInSPD) {
dwError = DeleteQMPolicy(
pServerName,
pQMPolicyState->pszPolicyName
);
if (!dwError) {
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
PAFreeQMPolicyState(pTemp);
}
else {
pQMPolicyState->dwErrorCode = dwError;
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
pTemp->pNext = pLeftQMPolicyState;
pLeftQMPolicyState = pTemp;
}
}
else {
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
PAFreeQMPolicyState(pTemp);
}
}
gpQMPolicyState = pLeftQMPolicyState;
return (dwError);
}
VOID
PAFreeQMPolicyStateList(
PQMPOLICYSTATE pQMPolicyState
)
{
PQMPOLICYSTATE pTemp = NULL;
while (pQMPolicyState) {
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
PAFreeQMPolicyState(pTemp);
}
}
PQMPOLICYSTATE
FindQMPolicyState(
GUID gPolicyID
)
{
PQMPOLICYSTATE pQMPolicyState = NULL;
pQMPolicyState = gpQMPolicyState;
while (pQMPolicyState) {
if (!memcmp(&(pQMPolicyState->gPolicyID), &gPolicyID, sizeof(GUID))) {
return (pQMPolicyState);
}
pQMPolicyState = pQMPolicyState->pNext;
}
return (NULL);
}
DWORD
PADeleteQMPolicies(
PIPSEC_NFA_DATA * ppIpsecNFAData,
DWORD dwNumNFACount
)
{
DWORD dwError = 0;
DWORD i = 0;
PIPSEC_NFA_DATA pIpsecNFAData = NULL;
PIPSEC_NEGPOL_DATA pIpsecNegPolData = NULL;
for (i = 0; i < dwNumNFACount; i++) {
pIpsecNFAData = *(ppIpsecNFAData + i);
pIpsecNegPolData = pIpsecNFAData->pIpsecNegPolData;
dwError = PADeleteQMPolicy(
pIpsecNegPolData->NegPolIdentifier
);
}
return (dwError);
}
DWORD
PADeleteQMPolicy(
GUID gPolicyID
)
{
DWORD dwError = 0;
PQMPOLICYSTATE pQMPolicyState = NULL;
LPWSTR pServerName = NULL;
pQMPolicyState = FindQMPolicyState(
gPolicyID
);
if (!pQMPolicyState) {
dwError = ERROR_SUCCESS;
return (dwError);
}
pQMPolicyState->cRef--;
if (pQMPolicyState->cRef > 0) {
dwError = ERROR_SUCCESS;
return (dwError);
}
if (pQMPolicyState->bInSPD) {
dwError = DeleteQMPolicy(
pServerName,
pQMPolicyState->pszPolicyName
);
if (dwError) {
pQMPolicyState->cRef++;
pQMPolicyState->dwErrorCode = dwError;
}
BAIL_ON_WIN32_ERROR(dwError);
}
PADeleteQMPolicyState(pQMPolicyState);
error:
return (dwError);
}
VOID
PADeleteQMPolicyState(
PQMPOLICYSTATE pQMPolicyState
)
{
PQMPOLICYSTATE * ppTemp = NULL;
ppTemp = &gpQMPolicyState;
while (*ppTemp) {
if (*ppTemp == pQMPolicyState) {
break;
}
ppTemp = &((*ppTemp)->pNext);
}
if (*ppTemp) {
*ppTemp = pQMPolicyState->pNext;
}
PAFreeQMPolicyState(pQMPolicyState);
return;
}
DWORD
PADeleteInUseQMPolicies(
)
{
DWORD dwError = 0;
PQMPOLICYSTATE pQMPolicyState = NULL;
LPWSTR pServerName = NULL;
PQMPOLICYSTATE pTemp = NULL;
PQMPOLICYSTATE pLeftQMPolicyState = NULL;
pQMPolicyState = gpQMPolicyState;
while (pQMPolicyState) {
if (pQMPolicyState->bInSPD &&
(pQMPolicyState->dwErrorCode == ERROR_IPSEC_QM_POLICY_IN_USE)) {
dwError = DeleteQMPolicy(
pServerName,
pQMPolicyState->pszPolicyName
);
if (!dwError) {
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
PAFreeQMPolicyState(pTemp);
}
else {
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
pTemp->pNext = pLeftQMPolicyState;
pLeftQMPolicyState = pTemp;
}
}
else {
pTemp = pQMPolicyState;
pQMPolicyState = pQMPolicyState->pNext;
pTemp->pNext = pLeftQMPolicyState;
pLeftQMPolicyState = pTemp;
}
}
gpQMPolicyState = pLeftQMPolicyState;
return (dwError);
}