|
|
//#--------------------------------------------------------------
//
// 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
|