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.
460 lines
14 KiB
460 lines
14 KiB
//////////////////////////////////////////////////////////////////////
|
|
// Policy.h : Declaration of base class for main mode and quick mode
|
|
// policies classes
|
|
// security WMI provider for SCE
|
|
// Copyright (c)1997-2001 Microsoft Corporation
|
|
//
|
|
// Original Create Date: 4/11/2001
|
|
// Original Author: shawnwu
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
#include "globals.h"
|
|
#include "IPSecBase.h"
|
|
|
|
extern CComVariant g_varRollbackGuid;
|
|
|
|
const DWORD DefaultMMPolicyFlag = 0;
|
|
const DWORD DefaultQMPolicyFlag = 0;
|
|
const DWORD DefaultMMPolicyOfferFlag = 0;
|
|
const DWORD DefaultQMPolicyOfferFlag = 0;
|
|
|
|
const DWORD DefaultaultSoftSAExpirationTime = DEFAULT_MM_KEY_EXPIRATION_TIME;
|
|
|
|
//
|
|
// any value is valid. 0 means unlimited
|
|
//
|
|
|
|
const DWORD DefaultQMModeLimit = 32;
|
|
|
|
//
|
|
// either DH_GROUP_1 or DH_GROUP_2 (stronger and more costly)
|
|
//
|
|
|
|
const DWORD DefaultDHGroup = DH_GROUP_1;
|
|
|
|
//
|
|
//IPSEC_DOI_ESP_3_DES is more cost
|
|
//
|
|
|
|
const DWORD DefaultEncryptAlgoID = IPSEC_DOI_ESP_DES;
|
|
|
|
const DWORD DefaultHashAlgoID = 0;
|
|
|
|
//
|
|
// either is valid, TRUE more cost
|
|
//
|
|
|
|
const BOOL DefaultPFSRequired = FALSE;
|
|
|
|
const DWORD DefaultPFSGroup = PFS_GROUP_NONE;
|
|
const DWORD DefaultNumAlgos = 1;
|
|
|
|
|
|
//
|
|
// If ENCRYPTION, then uAlgoIdentifier is the IPSEC_DOI_ESP_DES or IPSEC_DOI_ESP_3_DES
|
|
// and uSecAlgoIdentifier can't be HMAC_AH_NONE
|
|
// else if AUTHENTICATION then uAlgoIdentifier is IPSEC_DOI_AH_MD5 or IPSEC_DOI_AH_SHA1,
|
|
// and uSecAlgoIdentifier should be HMAC_AH_NONE
|
|
// else if COMPRESSION, ??
|
|
// else if SA_DELETE, ??
|
|
//
|
|
|
|
const IPSEC_OPERATION DefaultQMAlgoOperation = ENCRYPTION;
|
|
|
|
const ULONG DefaultAlgoID = IPSEC_DOI_ESP_DES;
|
|
|
|
const HMAC_AH_ALGO DefaultAlgoSecID = HMAC_AH_MD5;
|
|
|
|
//
|
|
// We have two different types of policies in SPD
|
|
//
|
|
|
|
enum EnumPolicyType
|
|
{
|
|
MainMode_Policy = 1,
|
|
QuickMode_Policy = 2,
|
|
};
|
|
|
|
|
|
/*
|
|
|
|
Class description
|
|
|
|
Naming:
|
|
|
|
CIPSecPolicy stands for IPSec Policy.
|
|
|
|
Base class:
|
|
|
|
CIPSecBase
|
|
|
|
Purpose of class:
|
|
|
|
(1) Being a base for both main mode policy and quick mode policy implementations.
|
|
|
|
Design:
|
|
|
|
(1) Provide property access (both Put and Get) that are common to both main mode
|
|
and quick mode. See GetPolicyFromWbemObj/CreateWbemObjFromPolicy.
|
|
|
|
(2) Provide rollback support. Both main mode and quick mode have the same logic.
|
|
|
|
(3) Provide some allocation/deallocation that can be parameterized using template functions.
|
|
|
|
|
|
Use:
|
|
|
|
(1) Class is designed for inheritance use.
|
|
|
|
(2) Rollback, GetPolicyFromWbemObj, and CreateWbemObjFromPolicy are the ones
|
|
you will use directly, even though all other static ones are also
|
|
available for the other classes, they are not intended for such use.
|
|
|
|
Notes:
|
|
|
|
(1) It contains several template functions. This reduces the duplicate code.
|
|
|
|
|
|
*/
|
|
|
|
class CIPSecPolicy :
|
|
public CIPSecBase
|
|
{
|
|
|
|
protected:
|
|
|
|
CIPSecPolicy(){}
|
|
virtual ~CIPSecPolicy(){}
|
|
|
|
public:
|
|
|
|
static
|
|
HRESULT Rollback (
|
|
IN IWbemServices * pNamespace,
|
|
IN LPCWSTR pszRollbackToken,
|
|
IN bool bClearAll
|
|
);
|
|
|
|
//
|
|
// some template functions
|
|
//
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CIPSecPolicy::GetPolicyFromWbemObj
|
|
|
|
Functionality:
|
|
|
|
Given a wbem object representing a policy (either main mode or quick mode), this
|
|
function either finds the policy from SPD or creates a new one and fill in the wbem
|
|
object's properties into the policy struct.
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pInst - The wbem object.
|
|
|
|
ppPolicy - Receives the policy. This can be PIPSEC_MM_POLICY or PIPSEC_QM_POLICY.
|
|
Caller needs to free this by calling FreePolicy;
|
|
|
|
pbPreExist - Whether SPD allocates the buffer (true) or not (false).
|
|
|
|
Return Value:
|
|
|
|
Success:
|
|
|
|
WBEM_NO_ERROR
|
|
|
|
Failure:
|
|
|
|
(1) WBEM_E_INVALID_PARAMETER if ppPolicy == NULL or pdwResumeHandle == NULL.
|
|
|
|
(2) WBEM_E_NOT_FOUND if the policy is not found.
|
|
|
|
Notes:
|
|
|
|
(1) Make sure that you call FreePolicy to free the buffer!
|
|
|
|
|
|
*/
|
|
|
|
template <class Policy>
|
|
static
|
|
HRESULT GetPolicyFromWbemObj (
|
|
IN IWbemClassObject * pInst,
|
|
OUT Policy ** ppPolicy,
|
|
OUT bool * pbPreExist
|
|
)
|
|
{
|
|
if (pInst == NULL || ppPolicy == NULL || pbPreExist == NULL)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
*ppPolicy = NULL;
|
|
*pbPreExist = false;
|
|
|
|
DWORD dwResumeHandle = 0;
|
|
|
|
// this var will be re-used again and again. Each should be Clear'ed before reuse.
|
|
CComVariant var;
|
|
// try to find out if the filter already exists
|
|
HRESULT hr = pInst->Get(g_pszPolicyName, 0, &var, NULL, NULL);
|
|
|
|
if (SUCCEEDED(hr) && var.vt == VT_BSTR)
|
|
{ // see if this is a filter we already have
|
|
hr = FindPolicyByName(var.bstrVal, ppPolicy, &dwResumeHandle);
|
|
|
|
if (SUCCEEDED(hr))
|
|
*pbPreExist = true;
|
|
else
|
|
{
|
|
// can't find it, fine. I will create a new one
|
|
hr = AllocPolicy(ppPolicy);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(*ppPolicy)->pszPolicyName = NULL;
|
|
hr = ::CoCreateGuid(&((*ppPolicy)->gPolicyID));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// give it the name
|
|
DWORD dwSize = wcslen(var.bstrVal) + 1;
|
|
(*ppPolicy)->pszPolicyName = new WCHAR[dwSize];
|
|
if (NULL == (*ppPolicy)->pszPolicyName)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
::memcpy((*ppPolicy)->pszPolicyName, var.bstrVal, dwSize * sizeof(WCHAR));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// dwFlags and pOffers
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
var.Clear();
|
|
// dwFlags. We allow this to be missing
|
|
if (SUCCEEDED(pInst->Get(g_pszPolicyFlag, 0, &var, NULL, NULL)) && var.vt == VT_I4)
|
|
(*ppPolicy)->dwFlags = var.lVal;
|
|
else
|
|
(*ppPolicy)->dwFlags = 0;
|
|
|
|
hr = pInst->Get(g_pszOfferCount, 0, &var, NULL, NULL);
|
|
if (SUCCEEDED(hr) && var.vt == VT_I4)
|
|
{
|
|
hr = AllocOffer( &((*ppPolicy)->pOffers), var.lVal);
|
|
if (SUCCEEDED(hr))
|
|
(*ppPolicy)->dwOfferCount = var.lVal;
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_OBJECT;
|
|
}
|
|
|
|
// set up the LifeTime
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
DWORD* pdwTimeKBytes = new DWORD[(*ppPolicy)->dwOfferCount];
|
|
if (pdwTimeKBytes == NULL)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
var.Clear();
|
|
// we will allow the life-time's expiration time to be missing since we have defaults
|
|
// if we successfully get the key life exp time, then set them
|
|
if ( SUCCEEDED(pInst->Get(g_pszKeyLifeTime, 0, &var, NULL, NULL)) &&
|
|
(var.vt & VT_ARRAY) == VT_ARRAY )
|
|
{
|
|
hr = ::GetDWORDSafeArrayElements(&var, (*ppPolicy)->dwOfferCount, pdwTimeKBytes);
|
|
|
|
// if get the exp times
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (long l = 0; l < (*ppPolicy)->dwOfferCount; l++)
|
|
{
|
|
(*ppPolicy)->pOffers[l].Lifetime.uKeyExpirationTime = pdwTimeKBytes[l];
|
|
}
|
|
}
|
|
}
|
|
|
|
var.Clear();
|
|
// set the expiration kbytes, again, we allow the info to be missing since we already has default
|
|
if ( SUCCEEDED(pInst->Get(g_pszKeyLifeTimeKBytes, 0, &var, NULL, NULL)) &&
|
|
(var.vt & VT_ARRAY) == VT_ARRAY )
|
|
{
|
|
hr = ::GetDWORDSafeArrayElements(&var, (*ppPolicy)->dwOfferCount, pdwTimeKBytes);
|
|
|
|
// if get the exp kbytes
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (long l = 0; l < (*ppPolicy)->dwOfferCount; l++)
|
|
{
|
|
(*ppPolicy)->pOffers[l].Lifetime.uKeyExpirationKBytes = pdwTimeKBytes[l];
|
|
}
|
|
}
|
|
}
|
|
|
|
delete [] pdwTimeKBytes;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
FreePolicy(ppPolicy, *pbPreExist);
|
|
}
|
|
return hr;
|
|
};
|
|
|
|
template<class Policy>
|
|
HRESULT CreateWbemObjFromPolicy(Policy* pPolicy, IWbemClassObject* pInst)
|
|
{
|
|
if (pInst == NULL || pPolicy == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
CComVariant var = pPolicy->pszPolicyName;
|
|
HRESULT hr = pInst->Put(g_pszPolicyName, 0, &var, CIM_EMPTY);
|
|
|
|
// put offer count
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
var.Clear();
|
|
var.vt = VT_I4;
|
|
|
|
// don't really care much about dwFlags
|
|
var.lVal = pPolicy->dwFlags;
|
|
pInst->Put(g_pszPolicyFlag, 0, &var, CIM_EMPTY);
|
|
|
|
var.lVal = pPolicy->dwOfferCount;
|
|
hr = pInst->Put(g_pszOfferCount, 0, &var, CIM_EMPTY);
|
|
}
|
|
|
|
// put LifeTime
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// create the a safearray
|
|
var.vt = VT_ARRAY | VT_I4;
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
rgsabound[0].lLbound = 0;
|
|
rgsabound[0].cElements = pPolicy->dwOfferCount;
|
|
var.parray = ::SafeArrayCreate(VT_I4, 1, rgsabound);
|
|
|
|
if (var.parray == NULL)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
long lIndecies[1];
|
|
|
|
// deal with uKeyExpirationTime
|
|
for (DWORD dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
|
|
{
|
|
lIndecies[0] = dwIndex;
|
|
hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].Lifetime.uKeyExpirationTime) );
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
hr = pInst->Put(g_pszKeyLifeTime, 0, &var, CIM_EMPTY);
|
|
|
|
// deal with uKeyExpirationKBytes
|
|
for (DWORD dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
|
|
{
|
|
lIndecies[0] = dwIndex;
|
|
hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].Lifetime.uKeyExpirationKBytes) );
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
hr = pInst->Put(g_pszKeyLifeTimeKBytes, 0, &var, CIM_EMPTY);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
protected:
|
|
|
|
template<class Policy>
|
|
static HRESULT AllocPolicy(Policy** ppPolicy)
|
|
{
|
|
if (ppPolicy == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
*ppPolicy = new Policy;
|
|
if (*ppPolicy)
|
|
{
|
|
(*ppPolicy)->pszPolicyName = NULL;
|
|
(*ppPolicy)->dwOfferCount = 0;
|
|
(*ppPolicy)->pOffers = NULL;
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
return hr;
|
|
}
|
|
|
|
static void GetDefaultOfferLifeTime(PIPSEC_MM_OFFER pOffer, DWORD* pdwDefFlag, ULONG* pulTime, ULONG* pulKBytes)
|
|
{
|
|
*pdwDefFlag = DefaultMMPolicyOfferFlag;
|
|
*pulTime = DEFAULT_MM_KEY_EXPIRATION_TIME;
|
|
*pulKBytes = DEFAULT_QM_KEY_EXPIRATION_KBYTES;
|
|
}
|
|
|
|
static void GetDefaultOfferLifeTime(PIPSEC_QM_OFFER pOffer, DWORD* pdwDefFlag, ULONG* pulTime, ULONG* pulKBytes)
|
|
{
|
|
*pdwDefFlag = DefaultQMPolicyOfferFlag;
|
|
*pulTime = DEFAULT_QM_KEY_EXPIRATION_TIME;
|
|
*pulKBytes = DEFAULT_QM_KEY_EXPIRATION_KBYTES;
|
|
}
|
|
|
|
template<class Offer>
|
|
static HRESULT AllocOffer(Offer** ppOffer, long lCount)
|
|
{
|
|
if (ppOffer == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
*ppOffer = new Offer[lCount];
|
|
if (*ppOffer != NULL)
|
|
{
|
|
ULONG ulTime, ulKBytes;
|
|
DWORD dwDefFlag;
|
|
GetDefaultOfferLifeTime(*ppOffer, &dwDefFlag, &ulTime, &ulKBytes);
|
|
|
|
for (long l = 0; l < lCount; l++)
|
|
{
|
|
(*ppOffer)[l].dwFlags = dwDefFlag;
|
|
(*ppOffer)[l].Lifetime.uKeyExpirationTime = ulTime;
|
|
(*ppOffer)[l].Lifetime.uKeyExpirationKBytes = ulKBytes;
|
|
}
|
|
return WBEM_NO_ERROR;
|
|
}
|
|
else
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
template<class Policy>
|
|
static void FreePolicy(Policy** ppPolicy, bool bPreExist)
|
|
{
|
|
if (ppPolicy == NULL || *ppPolicy == NULL)
|
|
return;
|
|
|
|
if (bPreExist)
|
|
::SPDApiBufferFree(*ppPolicy);
|
|
else
|
|
{
|
|
delete [] (*ppPolicy)->pszPolicyName;
|
|
delete [] (*ppPolicy)->pOffers;
|
|
delete *ppPolicy;
|
|
}
|
|
*ppPolicy = NULL;
|
|
};
|
|
|
|
static HRESULT ClearAllPolicies(IWbemServices* pNamespace);
|
|
|
|
HRESULT OnAfterAddPolicy(LPCWSTR pszPolicyName, EnumPolicyType eType);
|
|
};
|