You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2692 lines
75 KiB
2692 lines
75 KiB
//#--------------------------------------------------------------
|
|
//
|
|
// 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<MAX_PACKET_SIZE, task_allocator> 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 <LPVOID> (m_pInPacket)
|
|
);
|
|
hr = RADIUS_E_ERRORS_OCCURRED;
|
|
__leave;
|
|
}
|
|
|
|
pPacket = reinterpret_cast <PRADIUSPACKET> (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 <PRADIUSPACKET> (m_pInPacket);
|
|
|
|
//
|
|
// get a pointer to the packet end
|
|
//
|
|
pPacketEnd = reinterpret_cast <PRADIUSPACKET> (
|
|
reinterpret_cast <PBYTE> (pPacketStart)
|
|
+ m_wInPacketLength
|
|
);
|
|
//
|
|
// go through the attributes once, to verify they are of correct
|
|
// length
|
|
//
|
|
pAttrib = reinterpret_cast <PATTRIBUTE> (pPacketStart->AttributeStart);
|
|
|
|
const DWORD dwMinAttribOffset = sizeof (ATTRIBUTE) - sizeof (BYTE);
|
|
|
|
while (static_cast <PVOID> (
|
|
reinterpret_cast <PBYTE> (pAttrib) +
|
|
dwMinAttribOffset
|
|
) <=
|
|
static_cast <PVOID> (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 <LPVOID> (m_pInPacket)
|
|
);
|
|
hr = RADIUS_E_ERRORS_OCCURRED;
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// move to the next attribute
|
|
//
|
|
pAttrib = reinterpret_cast <PATTRIBUTE> (
|
|
reinterpret_cast <PBYTE> (pAttrib) +
|
|
pAttrib->byLength
|
|
);
|
|
//
|
|
// count the attributes
|
|
//
|
|
dwAttribCount++;
|
|
}
|
|
|
|
//
|
|
// if the attributes don't addup to end of packet
|
|
//
|
|
if (static_cast <PVOID> (pAttrib) != static_cast <PVOID> (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 <LPVOID> (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 <PRADIUSPACKET>
|
|
(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 <PATTRIBUTEPOSITION> (
|
|
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 <PIASATTRIBUTE*> (
|
|
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 <PATTRIBUTE> (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 <PACKETTYPE> (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 <PATTRIBUTE> (
|
|
reinterpret_cast <PBYTE> (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 <PRADIUSPACKET> (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 <LPVOID> (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 <LPVOID> (m_pInPacket)
|
|
);
|
|
hr = RADIUS_E_ERRORS_OCCURRED;
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// verify that the PACKET code is correct
|
|
//
|
|
if (
|
|
((ACCESS_REQUEST == static_cast <PACKETTYPE> (pPacket->byCode)) &&
|
|
(AUTH_PORTTYPE != GetPortType ()))
|
|
||
|
|
((ACCOUNTING_REQUEST == static_cast<PACKETTYPE>(pPacket->byCode)) &&
|
|
(ACCT_PORTTYPE != GetPortType ()))
|
|
||
|
|
(((ACCESS_REQUEST != static_cast<PACKETTYPE>(pPacket->byCode))) &&
|
|
((ACCOUNTING_REQUEST != static_cast<PACKETTYPE>(pPacket->byCode))))
|
|
)
|
|
{
|
|
|
|
//
|
|
// log error and generate audit event
|
|
//
|
|
IASTracePrintf (
|
|
"UnSupported Packet type:%d on this port",
|
|
static_cast <INT> (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 <LPVOID> (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 <PBYTE> (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 <PRADIUSPACKET>(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 <PRADIUSPACKET> (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 <PRADIUSPACKET>
|
|
(m_pInPacket);
|
|
|
|
return (static_cast <PACKETTYPE> (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 <PRADIUSPACKET> (m_pOutPacket);
|
|
|
|
return (static_cast <PACKETTYPE> (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 <PRADIUSPACKET>
|
|
(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 <PRADIUSPACKET> (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 <PBYTE> (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 <PRADIUSPACKET> (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 <PBYTE> (pOutPacket)) + dwPacketLength;
|
|
|
|
//
|
|
// goto start of attributes
|
|
//
|
|
pAttribStart = reinterpret_cast <PATTRIBUTE>
|
|
(pOutPacket->AttributeStart);
|
|
|
|
//
|
|
// Fix for Bug #190523 - 06/26/98 - MKarki
|
|
// we shouldn't be taking diff of PUNINTs
|
|
//
|
|
dwMaxPossibleAttribLength = static_cast <DWORD> (
|
|
reinterpret_cast<PBYTE> (pPacketEnd) -
|
|
reinterpret_cast<PBYTE> (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 <PBYTE> (pAttribStart) +
|
|
wAttributeLength;
|
|
pAttribStart = reinterpret_cast <PATTRIBUTE> (pTemp);
|
|
|
|
if ((reinterpret_cast <PBYTE> (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 <PBYTE> (pAttribStart)) -
|
|
(reinterpret_cast <PBYTE> (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 <PRADIUSPACKET> (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 <PRADIUSPACKET> (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 <PBYTE> (pPacket),
|
|
dwPacketHeaderSize,
|
|
pInAuthenticator,
|
|
AUTHENTICATOR_SIZE,
|
|
pPacket->AttributeStart,
|
|
dwAttributesLength,
|
|
const_cast<BYTE*>(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 <DWORD>
|
|
(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 <PCHAR>
|
|
(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 <PBYTE> (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 <DWORD> (pRadiusAttrib->byType)
|
|
);
|
|
|
|
reportMalformed();
|
|
|
|
m_pCReportEvent->Process (
|
|
RADIUS_MALFORMED_PACKET,
|
|
GetInCode (),
|
|
m_wInPacketLength,
|
|
m_dwInIPaddress,
|
|
NULL,
|
|
static_cast <LPVOID> (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 <PBYTE>
|
|
(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 <PBYTE>
|
|
(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 <DWORD> (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 <BYTE> (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 <PBYTE> (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 <PBYTE> (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 <IAS_INTEGER> (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 <PRADIUSPACKET> (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 <PRADIUSPACKET> (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<BYTE*>(bySecret),
|
|
dwSecretSize,
|
|
reinterpret_cast <PBYTE> (pPacket),
|
|
PACKET_HEADER_SIZE - AUTHENTICATOR_SIZE,
|
|
byAuthenticator,
|
|
AUTHENTICATOR_SIZE,
|
|
reinterpret_cast <PBYTE> (pPacket) + PACKET_HEADER_SIZE,
|
|
(reinterpret_cast <PBYTE> (pSignatureAttr) + ATTRIBUTE_HEADER_SIZE) -
|
|
(reinterpret_cast <PBYTE> (pPacket) + PACKET_HEADER_SIZE),
|
|
pSignatureValue,
|
|
SIGNATURE_SIZE,
|
|
reinterpret_cast <PBYTE> (pSignatureAttr) + pSignatureAttr->byLength,
|
|
reinterpret_cast <PBYTE> (reinterpret_cast <PBYTE> (pPacket) +
|
|
ntohs (pPacket->wLength)) -
|
|
reinterpret_cast <PBYTE> (reinterpret_cast <PBYTE>(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
|