1349 lines
27 KiB
C
1349 lines
27 KiB
C
/*++
|
|
|
|
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);
|
|
|
|
}
|
|
|