//#-------------------------------------------------------------- // // File: crascom.cpp // // Synopsis: Implementation of CRasCom class methods // // // History: 2/10/98 MKarki Created // 5/15/98 SBens Do not consolidate VSAs. // 9/16/98 SBens Signature of VSAFilter::radiusFromIAS changed. // 11/17/99 TPerraut Split code for MS-Filter Attribute added // 428843 // // // Copyright (C) Microsoft Corporation // All rights reserved. // //---------------------------------------------------------------- #include "rascominclude.h" #include "crascom.h" #include const DWORD MAX_SLEEP_TIME = 50; //milli-seconds // // const and defines below added for the split functions. 428843 // const CHAR NUL = '\0'; // // these are the largest values that the attribute type // packet type have // #define MAX_ATTRIBUTE_TYPE 255 // // these are the related constants // #define MAX_ATTRIBUTE_LENGTH 253 #define MAX_VSA_ATTRIBUTE_LENGTH 247 //++-------------------------------------------------------------- // // 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 // TPerraut Copied from CRecvFromPipe::SplitAndAdd 11/17/99 // // Called By: SplitAttributes // //---------------------------------------------------------------- HRESULT 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 ( ::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 ( ::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.pszAnsi = reinterpret_cast (::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 (::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 ((FAILED (hr)) && (ppAttribArray) && (0 == dwFailed)) { for (DWORD dwCount = 0; dwCount < dwPacketsNeeded; dwCount++) { ::IASAttributeRelease (ppAttribArray[dwCount]); } } if (ppAttribArray) {::CoTaskMemFree (ppAttribArray);} if (pAttribPos) {::CoTaskMemFree (pAttribPos);} } return (hr); } // end of SplitAndAdd 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 // TPerraut Copied from CRecvFromPipe::SplitAttributes // 11/17/99 // // Called By: CRasCom::Process method // //---------------------------------------------------------------- HRESULT 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 ( ::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 (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)); __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 SplitAttributes method //++-------------------------------------------------------------- // // Function: CRasCom // // Synopsis: This is CRasCom Class constructor // // Arguments: NONE // // Returns: NONE // // History: MKarki Created 2/10/98 // //---------------------------------------------------------------- CRasCom::CRasCom ( VOID ) :m_objCRequestSource (this), m_pIRequestHandler(NULL), m_pIClassFactory (NULL), m_bVSAFilterInitialized (FALSE), m_lRequestCount (0), m_eCompState (COMP_SHUTDOWN) { } // end of CRasCom class constructor //++-------------------------------------------------------------- // // Function: ~CRasCom // // Synopsis: This is CRasCom class destructor // // Arguments: NONE // // Returns: NONE // // // History: MKarki Created 2/10/98 // //---------------------------------------------------------------- CRasCom::~CRasCom( VOID ) { } // end of CRasCom class destructor //++-------------------------------------------------------------- // // Function: InitNew // // Synopsis: This is the InitNew method exposed through the // IIasComponent COM Interface. // For the RasCom Component it is implemented for // completeness // // // Arguments: none // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // // Called By: by the Component intializer through the IIasComponent // interface // //---------------------------------------------------------------- STDMETHODIMP CRasCom::InitNew ( VOID ) { // // InitNew call can only be made from SHUTDOWN state // if (COMP_SHUTDOWN != m_eCompState) { IASTracePrintf ("The Surrogate can not be called in this state"); return (E_UNEXPECTED); } // // reset the total pending request count // m_lRequestCount = 0; // // now we are initialized m_eCompState = COMP_UNINITIALIZED; return (S_OK); } // end of CRasCom::InitNew method //++-------------------------------------------------------------- // // Function: Initialize // // Synopsis: This is the Initialize method exposed through the // IIasComponent COM Interface. It initializes the // Request object ClassFactory // // Arguments: none // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // // Called By: by the Component intializer through the IIasComponent // interface // //---------------------------------------------------------------- STDMETHODIMP CRasCom::Initialize ( VOID ) { HRESULT hr = S_OK; // // Initialize call can only be made from Uninitialized state // if (COMP_INITIALIZED == m_eCompState) { return (S_OK); } else if (COMP_UNINITIALIZED != m_eCompState) { IASTracePrintf ("The Surrogate can not be initialized in this state"); return (E_UNEXPECTED); } // // get the IClassFactory interface to be used to create // the Request COM object // hr = ::CoGetClassObject ( __uuidof (Request), CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, reinterpret_cast (&m_pIClassFactory) ); if (FAILED (hr)) { IASTracePrintf ("The Surrogate was unable to obtain request factory"); return (hr); } // // initialize the VSAFilter class object // hr = m_objVSAFilter.initialize (); if (FAILED (hr)) { IASTracePrintf ("The Surrogate was unable to initializa VSA filtering"); m_pIClassFactory->Release (); m_pIClassFactory = NULL; return (hr); } else { m_bVSAFilterInitialized = TRUE; } // // correctly initialized the surrogate // m_eCompState = COMP_INITIALIZED; return (S_OK); } // end of CRasCom::Initialize method //++-------------------------------------------------------------- // // Function: Shutdown // // Synopsis: This is the ShutDown method exposed through the // IIasComponent COM Interface. It is used to stop // processing data // // Arguments: NONE // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // // Called By: by the Component shutdown through the IIasComponent // interface // //---------------------------------------------------------------- STDMETHODIMP CRasCom::Shutdown ( VOID ) { BOOL bStatus = FALSE; // // shutdown can only be called from the suspend state // if (COMP_SHUTDOWN == m_eCompState) { return (S_OK); } else if ( (COMP_SUSPENDED != m_eCompState) && (COMP_UNINITIALIZED != m_eCompState) ) { IASTracePrintf ("The Surrogate can not be shutdown in current state"); return (E_UNEXPECTED); } // // release the interfaces // if (NULL != m_pIRequestHandler) { m_pIRequestHandler->Release (); m_pIRequestHandler = NULL; } if (NULL != m_pIClassFactory) { m_pIClassFactory->Release (); m_pIClassFactory = NULL; } // // shutdown the VSAFilter // if (TRUE == m_bVSAFilterInitialized) { m_objVSAFilter.shutdown (); m_bVSAFilterInitialized = FALSE; } // // cleanly shutting down // m_eCompState = COMP_SHUTDOWN; return (S_OK); } // end of CRasCom::Shutdown method //++-------------------------------------------------------------- // // Function: Suspend // // Synopsis: This is the Suspend method exposed through the // IComponent COM Interface. It is used to suspend // packet processing operations // // Arguments: NONE // // Returns: HRESULT - status // // // History: MKarki Created 10/2/97 // //---------------------------------------------------------------- STDMETHODIMP CRasCom::Suspend ( VOID ) { BOOL bStatus = FALSE; HRESULT hr = S_OK; // // suspend can only be called from the initialized state // if (COMP_SUSPENDED == m_eCompState) { return (S_OK); } else if (COMP_INITIALIZED != m_eCompState) { IASTracePrintf ("The Surrogate can not be suspended in current state"); return (E_UNEXPECTED); } // // change state // m_eCompState = COMP_SUSPENDED; while (0 != m_lRequestCount) { Sleep (MAX_SLEEP_TIME); } // // we have successfully suspended RADIUS component's packet // processing operations // return (hr); } // end of CRasCom::Suspend method //++-------------------------------------------------------------- // // Function: Resume // // Synopsis: This is the Resume method exposed through the // IComponent COM Interface. It is used to resume // packet processing operations which had been // stopped by a previous call to Suspend API // // // Arguments: NONE // // Returns: HRESULT - status // // // History: MKarki Created 10/2/97 // //---------------------------------------------------------------- STDMETHODIMP CRasCom::Resume ( VOID ) { if (COMP_SUSPENDED != m_eCompState) { IASTracePrintf ("The Surrogate can not resume in current state"); return (E_UNEXPECTED); } // // we have successfully resumed operations in the RADIUS component // m_eCompState = COMP_INITIALIZED; return (S_OK); } // end of CRasCom::Resume method //++-------------------------------------------------------------- // // Function: GetProperty // // Synopsis: This is the IIasComponent Interface method. // Only Implemented for the sake of completeness // // Arguments: // [in] LONG - id // [out] VARIANT - *pValue // // Returns: HRESULT - status // // // History: MKarki Created 2/10/98 // //---------------------------------------------------------------- STDMETHODIMP CRasCom::GetProperty ( LONG id, VARIANT *pValue ) { return (S_OK); } // end of CRasCom::GetProperty method //++-------------------------------------------------------------- // // Function: PutProperty // // Synopsis: This is the IIasComponent Interface method. // Only Implemented for the sake of completeness // Arguments: // [in] LONG - id // [out] VARIANT - *pValue // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // //---------------------------------------------------------------- STDMETHODIMP CRasCom::PutProperty ( LONG id, VARIANT *pValue ) { HRESULT hr = S_OK; // // PutProperty method can only be called from // Uninitialized, Initialized or Suspended state // if ( (COMP_UNINITIALIZED != m_eCompState) && (COMP_INITIALIZED != m_eCompState) && (COMP_SUSPENDED == m_eCompState) ) { IASTracePrintf ("Surrogate can not put property in current state"); return (E_UNEXPECTED); } // // check if valid arguments where passed in // if (NULL == pValue) { return (E_POINTER); } // // carry out the property intialization now // switch (id) { case PROPERTY_PROTOCOL_REQUEST_HANDLER: if (NULL != m_pIRequestHandler) { // // clients can not be updated in INITIALIZED or // SUSPENDED state // hr = HRESULT_FROM_WIN32 (ERROR_ALREADY_INITIALIZED); } else if (VT_DISPATCH != pValue->vt) { hr = DISP_E_TYPEMISMATCH; } else if (NULL == pValue->punkVal) { hr = E_INVALIDARG; } else { // // initialize the providers // m_pIRequestHandler = reinterpret_cast (pValue->punkVal); m_pIRequestHandler->AddRef (); } break; default: hr = DISP_E_MEMBERNOTFOUND; break; } return (hr); } // end of CRasCom::PutProperty method //++-------------------------------------------------------------- // // Function: QueryInterfaceReqSrc // // Synopsis: This is the function called when this Component // is called and queried for its IRequestSource // interface // // Arguments: // [in] PVOID - this object refrence // [in] REFIID - IID of interface requested // [out] LPVOID - return appropriate interface // [in] DWORD // // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // //---------------------------------------------------------------- HRESULT WINAPI CRasCom::QueryInterfaceReqSrc ( PVOID pThis, REFIID riid, LPVOID *ppv, DWORD_PTR dwValue ) { if ((NULL == pThis) || (NULL == ppv)) return (E_FAIL); // // get a reference to the nested CRequestSource object // *ppv = &(static_cast(pThis))->m_objCRequestSource; // // increment count // ((LPUNKNOWN)*ppv)->AddRef(); return (S_OK); } // end of CRasCom::QueryInterfaceReqSrc method //++-------------------------------------------------------------- // // Function: CRequestSource // // Synopsis: This is the constructor of the CRequestSource // nested class // // Arguments: // [in] CRasCom* // // Returns: none // // History: MKarki Created 2/10/98 // //---------------------------------------------------------------- CRasCom::CRequestSource::CRequestSource( CRasCom *pCRasCom ) :m_pCRasCom (pCRasCom) { _ASSERT (NULL != pCRasCom); } // end of CRequestSource class constructor //++-------------------------------------------------------------- // // Function: ~CRequestSource // // Synopsis: This is the destructor of the CRequestSource // nested class // // Arguments: // // Returns: HRESULT - status // // // History: MKarki Created 11/21/97 // //---------------------------------------------------------------- CRasCom::CRequestSource::~CRequestSource() { } // end of CRequestSource destructor //++-------------------------------------------------------------- // // Function: OnRequestComplete // // Synopsis: This is a method of IRequestHandler COM interface // This is the function called when a request is // is being pushed back after backend processing // we just return here as we are only be doing // synchronous processing // // Arguments: // [in] IRequest* // [in] IASREQUESTSTATUS // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // // Called By: Pipeline through the IRequestHandler interface // //---------------------------------------------------------------- STDMETHODIMP CRasCom::CRequestSource::OnRequestComplete ( IRequest *pIRequest, IASREQUESTSTATUS eStatus ) { BOOL bStatus = FALSE; HANDLE hEvent = NULL; HRESULT hr = S_OK; unsigned hyper uhyState = 0; CComPtr pIRequestState; if (NULL == pIRequest) { IASTracePrintf ( "Surrogate passed invalid argumen in OnRequestComplete method" ); return (E_POINTER); } // // get the IRequestState interface now // hr = pIRequest->QueryInterface ( __uuidof(IRequestState), reinterpret_cast (&pIRequestState) ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to obtain IRequestState interface in" " OnRequestComplete method" ); return (hr); } // // get the CPacketRadius class object // hr = pIRequestState->Pop ( reinterpret_cast (&uhyState) ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to obtain information from Request State" " in OnRequestComplete method" ); return (hr); } // // get the hEvent; // hEvent = reinterpret_cast (uhyState); // // set the event now // bStatus = ::SetEvent (hEvent); if (FALSE == bStatus) { IASTracePrintf ( "Surrogate unable to send notification that request is" " processed in OnRequestComplete method" ); return (E_FAIL); } return (S_OK); } // end of CRasCom::CRequestSource::OnRequestComplete method //++-------------------------------------------------------------- // // Function: Process // // Synopsis: This is the method of the IRecvRequest COM interface // It is called to generate and send request to the // pipeline // // Arguments: // [in] DWORD - number of in attributes // [in] PIASATTRIBUTE* - array of pointer to attribs // [out] PDWORD - number of out attributes // [out] PIASATTRIBUTE** - pointer // [in] LONG // [in/out]LONG* // [in] IASPROTCOL // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // // Called By: Called by DoRequest C style API // //---------------------------------------------------------------- STDMETHODIMP CRasCom::Process ( /*[in]*/ DWORD dwInAttributeCount, /*[in]*/ PIASATTRIBUTE *ppInIasAttribute, /*[out]*/ PDWORD pdwOutAttributeCount, /*[out]*/ PIASATTRIBUTE **pppOutIasAttribute, /*[in]*/ LONG IasRequest, /*[in/out]*/ LONG *pIasResponse, /*[in]*/ IASPROTOCOL IasProtocol, /*[out]*/ PLONG plReason, /*[in]*/ BOOL bProcessVSA ) { DWORD dwCount = 0; HRESULT hr = S_OK; HANDLE hEvent = NULL; DWORD dwRetVal = 0; IRequest *pIRequest = NULL; IAttributesRaw *pIAttributesRaw = NULL; IRequestState *pIRequestState = NULL; PATTRIBUTEPOSITION pIasAttribPos = NULL; static DWORD dwRequestCount = 0; // // check if processing is enabled // if ((COMP_INITIALIZED != m_eCompState) || (NULL == m_pIRequestHandler)) { IASTracePrintf ( "Surrogate passed invalid argument for request processing" ); return (E_FAIL); } __try { // // increment the request count // InterlockedIncrement (&m_lRequestCount); // check if we are processing requests at this time // if ((COMP_INITIALIZED != m_eCompState) || (NULL == m_pIRequestHandler)) { IASTracePrintf ( "Surrogate unable to process request in the current state" ); hr = E_FAIL; __leave; } if ( (0 == dwInAttributeCount) || (NULL == ppInIasAttribute) || (NULL == pdwOutAttributeCount) || (NULL == pppOutIasAttribute) || (NULL == pIasResponse) || (NULL == plReason) ) { IASTracePrintf ( "Surrogate passed invalid argument for processing request" ); hr = E_INVALIDARG; __leave; } _ASSERT (NULL != m_pIClassFactory); // // create the request object // HRESULT hr = m_pIClassFactory->CreateInstance ( NULL, __uuidof (IRequest), reinterpret_cast (&pIRequest) ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate failed in creation of a new request object" ); __leave; } // // get IAttributesRaw interface // hr = pIRequest->QueryInterface ( __uuidof (IAttributesRaw), reinterpret_cast (&pIAttributesRaw) ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to obtain Attribute interface while" " processing request" ); __leave; } // // allocate memory for the ATTRIBUTEPOSITION array // pIasAttribPos = reinterpret_cast ( ::CoTaskMemAlloc ( sizeof (ATTRIBUTEPOSITION)*dwInAttributeCount) ); if (NULL == pIasAttribPos) { IASTracePrintf ( "Surrogate unable to allocate memory while processing request" ); hr = E_OUTOFMEMORY; __leave; } // // put the attributes in the ATTRIBUTEPOSITION structs // for (dwCount = 0; dwCount < dwInAttributeCount; dwCount++) { // // mark the attribute as having been received from client // ppInIasAttribute[dwCount]->dwFlags |= IAS_RECVD_FROM_CLIENT; pIasAttribPos[dwCount].pAttribute = ppInIasAttribute[dwCount]; } // // put the attributes collection that we are holding into the // Request object through the IAttributesRaw interface // hr = pIAttributesRaw->AddAttributes ( dwInAttributeCount, pIasAttribPos ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate failed to add attributes to request being processed" ); __leave; } // // set the request type now // hr = pIRequest->put_Request (IasRequest); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to set the request type for processing" ); __leave; } // // set the protocol now // hr = pIRequest->put_Protocol (IasProtocol); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to set protocol type in request for processing" ); __leave; } // // put your IRequestSource interface in now // hr = pIRequest->put_Source (&m_objCRequestSource); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to set source in request for processing" ); __leave; } // // convert the VSA attributes to IAS format if requested // if (TRUE == bProcessVSA) { hr = m_objVSAFilter.radiusToIAS (pIAttributesRaw); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to convert VSAs to IAS format" ); __leave; } } // // create an event which will be used to wake this thread // when the pipeline does multithreaded processing // hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (NULL == hEvent) { IASTracePrintf ( "Surrogate unable to create event while processing request" ); __leave; } // // get the request state interface to put in our state now // // hr = pIRequest->QueryInterface ( __uuidof (IRequestState), reinterpret_cast (&pIRequestState) ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to extract request state interface" ); __leave; } // // put in the request state - which is our event handle in // hr = pIRequestState->Push ( reinterpret_cast (hEvent) ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to set event in request state" ); __leave; } _ASSERT (NULL != m_pIRequestHandler); // // send the request to the pipeline now // hr = m_pIRequestHandler->OnRequest (pIRequest); if (FAILED (hr)) { IASTracePrintf ( "Surrogate request failed backend processing..." ); __leave; } // // now wait for the event now // dwRetVal = ::WaitForSingleObjectEx (hEvent, INFINITE, TRUE); if (0XFFFFFFFF == dwRetVal) { IASTracePrintf ( "Surrogate failed on waiting for process completion" ); hr = E_FAIL; __leave; } // // convert the IAS attributes to VSA format if requested // if (TRUE == bProcessVSA) { // // TPERRAUT ADDED Bug 428843 // Always called from RAS with bProcessVSA = true // // split the attributes which can not fit in a radius packet // hr = SplitAttributes (pIAttributesRaw); if (FAILED (hr)) { IASTracePrintf ( "TPERRAUT: Unable to split IAS attribute received from backend" ); __leave; } // TPERRAUT ADDED: END hr = m_objVSAFilter.radiusFromIAS (pIAttributesRaw); if (FAILED (hr)) { IASTracePrintf ( "Surrogate failed on extracting VSAs from IAS format" ); __leave; } } // // now its time to dismantle the request sent to find out // what we got back // hr = pIRequest->get_Response (pIasResponse); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to obtain response from processed request" ); __leave; } hr = pIRequest->get_Reason (plReason); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to obtain reason from processed request" ); __leave; } // // remove all the attributes from the request object now // hr = RemoveAttributesFromRequest ( *pIasResponse, pIAttributesRaw, pdwOutAttributeCount, pppOutIasAttribute ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to remove attributes from processed request" ); __leave; } } __finally { // // do the cleanup now // if (NULL != hEvent) { CloseHandle (hEvent); } if (NULL != pIasAttribPos) { ::CoTaskMemFree (pIasAttribPos); } if (NULL != pIRequestState) { pIRequestState->Release (); } if (NULL != pIAttributesRaw) { pIAttributesRaw->Release (); } if (NULL != pIRequest) { pIRequest->Release (); } // // increment the requestreceived // dwRequestCount = (0xFFFFFFFF == dwRequestCount) ? 1 : dwRequestCount+ 1; // // decrement the request count // InterlockedDecrement (&m_lRequestCount); } return (hr); } // end of CRasCom::Process method //++-------------------------------------------------------------- // // Function: RemoveAttributesFromRequest // // Synopsis: This is the CRasCom class private method // that is used to remove the attributes // from the Request object through the // IAttributesRaw interface // // Arguments: // [in] LONG - response received from pipe // [in] IAttributesRaw* // [out] PIASATTRIBUTE** // [out] PDWORD - out attribute count // // Returns: HRESULT - status // // History: MKarki Created 2/10/98 // // Called By: CRasCom::Process method // //---------------------------------------------------------------- STDMETHODIMP CRasCom::RemoveAttributesFromRequest ( LONG lResponse, IAttributesRaw *pIasAttributesRaw, PDWORD pdwOutAttributeCount, PIASATTRIBUTE **pppIasAttribute ) { HRESULT hr = S_OK; PATTRIBUTEPOSITION pIasOutAttributePos = NULL; DWORD dwCount = 0; DWORD dwAttribCount = 0; DWORD dwOutCount = 0; BOOL bGotAttributes = FALSE; PIASATTRIBUTE pIasAttribute = NULL; _ASSERT ( (NULL != pIasAttributesRaw) && (NULL != pppIasAttribute) && (NULL != pdwOutAttributeCount) ); __try { // // get the count of the attributes remaining in the collection // these will be the OUT attributes // hr = pIasAttributesRaw->GetAttributeCount (&dwAttribCount); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable to obtain attribute count from request in" "while removing attributes from request" ); __leave; } // // allocate memory for the ATTRIBUTEPOSITION array // pIasOutAttributePos = reinterpret_cast ( ::CoTaskMemAlloc ( sizeof (ATTRIBUTEPOSITION)*(dwAttribCount)) ); if (NULL == pIasOutAttributePos) { IASTracePrintf ( "Surrogate unable to allocate memory" "while removing attributes from request" ); hr = E_OUTOFMEMORY; __leave; } // // get all the attributes from the collection // hr = pIasAttributesRaw->GetAttributes ( &dwAttribCount, pIasOutAttributePos, 0, NULL ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable get attributes from request interface" "while removing attributes" ); __leave; } // // we have obtained the attributes // bGotAttributes = TRUE; // // remove the attributes from the collection now // hr = pIasAttributesRaw->RemoveAttributes ( dwAttribCount, pIasOutAttributePos ); if (FAILED (hr)) { IASTracePrintf ( "Surrogate unable remove attributes from request" ); __leave; } // // calculate the number of attributes not added by the client // *pdwOutAttributeCount = 0; for (dwCount = 0; dwCount < dwAttribCount; dwCount++) { pIasAttribute = pIasOutAttributePos[dwCount].pAttribute; // // verify that this attributes has to be sent to client // if ( ((pIasAttribute->dwFlags & IAS_INCLUDE_IN_ACCEPT) && (IAS_RESPONSE_ACCESS_ACCEPT == lResponse)) || ((pIasAttribute->dwFlags & IAS_INCLUDE_IN_REJECT) && (IAS_RESPONSE_ACCESS_REJECT == lResponse)) || ((pIasAttribute->dwFlags & IAS_INCLUDE_IN_CHALLENGE) && (IAS_RESPONSE_ACCESS_CHALLENGE == lResponse)) ) { (*pdwOutAttributeCount)++; } } // // allocate memory for PIASATTRIBUTE array // *pppIasAttribute = reinterpret_cast ( ::CoTaskMemAlloc (sizeof(PIASATTRIBUTE)*(*pdwOutAttributeCount)) ); if (NULL == *pppIasAttribute) { IASTracePrintf ( "Surrogate unable to allocate memory for attrib pointer array" "while removing attribute from request" ); hr = E_OUTOFMEMORY; __leave; } // // put the attributes in the PIASATTRIBUTE array // for (dwCount = 0, dwOutCount = 0; dwCount < dwAttribCount; dwCount++) { pIasAttribute = pIasOutAttributePos[dwCount].pAttribute; if ( (((pIasAttribute->dwFlags & IAS_INCLUDE_IN_ACCEPT) && (IAS_RESPONSE_ACCESS_ACCEPT == lResponse)) || ((pIasAttribute->dwFlags & IAS_INCLUDE_IN_REJECT) && (IAS_RESPONSE_ACCESS_REJECT == lResponse)) || ((pIasAttribute->dwFlags & IAS_INCLUDE_IN_CHALLENGE) && (IAS_RESPONSE_ACCESS_CHALLENGE == lResponse))) && (dwOutCount < *pdwOutAttributeCount) ) { // // put the out attribute in the output array // (*pppIasAttribute)[dwOutCount] = pIasAttribute; dwOutCount++; } else { // // decrement the reference count for the // attributes we created or the ones we are // not sending as out to client // ::IASAttributeRelease (pIasAttribute); } } // // now put in the number of out attribute we are actually // giving the client // *pdwOutAttributeCount = dwOutCount; } __finally { // // cleanup on failure // if (FAILED (hr)) { if (NULL != *pppIasAttribute) { ::CoTaskMemFree (*pppIasAttribute); pppIasAttribute = NULL; } // // correct the out attribute count // *pdwOutAttributeCount = 0; // // free up all the attributes also // if ((TRUE == bGotAttributes) && (NULL != pIasOutAttributePos)) { for (dwCount = 0; dwCount < dwAttribCount; dwCount++) { ::IASAttributeRelease ( pIasOutAttributePos[dwCount].pAttribute ); } } } // // delete the dynamically allocated memory // if (NULL != pIasOutAttributePos) { ::CoTaskMemFree (pIasOutAttributePos); } } return (hr); } // end of CRasCom::RemoveAttributesFromRequest method