Leaked source code of windows server 2003
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.
|
|
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corp. All rights reserved.
//
// FILE
//
// radutil.cpp
//
// SYNOPSIS
//
// This file defines methods for converting attributes to and from
// RADIUS wire format.
//
///////////////////////////////////////////////////////////////////////////////
#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 ) { 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.
DWORD dwErr = IASAttributeAnsiAlloc(const_cast<PIASATTRIBUTE>(&src)); if (dwErr != NO_ERROR) { // functions calling this are exception based
_com_issue_error(HRESULT_FROM_WIN32(dwErr)); }
// 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); } } }
|