windows-nt/Source/XPSP1/NT/net/ipsec/spd/server/qm-policy.c

1349 lines
27 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
qm-policy.c
Abstract:
Author:
Environment: User Mode
Revision History:
--*/
#include "precomp.h"
DWORD
AddQMPolicy(
LPWSTR pServerName,
DWORD dwFlags,
PIPSEC_QM_POLICY pQMPolicy
)
/*++
Routine Description:
This function adds a quick mode policy to the SPD.
Arguments:
pServerName - Server on which the quick mode policy is to be added.
pQMPolicy - Quick mode policy to be added.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
BOOL bPersist = FALSE;
bPersist = (BOOL) (dwFlags & PERSIST_SPD_OBJECT);
//
// Validate the quick mode policy.
//
dwError = ValidateQMPolicy(
pQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy = FindQMPolicy(
gpIniQMPolicy,
pQMPolicy->pszPolicyName
);
if (pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_EXISTS;
BAIL_ON_LOCK_ERROR(dwError);
}
pIniQMPolicy = FindQMPolicyByGuid(
gpIniQMPolicy,
pQMPolicy->gPolicyID
);
if (pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_EXISTS;
BAIL_ON_LOCK_ERROR(dwError);
}
if (bPersist && !gbLoadingPersistence) {
dwError = PersistQMPolicy(
pQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
}
dwError = CreateIniQMPolicy(
pQMPolicy,
&pIniQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy->bIsPersisted = bPersist;
pIniQMPolicy->pNext = gpIniQMPolicy;
gpIniQMPolicy = pIniQMPolicy;
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
gpIniDefaultQMPolicy = pIniQMPolicy;
}
LEAVE_SPD_SECTION();
return (dwError);
lock:
LEAVE_SPD_SECTION();
error:
if (pQMPolicy && bPersist && !gbLoadingPersistence) {
(VOID) SPDPurgeQMPolicy(
pQMPolicy->gPolicyID
);
}
return (dwError);
}
DWORD
ValidateQMPolicy(
PIPSEC_QM_POLICY pQMPolicy
)
{
DWORD dwError = 0;
if (!pQMPolicy) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if (!(pQMPolicy->pszPolicyName) || !(*(pQMPolicy->pszPolicyName))) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
dwError = ValidateQMOffers(
pQMPolicy->dwOfferCount,
pQMPolicy->pOffers
);
BAIL_ON_WIN32_ERROR(dwError);
error:
return (dwError);
}
DWORD
ValidateQMOffers(
DWORD dwOfferCount,
PIPSEC_QM_OFFER pOffers
)
{
DWORD dwError = 0;
DWORD i = 0;
PIPSEC_QM_OFFER pTemp = NULL;
DWORD j = 0;
BOOL bAH = FALSE;
BOOL bESP = FALSE;
DWORD dwQMGroup = PFS_GROUP_NONE;
if (!dwOfferCount || !pOffers || (dwOfferCount > IPSEC_MAX_QM_OFFERS)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
//
// Need to catch the exception when the number of offers
// specified is more than the actual number of offers.
//
pTemp = pOffers;
if (pTemp->bPFSRequired) {
if ((pTemp->dwPFSGroup != PFS_GROUP_1) &&
(pTemp->dwPFSGroup != PFS_GROUP_2) &&
(pTemp->dwPFSGroup != PFS_GROUP_MM)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
dwQMGroup=pTemp->dwPFSGroup;
}
else {
if (pTemp->dwPFSGroup != PFS_GROUP_NONE) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
}
for (i = 0; i < dwOfferCount; i++) {
if (dwQMGroup) {
if ((!pTemp->bPFSRequired) || (pTemp->dwPFSGroup != dwQMGroup)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
} else {
if ((pTemp->bPFSRequired) || (pTemp->dwPFSGroup != PFS_GROUP_NONE)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
}
if (!(pTemp->dwNumAlgos) || (pTemp->dwNumAlgos > QM_MAX_ALGOS)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
bAH = FALSE;
bESP = FALSE;
for (j = 0; j < (pTemp->dwNumAlgos); j++) {
switch (pTemp->Algos[j].Operation) {
case AUTHENTICATION:
if (bAH) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if ((pTemp->Algos[j].uAlgoIdentifier == IPSEC_DOI_AH_NONE) ||
(pTemp->Algos[j].uAlgoIdentifier >= IPSEC_DOI_AH_MAX)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if (pTemp->Algos[j].uSecAlgoIdentifier != HMAC_AH_NONE) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
bAH = TRUE;
break;
case ENCRYPTION:
if (bESP) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if (pTemp->Algos[j].uAlgoIdentifier >= IPSEC_DOI_ESP_MAX) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if (pTemp->Algos[j].uSecAlgoIdentifier >= HMAC_AH_MAX) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
if (pTemp->Algos[j].uAlgoIdentifier == IPSEC_DOI_ESP_NONE) {
if (pTemp->Algos[j].uSecAlgoIdentifier == HMAC_AH_NONE) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
}
bESP = TRUE;
break;
case NONE:
case COMPRESSION:
default:
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
break;
}
}
pTemp++;
}
error:
return (dwError);
}
DWORD
CreateIniQMPolicy(
PIPSEC_QM_POLICY pQMPolicy,
PINIQMPOLICY * ppIniQMPolicy
)
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
dwError = AllocateSPDMemory(
sizeof(INIQMPOLICY),
&pIniQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
memcpy(
&(pIniQMPolicy->gPolicyID),
&(pQMPolicy->gPolicyID),
sizeof(GUID)
);
dwError = AllocateSPDString(
pQMPolicy->pszPolicyName,
&(pIniQMPolicy->pszPolicyName)
);
BAIL_ON_WIN32_ERROR(dwError);
pIniQMPolicy->cRef = 0;
pIniQMPolicy->bIsPersisted = FALSE;
pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
pIniQMPolicy->pNext = NULL;
dwError = CreateIniQMOffers(
pQMPolicy->dwOfferCount,
pQMPolicy->pOffers,
&(pIniQMPolicy->dwOfferCount),
&(pIniQMPolicy->pOffers)
);
BAIL_ON_WIN32_ERROR(dwError);
*ppIniQMPolicy = pIniQMPolicy;
return (dwError);
error:
if (pIniQMPolicy) {
FreeIniQMPolicy(
pIniQMPolicy
);
}
*ppIniQMPolicy = NULL;
return (dwError);
}
DWORD
CreateIniQMOffers(
DWORD dwInOfferCount,
PIPSEC_QM_OFFER pInOffers,
PDWORD pdwOfferCount,
PIPSEC_QM_OFFER * ppOffers
)
{
DWORD dwError = 0;
PIPSEC_QM_OFFER pOffers = NULL;
PIPSEC_QM_OFFER pTemp = NULL;
PIPSEC_QM_OFFER pInTempOffer = NULL;
DWORD i = 0;
DWORD j = 0;
//
// Offer count and the offers themselves have already been validated.
//
dwError = AllocateSPDMemory(
sizeof(IPSEC_QM_OFFER) * dwInOfferCount,
&(pOffers)
);
BAIL_ON_WIN32_ERROR(dwError);
pTemp = pOffers;
pInTempOffer = pInOffers;
for (i = 0; i < dwInOfferCount; i++) {
memcpy(
&(pTemp->Lifetime),
&(pInTempOffer->Lifetime),
sizeof(KEY_LIFETIME)
);
pTemp->dwFlags = pInTempOffer->dwFlags;
pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
memcpy(
&(pTemp->Algos[j]),
&(pInTempOffer->Algos[j]),
sizeof(IPSEC_QM_ALGO)
);
}
pInTempOffer++;
pTemp++;
}
*pdwOfferCount = dwInOfferCount;
*ppOffers = pOffers;
return (dwError);
error:
if (pOffers) {
FreeIniQMOffers(
i,
pOffers
);
}
*pdwOfferCount = 0;
*ppOffers = NULL;
return (dwError);
}
VOID
FreeIniQMPolicy(
PINIQMPOLICY pIniQMPolicy
)
{
if (pIniQMPolicy) {
if (pIniQMPolicy->pszPolicyName) {
FreeSPDString(pIniQMPolicy->pszPolicyName);
}
FreeIniQMOffers(
pIniQMPolicy->dwOfferCount,
pIniQMPolicy->pOffers
);
FreeSPDMemory(pIniQMPolicy);
}
}
VOID
FreeIniQMOffers(
DWORD dwOfferCount,
PIPSEC_QM_OFFER pOffers
)
{
if (pOffers) {
FreeSPDMemory(pOffers);
}
}
PINIQMPOLICY
FindQMPolicy(
PINIQMPOLICY pIniQMPolicyList,
LPWSTR pszPolicyName
)
{
DWORD dwError = 0;
PINIQMPOLICY pTemp = NULL;
pTemp = pIniQMPolicyList;
while (pTemp) {
if (!_wcsicmp(pTemp->pszPolicyName, pszPolicyName)) {
return (pTemp);
}
pTemp = pTemp->pNext;
}
return (NULL);
}
DWORD
DeleteQMPolicy(
LPWSTR pServerName,
LPWSTR pszPolicyName
)
/*++
Routine Description:
This function deletes a quick mode policy from the SPD.
Arguments:
pServerName - Server on which the quick mode policy is to be deleted.
pszPolicyName - Quick mode policy to be deleted.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
GUID gPolicyID;
if (!pszPolicyName || !*pszPolicyName) {
return (ERROR_INVALID_PARAMETER);
}
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy = FindQMPolicy(
gpIniQMPolicy,
pszPolicyName
);
if (!pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
BAIL_ON_LOCK_ERROR(dwError);
}
if (pIniQMPolicy->cRef) {
dwError = ERROR_IPSEC_QM_POLICY_IN_USE;
memcpy(&gPolicyID, &pIniQMPolicy->gPolicyID, sizeof(GUID));
BAIL_ON_LOCK_ERROR(dwError);
}
memcpy(&gPolicyID, &pIniQMPolicy->gPolicyID, sizeof(GUID));
if (pIniQMPolicy->bIsPersisted) {
dwError = SPDPurgeQMPolicy(
gPolicyID
);
BAIL_ON_LOCK_ERROR(dwError);
}
dwError = DeleteIniQMPolicy(
pIniQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
LEAVE_SPD_SECTION();
if (gbIKENotify) {
(VOID) IKENotifyPolicyChange(
&(gPolicyID),
POLICY_GUID_QM
);
}
return (dwError);
lock:
LEAVE_SPD_SECTION();
if ((dwError == ERROR_IPSEC_QM_POLICY_IN_USE) && gbIKENotify) {
(VOID) IKENotifyPolicyChange(
&(gPolicyID),
POLICY_GUID_QM
);
}
return (dwError);
}
DWORD
EnumQMPolicies(
LPWSTR pServerName,
PIPSEC_QM_POLICY * ppQMPolicies,
DWORD dwPreferredNumEntries,
LPDWORD pdwNumPolicies,
LPDWORD pdwResumeHandle
)
/*++
Routine Description:
This function enumerates quick mode policies from the SPD.
Arguments:
pServerName - Server on which the quick mode policies are to
be enumerated.
ppQMPolicies - Enumerated quick mode policies returned to the
caller.
dwPreferredNumEntries - Preferred number of enumeration entries.
pdwNumPolicies - Number of quick mode policies actually enumerated.
pdwResumeHandle - Handle to the location in the quick mode policy
list from which to resume enumeration.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
DWORD dwResumeHandle = 0;
DWORD dwNumToEnum = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
DWORD i = 0;
PINIQMPOLICY pTemp = NULL;
DWORD dwNumPolicies = 0;
PIPSEC_QM_POLICY pQMPolicies = NULL;
PIPSEC_QM_POLICY pQMPolicy = NULL;
dwResumeHandle = *pdwResumeHandle;
if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_QMPOLICY_ENUM_COUNT)) {
dwNumToEnum = MAX_QMPOLICY_ENUM_COUNT;
}
else {
dwNumToEnum = dwPreferredNumEntries;
}
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy = gpIniQMPolicy;
for (i = 0; (i < dwResumeHandle) && (pIniQMPolicy != NULL); i++) {
pIniQMPolicy = pIniQMPolicy->pNext;
}
if (!pIniQMPolicy) {
dwError = ERROR_NO_DATA;
BAIL_ON_LOCK_ERROR(dwError);
}
pTemp = pIniQMPolicy;
while (pTemp && (dwNumPolicies < dwNumToEnum)) {
dwNumPolicies++;
pTemp = pTemp->pNext;
}
dwError = SPDApiBufferAllocate(
sizeof(IPSEC_QM_POLICY)*dwNumPolicies,
&pQMPolicies
);
BAIL_ON_LOCK_ERROR(dwError);
pTemp = pIniQMPolicy;
pQMPolicy = pQMPolicies;
for (i = 0; i < dwNumPolicies; i++) {
dwError = CopyQMPolicy(
pTemp,
pQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
pTemp = pTemp->pNext;
pQMPolicy++;
}
*ppQMPolicies = pQMPolicies;
*pdwResumeHandle = dwResumeHandle + dwNumPolicies;
*pdwNumPolicies = dwNumPolicies;
LEAVE_SPD_SECTION();
return (dwError);
lock:
LEAVE_SPD_SECTION();
if (pQMPolicies) {
FreeQMPolicies(
i,
pQMPolicies
);
}
*ppQMPolicies = NULL;
*pdwResumeHandle = dwResumeHandle;
*pdwNumPolicies = 0;
return (dwError);
}
DWORD
SetQMPolicy(
LPWSTR pServerName,
LPWSTR pszPolicyName,
PIPSEC_QM_POLICY pQMPolicy
)
/*++
Routine Description:
This function updates a quick mode policy in the SPD.
Arguments:
pServerName - Server on which the quick mode policy is to be
updated.
pszPolicyName - Name of the quick mode policy to be updated.
pQMPolicy - New quick mode policy which will replace the
existing policy.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
if (!pszPolicyName || !*pszPolicyName) {
return (ERROR_INVALID_PARAMETER);
}
//
// Validate quick mode policy.
//
dwError = ValidateQMPolicy(
pQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy = FindQMPolicy(
gpIniQMPolicy,
pszPolicyName
);
if (!pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
BAIL_ON_LOCK_ERROR(dwError);
}
if (memcmp(
&(pIniQMPolicy->gPolicyID),
&(pQMPolicy->gPolicyID),
sizeof(GUID))) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_LOCK_ERROR(dwError);
}
dwError = SetIniQMPolicy(
pIniQMPolicy,
pQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
if (pIniQMPolicy->bIsPersisted) {
dwError = PersistQMPolicy(
pQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
}
LEAVE_SPD_SECTION();
(VOID) IKENotifyPolicyChange(
&(pQMPolicy->gPolicyID),
POLICY_GUID_QM
);
return (dwError);
lock:
LEAVE_SPD_SECTION();
error:
return (dwError);
}
DWORD
GetQMPolicy(
LPWSTR pServerName,
LPWSTR pszPolicyName,
PIPSEC_QM_POLICY * ppQMPolicy
)
/*++
Routine Description:
This function gets a quick mode policy from the SPD.
Arguments:
pServerName - Server from which to get the quick mode policy.
pszPolicyName - Name of the quick mode policy to get.
ppQMPolicy - Quick mode policy found returned to the caller.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
PIPSEC_QM_POLICY pQMPolicy = NULL;
if (!pszPolicyName || !*pszPolicyName) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy = FindQMPolicy(
gpIniQMPolicy,
pszPolicyName
);
if (!pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
BAIL_ON_LOCK_ERROR(dwError);
}
dwError = GetIniQMPolicy(
pIniQMPolicy,
&pQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
*ppQMPolicy = pQMPolicy;
LEAVE_SPD_SECTION();
return (dwError);
lock:
LEAVE_SPD_SECTION();
error:
*ppQMPolicy = NULL;
return (dwError);
}
DWORD
SetIniQMPolicy(
PINIQMPOLICY pIniQMPolicy,
PIPSEC_QM_POLICY pQMPolicy
)
{
DWORD dwError = 0;
DWORD dwOfferCount = 0;
PIPSEC_QM_OFFER pOffers = NULL;
dwError = CreateIniQMOffers(
pQMPolicy->dwOfferCount,
pQMPolicy->pOffers,
&dwOfferCount,
&pOffers
);
BAIL_ON_WIN32_ERROR(dwError);
FreeIniQMOffers(
pIniQMPolicy->dwOfferCount,
pIniQMPolicy->pOffers
);
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
gpIniDefaultQMPolicy = NULL;
}
pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
pIniQMPolicy->dwOfferCount = dwOfferCount;
pIniQMPolicy->pOffers = pOffers;
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
gpIniDefaultQMPolicy = pIniQMPolicy;
}
error:
return (dwError);
}
DWORD
GetIniQMPolicy(
PINIQMPOLICY pIniQMPolicy,
PIPSEC_QM_POLICY * ppQMPolicy
)
{
DWORD dwError = 0;
PIPSEC_QM_POLICY pQMPolicy = NULL;
dwError = SPDApiBufferAllocate(
sizeof(IPSEC_QM_POLICY),
&pQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
dwError = CopyQMPolicy(
pIniQMPolicy,
pQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
*ppQMPolicy = pQMPolicy;
return (dwError);
error:
if (pQMPolicy) {
SPDApiBufferFree(pQMPolicy);
}
*ppQMPolicy = NULL;
return (dwError);
}
DWORD
CopyQMPolicy(
PINIQMPOLICY pIniQMPolicy,
PIPSEC_QM_POLICY pQMPolicy
)
{
DWORD dwError = 0;
memcpy(
&(pQMPolicy->gPolicyID),
&(pIniQMPolicy->gPolicyID),
sizeof(GUID)
);
dwError = SPDApiBufferAllocate(
wcslen(pIniQMPolicy->pszPolicyName)*sizeof(WCHAR)
+ sizeof(WCHAR),
&(pQMPolicy->pszPolicyName)
);
BAIL_ON_WIN32_ERROR(dwError);
wcscpy(pQMPolicy->pszPolicyName, pIniQMPolicy->pszPolicyName);
pQMPolicy->dwFlags = pIniQMPolicy->dwFlags;
dwError = CreateQMOffers(
pIniQMPolicy->dwOfferCount,
pIniQMPolicy->pOffers,
&(pQMPolicy->dwOfferCount),
&(pQMPolicy->pOffers)
);
BAIL_ON_WIN32_ERROR(dwError);
return (dwError);
error:
if (pQMPolicy->pszPolicyName) {
SPDApiBufferFree(pQMPolicy->pszPolicyName);
}
return (dwError);
}
DWORD
CreateQMOffers(
DWORD dwInOfferCount,
PIPSEC_QM_OFFER pInOffers,
PDWORD pdwOfferCount,
PIPSEC_QM_OFFER * ppOffers
)
{
DWORD dwError = 0;
PIPSEC_QM_OFFER pOffers = NULL;
PIPSEC_QM_OFFER pTemp = NULL;
PIPSEC_QM_OFFER pInTempOffer = NULL;
DWORD i = 0;
DWORD j = 0;
DWORD k = 0;
//
// Offer count and the offers themselves have already been validated.
//
dwError = SPDApiBufferAllocate(
sizeof(IPSEC_QM_OFFER) * dwInOfferCount,
&(pOffers)
);
BAIL_ON_WIN32_ERROR(dwError);
pTemp = pOffers;
pInTempOffer = pInOffers;
for (i = 0; i < dwInOfferCount; i++) {
memcpy(
&(pTemp->Lifetime),
&(pInTempOffer->Lifetime),
sizeof(KEY_LIFETIME)
);
pTemp->dwFlags = pInTempOffer->dwFlags;
pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
memcpy(
&(pTemp->Algos[j]),
&(pInTempOffer->Algos[j]),
sizeof(IPSEC_QM_ALGO)
);
}
for (k = j; k < QM_MAX_ALGOS; k++) {
memset(&(pTemp->Algos[k]), 0, sizeof(IPSEC_QM_ALGO));
}
pInTempOffer++;
pTemp++;
}
*pdwOfferCount = dwInOfferCount;
*ppOffers = pOffers;
return (dwError);
error:
if (pOffers) {
FreeQMOffers(
i,
pOffers
);
}
*pdwOfferCount = 0;
*ppOffers = NULL;
return (dwError);
}
DWORD
DeleteIniQMPolicy(
PINIQMPOLICY pIniQMPolicy
)
{
DWORD dwError = 0;
PINIQMPOLICY * ppTemp = NULL;
ppTemp = &gpIniQMPolicy;
while (*ppTemp) {
if (*ppTemp == pIniQMPolicy) {
break;
}
ppTemp = &((*ppTemp)->pNext);
}
if (*ppTemp) {
*ppTemp = pIniQMPolicy->pNext;
}
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
gpIniDefaultQMPolicy = NULL;
}
FreeIniQMPolicy(pIniQMPolicy);
return (dwError);
}
VOID
FreeQMOffers(
DWORD dwOfferCount,
PIPSEC_QM_OFFER pOffers
)
{
if (pOffers) {
SPDApiBufferFree(pOffers);
}
}
VOID
FreeIniQMPolicyList(
PINIQMPOLICY pIniQMPolicyList
)
{
PINIQMPOLICY pTemp = NULL;
PINIQMPOLICY pIniQMPolicy = NULL;
pTemp = pIniQMPolicyList;
while (pTemp) {
pIniQMPolicy = pTemp;
pTemp = pTemp->pNext;
FreeIniQMPolicy(pIniQMPolicy);
}
}
PINIQMPOLICY
FindQMPolicyByGuid(
PINIQMPOLICY pIniQMPolicyList,
GUID gPolicyID
)
{
DWORD dwError = 0;
PINIQMPOLICY pTemp = NULL;
pTemp = pIniQMPolicyList;
while (pTemp) {
if (!memcmp(&(pTemp->gPolicyID), &gPolicyID, sizeof(GUID))) {
return (pTemp);
}
pTemp = pTemp->pNext;
}
return (NULL);
}
VOID
FreeQMPolicies(
DWORD dwNumQMPolicies,
PIPSEC_QM_POLICY pQMPolicies
)
{
DWORD i = 0;
if (pQMPolicies) {
for (i = 0; i < dwNumQMPolicies; i++) {
if (pQMPolicies[i].pszPolicyName) {
SPDApiBufferFree(pQMPolicies[i].pszPolicyName);
}
FreeQMOffers(
pQMPolicies[i].dwOfferCount,
pQMPolicies[i].pOffers
);
}
SPDApiBufferFree(pQMPolicies);
}
}
DWORD
GetQMPolicyByID(
LPWSTR pServerName,
GUID gQMPolicyID,
PIPSEC_QM_POLICY * ppQMPolicy
)
/*++
Routine Description:
This function gets a quick mode policy from the SPD.
Arguments:
pServerName - Server from which to get the quick mode policy.
gQMFilter - Guid of the quick mode policy to get.
ppQMPolicy - Quick mode policy found returned to the caller.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
PIPSEC_QM_POLICY pQMPolicy = NULL;
ENTER_SPD_SECTION();
dwError = ValidateSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniQMPolicy = FindQMPolicyByGuid(
gpIniQMPolicy,
gQMPolicyID
);
if (!pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
BAIL_ON_LOCK_ERROR(dwError);
}
dwError = GetIniQMPolicy(
pIniQMPolicy,
&pQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
*ppQMPolicy = pQMPolicy;
LEAVE_SPD_SECTION();
return (dwError);
lock:
LEAVE_SPD_SECTION();
*ppQMPolicy = NULL;
return (dwError);
}
DWORD
LocateQMPolicy(
DWORD dwFlags,
GUID gPolicyID,
PINIQMPOLICY * ppIniQMPolicy
)
{
DWORD dwError = 0;
PINIQMPOLICY pIniQMPolicy = NULL;
if (dwFlags & IPSEC_QM_POLICY_DEFAULT_POLICY) {
if (!gpIniDefaultQMPolicy) {
dwError = ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND;
BAIL_ON_WIN32_ERROR(dwError);
}
pIniQMPolicy = gpIniDefaultQMPolicy;
}
else {
pIniQMPolicy = FindQMPolicyByGuid(
gpIniQMPolicy,
gPolicyID
);
if (!pIniQMPolicy) {
dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
BAIL_ON_WIN32_ERROR(dwError);
}
}
*ppIniQMPolicy = pIniQMPolicy;
return (dwError);
error:
*ppIniQMPolicy = NULL;
return (dwError);
}