Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1481 lines
46 KiB

//#--------------------------------------------------------------
//
// File: recvfrompipe.cpp
//
// Synopsis: Implementation of CRecvFromPip class methods
//
// Copyright (C) Microsoft Corporation All rights reserved.
//
//----------------------------------------------------------------
#include "radcommon.h"
#include "preprocessor.h"
#include "recvfrompipe.h"
#include "logresult.h"
#include <new>
#include <iastlutl.h>
const CHAR NUL = '\0';
extern LONG g_lPacketCount;
//++--------------------------------------------------------------
//
// Function: CRecvFromPipe
//
// Synopsis: This is the constructor of the CRecvFromPipe
// class
//
// Arguments: none
//
// Returns: none
//
//
// History: MKarki Created 10/22/97
//
//----------------------------------------------------------------
CRecvFromPipe::CRecvFromPipe(
CPreProcessor *pCPreProcessor,
CHashMD5 *pCHashMD5,
CHashHmacMD5 *pCHashHmacMD5,
CClients *pCClients,
VSAFilter *pCVSAFilter,
CTunnelPassword *pCTunnelPassword,
CReportEvent *pCReportEvent
)
:m_pCPreProcessor (pCPreProcessor),
m_pCHashMD5 (pCHashMD5),
m_pCHashHmacMD5 (pCHashHmacMD5),
m_pCClients (pCClients),
m_pCVSAFilter (pCVSAFilter),
m_pCTunnelPassword (pCTunnelPassword),
m_pCReportEvent (pCReportEvent)
{
_ASSERT (
(NULL != pCPreProcessor) &&
(NULL != pCHashMD5) &&
(NULL != pCHashHmacMD5) &&
(NULL != pCClients) &&
(NULL != pCVSAFilter) &&
(NULL != pCTunnelPassword) &&
(NULL != pCReportEvent)
);
} // end of CRecvFromPipe constructor
//++--------------------------------------------------------------
//
// Function: ~CRecvFromPipe
//
// Synopsis: This is the destructor of the CRecvFromPipe
// class
//
// Arguments: none
//
// Returns: none
//
//
// History: MKarki Created 10/22/97
//
//----------------------------------------------------------------
CRecvFromPipe::~CRecvFromPipe()
{
} // end of CRecvFromPipe destructor
//++--------------------------------------------------------------
//
// Function: Process
//
// Synopsis: This is the CRecvFromPipe class public method
// to start processing the packet on its way out
//
// Arguments:
// [in] CPacketRadius*
//
// Returns: HRESULT
//
//
// History: MKarki Created 10/22/97
//
// Called By:
// 1) CController::CRequestSource::OnRequest Method
//
//----------------------------------------------------------------
HRESULT
CRecvFromPipe::Process (
IRequest *pIRequest
)
{
BOOL bStatus = FALSE;
HRESULT hr = S_OK;
DWORD dwCode = 0;
DWORD dwCount = 0;
DWORD dwAttribCount = 0;
IAttributesRaw *pIAttributesRaw = NULL;
IRequestState *pIRequestState = NULL;
CPacketRadius *pCPacketRadius = NULL;
LONG iasResponse, iasReason = 0;
PACKETTYPE ePacketType;
PATTRIBUTEPOSITION pAttribPosition = NULL;
unsigned hyper uhyPacketAddress = 0;
RADIUSLOGTYPE RadiusError = RADIUS_DROPPED_PACKET;
_ASSERT (pIRequest);
__try
{
// We have to retrieve the CPacketRadius object first, so we can clean
// it up even in the error cases.
hr = pIRequest->QueryInterface (
__uuidof(IRequestState),
reinterpret_cast <PVOID*> (&pIRequestState)
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain request state in request received from "
"backend"
);
__leave;
}
//
// get the CPacketRadius class object
//
hr = pIRequestState->Pop (
reinterpret_cast <unsigned hyper*> (&uhyPacketAddress)
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain information from request state received "
"from backend"
);
__leave;
}
pCPacketRadius = reinterpret_cast <CPacketRadius*> (uhyPacketAddress);
//
// if this Request object has been generated by the backend then we
// don't have a CPacketRadius class object
//
if (NULL == pCPacketRadius)
{
//
// we most probably are sending out an EAP-Challenge
//
hr= GeneratePacketRadius (
&pCPacketRadius,
pIAttributesRaw
);
if (FAILED (hr)) { __leave; }
}
//
// get the IAttributesRaw interface now
//
hr = pIRequest->QueryInterface (
__uuidof(IAttributesRaw),
reinterpret_cast <PVOID*> (&pIAttributesRaw)
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain Attributes interface in request "
"received from backend"
);
__leave;
}
//
// split the attributes which can not fit in a radius packet
//
hr = SplitAttributes (pIAttributesRaw);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to split IAS attribute received from backend"
);
__leave;
}
//
// convert the IAS VSA attributes to RADIUS format
//
hr = m_pCVSAFilter->radiusFromIAS (pIAttributesRaw);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to convert IAS attribute to Radius VSAs in request "
"received from backend"
);
__leave;
}
//
// get the outbound packet code
//
hr = pIRequest->get_Response (&iasResponse);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain response code in request recieved from "
"backend"
);
__leave;
}
//
// get the outbound reason code
//
hr = pIRequest->get_Reason (&iasReason);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain reason code in request recieved from "
"backend"
);
__leave;
}
// Log the result of the request.
IASRadiusLogResult(pIRequest, pIAttributesRaw);
// If it failed convert the reason code.
if (iasReason != S_OK)
{
ConvertReasonToRadiusError (iasReason, &RadiusError);
}
//
// convert the IASRESPONSE type to RADIUS type
//
hr = ConvertResponseToRadiusCode (
iasResponse,
&ePacketType,
pCPacketRadius
);
if (FAILED (hr)) { __leave; }
//
// check if we have Tunnel-Password attribute, if yes
// then encrypt it
//
hr = m_pCTunnelPassword->Process (
ePacketType,
pIAttributesRaw,
pCPacketRadius
);
if (FAILED (hr)) { __leave; }
//
// inject Signature Attribute if needed
//
hr = InjectSignatureIfNeeded (
ePacketType,
pIAttributesRaw,
pCPacketRadius
);
if (FAILED (hr)) { __leave; }
//
// get the count of number of request
//
hr = pIAttributesRaw->GetAttributeCount (&dwAttribCount);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain attribute count in request received from "
"backend"
);
__leave;
}
//
// allocate the attribposition structures
//
pAttribPosition = reinterpret_cast <PATTRIBUTEPOSITION> (
CoTaskMemAlloc (
sizeof (ATTRIBUTEPOSITION)*dwAttribCount
));
if (NULL == pAttribPosition)
{
IASTracePrintf (
"Unable to allocate memory for attribute postion array "
"while processing request recieved from backend"
);
hr = E_OUTOFMEMORY;
__leave;
}
//
// get the attributes from the collection
//
hr = pIAttributesRaw->GetAttributes (
&dwAttribCount,
pAttribPosition,
0,
NULL
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to get attribute in request received from backend"
);
__leave;
}
//
// remove the attributes from the collection now
//
hr = pIAttributesRaw->RemoveAttributes (
dwAttribCount,
pAttribPosition
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to remove attribute in request received from backend"
);
__leave;
}
//
// carry out the generic packet building here
//
hr = pCPacketRadius->BuildOutPacket (
ePacketType,
pAttribPosition,
dwAttribCount
);
if (FAILED (hr)) { __leave; }
//
// sending out packet now
//
hr = m_pCPreProcessor->StartOutProcessing (pCPacketRadius);
if (FAILED (hr)) { __leave; }
}
__finally
{
//
// log event in case of both success and failure
//
if (SUCCEEDED (hr))
{
//
// log an event that inbound packet has been processed
// successfully
//
m_pCReportEvent->Process (
RADIUS_LOG_PACKET,
pCPacketRadius->GetInCode (),
pCPacketRadius->GetInLength (),
pCPacketRadius->GetInAddress (),
NULL,
static_cast <LPVOID> (pCPacketRadius->GetInPacket())
);
//
// log an event for the outbound packet successfully send
// out
//
m_pCReportEvent->Process (
RADIUS_LOG_PACKET,
pCPacketRadius->GetOutCode (),
pCPacketRadius->GetOutLength (),
pCPacketRadius->GetOutAddress (),
NULL,
static_cast <LPVOID> (pCPacketRadius->GetOutPacket())
);
}
else
{
if (hr != RADIUS_E_ERRORS_OCCURRED)
{
IASReportEvent(
RADIUS_E_INTERNAL_ERROR,
0,
sizeof(hr),
NULL,
&hr
);
}
else if (pCPacketRadius != 0)
{
//
// generate event that inbound packet has been dropped
//
m_pCReportEvent->Process (
RadiusError,
pCPacketRadius->GetInCode (),
pCPacketRadius->GetInLength (),
pCPacketRadius->GetInAddress (),
NULL,
static_cast <LPVOID> (pCPacketRadius->GetInPacket())
);
}
else
{
IASReportEvent(
RADIUS_E_INTERNAL_ERROR,
0,
sizeof(hr),
NULL,
&hr
);
}
}
//
// now delete the dynamically allocated memory
//
if (NULL != pAttribPosition)
{
//
// release the attributes first
//
for (dwCount = 0; dwCount < dwAttribCount; dwCount++)
{
::IASAttributeRelease (pAttribPosition[dwCount].pAttribute);
}
CoTaskMemFree (pAttribPosition);
}
if (pIRequestState) { pIRequestState->Release (); }
if (pIAttributesRaw) { pIAttributesRaw->Release (); }
//
// delete the packet
//
if (pCPacketRadius) { delete pCPacketRadius; }
//
// now decrement the global packet reference count
//
InterlockedDecrement (&g_lPacketCount);
}
return (hr);
} // end of CRecvFromPipe::Process method
//++--------------------------------------------------------------
//
// Function: ConvertResponseToRadiusCode
//
// Synopsis: This is the CRecvFromPipe class private method
// that converts the IASRESPONSE code to RADIUS
// packet type
//
// Arguments:
// [in] IASRESPONSE
// [out] PPACKETTYPE
//
// Returns: HRESULT - status
//
// History: MKarki Created 12/12/97
//
// Called By: CRecvFromPipe::Process method
//
//----------------------------------------------------------------
HRESULT
CRecvFromPipe::ConvertResponseToRadiusCode (
LONG iasResponse,
PPACKETTYPE pPacketType,
CPacketRadius *pCPacketRadius
)
{
HRESULT hr = S_OK;
_ASSERT (pPacketType && pCPacketRadius);
switch (iasResponse)
{
case IAS_RESPONSE_ACCESS_ACCEPT:
*pPacketType = ACCESS_ACCEPT;
break;
case IAS_RESPONSE_ACCESS_REJECT:
*pPacketType = ACCESS_REJECT;
break;
case IAS_RESPONSE_ACCESS_CHALLENGE:
*pPacketType = ACCESS_CHALLENGE;
break;
case IAS_RESPONSE_ACCOUNTING:
*pPacketType = ACCOUNTING_RESPONSE;
break;
case IAS_RESPONSE_FORWARD_PACKET:
//
// if we are forwarding this packet
// the the packet type remains the same
//
*pPacketType = pCPacketRadius->GetInCode ();
break;
case IAS_RESPONSE_DISCARD_PACKET:
hr = RADIUS_E_ERRORS_OCCURRED;
break;
case IAS_RESPONSE_INVALID:
default:
hr = E_FAIL;
break;
}
return (hr);
} // end of CRecvFromPipe::ConvertResponseToRadiusCode method
//++--------------------------------------------------------------
//
// Function: GetOutPacketInfo
//
// Synopsis: This is the CRecvFromPipe class private method
// that is used to used to get out bound packet
// information from the IAS attribute collection
//
// Arguments:
// [out] PDWORD - IP address
// [out] PWORD - UDP port
// [out] Client** - reference to CClient object
// [out] PBYTE - packet header
// [in] IAttributesRaw*
//
// Returns: BOOL status
//
// History: MKarki Created 1/9/97
//
// Called By: CRecvFromPipe::Process method
//
//----------------------------------------------------------------
HRESULT
CRecvFromPipe::GetOutPacketInfo (
PDWORD pdwIPAddress,
PWORD pwPort,
IIasClient **ppIIasClient,
PBYTE pPacketHeader,
IAttributesRaw *pIAttributesRaw
)
{
BOOL bStatus = TRUE;
HRESULT hr = S_OK;
DWORD dwCount = 0;
PIASATTRIBUTE pIasAttribute = NULL;
DWORD dwAttribPosCount = COMPONENT_SPECIFIC_ATTRIBUTE_COUNT;
DWORD dwAttribIDCount = COMPONENT_SPECIFIC_ATTRIBUTE_COUNT;
ATTRIBUTEPOSITION AttribPos[COMPONENT_SPECIFIC_ATTRIBUTE_COUNT];
static DWORD AttribIDs [] =
{
IAS_ATTRIBUTE_CLIENT_IP_ADDRESS,
IAS_ATTRIBUTE_CLIENT_UDP_PORT,
IAS_ATTRIBUTE_CLIENT_PACKET_HEADER
};
_ASSERT (
(NULL != pdwIPAddress) &&
(NULL != pwPort) &&
(NULL != pPacketHeader) &&
(NULL != ppIIasClient) &&
(NULL != pIAttributesRaw)
);
__try
{
//
// get client info
//
// get the attributes from the collection
//
hr = pIAttributesRaw->GetAttributes (
&dwAttribPosCount,
AttribPos,
dwAttribIDCount,
reinterpret_cast <LPDWORD> (AttribIDs)
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to get attributes while obtaining out-bound packet "
"information"
);
__leave;
}
else if (COMPONENT_SPECIFIC_ATTRIBUTE_COUNT != dwAttribPosCount)
{
IASTracePrintf (
"Request received from backend does not have all the "
"all the required attributes"
);
hr = E_FAIL;
__leave;
}
//
// go through the attributes and get values out
//
for (dwCount = 0; dwCount < dwAttribPosCount; dwCount++)
{
pIasAttribute = AttribPos[dwCount].pAttribute;
switch (pIasAttribute->dwId)
{
case IAS_ATTRIBUTE_CLIENT_IP_ADDRESS:
_ASSERT (IASTYPE_INET_ADDR == pIasAttribute->Value.itType),
*pdwIPAddress = pIasAttribute->Value.InetAddr;
break;
case IAS_ATTRIBUTE_CLIENT_UDP_PORT:
_ASSERT (IASTYPE_INTEGER == pIasAttribute->Value.itType);
*pwPort = pIasAttribute->Value.Integer;
break;
case IAS_ATTRIBUTE_CLIENT_PACKET_HEADER:
_ASSERT (
(IASTYPE_OCTET_STRING == pIasAttribute->Value.itType) &&
(PACKET_HEADER_SIZE == pIasAttribute->Value.OctetString.dwLength)
);
//
// copy the value into the buffer provided
//
CopyMemory (
pPacketHeader,
pIasAttribute->Value.OctetString.lpValue,
PACKET_HEADER_SIZE
);
break;
default:
_ASSERT (0);
IASTracePrintf (
"Attribute:%d, not requested, is present "
"in request received from backend",
pIasAttribute->dwId
);
hr = E_FAIL;
__leave;
break;
}
} // end of for loop
//
// get client information for this RADIUS packet
//
bStatus = m_pCClients->FindObject (
*pdwIPAddress,
ppIIasClient
);
if (FALSE == bStatus)
{
in_addr sin;
sin.s_addr = *pdwIPAddress;
IASTracePrintf (
"Unable to get information for client:%s "
"while processing request received from backend",
inet_ntoa (sin)
);
hr = E_FAIL;
__leave;
}
}
__finally
{
if (SUCCEEDED (hr))
{
for (dwCount = 0; dwCount < dwAttribPosCount; dwCount++)
{
//
// now release the reference to the attributes
//
::IASAttributeRelease (AttribPos[dwCount].pAttribute);
}
}
}
return (hr);
} // end of CPacketRadius::GetOutPacketInfo method
//++--------------------------------------------------------------
//
// Function: GeneratePacketRadius
//
// Synopsis: This is the CRecvFromPipe class private method
// that is used generate a new CPacketRadius
// class object and initialize it
//
// Arguments:
// [out] CPacketRadius**
// [in] IAttributesRaw*
//
// Returns: HRESULT - status
//
// History: MKarki Created 2/6/98
//
// Called By: CRecvFromPipe::Process method
//
//----------------------------------------------------------------
HRESULT
CRecvFromPipe:: GeneratePacketRadius (
CPacketRadius **ppCPacketRadius,
IAttributesRaw *pIAttributesRaw
)
{
PBYTE pPacketHeader = NULL;
DWORD dwAddress = 0;
WORD wPort = 0;
IIasClient *pIIasClient = NULL;
HRESULT hr = S_OK;
PATTRIBUTEPOSITION pAttribPosition = NULL;
_ASSERT (ppCPacketRadius && pIAttributesRaw);
//
// allocate memory for packet header
//
pPacketHeader =
reinterpret_cast <PBYTE> (CoTaskMemAlloc (PACKET_HEADER_SIZE));
if (NULL == pPacketHeader)
{
IASTracePrintf (
"Unable to allocate memory for packet header information "
"while generating out-bound packet"
);
hr = E_OUTOFMEMORY;
goto Cleanup;
}
//
// we need to gather information from the attribute collection
// needed to get create and initialize a CPacketRadius class
// object
//
hr = GetOutPacketInfo (
&dwAddress,
&wPort,
&pIIasClient,
pPacketHeader,
pIAttributesRaw
);
if (FAILED (hr)) { goto Cleanup; }
//
// create a new CPacketRadius class object
//
*ppCPacketRadius = new (std::nothrow) CPacketRadius (
m_pCHashMD5,
m_pCHashHmacMD5,
pIIasClient,
m_pCReportEvent,
pPacketHeader,
PACKET_HEADER_SIZE,
dwAddress,
wPort,
INVALID_SOCKET,
AUTH_PORTTYPE
);
if (NULL == *ppCPacketRadius)
{
IASTracePrintf (
"Unable to create a Packet-Radius object "
"while generating an out-bound packet"
);
pIIasClient->Release ();
hr = E_OUTOFMEMORY;
goto Cleanup;
}
Cleanup:
if ((FAILED (hr)) && (pPacketHeader))
{
CoTaskMemFree (pPacketHeader);
}
return (hr);
} // end of CRecvFromPipe::GeneratePacketRadius method
//++--------------------------------------------------------------
//
// Function: InjectSignatureIfNeeded
//
// Synopsis: This method is used to add a blank Signature attribute
// into the response if we see an EAP-Message attribute
// present
//
// Arguments:
// [in] PACKETTYPE
// [in] IAttributesRaw*
// [in] CPacketRadius*
//
// Returns: HRESULT - status
//
// History: MKarki Created 11/17/98
//
// Called By: CRecvFromPipe::Process method
//
//----------------------------------------------------------------
HRESULT CRecvFromPipe::InjectSignatureIfNeeded (
/*[in]*/ PACKETTYPE ePacketType,
/*[in]*/ IAttributesRaw *pIAttributesRaw,
/*[in]*/ CPacketRadius *pCPacketRadius
)
{
HRESULT hr = S_OK;
PATTRIBUTEPOSITION pAttribPos = NULL;
PIASATTRIBUTE pIasAttrib = NULL;
_ASSERT (pIAttributesRaw && pCPacketRadius);
__try
{
if (
(ACCESS_ACCEPT != ePacketType) &&
(ACCESS_REJECT != ePacketType) &&
(ACCESS_CHALLENGE != ePacketType)
)
{__leave;}
//
// get the count of the total attributes in the collection
//
DWORD dwAttributeCount = 0;
hr = pIAttributesRaw->GetAttributeCount (&dwAttributeCount);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain attribute count in request while "
"processing message authenticator attribute in out-bound packet "
);
__leave;
}
else if (0 == dwAttributeCount)
{
__leave;
}
//
// allocate memory for the ATTRIBUTEPOSITION array
//
pAttribPos = reinterpret_cast <PATTRIBUTEPOSITION> (
CoTaskMemAlloc (
sizeof (ATTRIBUTEPOSITION)*dwAttributeCount));
if (NULL == pAttribPos)
{
IASTracePrintf (
"Unable to allocate memory for attribute position array "
"while processing message authenticator attribute in out-bound packet"
);
hr = E_OUTOFMEMORY;
__leave;
}
//
// get the EAP-Message attribute from the interface
//
DWORD dwAttrId = RADIUS_ATTRIBUTE_EAP_MESSAGE;
hr = pIAttributesRaw->GetAttributes (
&dwAttributeCount,
pAttribPos,
1,
&dwAttrId
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain information about EAP-Message attribute "
"while processing out-bound RADIUS packet"
);
}
else if (0 == dwAttributeCount)
{
__leave;
}
bool bFound = false;
for (DWORD dwCount = 0; dwCount < dwAttributeCount; dwCount++)
{
if (
(!bFound) &&
(pCPacketRadius->IsOutBoundAttribute (
ePacketType,
pAttribPos[dwCount].pAttribute
))
)
{
bFound = true;
}
::IASAttributeRelease (pAttribPos[dwCount].pAttribute);
}
if (bFound)
{
//
// if we have an out-bound EAP-Message attribute then
// we need to insert a Signature attribute too
//
//
// create a new blank attribute
//
DWORD dwRetVal = ::IASAttributeAlloc ( 1, &pIasAttrib);
if (0 != dwRetVal)
{
IASTracePrintf (
"Unable to allocate IAS attribute for message authenticator "
"while processing out-bound RADIUS packet"
);
hr = HRESULT_FROM_WIN32 (dwRetVal);
__leave;
}
//
// allocate dynamic memory for the Signature
//
pIasAttrib->Value.OctetString.lpValue =
reinterpret_cast <PBYTE>
(CoTaskMemAlloc (SIGNATURE_SIZE));
if (NULL == pIasAttrib->Value.OctetString.lpValue)
{
IASTracePrintf (
"Unable to allocate dynamic memory for message authenticator "
"attribute value while processing out-bound RADIUS packet"
);
hr = E_OUTOFMEMORY;
__leave;
}
else
{
//
// put the signature attribute with no value
// but correct size
//
pIasAttrib->dwId = RADIUS_ATTRIBUTE_SIGNATURE;
pIasAttrib->Value.itType = IASTYPE_OCTET_STRING;
pIasAttrib->Value.OctetString.dwLength = SIGNATURE_SIZE;
pIasAttrib->dwFlags = IAS_INCLUDE_IN_RESPONSE;
//
// add the attribute to the collection now
//
ATTRIBUTEPOSITION attrPos;
attrPos.pAttribute = pIasAttrib;
hr = pIAttributesRaw->AddAttributes (1, &attrPos);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to add message authenticator attribute to request while "
"processing out-bound RADIUS packet"
);
__leave;
}
IASTracePrintf (
"message authenticator Attribute added to out-bound RADIUS packet"
);
}
}
}
__finally
{
if (pAttribPos) { CoTaskMemFree (pAttribPos); }
if (pIasAttrib) { ::IASAttributeRelease(pIasAttrib);}
}
return (hr);
} // end of CRecvFromPipe::InjectSignatureIfNeeded method
//++--------------------------------------------------------------
//
// Function: SplitAttributes
//
// Synopsis: This method is used to split up the following
// out-bound attributes:
// 1) Reply-Message attribute
// 2) MS-Filter-VSA attribute
// 3) MS QuarantineIpFilter attribute (VSA)
//
// Arguments:
// [in] IAttributesRaw*
//
// Returns: HRESULT - status
//
// History: MKarki Created 1/19/99
//
// Called By: CRecvFromPipe::Process method
//
//----------------------------------------------------------------
HRESULT CRecvFromPipe::SplitAttributes (
/*[in]*/ IAttributesRaw *pIAttributesRaw
)
{
const DWORD SPLIT_ATTRIBUTE_COUNT = 3;
static DWORD AttribIds [] = {
RADIUS_ATTRIBUTE_REPLY_MESSAGE,
MS_ATTRIBUTE_FILTER,
MS_ATTRIBUTE_QUARANTINE_IPFILTER
};
HRESULT hr = S_OK;
DWORD dwAttributesFound = 0;
PATTRIBUTEPOSITION pAttribPos = NULL;
_ASSERT (pIAttributesRaw);
__try
{
//
// get the count of the total attributes in the collection
//
DWORD dwAttributeCount = 0;
hr = pIAttributesRaw->GetAttributeCount (&dwAttributeCount);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain attribute count in request while "
"splitting attributes in out-bound packet "
);
__leave;
}
else if (0 == dwAttributeCount)
{
__leave;
}
//
// allocate memory for the ATTRIBUTEPOSITION array
//
pAttribPos = reinterpret_cast <PATTRIBUTEPOSITION> (
CoTaskMemAlloc (
sizeof (ATTRIBUTEPOSITION)*dwAttributeCount)
);
if (NULL == pAttribPos)
{
IASTracePrintf (
"Unable to allocate memory for attribute position array "
"while splitting attributes in out-bound packet"
);
hr = E_OUTOFMEMORY;
__leave;
}
//
// get the attributes we are interested in from the interface
//
hr = pIAttributesRaw->GetAttributes (
&dwAttributeCount,
pAttribPos,
SPLIT_ATTRIBUTE_COUNT,
static_cast <PDWORD> (AttribIds)
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain information about attributes"
"while splitting attributes in out-bound RADIUS packet"
);
__leave;
}
else if (0 == dwAttributeCount)
{
__leave;
}
//
// save the count of attributes returned
//
dwAttributesFound = dwAttributeCount;
DWORD dwAttribLength = 0;
DWORD dwMaxPossibleLength = 0;
IASTYPE iasType = IASTYPE_INVALID;
//
// evaluate each attribute now
//
for (DWORD dwCount = 0; dwCount < dwAttributeCount; dwCount++)
{
if ((pAttribPos[dwCount].pAttribute)->dwFlags &
IAS_INCLUDE_IN_RESPONSE)
{
//
// get attribute type and length
//
if (
(iasType = (pAttribPos[dwCount].pAttribute)->Value.itType) ==
IASTYPE_STRING
)
{
DWORD dwErr = ::IASAttributeAnsiAlloc(pAttribPos[dwCount].pAttribute);
if (dwErr != NO_ERROR)
{
hr = HRESULT_FROM_WIN32(dwErr);
IASTracePrintf (
"Unable to allocate memory for string attribute "
"while splitting attributes in out-bound packet"
);
__leave;
}
dwAttribLength =
strlen (
(pAttribPos[dwCount].pAttribute)->Value.String.pszAnsi);
}
else if (
(iasType = (pAttribPos[dwCount].pAttribute)->Value.itType) ==
IASTYPE_OCTET_STRING
)
{
dwAttribLength =
(pAttribPos[dwCount].pAttribute)->Value.OctetString.dwLength;
}
else
{
//
// only string values need to be split
//
continue;
}
//
// get max possible attribute length
//
if ((pAttribPos[dwCount].pAttribute)->dwId > MAX_ATTRIBUTE_TYPE)
{
dwMaxPossibleLength = MAX_VSA_ATTRIBUTE_LENGTH;
}
else
{
dwMaxPossibleLength = MAX_ATTRIBUTE_LENGTH;
}
//
// check if we need to split this attribute
//
if (dwAttribLength <= dwMaxPossibleLength) {continue;}
//
// split the attribute now
//
hr = SplitAndAdd (
pIAttributesRaw,
pAttribPos[dwCount].pAttribute,
iasType,
dwAttribLength,
dwMaxPossibleLength
);
if (SUCCEEDED (hr))
{
//
// remove this attribute from the collection now
//
hr = pIAttributesRaw->RemoveAttributes (
1,
&(pAttribPos[dwCount])
);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to remove attribute from collection"
"while splitting out-bound attributes"
);
}
}
}
}
}
__finally
{
if (pAttribPos)
{
for (DWORD dwCount = 0; dwCount < dwAttributesFound; dwCount++)
{
::IASAttributeRelease (pAttribPos[dwCount].pAttribute);
}
CoTaskMemFree (pAttribPos);
}
}
return (hr);
} // end of CRecvFromPipe::SplitAttributes method
//++--------------------------------------------------------------
//
// Function: SplitAndAdd
//
// Synopsis: This method is used to remove the original attribute
// and add new ones
// Arguments:
// [in] IAttributesRaw*
// [in] PIASATTRIBUTE
// [in] IASTYPE
// [in] DWORD - attribute length
// [in] DWORD - max attribute length
//
// Returns: HRESULT - status
//
// History: MKarki Created 1/19/99
//
// Called By: CRecvFromPipe::SplitAttributes method
//
//----------------------------------------------------------------
HRESULT CRecvFromPipe::SplitAndAdd (
/*[in]*/ IAttributesRaw *pIAttributesRaw,
/*[in]*/ PIASATTRIBUTE pIasAttribute,
/*[in]*/ IASTYPE iasType,
/*[in]*/ DWORD dwAttributeLength,
/*[in]*/ DWORD dwMaxLength
)
{
HRESULT hr = S_OK;
DWORD dwPacketsNeeded = 0;
DWORD dwFailed = 0;
PIASATTRIBUTE *ppAttribArray = NULL;
PATTRIBUTEPOSITION pAttribPos = NULL;
_ASSERT (pIAttributesRaw && pIasAttribute);
__try
{
dwPacketsNeeded = dwAttributeLength / dwMaxLength;
if (dwAttributeLength % dwMaxLength) {++dwPacketsNeeded;}
//
// allocate memory for the ATTRIBUTEPOSITION array
//
pAttribPos = reinterpret_cast <PATTRIBUTEPOSITION> (
CoTaskMemAlloc (
sizeof (ATTRIBUTEPOSITION)*dwPacketsNeeded));
if (NULL == pAttribPos)
{
IASTracePrintf (
"Unable to allocate memory for attribute position array "
"while split and add of attributese in out-bound packet"
);
hr = E_OUTOFMEMORY;
__leave;
}
//
// allocate array to store the attributes in
//
ppAttribArray =
reinterpret_cast <PIASATTRIBUTE*> (
CoTaskMemAlloc (sizeof (PIASATTRIBUTE)*dwPacketsNeeded));
if (NULL == ppAttribArray)
{
IASTracePrintf (
"Unable to allocate memory"
"while split and add of out-bound attribues"
);
hr = E_OUTOFMEMORY;
__leave;
}
DWORD dwFailed =
::IASAttributeAlloc (dwPacketsNeeded, ppAttribArray);
if (0 != dwFailed)
{
IASTracePrintf (
"Unable to allocate attributes while splitting out-bound"
"attributes"
);
hr = HRESULT_FROM_WIN32 (dwFailed);
__leave;
}
if (IASTYPE_STRING == iasType)
{
PCHAR pStart = (pIasAttribute->Value).String.pszAnsi;
DWORD dwCopySize = dwMaxLength;
//
// set value in each of the new attributes
//
for (DWORD dwCount1 = 0; dwCount1 < dwPacketsNeeded; dwCount1++)
{
(ppAttribArray[dwCount1])->Value.String.pszWide = NULL;
(ppAttribArray[dwCount1])->Value.String.pszAnsi =
reinterpret_cast <PCHAR>
(CoTaskMemAlloc ((dwCopySize + 1)*sizeof (CHAR)));
if (NULL == (ppAttribArray[dwCount1])->Value.String.pszAnsi)
{
IASTracePrintf (
"Unable to allocate memory for new attribute values"
"while split and add of out-bound attribues"
);
hr = E_OUTOFMEMORY;
__leave;
}
//
// set the value now
//
::CopyMemory (
(ppAttribArray[dwCount1])->Value.String.pszAnsi,
pStart,
dwCopySize
);
//
// nul terminate the values
//
((ppAttribArray[dwCount1])->Value.String.pszAnsi)[dwCopySize]=NUL;
(ppAttribArray[dwCount1])->Value.itType = iasType;
(ppAttribArray[dwCount1])->dwId = pIasAttribute->dwId;
(ppAttribArray[dwCount1])->dwFlags = pIasAttribute->dwFlags;
//
// calculate for next attribute
//
pStart = pStart + dwCopySize;
dwAttributeLength -= dwCopySize;
dwCopySize = (dwAttributeLength > dwMaxLength) ?
dwMaxLength : dwAttributeLength;
//
// add attribute to position array
//
pAttribPos[dwCount1].pAttribute = ppAttribArray[dwCount1];
}
}
else
{
PBYTE pStart = (pIasAttribute->Value).OctetString.lpValue;
DWORD dwCopySize = dwMaxLength;
//
// fill the new attributes now
//
for (DWORD dwCount1 = 0; dwCount1 < dwPacketsNeeded; dwCount1++)
{
(ppAttribArray[dwCount1])->Value.OctetString.lpValue =
reinterpret_cast <PBYTE> (CoTaskMemAlloc (dwCopySize));
if (NULL ==(ppAttribArray[dwCount1])->Value.OctetString.lpValue)
{
IASTracePrintf (
"Unable to allocate memory for new attribute values"
"while split and add of out-bound attribues"
);
hr = E_OUTOFMEMORY;
__leave;
}
//
// set the value now
//
::CopyMemory (
(ppAttribArray[dwCount1])->Value.OctetString.lpValue,
pStart,
dwCopySize
);
(ppAttribArray[dwCount1])->Value.OctetString.dwLength = dwCopySize;
(ppAttribArray[dwCount1])->Value.itType = iasType;
(ppAttribArray[dwCount1])->dwId = pIasAttribute->dwId;
(ppAttribArray[dwCount1])->dwFlags = pIasAttribute->dwFlags;
//
// calculate for next attribute
//
pStart = pStart + dwCopySize;
dwAttributeLength -= dwCopySize;
dwCopySize = (dwAttributeLength > dwMaxLength) ?
dwMaxLength :
dwAttributeLength;
//
// add attribute to position array
//
pAttribPos[dwCount1].pAttribute = ppAttribArray[dwCount1];
}
}
//
// add the attribute to the collection
//
hr = pIAttributesRaw->AddAttributes (dwPacketsNeeded, pAttribPos);
if (FAILED (hr))
{
IASTracePrintf (
"Failed to add attributes to the collection"
"on split and add out-bound attributes"
);
__leave;
}
}
__finally
{
if (ppAttribArray && !dwFailed)
{
for (DWORD dwCount = 0; dwCount < dwPacketsNeeded; dwCount++)
{
::IASAttributeRelease (ppAttribArray[dwCount]);
}
}
if (ppAttribArray) {CoTaskMemFree (ppAttribArray);}
if (pAttribPos) {CoTaskMemFree (pAttribPos);}
}
return (hr);
} // end of CRecvFromPipe::SplitAndAdd method
//++--------------------------------------------------------------
//
// Function: ConvertReasonToRadiusError
//
// Synopsis:
//
// Arguments:
// [in] iasReason
// [out] Radius Error
//
// Returns: HRESULT - status
//
// History: MKarki Created 12/31/98
//
// Called By: CRecvFromPipe::Process method
//
//----------------------------------------------------------------
HRESULT
CRecvFromPipe::ConvertReasonToRadiusError (
/*[in]*/ LONG iasReason,
/*[out]*/ PRADIUSLOGTYPE pRadError
)
{
HRESULT hr = S_OK;
_ASSERT (pRadError);
switch (iasReason)
{
case IAS_NO_RECORD:
*pRadError = RADIUS_NO_RECORD;
break;
case IAS_MALFORMED_REQUEST:
*pRadError = RADIUS_MALFORMED_PACKET;
break;
default:
hr = E_FAIL;
break;
}
return (hr);
} // end of CRecvFromPipe::ConvertReasonToRadiusError method