//#-------------------------------------------------------------- // // File: packetradius.cpp // // Synopsis: Implementation of CPacketRadius class methods // // Copyright (C) Microsoft Corporation All rights reserved. // //---------------------------------------------------------------- #include "radcommon.h" #include "iasutil.h" #include "packetradius.h" const CHAR NUL = '\0'; const DWORD DEFAULT_ATTRIB_ARRAY_SIZE = 64; memory_pool CPacketRadius::m_OutBufferPool; namespace { const DWORDLONG UNIX_EPOCH = 116444736000000000ui64; } void CPacketRadius::reportMalformed() const throw () { PCWSTR strings[] = { GetClientName() }; IASReportEvent( RADIUS_E_MALFORMED_PACKET, 1, GetInLength(), strings, GetInPacket() ); } //++-------------------------------------------------------------- // // Function: CPacketRadius // // Synopsis: This is the constructor of the CPacketRadius class // // Arguments: NONE // // Returns: NONE // // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- CPacketRadius::CPacketRadius( CHashMD5 *pCHashMD5, CHashHmacMD5 *pCHashHmacMD5, IIasClient *pIIasClient, CReportEvent *pCReportEvent, PBYTE pInBuffer, DWORD dwInLength, DWORD dwIPAddress, WORD wInPort, SOCKET sock, PORTTYPE portType ) : m_wInPort (wInPort), m_dwInIPaddress (dwIPAddress), m_socket (sock), m_porttype (portType), m_pCProxyInfo (NULL), m_pCHashMD5 (pCHashMD5), m_pCHashHmacMD5 (pCHashHmacMD5), m_pIIasClient (pIIasClient), m_pCReportEvent (pCReportEvent), m_pIasAttribPos (NULL), m_pInPacket (pInBuffer), m_dwInLength(dwInLength), m_pOutPacket (NULL), m_pInSignature (NULL), m_pOutSignature(NULL), m_pUserName (NULL), m_pPasswordAttrib (NULL) { _ASSERT ( (NULL != pInBuffer) && (NULL != pCHashMD5) && (NULL != pCHashHmacMD5) && (NULL != pIIasClient) ); m_pIIasClient->AddRef (); } // end of CPacketRadius constructor //++-------------------------------------------------------------- // // Function: ~CPacketRadius // // Synopsis: This is the destructor of the CPacketRadius class // // Arguments: NONE // // Returns: NONE // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- CPacketRadius::~CPacketRadius() { if (NULL != m_pIasAttribPos) { // // release the attribute // for ( DWORD dwCount = 0; dwCount < (m_dwInAttributeCount + COMPONENT_SPECIFIC_ATTRIBUTE_COUNT); dwCount++ ) { ::IASAttributeRelease (m_pIasAttribPos[dwCount].pAttribute); } // // delete the attribute position array now // CoTaskMemFree (m_pIasAttribPos); } // // release the reference to Client object // if (m_pIIasClient) { m_pIIasClient->Release ();} // // delete the out-packet buffer // if (m_pOutPacket) { m_OutBufferPool.deallocate (m_pOutPacket); } // // delete the in packet buffer // if (m_pInPacket) { CoTaskMemFree (m_pInPacket); } } // end of CPacketRadius destructor //+++------------------------------------------------------------- // // Function: PrelimVerification // // Synopsis: The method starts the verification of the // buffer passed in this is done only when // the class objec is created for an inbound // packet // // Arguments: // [in] CDictionary* // [in] DWORD - size of the buffer provided // // Returns: HRESULT - status // // Called By: CPacketReceiver::ReceivePacket class method // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- HRESULT CPacketRadius::PrelimVerification ( CDictionary *pCDictionary, DWORD dwBufferSize ) { PRADIUSPACKET pPacket = NULL; DWORD dwAttribCount = 0; TCHAR szErrorString [IAS_ERROR_STRING_LENGTH]; HRESULT hr = S_OK; __try { // // check that the buffer received is atleast big enough to // accomdate out RADIUSPACKET struct // if (dwBufferSize < MIN_PACKET_SIZE) { IASTracePrintf ( "Packet received is smaller than minimum Radius packet" ); reportMalformed(); m_pCReportEvent->Process ( RADIUS_MALFORMED_PACKET, (AUTH_PORTTYPE == GetPortType ())? ACCESS_REQUEST:ACCOUNTING_REQUEST, dwBufferSize, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } pPacket = reinterpret_cast (m_pInPacket); // // now save values in host byte order // m_wInPacketLength = ntohs (pPacket->wLength); // // validate the fields of the packet, except the attributes // hr = ValidatePacketFields (dwBufferSize); if (FAILED (hr)) { __leave; } // // verify that the attributes are completely formed // hr = VerifyAttributes (pCDictionary); if (FAILED (hr)) { __leave; } // // now we have to create the attributes collection // hr = CreateAttribCollection (pCDictionary); if (FAILED (hr)) { __leave; } // // success // } __finally { } return (hr); } // end of CPacketRadius::PrelimVerification method //+++------------------------------------------------------------- // // Function: VerifyAttributes // // Synopsis: This is a CPacketRadius class private method used // verify that the attributes received are well formed // // Arguments: none // // Returns: HRESULT - status // // History: MKarki Created 10/3/97 // // Called By: CPacketRadius::PrelimVerification method // //---------------------------------------------------------------- HRESULT CPacketRadius::VerifyAttributes ( CDictionary *pCDictionary ) { PRADIUSPACKET pPacketEnd = NULL; PRADIUSPACKET pPacketStart = NULL; PATTRIBUTE pAttrib = NULL; DWORD dwAttribCount = 0; TCHAR szErrorString [IAS_ERROR_STRING_LENGTH]; HRESULT hr = S_OK; BOOL bStatus = FALSE; _ASSERT (pCDictionary); __try { pPacketStart = reinterpret_cast (m_pInPacket); // // get a pointer to the packet end // pPacketEnd = reinterpret_cast ( reinterpret_cast (pPacketStart) + m_wInPacketLength ); // // go through the attributes once, to verify they are of correct // length // pAttrib = reinterpret_cast (pPacketStart->AttributeStart); const DWORD dwMinAttribOffset = sizeof (ATTRIBUTE) - sizeof (BYTE); while (static_cast ( reinterpret_cast (pAttrib) + dwMinAttribOffset ) <= static_cast (pPacketEnd) ) { // // verify that the attributes is of correct length // and in any case not of length 0 // MKarki Fix #147284 // Fix summary - forgot the "__leave" // if (pAttrib->byLength < ATTRIBUTE_HEADER_SIZE) { reportMalformed(); m_pCReportEvent->Process ( RADIUS_MALFORMED_PACKET, GetInCode (), m_wInPacketLength, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } // // move to the next attribute // pAttrib = reinterpret_cast ( reinterpret_cast (pAttrib) + pAttrib->byLength ); // // count the attributes // dwAttribCount++; } // // if the attributes don't addup to end of packet // if (static_cast (pAttrib) != static_cast (pPacketEnd)) { IASTracePrintf ( "Attributes do not add up to end of Radius packet" ); reportMalformed(); m_pCReportEvent->Process ( RADIUS_MALFORMED_PACKET, GetInCode (), m_wInPacketLength, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } // // verified // m_dwInAttributeCount = dwAttribCount; } __finally { } return (hr); } // end of CPacketRadius::VerifyAttributes method //+++------------------------------------------------------------- // // Function: CreateAttribCollection // // Synopsis: This is a CPacketRadius class private method used // to put the RADIUS attributes into the CAttributes // collection // // Arguments: none // // Returns: HRESULT - status // // History: MKarki Created 9/23/97 // // Called By: CPacketRadius::Init method // //---------------------------------------------------------------- HRESULT CPacketRadius::CreateAttribCollection( CDictionary *pCDictionary ) { HRESULT hr = S_OK; PATTRIBUTE pAttrib = NULL; DWORD dwAttribType = 0; DWORD dwCount = 0; DWORD dwRetVal = ERROR_NOT_ENOUGH_MEMORY; PIASATTRIBUTE AttributePtrArray[DEFAULT_ATTRIB_ARRAY_SIZE]; PIASATTRIBUTE *ppAttribArray = NULL; PRADIUSPACKET pPacketStart = reinterpret_cast (m_pInPacket); const DWORD dwTotalAttribCount = m_dwInAttributeCount + COMPONENT_SPECIFIC_ATTRIBUTE_COUNT; _ASSERT (pCDictionary); // // allocate an ATTRIBUTEPOSITION array to carry the attribute // around // m_pIasAttribPos = reinterpret_cast ( CoTaskMemAlloc ( sizeof (ATTRIBUTEPOSITION)*dwTotalAttribCount )); if (NULL == m_pIasAttribPos) { IASTracePrintf ( "Unable to allocate memory for Attribute position array " "while creating attribute collection" ); hr = E_OUTOFMEMORY; goto Cleanup; } if (dwTotalAttribCount > DEFAULT_ATTRIB_ARRAY_SIZE) { // // allocate array to store the attributes in // ppAttribArray = reinterpret_cast ( CoTaskMemAlloc ( sizeof (PIASATTRIBUTE)*dwTotalAttribCount )); if (NULL == ppAttribArray) { IASTracePrintf ( "Unable to allocate memory for Attribute array " "while creating attribute collection" ); hr = E_OUTOFMEMORY; goto Cleanup; } } else { // // the default array is big enough // ppAttribArray = AttributePtrArray; } // // create a bunch of new blank attributes to fill up the positions // dwRetVal = ::IASAttributeAlloc (dwTotalAttribCount, ppAttribArray); if (0 != dwRetVal) { IASTracePrintf ( "Unable to allocate IAS attribute while creating attribute " "collection" ); hr = HRESULT_FROM_WIN32 (dwRetVal); goto Cleanup; } // // go through the attributes storing them in the collection // pAttrib = reinterpret_cast (pPacketStart->AttributeStart); // // now initialize the IASATTRIBUTE value structs with the values // in the packet // for (dwCount = 0; dwCount < m_dwInAttributeCount; dwCount++) { hr = FillInAttributeInfo ( pCDictionary, static_cast (pPacketStart->byCode), ppAttribArray[dwCount], pAttrib ); if (FAILED (hr)) { goto Cleanup; } // // now put this in the attribute position structure // m_pIasAttribPos[dwCount].pAttribute = ppAttribArray[dwCount]; // // now store a reference to the attribute here if its // a User-Password attribute, because we know we will // access it later and don't want to have to search for // it // TODO - do the same kind of stuff for ProxyState // as we would need the proxystate too. // if (USER_PASSWORD_ATTRIB == pAttrib->byType) { m_pPasswordAttrib = ppAttribArray[dwCount]; } else if (SIGNATURE_ATTRIB == pAttrib->byType) { // // for Signature we want its position in the // raw input buffer // m_pInSignature = pAttrib; } else if (USER_NAME_ATTRIB == pAttrib->byType) { // // for UserName we want its position in the // raw input buffer // m_pUserName = pAttrib; } // // move to the next attribute now // pAttrib = reinterpret_cast ( reinterpret_cast (pAttrib) + pAttrib->byLength ); } // end of for loop // // put in Client IP address in an attribute // hr = FillClientIPInfo (ppAttribArray[m_dwInAttributeCount]); if (FAILED (hr)) { goto Cleanup; } m_pIasAttribPos[m_dwInAttributeCount].pAttribute = ppAttribArray[m_dwInAttributeCount]; // // put in Client Port number in the attribute // hr = FillClientPortInfo (ppAttribArray[m_dwInAttributeCount +1]); if (FAILED (hr)) { goto Cleanup; } m_pIasAttribPos[m_dwInAttributeCount +1].pAttribute = ppAttribArray[m_dwInAttributeCount +1]; // // put in the packet header information // hr = FillPacketHeaderInfo (ppAttribArray[m_dwInAttributeCount +2]); if (FAILED (hr)) { goto Cleanup; } m_pIasAttribPos[m_dwInAttributeCount +2].pAttribute = ppAttribArray[m_dwInAttributeCount +2]; // // put in the Shared Secret // hr = FillSharedSecretInfo (ppAttribArray[m_dwInAttributeCount +3]); if (FAILED (hr)) { goto Cleanup; } m_pIasAttribPos[m_dwInAttributeCount +3].pAttribute = ppAttribArray[m_dwInAttributeCount +3]; // // put in the Client Vendor Type // hr = FillClientVendorType (ppAttribArray[m_dwInAttributeCount +4]); if (FAILED (hr)) { goto Cleanup; } m_pIasAttribPos[m_dwInAttributeCount +4].pAttribute = ppAttribArray[m_dwInAttributeCount +4]; // // put in the Client Name // hr = FillClientName (ppAttribArray[m_dwInAttributeCount +5]); if (FAILED (hr)) { goto Cleanup; } m_pIasAttribPos[m_dwInAttributeCount +5].pAttribute = ppAttribArray[m_dwInAttributeCount +5]; // // successfully collected attributes // Cleanup: if (FAILED (hr)) { if (0 == dwRetVal) { // // release the attribute // for (dwCount = 0; dwCount < dwTotalAttribCount ; dwCount++) { ::IASAttributeRelease (ppAttribArray[dwCount]); } } if (NULL != m_pIasAttribPos) { CoTaskMemFree (m_pIasAttribPos); m_pIasAttribPos = NULL; } } // // the attribute array is always freed // if ( (NULL != ppAttribArray) && (dwTotalAttribCount > DEFAULT_ATTRIB_ARRAY_SIZE) ) { CoTaskMemFree (ppAttribArray); } return (hr); } // end of CPacketRadius::CreateAttribCollection method //+++------------------------------------------------------------- // // Function: ValidatePacketFields // // Synopsis: This is a CPacketRadius class private method used // to validate the fields of the RADIUS packet, execpt // the attributes // // Arguments: [in] DWORD - buffer size // // // Returns: HRESULT - status // // // History: MKarki Created 9/23/97 // // Called By: CPacketRadius::PrelimVerification method // //---------------------------------------------------------------- HRESULT CPacketRadius::ValidatePacketFields( DWORD dwBufferSize ) { HRESULT hr = S_OK; TCHAR szErrorString [IAS_ERROR_STRING_LENGTH]; PRADIUSPACKET pPacket = reinterpret_cast (m_pInPacket); __try { // // check that we have received the complete packet // if (m_wInPacketLength > dwBufferSize) { // // log error and generate audit event // IASTracePrintf ( "Packet length:%d is greater than received buffer:%d", m_wInPacketLength, dwBufferSize ); reportMalformed(); m_pCReportEvent->Process ( RADIUS_MALFORMED_PACKET, (AUTH_PORTTYPE== GetPortType ())? ACCESS_REQUEST:ACCOUNTING_REQUEST, dwBufferSize, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } // // verify that the packet is of correct lenth; // i.e between 20 to 4096 octets // if ( (m_wInPacketLength < MIN_PACKET_SIZE) || (m_wInPacketLength > MAX_PACKET_SIZE) ) { // // Log Error and Audit Event // IASTracePrintf ( "Incorrect received packet size:%d", m_wInPacketLength ); reportMalformed(); m_pCReportEvent->Process ( RADIUS_MALFORMED_PACKET, (AUTH_PORTTYPE == GetPortType ())? ACCESS_REQUEST:ACCOUNTING_REQUEST, dwBufferSize, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } // // verify that the PACKET code is correct // if ( ((ACCESS_REQUEST == static_cast (pPacket->byCode)) && (AUTH_PORTTYPE != GetPortType ())) || ((ACCOUNTING_REQUEST == static_cast(pPacket->byCode)) && (ACCT_PORTTYPE != GetPortType ())) || (((ACCESS_REQUEST != static_cast(pPacket->byCode))) && ((ACCOUNTING_REQUEST != static_cast(pPacket->byCode)))) ) { // // log error and generate audit event // IASTracePrintf ( "UnSupported Packet type:%d on this port", static_cast (pPacket->byCode) ); WCHAR packetCode[11]; _ultow(pPacket->byCode, packetCode, 10); sockaddr_in sin; int namelen = sizeof(sin); getsockname(GetSocket(), (sockaddr*)&sin, &namelen); WCHAR dstPort[11]; _ultow(ntohs(sin.sin_port), dstPort, 10); PCWSTR strings[] = { packetCode, dstPort, GetClientName() }; IASReportEvent( RADIUS_E_INVALID_PACKET_TYPE, 3, 0, strings, NULL ); m_pCReportEvent->Process ( RADIUS_UNKNOWN_TYPE, (AUTH_PORTTYPE == GetPortType ())? ACCESS_REQUEST:ACCOUNTING_REQUEST, dwBufferSize, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } } __finally { } return (hr); } // end of CPacketRadius::ValidatePacketFields method //+++------------------------------------------------------------- // // Function: SetPassword // // Synopsis: Thie is a CPacketRadius class public method used to // store the user password. // // Arguments: [in] PBYTE - buffer to return password // [in] PDWORD - holds the buffer size // // // Returns: HRESULT - status // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- HRESULT CPacketRadius::SetPassword ( PBYTE pPassword, DWORD dwSize ) { if (dwSize > MAX_ATTRIBUTE_LENGTH) { IASTracePrintf ( "Password length is greater than max attribute value size" ); return (E_INVALIDARG); } // // delete the dynamically allocated memory if its not big enough // if (dwSize > m_pPasswordAttrib->Value.OctetString.dwLength) { if (NULL != m_pPasswordAttrib->Value.OctetString.lpValue) { CoTaskMemFree (m_pPasswordAttrib->Value.OctetString.lpValue); } // // allocate memory for OctetString // m_pPasswordAttrib->Value.OctetString.lpValue = reinterpret_cast (CoTaskMemAlloc (dwSize)); if (NULL == m_pPasswordAttrib->Value.OctetString.lpValue) { IASTracePrintf ( "Unable to allocate memory for password attribute " "during packet processing" ); return (E_OUTOFMEMORY); } } // // copy the value now // CopyMemory ( m_pPasswordAttrib->Value.OctetString.lpValue, pPassword, dwSize ); m_pPasswordAttrib->Value.OctetString.dwLength = dwSize; return (S_OK); } // end of CPacketRadius::SetPassword method //++-------------------------------------------------------------- // // Function: GetUserName // // Synopsis: Thie is a CPacketRadius class public method used to // return the RADIUS UserName // // Arguments: [in] PBYTE - buffer to return the password in // [in/out] PDWORD - holds the buffer size // // Returns: BOOL - status // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- BOOL CPacketRadius :: GetUserName ( PBYTE pbyUserName, PDWORD pdwBufferSize ) { _ASSERT ((pbyUserName) && (pdwBufferSize)); if (NULL == m_pUserName) { IASTracePrintf ( "No User-Name attribute found during packet processing" ); return (FALSE); } DWORD dwNameLength = m_pUserName->byLength - ATTRIBUTE_HEADER_SIZE; if (*pdwBufferSize < dwNameLength) { IASTracePrintf ( "User-Name Buffer Size is less than length of attribute value" ); return (FALSE); } // // copy the password into the out buffer // CopyMemory (pbyUserName, m_pUserName->ValueStart, dwNameLength); *pdwBufferSize = dwNameLength; return (TRUE); } // end of CPacketRadius::GetPassword method //++-------------------------------------------------------------- // // Function: IsProxyStatePresent // // Synopsis: Thie is a CPacketRadius class public method used to // check if the RADIUS packet has a proxy state present. // // // Arguments: none // // // Returns: BOOL - status // // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- BOOL CPacketRadius::IsProxyStatePresent ( VOID ) { return (NULL != m_pCProxyInfo); } // end of CPacketRadius::IsProxyStatePresent method //++-------------------------------------------------------------- // // Function: GetInAuthenticator // // Synopsis: Thie is a CPacketRadius class public method used // to get the inbound RADIUS packet authenticator // field. // // // Arguments: [out] PBYTE - buffer to hold authenticator // // // Returns: BOOL - status // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- HRESULT CPacketRadius::GetInAuthenticator ( PBYTE pbyAuthenticator, PDWORD pdwBufSize ) { HRESULT hr = S_OK; PRADIUSPACKET pPacket = reinterpret_cast (m_pInPacket); _ASSERT ((pbyAuthenticator) && (pdwBufSize) && (pPacket)); if (*pdwBufSize < AUTHENTICATOR_SIZE) { hr = E_INVALIDARG; } else { CopyMemory ( pbyAuthenticator, pPacket->Authenticator, AUTHENTICATOR_SIZE ); } *pdwBufSize = AUTHENTICATOR_SIZE; return hr; } // end of CPacketRadius::GetInAuthenticator method //++-------------------------------------------------------------- // // Function: SetOutAuthenticator // // Synopsis: Thie is a CPacketRadius class public method used // to set the RADIUS authenticator field in the outbound // packet // // // Arguments: [in] PBYTE - buffer hold authenticator // // // Returns: BOOL - status // // // History: MKarki Created 11/11/97 // //---------------------------------------------------------------- BOOL CPacketRadius::SetOutAuthenticator ( PBYTE pbyAuthenticator ) { PRADIUSPACKET pPacket = reinterpret_cast (m_pOutPacket); _ASSERT ((pbyAuthenticator) && (pPacket)); CopyMemory ( pPacket->Authenticator, pbyAuthenticator, AUTHENTICATOR_SIZE ); return (TRUE); } // end of CPacketRadius::SetOutAuthenticator method //++-------------------------------------------------------------- // // Function: SetOutSignature // // Synopsis: Thie is a CPacketRadius class public method used // to set the RADIUS Signature attribute value in the // outbound packet // // // Arguments: [in] PBYTE - buffer holds signature // // // Returns: BOOL - status // // // History: MKarki Created 11/18/98 // //---------------------------------------------------------------- HRESULT CPacketRadius::SetOutSignature ( PBYTE pbySignature ) { _ASSERT (pbySignature && m_pOutPacket && m_pOutSignature); CopyMemory ( m_pOutSignature->ValueStart, pbySignature, SIGNATURE_SIZE ); return (S_OK); } // end of CPacketRadius::SetOutSignature method //+++------------------------------------------------------------- // // Function: GetInCode // // Synopsis: Thie is a CPacketRadius class public method used // to get the inbound RADIUS packet code field. // // // Arguments: none // // // Returns: PACKETTYPE // // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- PACKETTYPE CPacketRadius::GetInCode ( VOID ) { PRADIUSPACKET pPacket = reinterpret_cast (m_pInPacket); return (static_cast (pPacket->byCode)); } // end of CPacketRadius::GetInCode method //++-------------------------------------------------------------- // // Function: GetOutCode // // Synopsis: Thie is a CPacketRadius class public method used // to get the outbound RADIUS packet code field. // // // Arguments: NONE // // // Returns: PACKETTYPE // // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- PACKETTYPE CPacketRadius::GetOutCode ( VOID ) { PRADIUSPACKET pPacket = reinterpret_cast (m_pOutPacket); return (static_cast (pPacket->byCode)); } // end of CPacketRadius::GetOutCode method //++-------------------------------------------------------------- // // Function: GetOutLength // // Synopsis: Thie is a CPacketRadius class public method used // to get the outbound RADIUS packet length. // // // Arguments: none // // // Returns: WORD - RADIUS in packet length // // // History: MKarki Created 9/23/97 // //---------------------------------------------------------------- WORD CPacketRadius::GetOutLength ( VOID ) { PRADIUSPACKET pPacket = reinterpret_cast (m_pOutPacket); return (ntohs (pPacket->wLength)); } // end of CPacketRadius::GetOutLength method //++-------------------------------------------------------------- // // Function: SetProxyState // // Synopsis: Thie is a CPacketRadius class public method used // to set the proxy state to TRUE // // Arguments: none // // Returns: BOOL - status // // History: MKarki Created 10/2/97 // //---------------------------------------------------------------- VOID CPacketRadius::SetProxyState ( VOID ) { return; } // end of CPacketRadius::SetProxyState method //++-------------------------------------------------------------- // // Function: SetProxyInfo // // Synopsis: Thie is a CPacketRadius class public method used // to set the proxy state information for the packet // // Arguments: [in] CProxyInfo* // // Returns: BOOL - status // // History: MKarki Created 10/2/97 // //---------------------------------------------------------------- BOOL CPacketRadius::SetProxyInfo ( CProxyInfo *pCProxyInfo ) { BOOL bRetVal = FALSE; _ASSERT (pCProxyInfo); m_pCProxyInfo = pCProxyInfo; return (TRUE); } // end of CPacketRadius::SetProxyInfo method //++-------------------------------------------------------------- // // Function: BuildOutPacket // // Synopsis: This is a CPacketRadius class public method used // to build the outbound packet // // Arguments: // [in] PACKETTYPE - out packet type // [in] PATTRIBUTEPOSITION - out attributes array // [in] DWORD - Attributes Count // // Returns: HRESULT - status // // History: MKarki Created 10/22/97 // //---------------------------------------------------------------- HRESULT CPacketRadius::BuildOutPacket ( PACKETTYPE ePacketType, PATTRIBUTEPOSITION pAttribPos, DWORD dwTotalAttributes ) { BOOL bRetVal = FALSE; PRADIUSPACKET pOutPacket = NULL; PRADIUSPACKET pInPacket = reinterpret_cast (m_pInPacket); PATTRIBUTE pCurrent = NULL; PATTRIBUTE pAttribStart = NULL; PBYTE pPacketEnd = NULL; WORD wAttributeLength = 0; DWORD dwPacketLength = 0; DWORD dwMaxPossibleAttribLength = 0; HRESULT hr = S_OK; __try { dwPacketLength = PACKET_HEADER_SIZE + dwTotalAttributes*(MAX_ATTRIBUTE_LENGTH + ATTRIBUTE_HEADER_SIZE); // // limit the packet size to max UDP packet size // dwPacketLength = (dwPacketLength > MAX_PACKET_SIZE) ? MAX_PACKET_SIZE : dwPacketLength; m_pOutPacket = reinterpret_cast (m_OutBufferPool.allocate ()); if (NULL == m_pOutPacket) { IASTracePrintf ( "Unable to allocate memory for pool for out-bound packet" ); hr = E_OUTOFMEMORY; __leave; } pOutPacket = reinterpret_cast (m_pOutPacket); // // put the packet type // pOutPacket->byCode = ePacketType; // // put the packet ID // pOutPacket->byIdentifier = pInPacket->byIdentifier; // // now fill in the current packet length // pOutPacket->wLength = htons (PACKET_HEADER_SIZE); // // get the end of buffer // pPacketEnd = (reinterpret_cast (pOutPacket)) + dwPacketLength; // // goto start of attributes // pAttribStart = reinterpret_cast (pOutPacket->AttributeStart); // // Fix for Bug #190523 - 06/26/98 - MKarki // we shouldn't be taking diff of PUNINTs // dwMaxPossibleAttribLength = static_cast ( reinterpret_cast (pPacketEnd) - reinterpret_cast (pAttribStart) ); // // filled the attributes now // for ( DWORD dwAttribCount = 0; dwAttribCount < dwTotalAttributes; dwAttribCount++ ) { if (IsOutBoundAttribute ( ePacketType, pAttribPos[dwAttribCount].pAttribute )) { // // fill the attribute in the packet buffer // hr = FillOutAttributeInfo ( pAttribStart, pAttribPos[dwAttribCount].pAttribute, &wAttributeLength, dwMaxPossibleAttribLength ); if (FAILED (hr)) { __leave; } dwMaxPossibleAttribLength -= wAttributeLength; // // go to the next attribute start // PBYTE pTemp = reinterpret_cast (pAttribStart) + wAttributeLength; pAttribStart = reinterpret_cast (pTemp); if ((reinterpret_cast (pAttribStart)) > pPacketEnd) { // // log error // IASTracePrintf ( "Attributes can not fit in out-bound packet" ); hr = RADIUS_E_PACKET_OVERFLOW; __leave; } } // end of if } // end of for loop m_wOutPort = m_wInPort; m_dwOutIPaddress = m_dwInIPaddress; // // now update the length of the packet // pOutPacket->wLength = htons ( (reinterpret_cast (pAttribStart)) - (reinterpret_cast (pOutPacket)) ); // // success // } __finally { } if (hr == RADIUS_E_PACKET_OVERFLOW) { PCWSTR strings[] = { GetClientName() }; IASReportEvent( RADIUS_E_PACKET_OVERFLOW, 1, 0, strings, 0 ); hr = RADIUS_E_ERRORS_OCCURRED; } return (hr); } // end of CPacketRadius::BuildOutPacket method //++-------------------------------------------------------------- // // Function: GetInSignature // // Synopsis: This is CPacketARadius class public method // that returns the Signature attribute present // in the in bound request // // Arguments: // [out] PBYTE - signature // // Returns: BOOL - status // // History: MKarki Created 1/6/98 // //---------------------------------------------------------------- BOOL CPacketRadius::GetInSignature ( PBYTE pSignatureValue ) { BOOL bRetVal = TRUE; _ASSERT (pSignatureValue); // // assuming that the caller provides a buffer of 16 bytes // as this the signature size ALWAYS // if (NULL == m_pInSignature) { // // no signature attribute received // bRetVal = FALSE; } else { CopyMemory ( pSignatureValue, m_pInSignature->ValueStart, SIGNATURE_SIZE ); } return (bRetVal); } // end of CPacketRadius::GetInSignature method //++-------------------------------------------------------------- // // Function: GenerateInAuthenticator // // Synopsis: This is CPacketARadius class public method // that generates the authenticator from the // input packet // // Arguments: // [in] PBYTE - Inbound Authenticator // [out] PBYTE - Outbound Authenticator // // Returns: BOOL - status // // History: MKarki Created 12/8/97 // // //---------------------------------------------------------------- BOOL CPacketRadius::GenerateInAuthenticator ( PBYTE pInAuthenticator, PBYTE pOutAuthenticator ) { PRADIUSPACKET pPacket = reinterpret_cast (m_pInPacket); _ASSERT ((pOutAuthenticator) && (pInAuthenticator) && (pPacket)); return (InternalGenerator ( pInAuthenticator, pOutAuthenticator, pPacket )); } // end of CPacketRadius::GenerateInAuthenticator //++-------------------------------------------------------------- // // Function: GenerateOutAuthenticator // // Synopsis: This is CPacketARadius class public method // that generates the authenticator from the // outbound packet // // Arguments: // [in] PBYTE - Inbound authenticator // [out] PBYTE - Outbound authenticator // // Returns: BOOL - status // // History: MKarki Created 12/8/97 // // //---------------------------------------------------------------- BOOL CPacketRadius::GenerateOutAuthenticator() { PRADIUSPACKET pPacket = reinterpret_cast (m_pOutPacket); _ASSERT ((pOutAuthenticator) && (pInAuthenticator) && (pPacket)); return (InternalGenerator ( m_pInPacket + 4, pPacket->Authenticator, pPacket )); } // end of CPacketRadius::GenerateOutAuthenticator method //++-------------------------------------------------------------- // // Function: InternalGenerator // // Synopsis: This is CPacketARadius class private method // that generates the response authenticator for the // packet provided // // Arguments: // [in] PBYTE - InAuthenticator // [out] PBYTE - OutAuthenticator // [in] PPACKETRADIUS // // Returns: BOOL - status // // History: MKarki Created 12/8/97 // // //---------------------------------------------------------------- BOOL CPacketRadius::InternalGenerator( PBYTE pInAuthenticator, PBYTE pOutAuthenticator, PRADIUSPACKET pPacket ) { BOOL bStatus = TRUE; DWORD dwPacketHeaderSize = 0; DWORD dwAttributesLength = 0; _ASSERT ((pInAuthenticator) && (pOutAuthenticator) && (pPacket)); __try { // // get the size of the packet without the attributes and // request authenticator // dwPacketHeaderSize = sizeof (RADIUSPACKET) - sizeof (BYTE) - AUTHENTICATOR_SIZE; // // get the total attributes length now // dwAttributesLength = ntohs (pPacket->wLength) - (dwPacketHeaderSize + AUTHENTICATOR_SIZE); // // get the shared secret // DWORD dwSecretSize; const BYTE* bySecret = m_pIIasClient->GetSecret(&dwSecretSize); // // do the hashing here // m_pCHashMD5->HashIt ( pOutAuthenticator, NULL, 0, reinterpret_cast (pPacket), dwPacketHeaderSize, pInAuthenticator, AUTHENTICATOR_SIZE, pPacket->AttributeStart, dwAttributesLength, const_cast(bySecret), dwSecretSize, 0, 0 ); // // we have successfully got the outbound authenticator // } __finally { } return (bStatus); } // end of CPacketRadius::InternalGenerator method //++-------------------------------------------------------------- // // Function: FillInAttributeInfo // // Synopsis: This is CPacketARadius class private method // that fills up the attribute information into // the IASATTRIBUTE struct from the raw RADIUS // packet // // Arguments: // [in] PACKETTYPE // [in] PIASATTRIBUTE // [in] PATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 12/31/97 // //--------------------------------------------------------------- HRESULT CPacketRadius::FillInAttributeInfo ( CDictionary *pCDictionary, PACKETTYPE ePacketType, PIASATTRIBUTE pIasAttrib, PATTRIBUTE pRadiusAttrib ) { HRESULT hr = S_OK; _ASSERT ((pCDictionary) && (pIasAttrib) && (pRadiusAttrib)); __try { // IAS IDs always match the RADIUS ID. pIasAttrib->dwId = pRadiusAttrib->byType; // Get the IAS syntax from the dictionary. pIasAttrib->Value.itType = pCDictionary->getAttributeType(pRadiusAttrib->byType); // // get the length of the value // DWORD dwValueLength = static_cast (pRadiusAttrib->byLength - ATTRIBUTE_HEADER_SIZE); // // Set Value now // switch (pIasAttrib->Value.itType) { case IASTYPE_BOOLEAN: if (sizeof (DWORD) != dwValueLength) { hr = RADIUS_E_MALFORMED_PACKET; __leave; } pIasAttrib->Value.Boolean = IASExtractDWORD( pRadiusAttrib->ValueStart ); break; case IASTYPE_INTEGER: if (sizeof (DWORD) != dwValueLength) { hr = RADIUS_E_MALFORMED_PACKET; __leave; } pIasAttrib->Value.Integer = IASExtractDWORD( pRadiusAttrib->ValueStart ); break; case IASTYPE_ENUM: if (sizeof (DWORD) != dwValueLength) { hr = RADIUS_E_MALFORMED_PACKET; __leave; } pIasAttrib->Value.Enumerator = IASExtractDWORD( pRadiusAttrib->ValueStart ); break; case IASTYPE_INET_ADDR: if (sizeof (DWORD) != dwValueLength) { hr = RADIUS_E_MALFORMED_PACKET; __leave; } pIasAttrib->Value.InetAddr = IASExtractDWORD( pRadiusAttrib->ValueStart ); break; case IASTYPE_STRING: // // allocate memory for string + ending NUL // if(0 == dwValueLength) { pIasAttrib->Value.String.pszAnsi = NULL; } else { pIasAttrib->Value.String.pszAnsi = reinterpret_cast (CoTaskMemAlloc (dwValueLength + 1)); if (NULL == pIasAttrib->Value.String.pszAnsi) { hr = E_OUTOFMEMORY; __leave; } CopyMemory ( pIasAttrib->Value.String.pszAnsi, pRadiusAttrib->ValueStart, dwValueLength ); pIasAttrib->Value.String.pszAnsi[dwValueLength] = NUL; } pIasAttrib->Value.String.pszWide = NUL; break; case IASTYPE_OCTET_STRING: pIasAttrib->Value.OctetString.dwLength = dwValueLength; // // here dwValueLength == 0 // if(0 == dwValueLength) { pIasAttrib->Value.OctetString.lpValue = NULL; } else { pIasAttrib->Value.OctetString.lpValue = reinterpret_cast (CoTaskMemAlloc (dwValueLength)); if (NULL == pIasAttrib->Value.OctetString.lpValue) { hr = E_OUTOFMEMORY; __leave; } CopyMemory ( pIasAttrib->Value.OctetString.lpValue, pRadiusAttrib->ValueStart, dwValueLength ); } break; case IASTYPE_UTC_TIME: { if (dwValueLength != 4) { hr = RADIUS_E_MALFORMED_PACKET; __leave; } DWORDLONG val; // Extract the UNIX time. val = IASExtractDWORD(pRadiusAttrib->ValueStart); // Convert from seconds to 100 nsec intervals. val *= 10000000; // Shift to the NT epoch. val += UNIX_EPOCH; // Split into the high and low DWORDs. pIasAttrib->Value.UTCTime.dwLowDateTime = (DWORD)val; pIasAttrib->Value.UTCTime.dwHighDateTime = (DWORD)(val >> 32); } break; case IASTYPE_INVALID: case IASTYPE_PROV_SPECIFIC: default: hr = E_FAIL; __leave; } // // sign the attribute that the Protocol component created it // pIasAttrib->dwFlags |= (IAS_RECVD_FROM_CLIENT | IAS_RECVD_FROM_PROTOCOL); // // also if this is a proxy state attribute also send // it out on the wire // if (PROXY_STATE_ATTRIB == pIasAttrib->dwId) { pIasAttrib->dwFlags |= IAS_INCLUDE_IN_RESPONSE; } // // success // } __finally { if (hr == RADIUS_E_MALFORMED_PACKET) { IASTracePrintf ( "Incorrect attribute:%d in packet", static_cast (pRadiusAttrib->byType) ); reportMalformed(); m_pCReportEvent->Process ( RADIUS_MALFORMED_PACKET, GetInCode (), m_wInPacketLength, m_dwInIPaddress, NULL, static_cast (m_pInPacket) ); hr = RADIUS_E_ERRORS_OCCURRED; } } return (hr); } // end of CPacketRadius::FillInAttributeInfo method //++-------------------------------------------------------------- // // Function: FillOutAttributeInfo // // Synopsis: This is CPacketARadius class private method // that fills up the attribute information into // the outbound RADIUS packet from the IASATTRIBUTE // struct // // Arguments: // [in] PATTRIBUTE // [in] PIASATTRIBUTE // [out] PWORD - return attribute length // [in] DWORD - Max possible attribute length // // Returns: HRESULT - status // // History: MKarki Created 1/3/97 // //---------------------------------------------------------------- HRESULT CPacketRadius::FillOutAttributeInfo ( PATTRIBUTE pRadiusAttrib, PIASATTRIBUTE pIasAttrib, PWORD pwAttributeLength, DWORD dwMaxPossibleAttribSize ) { DWORD dwAttributeLength = 0; IAS_BOOLEAN iasBoolean = 0; IAS_INTEGER iasInteger = 0; IAS_ENUM iasEnum = 0; IAS_INET_ADDR iasAddr = 0; HRESULT hr = S_OK; _ASSERT ((pRadiusAttrib) && (pIasAttrib) && (pwAttributeLength)); __try { // // now put the value into the buffer // switch (pIasAttrib->Value.itType) { case IASTYPE_BOOLEAN: iasBoolean = htonl (pIasAttrib->Value.Boolean); dwAttributeLength = ATTRIBUTE_HEADER_SIZE + sizeof (IAS_BOOLEAN); if (dwMaxPossibleAttribSize >= dwAttributeLength) { CopyMemory ( pRadiusAttrib->ValueStart, &iasBoolean, sizeof (IAS_BOOLEAN) ); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } break; case IASTYPE_INTEGER: iasInteger = htonl (pIasAttrib->Value.Integer); dwAttributeLength = ATTRIBUTE_HEADER_SIZE + sizeof (IAS_INTEGER); if (dwMaxPossibleAttribSize >= dwAttributeLength) { CopyMemory ( pRadiusAttrib->ValueStart, &iasInteger, sizeof (IAS_INTEGER) ); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } break; case IASTYPE_ENUM: iasEnum = htonl (pIasAttrib->Value.Enumerator); dwAttributeLength = ATTRIBUTE_HEADER_SIZE + sizeof (IAS_ENUM); if (dwMaxPossibleAttribSize >= dwAttributeLength) { CopyMemory ( pRadiusAttrib->ValueStart, &iasEnum, sizeof (IAS_ENUM) ); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } break; case IASTYPE_INET_ADDR: iasAddr = htonl (pIasAttrib->Value.InetAddr); dwAttributeLength = ATTRIBUTE_HEADER_SIZE + sizeof (IAS_INET_ADDR); if (dwMaxPossibleAttribSize >= dwAttributeLength) { CopyMemory ( pRadiusAttrib->ValueStart, &iasAddr, sizeof (IAS_INET_ADDR) ); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } break; case IASTYPE_STRING: { // // for RADIUS protocol always ANSI // DWORD dwErr = IASAttributeAnsiAlloc (pIasAttrib); if (dwErr != NO_ERROR) { hr = HRESULT_FROM_WIN32(dwErr); __leave; } dwAttributeLength = ATTRIBUTE_HEADER_SIZE + strlen (pIasAttrib->Value.String.pszAnsi); if (dwMaxPossibleAttribSize >= dwAttributeLength) { CopyMemory ( pRadiusAttrib->ValueStart, reinterpret_cast (pIasAttrib->Value.String.pszAnsi), strlen (pIasAttrib->Value.String.pszAnsi) ); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } break; } case IASTYPE_OCTET_STRING: dwAttributeLength = ATTRIBUTE_HEADER_SIZE + pIasAttrib->Value.OctetString.dwLength; if (dwMaxPossibleAttribSize >= dwAttributeLength) { CopyMemory ( pRadiusAttrib->ValueStart, static_cast (pIasAttrib->Value.OctetString.lpValue), pIasAttrib->Value.OctetString.dwLength ); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } break; case IASTYPE_UTC_TIME: { dwAttributeLength = ATTRIBUTE_HEADER_SIZE + 4; if (dwAttributeLength <= dwMaxPossibleAttribSize) { DWORDLONG val; // Move in the high DWORD. val = pIasAttrib->Value.UTCTime.dwHighDateTime; val <<= 32; // Move in the low DWORD. val |= pIasAttrib->Value.UTCTime.dwLowDateTime; // Convert to the UNIX epoch. val -= UNIX_EPOCH; // Convert to seconds. val /= 10000000; IASInsertDWORD(pRadiusAttrib->ValueStart, (DWORD)val); } else { hr = RADIUS_E_PACKET_OVERFLOW; __leave; } } break; case IASTYPE_PROV_SPECIFIC: case IASTYPE_INVALID: default: _ASSERT (0); // // should never reach here // IASTracePrintf ( "Unknown IAS Value type :%d encountered " "while building out-bound packet", static_cast (pIasAttrib->Value.itType) ); __leave; hr = E_FAIL; break; } // end of switch // // check the size against spec // if (dwAttributeLength > (MAX_ATTRIBUTE_LENGTH + ATTRIBUTE_HEADER_SIZE)) { PCWSTR strings[] = { GetClientName() }; IASReportEvent( RADIUS_E_ATTRIBUTE_OVERFLOW, 1, sizeof(pIasAttrib->dwId), strings, &(pIasAttrib->dwId) ); hr = RADIUS_E_ERRORS_OCCURRED; __leave; } // // IAS attribute type matches RADIUS attribute type // pRadiusAttrib->byType = static_cast (pIasAttrib->dwId); // // hold a reference to the signature attribute for future use // if (RADIUS_ATTRIBUTE_SIGNATURE == pIasAttrib->dwId) { m_pOutSignature = pRadiusAttrib; } // // set the length in the packet // *pwAttributeLength = pRadiusAttrib->byLength = dwAttributeLength; // // success // } __finally { } return (hr); } // end of CPacketRadius::FillOutAttributeInfo method //++-------------------------------------------------------------- // // Function: FillClientIPInfo // // Synopsis: This is CPacketARadius class private method // that fills the attribute information for Client // IP address // // Arguments: // [in] PIASATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 1/6/98 // // Called By: CPacketRadius::CreateAttribCollection private method // //---------------------------------------------------------------- HRESULT CPacketRadius::FillClientIPInfo ( PIASATTRIBUTE pIasAttrib ) { _ASSERT (pIasAttrib); // // put in the values now // pIasAttrib->dwId = IAS_ATTRIBUTE_CLIENT_IP_ADDRESS; pIasAttrib->Value.itType = IASTYPE_INET_ADDR; pIasAttrib->Value.InetAddr = m_dwInIPaddress; pIasAttrib->dwFlags = IAS_RECVD_FROM_PROTOCOL; return (S_OK); } // end of CPacketRadius::FillClientIPInfo method //++-------------------------------------------------------------- // // Function: FillClientPortInfo // // Synopsis: This is CPacketARadius class private method // that fills the attribute information for Client // UDP port // // Arguments: // [in] PIASATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 1/6/98 // // Called By: CPacketRadius::CreateAttribCollection private method // //---------------------------------------------------------------- HRESULT CPacketRadius::FillClientPortInfo ( PIASATTRIBUTE pIasAttrib ) { _ASSERT (pIasAttrib); // // put in the values now // pIasAttrib->dwId = IAS_ATTRIBUTE_CLIENT_UDP_PORT; pIasAttrib->Value.itType = IASTYPE_INTEGER; pIasAttrib->Value.Integer = m_wInPort; pIasAttrib->dwFlags = IAS_RECVD_FROM_PROTOCOL; return (S_OK); } // end of CPacketRadius::FillClientPortInfo method //++-------------------------------------------------------------- // // Function: FillPacketHeaderInfo // // Synopsis: This is CPacketARadius class private method // that fills the attribute information for // RADIUS packet header // // Arguments: // [in] PIASATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 1/6/98 // // Called By: CPacketRadius::CreateAttribCollection private method // //---------------------------------------------------------------- HRESULT CPacketRadius::FillPacketHeaderInfo ( PIASATTRIBUTE pIasAttrib ) { HRESULT hr = S_OK; _ASSERT (pIasAttrib); // // allocate dynamic memory for the packet header // pIasAttrib->Value.OctetString.lpValue = reinterpret_cast (CoTaskMemAlloc (PACKET_HEADER_SIZE)); if (NULL == pIasAttrib->Value.OctetString.lpValue) { IASTracePrintf ( "Unable to allocate dynamic memory for packet header info " "during in-packet processing" ); hr = E_OUTOFMEMORY; } else { // // put in the values now // pIasAttrib->dwId = IAS_ATTRIBUTE_CLIENT_PACKET_HEADER; pIasAttrib->Value.itType = IASTYPE_OCTET_STRING; CopyMemory ( pIasAttrib->Value.OctetString.lpValue, m_pInPacket, PACKET_HEADER_SIZE ); pIasAttrib->Value.OctetString.dwLength = PACKET_HEADER_SIZE; pIasAttrib->dwFlags = IAS_RECVD_FROM_PROTOCOL; } return (hr); } // end of CPacketRadius::FillPacketHeaderInfo method //++-------------------------------------------------------------- // // Function: FillSharedSecretInfo // // Synopsis: This is CPacketARadius class private method // that fills the shared secret that the server // shares with the client from which this request // has been received // // Arguments: // [in] PIASATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 1/6/98 // // Called By: CPacketRadius::CreateAttribCollection private method // //---------------------------------------------------------------- HRESULT CPacketRadius::FillSharedSecretInfo ( PIASATTRIBUTE pIasAttrib ) { BOOL bStatus = FALSE; HRESULT hr = S_OK; _ASSERT ((pIasAttrib) && (m_pIIasClient)); __try { // // get the client secret // DWORD dwSecretSize; const BYTE* SharedSecret = m_pIIasClient->GetSecret(&dwSecretSize); // // allocate dynamic memory for the client secret // pIasAttrib->Value.OctetString.lpValue = reinterpret_cast (CoTaskMemAlloc (dwSecretSize)); if (NULL == pIasAttrib->Value.OctetString.lpValue) { IASTracePrintf ( "Unable to allocate memory for client secret " "during in-packet processing" ); hr = E_OUTOFMEMORY; __leave; } // // put in the values now // pIasAttrib->dwId = IAS_ATTRIBUTE_SHARED_SECRET; pIasAttrib->Value.itType = IASTYPE_OCTET_STRING; CopyMemory ( pIasAttrib->Value.OctetString.lpValue, SharedSecret, dwSecretSize ); pIasAttrib->Value.OctetString.dwLength = dwSecretSize; pIasAttrib->dwFlags = IAS_RECVD_FROM_PROTOCOL; // // success // } __finally { } return (hr); } // end of CPacketRadius::FillSharedSecretInfo method //++-------------------------------------------------------------- // // Function: FillClientVendorType // // Synopsis: This is CPacketARadius class private method // that fills the Client-Vendor-Type information // // Arguments: // [in] PIASATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 3/16/98 // // Called By: CPacketRadius::CreateAttribCollection private method // //---------------------------------------------------------------- HRESULT CPacketRadius::FillClientVendorType ( PIASATTRIBUTE pIasAttrib ) { _ASSERT ((pIasAttrib) && (m_pIIasClient)); // // put in the values now // pIasAttrib->dwId = IAS_ATTRIBUTE_CLIENT_VENDOR_TYPE; pIasAttrib->Value.itType = IASTYPE_INTEGER; pIasAttrib->dwFlags = IAS_RECVD_FROM_PROTOCOL; // // get the client vendor type // LONG lVendorType = m_pIIasClient->GetVendorType(); _ASSERT (SUCCEEDED (hr)); pIasAttrib->Value.Integer = static_cast (lVendorType); return (S_OK); } // end of CPacketRadius::ClientVendorType method //++-------------------------------------------------------------- // // Function: FillClientName // // Synopsis: This is CPacketARadius class private method // that fills the Client-Name information // // Arguments: // [in] PIASATTRIBUTE // // Returns: HRESULT - status // // History: MKarki Created 3/30/98 // // Called By: CPacketRadius::CreateAttribCollection private method // //---------------------------------------------------------------- HRESULT CPacketRadius::FillClientName ( PIASATTRIBUTE pIasAttrib ) { _ASSERT ((pIasAttrib) && (m_pIIasClient)); // Fill in the attribute fields. pIasAttrib->dwId = IAS_ATTRIBUTE_CLIENT_NAME; pIasAttrib->Value.itType = IASTYPE_STRING; pIasAttrib->dwFlags = IAS_RECVD_FROM_PROTOCOL; pIasAttrib->Value.String.pszAnsi = NULL; // Get the client name and length. PCWSTR name = m_pIIasClient->GetClientNameW(); SIZE_T nbyte = (wcslen(name) + 1) * sizeof(WCHAR); // Make a copy. pIasAttrib->Value.String.pszWide = (PWSTR)CoTaskMemAlloc(nbyte); if (!pIasAttrib->Value.String.pszWide) { return E_OUTOFMEMORY; } memcpy(pIasAttrib->Value.String.pszWide, name, nbyte); return S_OK; } //+++------------------------------------------------------------- // // Function: GenerateInSignature // // Synopsis: This is CPacketARadius class public method // that carries out generation of Signature // over the in-bound RADIUS packet // // Arguments: // [out] PBYTE - signature // [in/out] PDWORD - signature size // // Returns: BOOL - status // // History: MKarki Created 1/6/98 // //---------------------------------------------------------------- HRESULT CPacketRadius::GenerateInSignature ( PBYTE pSignatureValue, PDWORD pdwSigSize ) { HRESULT hr = S_OK; PRADIUSPACKET pPacket = reinterpret_cast (m_pInPacket); PATTRIBUTE pSignature = m_pInSignature; _ASSERT (pSignatureValue && pdwSigSize && pSignature); if (*pdwSigSize >= SIGNATURE_SIZE) { // // generate the signature now // hr = InternalSignatureGenerator ( pSignatureValue, pdwSigSize, pPacket, pSignature ); } else { IASTracePrintf ( "Buffer not large enough to hold generated Message Authenticator" ); *pdwSigSize = SIGNATURE_SIZE; hr = E_INVALIDARG; } return (hr); } // end of CPacketRadius::GenerateInSignature method //+++------------------------------------------------------------- // // Function: GenerateOutSignature // // Synopsis: This is CPacketARadius class public method // that carries out generation of Signature // for the outbound RADIUS packet // // Arguments: // [out] PBYTE - signature // [in/out] PDWORD - signature size // // Returns: BOOL - status // // History: MKarki Created 11/18/98 // //---------------------------------------------------------------- HRESULT CPacketRadius::GenerateOutSignature ( PBYTE pSignatureValue, PDWORD pdwSigSize ) { HRESULT hr = S_OK; PRADIUSPACKET pPacket = reinterpret_cast (m_pOutPacket); PATTRIBUTE pSignature = m_pOutSignature; _ASSERT (pSignatureValue && pdwSigSize && pSignature); if (*pdwSigSize >= SIGNATURE_SIZE) { // // generate the signature now // hr = InternalSignatureGenerator ( pSignatureValue, pdwSigSize, pPacket, pSignature ); } else { IASTracePrintf ( "Buffer not large enough to hold generated Message Authenticator" ); *pdwSigSize = SIGNATURE_SIZE; hr = E_INVALIDARG; } return (hr); } // end of CPacketRadius::GenerateOutSignature method //+++------------------------------------------------------------- // // Function: InternalSignatureGenerator // // Synopsis: This is CPacketARadius class public method // that carries out the HMAC-MD5 hash to give the // signature value // // Arguments: // [out] PBYTE - signature // [in/out] PDWORD - signature size // [in] PRADIUSPACKET // // Returns: BOOL - status // // History: MKarki Created 1/6/98 // //---------------------------------------------------------------- HRESULT CPacketRadius::InternalSignatureGenerator ( PBYTE pSignatureValue, PDWORD pdwSigSize, PRADIUSPACKET pPacket, PATTRIBUTE pSignatureAttr ) { BYTE byAuthenticator[AUTHENTICATOR_SIZE]; DWORD dwAuthenticatorSize = AUTHENTICATOR_SIZE; HRESULT hr = S_OK; _ASSERT ( (NULL != pSignatureValue) && (NULL != pdwSigSize) && (NULL != pPacket) && (NULL != pSignatureAttr) && (NULL != m_pIIasClient) ); // // get the In authenticator // hr = GetInAuthenticator (byAuthenticator, &dwAuthenticatorSize); if (FAILED (hr)) { return (hr); } // // get the shared secret // DWORD dwSecretSize; const BYTE* bySecret = m_pIIasClient->GetSecret(&dwSecretSize); // // we will have all zero's in packet for signature generation // ZeroMemory (pSignatureValue, SIGNATURE_SIZE); // // Fixing bug #181029 - MKarki // Don't prepend secret in case of HMAC-MD5 hash // // // carry out the HmacMD5 hashing now // m_pCHashHmacMD5->HashIt ( pSignatureValue, const_cast(bySecret), dwSecretSize, reinterpret_cast (pPacket), PACKET_HEADER_SIZE - AUTHENTICATOR_SIZE, byAuthenticator, AUTHENTICATOR_SIZE, reinterpret_cast (pPacket) + PACKET_HEADER_SIZE, (reinterpret_cast (pSignatureAttr) + ATTRIBUTE_HEADER_SIZE) - (reinterpret_cast (pPacket) + PACKET_HEADER_SIZE), pSignatureValue, SIGNATURE_SIZE, reinterpret_cast (pSignatureAttr) + pSignatureAttr->byLength, reinterpret_cast (reinterpret_cast (pPacket) + ntohs (pPacket->wLength)) - reinterpret_cast (reinterpret_cast (pSignatureAttr) + pSignatureAttr->byLength) ); *pdwSigSize = SIGNATURE_SIZE; return (hr); } // end of CPacketRadius::GenerateInSignature method //++-------------------------------------------------------------- // // Function: IsOutBoundAttribute // // Synopsis: This is CPacketARadius class private method // that checks if this attribute has to be put // in the outbound RADIUS packet // // Arguments: // [in] PACKETTYPE // [in] PIASATTRIBUTE // // Returns: BOOL - status // // History: MKarki Created 1/6/98 // // Called By: CPacketRadius::BuildOutPacket private method // //---------------------------------------------------------------- BOOL CPacketRadius::IsOutBoundAttribute ( PACKETTYPE ePacketType, PIASATTRIBUTE pIasAttribute ) { _ASSERT (pIasAttribute); // Ensure this is a RADIUS attribute ... if (pIasAttribute->dwId < 1 || pIasAttribute->dwId > 255) { return FALSE; } // ... and it's flagged to be sent over the wire. switch (ePacketType) { case ACCESS_ACCEPT: case ACCOUNTING_RESPONSE: return pIasAttribute->dwFlags & IAS_INCLUDE_IN_ACCEPT; case ACCESS_REJECT: return pIasAttribute->dwFlags & IAS_INCLUDE_IN_REJECT; case ACCESS_CHALLENGE: return pIasAttribute->dwFlags & IAS_INCLUDE_IN_CHALLENGE; } // Always return the Proxy-State. return pIasAttribute->dwId == PROXY_STATE_ATTRIB; } HRESULT CPacketRadius::cryptBuffer( BOOL encrypt, BOOL salted, PBYTE buf, ULONG buflen ) const throw () { // Get the shared secret. DWORD secretLen; const BYTE* secret = m_pIIasClient->GetSecret(&secretLen); // Crypt the buffer. IASRadiusCrypt( encrypt, salted, secret, secretLen, m_pInPacket + 4, buf, buflen ); return S_OK; } //++-------------------------------------------------------------- // // Function: GetClient // // Synopsis: This is CPacketARadius class public method // that returns the the Client object // // // Arguments: // [out] IIASClient** // // Returns: HRESULT - status // // History: MKarki Created 3/30/98 // // Called By: // //---------------------------------------------------------------- HRESULT CPacketRadius::GetClient ( /*[out]*/ IIasClient **ppIasClient ) { _ASSERT (ppIasClient); m_pIIasClient->AddRef (); *ppIasClient = m_pIIasClient; return (S_OK); } // end of CPacketRadius::GetClient method