You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1691 lines
37 KiB
1691 lines
37 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
qm-policy.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Author:
|
|
|
|
|
|
Environment: User Mode
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#ifdef TRACE_ON
|
|
#include "qm-policy.tmh"
|
|
#endif
|
|
|
|
|
|
DWORD
|
|
AddQMPolicyInternal(
|
|
LPWSTR pServerName,
|
|
DWORD dwVersion,
|
|
DWORD dwFlags,
|
|
DWORD dwSource,
|
|
PIPSEC_QM_POLICY pQMPolicy,
|
|
LPVOID pvReserved
|
|
)
|
|
/*++
|
|
|
|
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;
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
dwError = CreateIniQMPolicy(
|
|
pQMPolicy,
|
|
&pIniQMPolicy
|
|
);
|
|
if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
|
|
BAIL_ON_LOCK_ERROR(dwError);
|
|
}
|
|
|
|
pIniQMPolicy->dwSource = dwSource;
|
|
|
|
pIniQMPolicy->pNext = gpIniQMPolicy;
|
|
gpIniQMPolicy = pIniQMPolicy;
|
|
|
|
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
|
|
gpIniDefaultQMPolicy = pIniQMPolicy;
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
(L"Set default QM policy to \"%ls\" (%!guid!)",
|
|
pQMPolicy->pszPolicyName,
|
|
&pQMPolicy->gPolicyID)
|
|
);
|
|
|
|
}
|
|
|
|
LEAVE_SPD_SECTION();
|
|
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
(L"Added QM policy \"%ls\"(%!guid!)",
|
|
pQMPolicy->pszPolicyName,
|
|
&pQMPolicy->gPolicyID)
|
|
);
|
|
|
|
return (dwError);
|
|
|
|
lock:
|
|
|
|
LEAVE_SPD_SECTION();
|
|
|
|
error:
|
|
#ifdef TRACE_ON
|
|
if (pQMPolicy) {
|
|
TRACE(
|
|
TRC_ERROR,
|
|
(L"Failed to add QM policy \"%ls\"(%!guid!): %!winerr!",
|
|
pQMPolicy->pszPolicyName,
|
|
&pQMPolicy->gPolicyID,
|
|
dwError)
|
|
);
|
|
} else {
|
|
TRACE(
|
|
TRC_ERROR,
|
|
(L"Failed to add MM policy. Policy details unavailable since pQMPolicy is null: %!winerr!",
|
|
dwError)
|
|
);
|
|
}
|
|
#endif
|
|
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
DWORD
|
|
AddQMPolicy(
|
|
LPWSTR pServerName,
|
|
DWORD dwVersion,
|
|
DWORD dwFlags,
|
|
PIPSEC_QM_POLICY pQMPolicy,
|
|
LPVOID pvReserved
|
|
)
|
|
{
|
|
return
|
|
AddQMPolicyInternal(
|
|
pServerName,
|
|
dwVersion,
|
|
dwFlags,
|
|
IPSEC_SOURCE_WINIPSEC,
|
|
pQMPolicy,
|
|
pvReserved);
|
|
}
|
|
|
|
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:
|
|
#ifdef TRACE_ON
|
|
if (dwError) {
|
|
TRACE(TRC_ERROR, ("Failed QM policy validation: %!winerr!", dwError));
|
|
}
|
|
#endif
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
ValidateQMOffers(
|
|
DWORD dwOfferCount,
|
|
PIPSEC_QM_OFFER pOffers
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
|
|
if (!dwOfferCount || !pOffers || (dwOfferCount > IPSEC_MAX_QM_OFFERS)) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
error:
|
|
#ifdef TRACE_ON
|
|
if (dwError) {
|
|
TRACE(TRC_ERROR, ("Failed QM offers validation: %!winerr!", dwError));
|
|
}
|
|
#endif
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
DWORD
|
|
ValidateQMOffer(
|
|
PIPSEC_QM_OFFER pOffer,
|
|
BOOL *pbInitGroup,
|
|
LPDWORD pdwPFSGroup
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
DWORD j = 0;
|
|
BOOL bAH = FALSE;
|
|
BOOL bESP = FALSE;
|
|
DWORD dwPFSGroup = *pdwPFSGroup;
|
|
BOOL bInitGroup = *pbInitGroup;
|
|
|
|
if (!bInitGroup) {
|
|
if (pOffer->bPFSRequired) {
|
|
if ((pOffer->dwPFSGroup != PFS_GROUP_1) &&
|
|
(pOffer->dwPFSGroup != PFS_GROUP_2) &&
|
|
(pOffer->dwPFSGroup != PFS_GROUP_2048) &&
|
|
(pOffer->dwPFSGroup != PFS_GROUP_MM)) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
dwPFSGroup=pOffer->dwPFSGroup;
|
|
}
|
|
else {
|
|
if (pOffer->dwPFSGroup != PFS_GROUP_NONE) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
dwPFSGroup=PFS_GROUP_NONE;
|
|
}
|
|
bInitGroup = TRUE;
|
|
|
|
}
|
|
|
|
if (dwPFSGroup) {
|
|
if ((!pOffer->bPFSRequired) || (pOffer->dwPFSGroup != dwPFSGroup)) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
} else {
|
|
if ((pOffer->bPFSRequired) || (pOffer->dwPFSGroup != PFS_GROUP_NONE)) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
}
|
|
|
|
if (!(pOffer->dwNumAlgos) || (pOffer->dwNumAlgos > QM_MAX_ALGOS)) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
bAH = FALSE;
|
|
bESP = FALSE;
|
|
|
|
for (j = 0; j < (pOffer->dwNumAlgos); j++) {
|
|
|
|
switch (pOffer->Algos[j].Operation) {
|
|
|
|
case AUTHENTICATION:
|
|
if (bAH) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
if ((pOffer->Algos[j].uAlgoIdentifier == AUTH_ALGO_NONE) ||
|
|
(pOffer->Algos[j].uAlgoIdentifier >= AUTH_ALGO_MAX)) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
if (pOffer->Algos[j].uSecAlgoIdentifier != HMAC_AUTH_ALGO_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 (pOffer->Algos[j].uAlgoIdentifier >= CONF_ALGO_MAX) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
if (pOffer->Algos[j].uSecAlgoIdentifier >= HMAC_AUTH_ALGO_MAX) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
if (pOffer->Algos[j].uAlgoIdentifier == CONF_ALGO_NONE) {
|
|
if (pOffer->Algos[j].uSecAlgoIdentifier == HMAC_AUTH_ALGO_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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*pdwPFSGroup = dwPFSGroup;
|
|
*pbInitGroup = bInitGroup;
|
|
|
|
error:
|
|
#ifdef TRACE_ON
|
|
if (dwError) {
|
|
TRACE(TRC_ERROR, ("Failed a QM offer validation: %!winerr!", dwError));
|
|
}
|
|
#endif
|
|
|
|
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->dwSource = 0;
|
|
|
|
pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
|
|
pIniQMPolicy->dwReserved = pQMPolicy->dwReserved;
|
|
pIniQMPolicy->pNext = NULL;
|
|
|
|
dwError = CreateIniQMOffers(
|
|
pQMPolicy->dwOfferCount,
|
|
pQMPolicy->pOffers,
|
|
&(pIniQMPolicy->dwOfferCount),
|
|
&(pIniQMPolicy->pOffers)
|
|
);
|
|
if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
*ppIniQMPolicy = pIniQMPolicy;
|
|
return (dwError);
|
|
|
|
error:
|
|
TRACE(TRC_ERROR, ("Failed to create QM Policy link node: %!winerr!", dwError));
|
|
|
|
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;
|
|
|
|
BOOL bGroupInit = FALSE;
|
|
DWORD dwPFSGroup = PFS_GROUP_NONE;
|
|
DWORD dwOfferCount = 0;
|
|
DWORD dwCurIndex = 0;
|
|
|
|
for (i = 0; i < dwInOfferCount; i++) {
|
|
|
|
dwError = ValidateQMOffer(&pInOffers[i],
|
|
&bGroupInit,
|
|
&dwPFSGroup);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
dwOfferCount++;
|
|
}
|
|
}
|
|
|
|
if (dwOfferCount == 0) {
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
//
|
|
// Offer count and the offers themselves have already been validated.
|
|
//
|
|
|
|
dwError = AllocateSPDMemory(
|
|
sizeof(IPSEC_QM_OFFER) * dwOfferCount,
|
|
&(pOffers)
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
for (i = 0; i < dwInOfferCount; i++) {
|
|
|
|
pTemp = &pOffers[dwCurIndex];
|
|
pInTempOffer = &pInOffers[i];
|
|
|
|
dwError = ValidateQMOffer(pInTempOffer,
|
|
&bGroupInit,
|
|
&dwPFSGroup);
|
|
if (dwError) {
|
|
continue;
|
|
}
|
|
|
|
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)
|
|
);
|
|
}
|
|
|
|
pTemp->dwReserved = pInTempOffer->dwReserved;
|
|
|
|
dwCurIndex++;
|
|
|
|
}
|
|
|
|
*pdwOfferCount = dwOfferCount;
|
|
*ppOffers = pOffers;
|
|
|
|
if (dwOfferCount != dwInOfferCount) {
|
|
return WARNING_IPSEC_QM_POLICY_PRUNED;
|
|
}
|
|
return (ERROR_SUCCESS);
|
|
|
|
error:
|
|
TRACE(TRC_ERROR, ("Failed to create QM offers node: %!winerr!", dwError));
|
|
|
|
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,
|
|
DWORD dwVersion,
|
|
LPWSTR pszPolicyName,
|
|
LPVOID pvReserved
|
|
)
|
|
/*++
|
|
|
|
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));
|
|
|
|
dwError = DeleteIniQMPolicy(
|
|
pIniQMPolicy
|
|
);
|
|
BAIL_ON_LOCK_ERROR(dwError);
|
|
|
|
LEAVE_SPD_SECTION();
|
|
|
|
if (gbIKENotify) {
|
|
(VOID) IKENotifyPolicyChange(
|
|
&(gPolicyID),
|
|
POLICY_GUID_QM
|
|
);
|
|
}
|
|
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
("Deleted QM Policy \"%ls\"(%!guid!)",
|
|
pszPolicyName,
|
|
&gPolicyID)
|
|
);
|
|
|
|
return (dwError);
|
|
|
|
lock:
|
|
#ifdef TRACE_ON
|
|
if (pIniQMPolicy) {
|
|
TRACE(
|
|
TRC_ERROR,
|
|
(L"Failed to delete QM policy \"%ls\"(%!guid!): %!winerr!",
|
|
pIniQMPolicy->pszPolicyName,
|
|
&pIniQMPolicy->gPolicyID,
|
|
dwError)
|
|
);
|
|
} else {
|
|
TRACE(
|
|
TRC_ERROR,
|
|
(L"Failed to delete QM policy \"%ls\": %!winerr!",
|
|
pszPolicyName,
|
|
dwError)
|
|
);
|
|
}
|
|
#endif
|
|
|
|
LEAVE_SPD_SECTION();
|
|
|
|
if ((dwError == ERROR_IPSEC_QM_POLICY_IN_USE) && gbIKENotify) {
|
|
(VOID) IKENotifyPolicyChange(
|
|
&(gPolicyID),
|
|
POLICY_GUID_QM
|
|
);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
EnumQMPolicies(
|
|
LPWSTR pServerName,
|
|
DWORD dwVersion,
|
|
PIPSEC_QM_POLICY pQMTemplatePolicy,
|
|
DWORD dwFlags,
|
|
DWORD dwPreferredNumEntries,
|
|
PIPSEC_QM_POLICY * ppQMPolicies,
|
|
LPDWORD pdwNumPolicies,
|
|
LPDWORD pdwResumeHandle,
|
|
LPVOID pvReserved
|
|
)
|
|
/*++
|
|
|
|
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(
|
|
dwFlags,
|
|
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,
|
|
DWORD dwVersion,
|
|
LPWSTR pszPolicyName,
|
|
PIPSEC_QM_POLICY pQMPolicy,
|
|
LPVOID pvReserved
|
|
)
|
|
/*++
|
|
|
|
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;
|
|
DWORD dwStatus = 0;
|
|
|
|
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
|
|
);
|
|
if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
|
|
BAIL_ON_LOCK_ERROR(dwError);
|
|
} else {
|
|
dwStatus = dwError;
|
|
}
|
|
|
|
LEAVE_SPD_SECTION();
|
|
|
|
(VOID) IKENotifyPolicyChange(
|
|
&(pQMPolicy->gPolicyID),
|
|
POLICY_GUID_QM
|
|
);
|
|
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
(L"Changed QM Policy \"%ls\" (%!guid!)",
|
|
pQMPolicy->pszPolicyName,
|
|
&pQMPolicy->gPolicyID)
|
|
);
|
|
|
|
return (dwStatus);
|
|
|
|
lock:
|
|
|
|
LEAVE_SPD_SECTION();
|
|
|
|
error:
|
|
#ifdef TRACE_ON
|
|
if (pIniQMPolicy) {
|
|
TRACE(
|
|
TRC_ERROR,
|
|
(L"Failed to change QM policy \"%ls\"(%!guid!): %!winerr!",
|
|
pIniQMPolicy->pszPolicyName,
|
|
&pIniQMPolicy->gPolicyID,
|
|
dwError)
|
|
);
|
|
} else {
|
|
TRACE(
|
|
TRC_ERROR,
|
|
(L"Failed to change QM policy \"%ls\": %!winerr!",
|
|
pszPolicyName,
|
|
dwError)
|
|
);
|
|
}
|
|
#endif
|
|
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetQMPolicy(
|
|
LPWSTR pServerName,
|
|
DWORD dwVersion,
|
|
LPWSTR pszPolicyName,
|
|
DWORD dwFlags,
|
|
PIPSEC_QM_POLICY * ppQMPolicy,
|
|
LPVOID pvReserved
|
|
)
|
|
/*++
|
|
|
|
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(
|
|
dwFlags,
|
|
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
|
|
);
|
|
if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
FreeIniQMOffers(
|
|
pIniQMPolicy->dwOfferCount,
|
|
pIniQMPolicy->pOffers
|
|
);
|
|
|
|
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
|
|
gpIniDefaultQMPolicy = NULL;
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
(L"Cleared default QM policy \"%ls\" (%!guid!)",
|
|
pIniQMPolicy->pszPolicyName,
|
|
&pIniQMPolicy->gPolicyID)
|
|
);
|
|
|
|
}
|
|
|
|
pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
|
|
pIniQMPolicy->dwReserved = pQMPolicy->dwReserved;
|
|
pIniQMPolicy->dwOfferCount = dwOfferCount;
|
|
pIniQMPolicy->pOffers = pOffers;
|
|
|
|
if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
|
|
gpIniDefaultQMPolicy = pIniQMPolicy;
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
(L"Set default QM policy to \"%ls\" (%!guid!)",
|
|
pIniQMPolicy->pszPolicyName,
|
|
&pIniQMPolicy->gPolicyID)
|
|
);
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetIniQMPolicy(
|
|
DWORD dwFlags,
|
|
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(
|
|
dwFlags,
|
|
pIniQMPolicy,
|
|
pQMPolicy
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
*ppQMPolicy = pQMPolicy;
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
if (pQMPolicy) {
|
|
SPDApiBufferFree(pQMPolicy);
|
|
}
|
|
|
|
*ppQMPolicy = NULL;
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
CopyQMPolicy(
|
|
DWORD dwFlags,
|
|
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;
|
|
pQMPolicy->dwReserved = pIniQMPolicy->dwReserved;
|
|
|
|
if (dwFlags & RETURN_NON_AH_OFFERS) {
|
|
dwError = CreateNonAHQMOffers(
|
|
pIniQMPolicy->dwOfferCount,
|
|
pIniQMPolicy->pOffers,
|
|
&(pQMPolicy->dwOfferCount),
|
|
&(pQMPolicy->pOffers)
|
|
);
|
|
}
|
|
else {
|
|
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));
|
|
}
|
|
|
|
pTemp->dwReserved = pInTempOffer->dwReserved;
|
|
|
|
pInTempOffer++;
|
|
pTemp++;
|
|
|
|
}
|
|
|
|
*pdwOfferCount = dwInOfferCount;
|
|
*ppOffers = pOffers;
|
|
return (dwError);
|
|
|
|
error:
|
|
TRACE(TRC_ERROR, ("Failed to create QM offers"));
|
|
|
|
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;
|
|
TRACE(
|
|
TRC_INFORMATION,
|
|
(L"Cleared default QM policy \"%ls\" (%!guid!)",
|
|
pIniQMPolicy->pszPolicyName,
|
|
&pIniQMPolicy->gPolicyID)
|
|
);
|
|
}
|
|
|
|
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,
|
|
DWORD dwVersion,
|
|
GUID gQMPolicyID,
|
|
DWORD dwFlags,
|
|
PIPSEC_QM_POLICY * ppQMPolicy,
|
|
LPVOID pvReserved
|
|
)
|
|
/*++
|
|
|
|
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(
|
|
dwFlags,
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateNonAHQMOffers(
|
|
DWORD dwInOfferCount,
|
|
PIPSEC_QM_OFFER pInOffers,
|
|
PDWORD pdwOfferCount,
|
|
PIPSEC_QM_OFFER * ppOffers
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
PIPSEC_QM_OFFER pInTempOffer = NULL;
|
|
DWORD i = 0;
|
|
BOOL bAH = FALSE;
|
|
DWORD dwNonAHOfferCount = 0;
|
|
PIPSEC_QM_OFFER pOffers = NULL;
|
|
PIPSEC_QM_OFFER pTemp = NULL;
|
|
DWORD j = 0;
|
|
DWORD k = 0;
|
|
|
|
|
|
pInTempOffer = pInOffers;
|
|
|
|
for (i = 0; i < dwInOfferCount; i++) {
|
|
|
|
bAH = IsAHQMOffer(pInTempOffer);
|
|
if (!bAH) {
|
|
dwNonAHOfferCount++;
|
|
}
|
|
|
|
pInTempOffer++;
|
|
|
|
}
|
|
|
|
if (!dwNonAHOfferCount) {
|
|
*pdwOfferCount = 0;
|
|
*ppOffers = NULL;
|
|
return (dwError);
|
|
}
|
|
|
|
dwError = SPDApiBufferAllocate(
|
|
sizeof(IPSEC_QM_OFFER) * dwNonAHOfferCount,
|
|
&(pOffers)
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
pTemp = pOffers;
|
|
pInTempOffer = pInOffers;
|
|
|
|
for (i = 0; i < dwInOfferCount; i++) {
|
|
|
|
bAH = IsAHQMOffer(pInTempOffer);
|
|
if (bAH) {
|
|
pInTempOffer++;
|
|
continue;
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
pTemp->dwReserved = pInTempOffer->dwReserved;
|
|
|
|
pInTempOffer++;
|
|
pTemp++;
|
|
|
|
}
|
|
|
|
*pdwOfferCount = dwNonAHOfferCount;
|
|
*ppOffers = pOffers;
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
if (pOffers) {
|
|
FreeQMOffers(
|
|
i,
|
|
pOffers
|
|
);
|
|
}
|
|
|
|
*pdwOfferCount = 0;
|
|
*ppOffers = NULL;
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsAHQMOffer(
|
|
PIPSEC_QM_OFFER pIpsecQMOffer
|
|
)
|
|
{
|
|
BOOL bAH = FALSE;
|
|
DWORD j = 0;
|
|
|
|
|
|
for (j = 0; j < (pIpsecQMOffer->dwNumAlgos); j++) {
|
|
|
|
switch (pIpsecQMOffer->Algos[j].Operation) {
|
|
|
|
case AUTHENTICATION:
|
|
bAH = TRUE;
|
|
break;
|
|
|
|
case ENCRYPTION:
|
|
break;
|
|
|
|
case NONE:
|
|
case COMPRESSION:
|
|
default:
|
|
ASSERT(FALSE);
|
|
break;
|
|
|
|
}
|
|
|
|
if (bAH) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return (bAH);
|
|
}
|
|
|