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.
229 lines
5.5 KiB
229 lines
5.5 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FILE
|
|
//
|
|
// enforcer.cpp
|
|
//
|
|
// SYNOPSIS
|
|
//
|
|
// This file defines the class PolicyEnforcer.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <ias.h>
|
|
#include <iastlutl.h>
|
|
#include <iasutil.h>
|
|
#include <sdoias.h>
|
|
#include <enforcer.h>
|
|
#include <factory.h>
|
|
#include <policylist.h>
|
|
#include <SortedSdoCollection.h>
|
|
#include <TunnelTagger.h>
|
|
|
|
#include <BuildTree.h>
|
|
#include <xprparse.h>
|
|
|
|
_COM_SMARTPTR_TYPEDEF(ISdo, __uuidof(ISdo));
|
|
_COM_SMARTPTR_TYPEDEF(ISdoCollection, __uuidof(ISdoCollection));
|
|
|
|
|
|
PolicyEnforcerBase::~PolicyEnforcerBase() throw ()
|
|
{
|
|
TunnelTagger::Free(tagger);
|
|
}
|
|
|
|
|
|
void PolicyEnforcerBase::processException(
|
|
IRequest* pRequest,
|
|
const _com_error& ce
|
|
) throw ()
|
|
{
|
|
LONG reason;
|
|
if (ce.Error() == HRESULT_FROM_WIN32(ERROR_MORE_DATA))
|
|
{
|
|
reason = IAS_MALFORMED_REQUEST;
|
|
}
|
|
else
|
|
{
|
|
reason = IAS_INTERNAL_ERROR;
|
|
}
|
|
|
|
// If there was any kind of error, discard the packet.
|
|
pRequest->SetResponse(IAS_RESPONSE_DISCARD_PACKET, reason);
|
|
}
|
|
|
|
|
|
void PolicyEnforcerBase::setPolicies(IDispatch* pDisp)
|
|
{
|
|
using _com_util::CheckError;
|
|
|
|
if (tagger == 0)
|
|
{
|
|
tagger = TunnelTagger::Alloc();
|
|
}
|
|
|
|
// Get the underlying collection.
|
|
ISdoCollectionPtr collection(pDisp);
|
|
|
|
// Get the enumerator out of the collection.
|
|
IUnknownPtr unk;
|
|
CheckError(get__NewSortedEnum(collection, &unk, PROPERTY_POLICY_MERIT));
|
|
IEnumVARIANTPtr iter(unk);
|
|
|
|
// Find out how many policies there are ...
|
|
long count;
|
|
CheckError(collection->get_Count(&count));
|
|
|
|
// ... and create a temporary list to hold them.
|
|
PolicyList temp;
|
|
temp.reserve(count);
|
|
|
|
//////////
|
|
// Iterate through each policy in the collection.
|
|
//////////
|
|
|
|
_variant_t element;
|
|
unsigned long fetched;
|
|
|
|
while (iter->Next(1, &element, &fetched) == S_OK && fetched == 1)
|
|
{
|
|
// Get an SDO out of the variant.
|
|
ISdoPtr policy(element);
|
|
element.Clear();
|
|
|
|
// Get the action and expression from the SDO.
|
|
_variant_t policyName, propAction, propExpr;
|
|
CheckError(policy->GetProperty(PROPERTY_SDO_NAME, &policyName));
|
|
CheckError(policy->GetProperty(PROPERTY_POLICY_ACTION, &propAction));
|
|
CheckError(policy->GetProperty(PROPERTY_POLICY_CONSTRAINT, &propExpr));
|
|
|
|
// Create the Action object.
|
|
ActionPtr action(
|
|
new Action(
|
|
V_BSTR(&policyName),
|
|
nameAttr,
|
|
propAction,
|
|
*tagger
|
|
)
|
|
);
|
|
|
|
// Parse the msNPConstraint strings into a token array.
|
|
_variant_t tokens;
|
|
CheckError(IASParseExpressionEx(&propExpr, &tokens));
|
|
|
|
// Convert the token array into a logic tree.
|
|
IConditionPtr expr;
|
|
CheckError(IASBuildExpression(&tokens, &expr));
|
|
|
|
// Insert the objects into our policy list.
|
|
temp.insert(expr, action);
|
|
}
|
|
|
|
//////////
|
|
// We successfully traversed the collection, so save the results.
|
|
//////////
|
|
|
|
policies.swap(temp);
|
|
}
|
|
|
|
|
|
STDMETHODIMP PolicyEnforcerBase::Shutdown()
|
|
{
|
|
policies.clear();
|
|
|
|
// We may as well clear the factory cache here.
|
|
theFactoryCache.clear();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP PolicyEnforcerBase::PutProperty(LONG Id, VARIANT *pValue)
|
|
{
|
|
if (pValue == NULL) { return E_INVALIDARG; }
|
|
|
|
switch (Id)
|
|
{
|
|
case PROPERTY_NAP_POLICIES_COLLECTION:
|
|
{
|
|
if (V_VT(pValue) != VT_DISPATCH) { return DISP_E_TYPEMISMATCH; }
|
|
try
|
|
{
|
|
setPolicies(V_DISPATCH(pValue));
|
|
}
|
|
CATCH_AND_RETURN();
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
IASREQUESTSTATUS PolicyEnforcerBase::onSyncRequest(IRequest* pRequest) throw ()
|
|
{
|
|
_ASSERT(pRequest != NULL);
|
|
return IAS_REQUEST_STATUS_ABORT;
|
|
}
|
|
|
|
|
|
IASREQUESTSTATUS PolicyEnforcer::onSyncRequest(IRequest* pRequest) throw ()
|
|
{
|
|
_ASSERT(pRequest != NULL);
|
|
|
|
try
|
|
{
|
|
IASRequest request(pRequest);
|
|
|
|
if (!policies.apply(request))
|
|
{
|
|
// Access-Request: reject the user.
|
|
request.SetResponse(IAS_RESPONSE_ACCESS_REJECT,
|
|
IAS_NO_POLICY_MATCH);
|
|
}
|
|
}
|
|
catch (const _com_error& ce)
|
|
{
|
|
processException(pRequest, ce);
|
|
}
|
|
|
|
return IAS_REQUEST_STATUS_HANDLED;
|
|
}
|
|
|
|
IASREQUESTSTATUS ProxyPolicyEnforcer::onSyncRequest(IRequest* pRequest) throw ()
|
|
{
|
|
_ASSERT(pRequest != NULL);
|
|
|
|
try
|
|
{
|
|
IASRequest request(pRequest);
|
|
|
|
if (!policies.apply(request))
|
|
{
|
|
// If no policy fired, then check is that was an Accounting
|
|
// or an access request
|
|
// Accounting: discard the packet
|
|
if (request.get_Request() == IAS_REQUEST_ACCOUNTING)
|
|
{
|
|
request.SetResponse(IAS_RESPONSE_DISCARD_PACKET,
|
|
IAS_NO_CXN_REQ_POLICY_MATCH);
|
|
}
|
|
else
|
|
{
|
|
// Access-Request: reject the user.
|
|
request.SetResponse(IAS_RESPONSE_ACCESS_REJECT,
|
|
IAS_NO_CXN_REQ_POLICY_MATCH);
|
|
}
|
|
}
|
|
}
|
|
catch (const _com_error& ce)
|
|
{
|
|
processException(pRequest, ce);
|
|
}
|
|
|
|
return IAS_REQUEST_STATUS_HANDLED;
|
|
}
|