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

396 lines
11 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, Microsoft Corp. All rights reserved.
//
// FILE
//
// logresult.cpp
//
// SYNOPSIS
//
// Defines the function IASRadiusLogResult.
//
///////////////////////////////////////////////////////////////////////////////
#include <radcommon.h>
#include <iastlutl.h>
#include <iasutil.h>
#include <logresult.h>
// Dummy attribute ID for the stringized reason code.
const DWORD IAS_ATTRIBUTE_REASON_STRING = 0xBADF00D;
// An empty string.
WCHAR emptyString[1];
// Create a newly-allocated copy of a string.
PWSTR copyString(PCWSTR sz) throw ()
{
if (sz)
{
// Calculate the number of bytes.
size_t nbyte = (wcslen(sz) + 1) * sizeof(WCHAR);
// Allocate the memory.
PVOID p = LocalAlloc(LMEM_FIXED, nbyte);
if (p)
{
// Copy the string and return.
return (PWSTR)memcpy(p, sz, nbyte);
}
}
// If anything went wrong, return an empty string.
return emptyString;
}
// Frees a string returned by copyString.
void freeString(PWSTR sz) throw ()
{
if (sz != emptyString) { LocalFree(sz); }
}
// Format an integer value.
PWSTR formatInteger(DWORD value) throw ()
{
WCHAR buffer[11], *p = buffer + 10;
*p = L'\0';
do { *--p = L'0' + (WCHAR)(value % 10); } while (value /= 10);
return copyString(p);
}
// Format a parameter value.
PWSTR formatParameter(DWORD value) throw ()
{
WCHAR buffer[13], *p = buffer + 12;
*p = L'\0';
do { *--p = L'0' + (WCHAR)(value % 10); } while (value /= 10);
*--p = L'%';
*--p = L'%';
return copyString(p);
}
// Format the IAS_ATTRIBUTE_PROVIDER_TYPE value.
PWSTR formatProviderType(DWORD type) throw ()
{
switch (type)
{
case IAS_PROVIDER_WINDOWS:
return formatParameter(IASP_PROVIDER_WINDOWS);
case IAS_PROVIDER_RADIUS_PROXY:
return formatParameter(IASP_PROVIDER_RADIUS_PROXY);
default:
return formatParameter(IASP_NONE);
}
}
// Format the IAS_ATTRIBUTE_AUTHENTICATION_TYPE value.
PWSTR formatAuthType(DWORD type) throw ()
{
switch (type)
{
case IAS_AUTH_PAP:
return copyString(L"PAP");
case IAS_AUTH_MD5CHAP:
return copyString(L"MD5-CHAP");
case IAS_AUTH_MSCHAP:
return copyString(L"MS-CHAPv1");
case IAS_AUTH_MSCHAP2:
return copyString(L"MS-CHAPv2");
case IAS_AUTH_EAP:
return copyString(L"EAP");
case IAS_AUTH_ARAP:
return copyString(L"ARAP");
case IAS_AUTH_NONE:
return copyString(L"Unauthenticated");
case IAS_AUTH_CUSTOM:
return copyString(L"Extension");
case IAS_AUTH_MSCHAP_CPW:
return copyString(L"MS-CHAPv1 CPW");
case IAS_AUTH_MSCHAP2_CPW:
return copyString(L"MS-CHAPv2 CPW");
default:
return formatInteger(type);
}
}
// Format the NAS-Port-Type value.
PWSTR formatPortType(DWORD type) throw ()
{
switch (type)
{
case 0:
return copyString(L"Async");
case 1:
return copyString(L"Sync");
case 2:
return copyString(L"ISDN Sync");
case 3:
return copyString(L"ISDN Async V.120");
case 4:
return copyString(L"ISDN Async V.110");
case 5:
return copyString(L"Virtual");
case 6:
return copyString(L"PIAFS");
case 7:
return copyString(L"HDLC Clear Channel");
case 8:
return copyString(L"X.25");
case 9:
return copyString(L"X.75");
case 10:
return copyString(L"G.3 Fax");
case 11:
return copyString(L"SDSL");
case 12:
return copyString(L"ADSL-CAP");
case 13:
return copyString(L"ADSL-DMT");
case 14:
return copyString(L"IDSL");
case 15:
return copyString(L"Ethernet");
case 16:
return copyString(L"xDSL");
case 17:
return copyString(L"Cable");
case 18:
return copyString(L"Wireless - Other");
case 19:
return copyString(L"Wireless - IEEE 802.11");
default:
return formatInteger(type);
}
}
PWSTR formatAttribute(
IRequest* request,
IAttributesRaw* raw,
DWORD dwId,
DWORD defaultValue
) throw ()
{
// Is this one of the 'special' attributes ?
switch (dwId)
{
case IAS_ATTRIBUTE_REASON_CODE:
{
LONG reason = 0;
request->get_Reason(&reason);
return formatInteger(reason);
}
case IAS_ATTRIBUTE_REASON_STRING:
{
LONG reason = 0;
request->get_Reason(&reason);
return formatParameter(reason + 0x1000);
}
}
// Get a single attribute with the give ID.
DWORD posCount = 1;
ATTRIBUTEPOSITION pos;
raw->GetAttributes(&posCount, &pos, 1, &dwId);
// If it's not present, use the defaultValue parameter.
if (!posCount) { return formatParameter(defaultValue); }
// Otherwise, save and release.
const IASVALUE& val = pos.pAttribute->Value;
IASAttributeRelease(pos.pAttribute);
// Format the value.
switch (val.itType)
{
case IASTYPE_ENUM:
case IASTYPE_INTEGER:
{
switch (dwId)
{
case RADIUS_ATTRIBUTE_NAS_PORT_TYPE:
return formatPortType(val.Enumerator);
case IAS_ATTRIBUTE_PROVIDER_TYPE:
return formatProviderType(val.Enumerator);
case IAS_ATTRIBUTE_AUTHENTICATION_TYPE:
return formatAuthType(val.Enumerator);
// Fall through.
}
return formatInteger(val.Integer);
}
case IASTYPE_INET_ADDR:
{
WCHAR buffer[16];
return copyString(ias_inet_htow(val.InetAddr, buffer));
}
case IASTYPE_STRING:
{
if (val.String.pszWide)
{
return copyString(val.String.pszWide);
}
else
{
USES_CONVERSION;
return copyString(A2W(val.String.pszAnsi));
}
}
case IASTYPE_OCTET_STRING:
{
return copyString(IAS_OCT2WIDE(val.OctetString));
}
}
return emptyString;
}
///////
// An InsertionString definition consists of the attribute ID and a
// defaultValue to be used if the attribute isn't present.
///////
struct InsertionString
{
DWORD attrID;
DWORD defaultValue;
};
// Insertion strings for an Access-Accept.
InsertionString ACCEPT_ATTRS[] =
{
{ RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
{ RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
{ IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_NP_NAME, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_AUTHENTICATION_TYPE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_EAP_FRIENDLY_NAME, IASP_UNDETERMINED },
{ ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
};
// Insertion strings for an Access-Reject.
InsertionString REJECT_ATTRS[] =
{
{ RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
{ RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_CALLED_STATION_ID, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
{ IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_NP_NAME, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_AUTHENTICATION_TYPE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_EAP_FRIENDLY_NAME, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REASON_CODE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REASON_STRING, IASP_UNDETERMINED },
{ ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
};
// Insertion strings for a discarded request.
InsertionString DISCARD_ATTRS[] =
{
{ RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
{ RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_CALLED_STATION_ID, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
{ RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
{ IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
{ IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REASON_CODE, IASP_UNDETERMINED },
{ IAS_ATTRIBUTE_REASON_STRING, IASP_UNDETERMINED },
{ ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
};
VOID
WINAPI
IASRadiusLogResult(
IRequest* request,
IAttributesRaw* raw
)
{
// We only care about Access-Requests.
LONG type = 0;
request->get_Request(&type);
if (type != IAS_REQUEST_ACCESS_REQUEST) { return; }
// Determine which response type this is.
request->get_Response(&type);
DWORD eventID;
InsertionString* attrs;
switch (type)
{
case IAS_RESPONSE_ACCESS_ACCEPT:
eventID = IAS_RESPONSE_ACCEPT;
attrs = ACCEPT_ATTRS;
break;
case IAS_RESPONSE_ACCESS_REJECT:
eventID = IAS_RESPONSE_REJECT;
attrs = REJECT_ATTRS;
break;
case IAS_RESPONSE_DISCARD_PACKET:
eventID = IAS_RESPONSE_DISCARD;
attrs = DISCARD_ATTRS;
break;
default:
return;
}
// Format the insertion strings.
PWSTR strings[24];
DWORD numStrings = 0;
for ( ; attrs->attrID != ATTRIBUTE_UNDEFINED; ++attrs, ++numStrings)
{
strings[numStrings] = formatAttribute(
request,
raw,
attrs->attrID,
attrs->defaultValue
);
}
// Report the event.
IASReportEvent(
eventID,
numStrings,
0,
(PCWSTR*)strings,
NULL
);
// Free the insertion strings.
while (numStrings--)
{
freeString(strings[numStrings]);
}
}