windows-nt/Source/XPSP1/NT/net/ias/protocol/radius/client.cpp
2020-09-26 16:20:57 +08:00

703 lines
16 KiB
C++

//#--------------------------------------------------------------
//
// File: client.cpp
//
// Synopsis: Implementation of CClient class methods
//
//
// History: 9/23/97 MKarki Created
//
// Copyright (C) 1997-98 Microsoft Corporation
// All rights reserved.
//
//----------------------------------------------------------------
#include "radcommon.h"
#include "client.h"
#include "iasevent.h"
#include <iasutil.h>
#include <memory>
inline BOOL IsDottedDecimal(PCWSTR sz) throw ()
{
return wcsspn(sz, L"0123456789./") == wcslen(sz);
}
//++--------------------------------------------------------------
//
// Function: CClient
//
// Synopsis: This is the constructor of the Client class
//
// Arguments: NONE
//
// Returns: NONE
//
// History: MKarki Created 9/26/97
//
//----------------------------------------------------------------
CClient::CClient (
VOID
)
: m_adwAddrList (m_adwAddressBuffer),
m_lVendorType (0),
m_bSignatureCheck (FALSE)
{
m_adwAddressBuffer[0].ipAddress = INADDR_NONE;
ZeroMemory (m_szSecret, MAX_SECRET_SIZE + 1);
} // end of CClient constructor
//++--------------------------------------------------------------
//
// Function: ~CClient
//
// Synopsis: This is the destructor of the Client class
//
// Arguments: NONE
//
// Returns: NONE
//
// History: MKarki Created 9/26/97
//
//----------------------------------------------------------------
CClient::~CClient(
VOID
)
{
ClearAddress();
} // end of CClient constructor
//++--------------------------------------------------------------
//
// Function: Init
//
// Synopsis: This is the CClient public method used
// to initialize the object with the
// ISdo interface
//
// Arguments:
// [in] ISdo*
//
// Returns: NONE
//
// History: MKarki Created 9/26/97
//
// Called By: CClients::SetClients public method
//
//----------------------------------------------------------------
STDMETHODIMP
CClient::Init (
ISdo *pISdo
)
{
BOOL bStatus = FALSE;
HRESULT hr = S_OK;
CComVariant varClient;
_ASSERT (pISdo);
//
// get the client address first
//
hr = pISdo->GetProperty (PROPERTY_CLIENT_ADDRESS, &varClient);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain Client Address Property "
"during Client object initialization"
);
hr = E_FAIL;
return (hr);
}
//
// store the address
//
bStatus = SetAddress (varClient);
if (FALSE == bStatus)
{
hr = E_FAIL;
return (hr);
}
varClient.Clear ();
//
// get the client address first
//
hr = pISdo->GetProperty (PROPERTY_CLIENT_SHARED_SECRET, &varClient);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain Client shared secret Property "
"during Client object initialization"
);
return (hr);
}
//
// now store away the shared secret
//
bStatus = SetSecret (varClient);
if (FALSE == bStatus)
{
hr = E_FAIL;
return (hr);
}
varClient.Clear ();
//
// get signature information
//
hr = pISdo->GetProperty (PROPERTY_CLIENT_REQUIRE_SIGNATURE, &varClient);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain Client Signature Property "
"during Client object initialization"
);
return (hr);
}
//
// store away the signature information
//
bStatus = SetSignatureFlag (varClient);
if (FALSE == bStatus)
{
hr = E_FAIL;
return (hr);
}
varClient.Clear ();
//
// get the client NAS Manufacturer information
//
hr = pISdo->GetProperty (PROPERTY_CLIENT_NAS_MANUFACTURER, &varClient);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain Client NAS Manufacturer Property "
"during Client object initialization"
);
return (hr);
}
//
// store away the Nas Manufacturer information
//
bStatus = SetVendorType (varClient);
if (FALSE == bStatus)
{
hr = E_FAIL;
return (hr);
}
varClient.Clear ();
//
// get the client name
//
hr = pISdo->GetProperty (PROPERTY_SDO_NAME, &varClient);
if (FAILED (hr))
{
IASTracePrintf (
"Unable to obtain SDO Name Property "
"during Client object initialization"
);
return (hr);
}
//
// store away the client name information
//
bStatus = SetClientName (varClient);
if (FALSE == bStatus)
{
hr = E_FAIL;
return (hr);
}
varClient.Clear ();
return (hr);
} // end of CClient::Init method
void CClient::ClearAddress() throw ()
{
if (m_adwAddrList != m_adwAddressBuffer)
{
delete[] m_adwAddrList;
}
m_adwAddressBuffer[0].ipAddress = INADDR_NONE;
m_adwAddrList = m_adwAddressBuffer;
}
//++--------------------------------------------------------------
//
// Function: SetAddress
//
// Synopsis: This is the CClient private method used
// to set the Client IP address
//
// Arguments: VARIANT - holds the IP address
//
// Returns: status
//
// History: MKarki Created 2/3/98
//
// Called By: CClient::Init method
//
//----------------------------------------------------------------
BOOL
CClient::SetAddress (
VARIANT varAddress
)
{
_ASSERT (VT_BSTR == varAddress.vt);
//
// copy the address into the CClient Object
//
lstrcpy (
m_wszClientAddress,
reinterpret_cast <LPCWSTR> (varAddress.pbstrVal)
);
return (TRUE);
} // end of CClient::SetAddress method
//++--------------------------------------------------------------
//
// Function: ResolveAddress
//
// Synopsis: This is the CClient public method used
// to resolve the Client IP address obtained previously
// which could be a DNS name or dotted octed
//
// Arguments: VOID
//
// Returns: HRESULT
//
// History: MKarki Created 2/3/98
//
// Called By: CClient::Init method
//
//----------------------------------------------------------------
STDMETHODIMP
CClient::ResolveAddress (
VOID
)
{
INT iRetVal = 0;
PHOSTENT pHostent = NULL;
BOOL bDNSName = FALSE;
BOOL bRetVal = TRUE;
CHAR szClient[MAX_CLIENT_SIZE +1];
HRESULT hr = S_OK;
// Clear any existing addresses.
ClearAddress();
__try
{
//
// check if this address is dotted octet or DNS name
//
if (!IsDottedDecimal(m_wszClientAddress))
{
//
// we probably have a DNS name so
// get the address information
//
pHostent = IASGetHostByName (m_wszClientAddress);
if (NULL == pHostent)
{
IASTracePrintf (
"Unable to get client IP Address through IASGetHostByName () "
"during client address resolution"
);
//
// log an event here
//
PCWSTR strings[] = { m_wszClientAddress, m_wszClientName };
int data = WSAGetLastError();
IASReportEvent(
RADIUS_E_CANT_RESOLVE_CLIENT_NAME,
2,
sizeof(data),
strings,
&data
);
hr = E_FAIL;
__leave;
}
//
// store addresses in host byte order
//
size_t count;
for (count = 0; pHostent->h_addr_list[count]; ++count) { }
if (count > 1)
{
m_adwAddrList = new (std::nothrow) Address[count + 1];
if (!m_adwAddrList)
{
m_adwAddrList = m_adwAddressBuffer;
hr = E_OUTOFMEMORY;
__leave;
}
}
for (count = 0; pHostent->h_addr_list[count]; ++count)
{
m_adwAddrList[count].ipAddress =
ntohl(*(PDWORD)pHostent->h_addr_list[count]);
m_adwAddrList[count].width = 32;
}
m_adwAddrList[count].ipAddress = INADDR_NONE;
}
else
{
//
// this could be a dotted-octet address
//
ULONG width;
m_adwAddressBuffer[0].ipAddress = IASStringToSubNetW(
m_wszClientAddress,
&m_adwAddressBuffer[0].width
);
if (INADDR_NONE == m_adwAddressBuffer[0].ipAddress)
{
IASTracePrintf (
"Unable to get client IP Address through inet_addr () "
"during client address resolution"
);
//
// log an event here
//
PCWSTR strings[] = { m_wszClientAddress, m_wszClientName };
IASReportEvent(
RADIUS_E_INVALID_CLIENT_ADDRESS,
2,
0,
strings,
NULL
);
hr = E_FAIL;
__leave;
}
// Terminate the array.
m_adwAddressBuffer[1].ipAddress = INADDR_NONE;
}
}
__finally
{
if (bRetVal)
{
IASTracePrintf (
"Resolved Client:%S, to IP address:%ul", m_wszClientAddress, m_adwAddrList[0].ipAddress
);
}
if (pHostent) { LocalFree(pHostent); }
}
return (hr);
} // end of CClient::ResolveAddress method
//++--------------------------------------------------------------
//
// Function: SetSecret
//
// Synopsis: This is the CClient private method used
// to set the shared secret
//
// Arguments: VARIANT - holds the secret as a BSTR
//
// Returns: status
//
// History: MKarki Created 2/3/98
//
// Called By: CClient::Init method
//
//----------------------------------------------------------------
BOOL
CClient::SetSecret (
VARIANT varSecret
)
{
INT iRetVal = 0;
_ASSERT (VT_BSTR == varSecret.vt);
iRetVal = ::WideCharToMultiByte (
CP_ACP,
0,
reinterpret_cast <LPCWSTR> (varSecret.pbstrVal),
-1,
m_szSecret,
MAX_SECRET_SIZE,
NULL,
NULL
);
if (0 == iRetVal)
{
IASTracePrintf (
"Unable to convert client shared secret to multi-byte string "
"during Client processing"
);
return (FALSE);
}
//
// set secret size
//
m_dwSecretSize = strlen (m_szSecret);
return (TRUE);
} // end of CClient::SetSecret method
//++--------------------------------------------------------------
//
// Function: SetClientName
//
// Synopsis: This is the CClient private method used
// to set the Client SDO Name
//
// Arguments: VARIANT - holds the secret as a BSTR
//
// Returns: status
//
// History: MKarki Created 2/3/98
//
// Called By: CClient::Init method
//
//----------------------------------------------------------------
BOOL
CClient::SetClientName (
VARIANT varClientName
)
{
INT iRetVal = 0;
_ASSERT (VT_BSTR == varClientName.vt);
lstrcpy (m_wszClientName, (const PWCHAR)(varClientName.pbstrVal));
return (TRUE);
} // end of CClient::SetSecret method
//++--------------------------------------------------------------
//
// Function: SetSignatureFlag
//
// Synopsis: This is the CClient private method used
// to set the Client Signature flag
//
// Arguments: VARIANT - holds the signature as a boolean
//
// Returns: status
//
// History: MKarki Created 2/3/98
//
// Called By: CClient::Init method
//
//----------------------------------------------------------------
BOOL
CClient::SetSignatureFlag (
VARIANT varSigFlag
)
{
_ASSERT (VT_BOOL == varSigFlag.vt);
if (0 == varSigFlag.boolVal)
{
m_bSignatureCheck = FALSE;
}
else
{
m_bSignatureCheck = TRUE;
}
return (TRUE);
} // end of CClient::SetSignatureFlag method
//++--------------------------------------------------------------
//
// Function: SetVendorType
//
// Synopsis: This is the CClient private method used
// to set the Client Vendor Type
//
// Arguments: VARIANT - holds the Vendor Type
//
// Returns: status
//
// History: MKarki Created 3/16/98
//
// Called By: CClient::Init method
//
//----------------------------------------------------------------
BOOL
CClient::SetVendorType (
VARIANT varVendorType
)
{
_ASSERT (VT_I4 == varVendorType.vt);
m_lVendorType = varVendorType.lVal;
return (TRUE);
} // end of CClient::SetVendorType method
//++--------------------------------------------------------------
//
// Function: GetSecret
//
// Synopsis: This is the CClient public method used
// to get the shared secret
//
// Arguments:
// [out] PBYTE - Secret
// [in/out] - buffer size
//
// Returns: HRESULT
//
// History: MKarki Created 9/26/97
//
//----------------------------------------------------------------
STDMETHODIMP
CClient::GetSecret(
PBYTE pbySecret,
PDWORD pdwSecretSize
)
{
HRESULT hr = S_OK;
_ASSERT (pdwSecretSize != NULL);
//
// check if there is enough space in the array
// provided
//
if (*pdwSecretSize >= m_dwSecretSize)
{
_ASSERT (pbySecret != NULL);
::CopyMemory (pbySecret, m_szSecret, m_dwSecretSize);
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
*pdwSecretSize = m_dwSecretSize;
return (hr);
} // end of CClient::GetSecret method
//++--------------------------------------------------------------
//
// Function: GetAddress
//
// Synopsis: This is the CClient public method used
// to get the address from the object
//
// Arguments: PDWORD
//
// Returns: HRESULT
//
// History: MKarki Created 3/20/98
//
// Called By: CClients::SetClients method
//
//----------------------------------------------------------------
STDMETHODIMP
CClient::GetAddress (
PDWORD pdwAddress
)
{
_ASSERT (pdwAddress);
*pdwAddress = m_adwAddrList[0].ipAddress;
return (S_OK);
} // end of CClient::GetAddress method
//++--------------------------------------------------------------
//
// Function: NeedSignatureCheck
//
// Synopsis: This is the CClient public method used
// to check if signature is required
//
// Arguments: PBOOL
//
// Returns: HRESULT
//
// History: MKarki Created 3/20/98
//
// Called By:
//
//----------------------------------------------------------------
STDMETHODIMP
CClient::NeedSignatureCheck (
PBOOL pbCheckNeeded
)
{
_ASSERT (pbCheckNeeded);
*pbCheckNeeded = m_bSignatureCheck;
return (S_OK);
} // end of CClient::NeedSignatureCheck method
//++--------------------------------------------------------------
//
// Function: GetVendorType
//
// Synopsis: This is the CClient public method used
// to get the VendorType from the object
//
// Arguments: PLONG
//
// Returns: HRESULT
//
// History: MKarki Created 3/20/98
//
// Called By:
//
//----------------------------------------------------------------
STDMETHODIMP
CClient::GetVendorType (
PLONG plVendorType
)
{
_ASSERT (plVendorType);
*plVendorType = m_lVendorType;
return (S_OK);
} // end of CClient::GetAddress method