241 lines
5.8 KiB
C++
241 lines
5.8 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) 1998, Microsoft Corp. All rights reserved.
|
||
|
//
|
||
|
// FILE
|
||
|
//
|
||
|
// radutil.cpp
|
||
|
//
|
||
|
// SYNOPSIS
|
||
|
//
|
||
|
// This file defines methods for converting attributes to and from
|
||
|
// RADIUS wire format.
|
||
|
//
|
||
|
// MODIFICATION HISTORY
|
||
|
//
|
||
|
// 03/08/1998 Original version.
|
||
|
// 08/11/1998 Packing functions moved to iasutil.
|
||
|
// Set pszWide to NULL when initializing IASTYPE_STRING.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include <radcommon.h>
|
||
|
#include <iasutil.h>
|
||
|
#include <iastlutl.h>
|
||
|
|
||
|
#include <radutil.h>
|
||
|
|
||
|
//////////
|
||
|
// The offset between the UNIX and NT epochs.
|
||
|
//////////
|
||
|
const DWORDLONG UNIX_EPOCH = 116444736000000000ui64;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// METHOD
|
||
|
//
|
||
|
// RadiusUtil::decode
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// Decodes an octet string into a newly-allocated IAS Attribute of the
|
||
|
// specified type.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
PIASATTRIBUTE RadiusUtil::decode(
|
||
|
IASTYPE dstType,
|
||
|
PBYTE src,
|
||
|
ULONG srclen
|
||
|
)
|
||
|
{
|
||
|
// Allocate an attribute to hold the decoded value.
|
||
|
IASTL::IASAttribute dst(true);
|
||
|
|
||
|
// Switch based on the destination type.
|
||
|
switch (dstType)
|
||
|
{
|
||
|
case IASTYPE_BOOLEAN:
|
||
|
{
|
||
|
if (srclen != 4) { _com_issue_error(E_INVALIDARG); }
|
||
|
dst->Value.Boolean = IASExtractDWORD(src) ? TRUE : FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_INTEGER:
|
||
|
case IASTYPE_ENUM:
|
||
|
case IASTYPE_INET_ADDR:
|
||
|
{
|
||
|
if (srclen != 4) { _com_issue_error(E_INVALIDARG); }
|
||
|
dst->Value.Integer = IASExtractDWORD(src);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_UTC_TIME:
|
||
|
{
|
||
|
if (srclen != 4) { _com_issue_error(E_INVALIDARG); }
|
||
|
|
||
|
DWORDLONG val;
|
||
|
|
||
|
// Extract the UNIX time.
|
||
|
val = IASExtractDWORD(src);
|
||
|
|
||
|
// Convert from seconds to 100 nsec intervals.
|
||
|
val *= 10000000;
|
||
|
|
||
|
// Shift to the NT epoch.
|
||
|
val += 116444736000000000ui64;
|
||
|
|
||
|
// Split into the high and low DWORDs.
|
||
|
dst->Value.UTCTime.dwLowDateTime = (DWORD)val;
|
||
|
dst->Value.UTCTime.dwHighDateTime = (DWORD)(val >> 32);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_STRING:
|
||
|
{
|
||
|
dst.setString(srclen, src);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_OCTET_STRING:
|
||
|
case IASTYPE_PROV_SPECIFIC:
|
||
|
{
|
||
|
dst.setOctetString(srclen, src);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// All went well, so set type attribute type ...
|
||
|
dst->Value.itType = dstType;
|
||
|
|
||
|
// ... and return.
|
||
|
return dst.detach();
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// METHOD
|
||
|
//
|
||
|
// RadiusUtil::getEncodedSize
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// Returns the size in bytes of the IASATTRIBUTE when converted to RADIUS
|
||
|
// wire format. This does NOT include the attribute header.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
ULONG RadiusUtil::getEncodedSize(
|
||
|
const IASATTRIBUTE& src
|
||
|
) throw ()
|
||
|
{
|
||
|
switch (src.Value.itType)
|
||
|
{
|
||
|
case IASTYPE_BOOLEAN:
|
||
|
case IASTYPE_INTEGER:
|
||
|
case IASTYPE_ENUM:
|
||
|
case IASTYPE_INET_ADDR:
|
||
|
case IASTYPE_UTC_TIME:
|
||
|
{
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_STRING:
|
||
|
{
|
||
|
// Convert the string to ANSI so we can count octets.
|
||
|
IASAttributeAnsiAlloc(const_cast<PIASATTRIBUTE>(&src));
|
||
|
|
||
|
// Allow for NULL strings and don't count the terminator.
|
||
|
return src.Value.String.pszAnsi ? strlen(src.Value.String.pszAnsi)
|
||
|
: 0;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_OCTET_STRING:
|
||
|
case IASTYPE_PROV_SPECIFIC:
|
||
|
{
|
||
|
return src.Value.OctetString.dwLength;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// All other types have no wire representation.
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// METHOD
|
||
|
//
|
||
|
// RadiusUtil::encode
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// Encodes the IASATTRIBUTE into RADIUS wire format and copies the value
|
||
|
// to the buffer pointed to by 'dst'. The caller should ensure that the
|
||
|
// destination buffer is large enough by first calling getEncodedSize.
|
||
|
// This method only encodes the attribute value, not the header.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
void RadiusUtil::encode(
|
||
|
PBYTE dst,
|
||
|
const IASATTRIBUTE& src
|
||
|
) throw ()
|
||
|
{
|
||
|
// Switch based on the source's type.
|
||
|
switch (src.Value.itType)
|
||
|
{
|
||
|
case IASTYPE_BOOLEAN:
|
||
|
{
|
||
|
IASInsertDWORD(dst, (src.Value.Boolean ? 1 : 0));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_INTEGER:
|
||
|
case IASTYPE_ENUM:
|
||
|
case IASTYPE_INET_ADDR:
|
||
|
{
|
||
|
IASInsertDWORD(dst, src.Value.Integer);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_UTC_TIME:
|
||
|
{
|
||
|
DWORDLONG val;
|
||
|
|
||
|
// Move in the high DWORD.
|
||
|
val = src.Value.UTCTime.dwHighDateTime;
|
||
|
val <<= 32;
|
||
|
|
||
|
// Move in the low DWORD.
|
||
|
val |= src.Value.UTCTime.dwLowDateTime;
|
||
|
|
||
|
// Convert to the UNIX epoch.
|
||
|
val -= UNIX_EPOCH;
|
||
|
|
||
|
// Convert to seconds.
|
||
|
val /= 10000000;
|
||
|
|
||
|
IASInsertDWORD(dst, (DWORD)val);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_STRING:
|
||
|
{
|
||
|
const BYTE* p = (const BYTE*)src.Value.String.pszAnsi;
|
||
|
|
||
|
// Don't use strcpy since we don't want the null terminator.
|
||
|
if (p) while (*p) *dst++ = *p++;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IASTYPE_OCTET_STRING:
|
||
|
case IASTYPE_PROV_SPECIFIC:
|
||
|
{
|
||
|
memcpy(dst,
|
||
|
src.Value.OctetString.lpValue,
|
||
|
src.Value.OctetString.dwLength);
|
||
|
}
|
||
|
}
|
||
|
}
|