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.
224 lines
4.8 KiB
224 lines
4.8 KiB
//=============================================================================
|
|
//
|
|
// MODULE: ASN1Base.cxx
|
|
//
|
|
// Description:
|
|
//
|
|
// Implementation of the ASN1ParserBase class
|
|
//
|
|
// Modification History
|
|
//
|
|
// Mark Pustilnik Date: 06/09/02 - created
|
|
//
|
|
//=============================================================================
|
|
|
|
#include "ASN1Parser.hxx"
|
|
|
|
//
|
|
// For a frame which starts with 6a 82 01 30 ... (long form)
|
|
//
|
|
// 82 (*(Frame+1)) indicates "long form" where Size is 2 (0x82 & 0x7F)
|
|
// and the return value is ( 0x01 << 8 ) | 0x30 = 0x130
|
|
//
|
|
// For a frame which starts with 6a 30 ... (short form)
|
|
//
|
|
// the return value is simply 0x30
|
|
//
|
|
|
|
DWORD
|
|
ASN1ParserBase::DataLength(
|
|
IN ASN1FRAME * Frame
|
|
)
|
|
{
|
|
LPBYTE LengthPortion = Frame->Address + 1;
|
|
|
|
if ( *LengthPortion & 0x80 ) // long form
|
|
{
|
|
USHORT i;
|
|
DWORD Sum = 0;
|
|
BYTE Size = *LengthPortion & 0x7F;
|
|
|
|
for ( i = 1; i <= Size; i++ )
|
|
{
|
|
Sum <<= 8;
|
|
Sum |= *(LengthPortion + i);
|
|
}
|
|
|
|
return Sum;
|
|
}
|
|
else // short form
|
|
{
|
|
return *LengthPortion;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calculates the length of the length header in either short or long form
|
|
// Returns '3' for "82 01 30"
|
|
// Returns '1' for "30"
|
|
//
|
|
|
|
ULONG
|
|
ASN1ParserBase::HeaderLength(
|
|
IN ULPBYTE Address
|
|
)
|
|
{
|
|
if ( *Address & 0x80 )
|
|
{
|
|
//
|
|
// If long form, assign size to value of bits 7-1
|
|
//
|
|
|
|
return ( 1 + *Address & 0x7F);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Short form only takes one octet
|
|
//
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Verifies that the frame is pointing at the type of item we expect by
|
|
// performing a descriptor comparison, then moves past the descriptor and
|
|
// the length header. The caller uses this to point the frame at the next
|
|
// item to be parsed.
|
|
//
|
|
|
|
DWORD
|
|
ASN1ParserBase::VerifyAndSkipHeader(
|
|
IN OUT ASN1FRAME * Frame
|
|
)
|
|
{
|
|
DWORD dw;
|
|
|
|
//
|
|
// Check both optional descriptors associated with this frame
|
|
//
|
|
|
|
BYTE Descriptors[2] = { m_Descriptor, m_AppDescriptor };
|
|
|
|
for ( ULONG i = 0; i < ARRAY_COUNT( Descriptors ); i++ )
|
|
{
|
|
if ( Descriptors[i] != 0 )
|
|
{
|
|
//
|
|
// Verify the descriptor and bail on mismatch
|
|
//
|
|
|
|
if ( *Frame->Address != Descriptors[i] )
|
|
{
|
|
dw = ERROR_INVALID_USER_BUFFER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Skip over the descriptor
|
|
//
|
|
|
|
Frame->Address++;
|
|
|
|
//
|
|
// Skip over the length header
|
|
//
|
|
|
|
Frame->Address += HeaderLength( Frame->Address );
|
|
}
|
|
}
|
|
|
|
dw = ERROR_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
return dw;
|
|
}
|
|
|
|
//
|
|
// Displays the value of the unit, mapping between the ASN.1 encoding and the
|
|
// actual parsed-out value as necessary
|
|
//
|
|
|
|
DWORD
|
|
ASN1ParserBase::Display(
|
|
IN ASN1FRAME * Frame,
|
|
IN ASN1VALUE * Value,
|
|
IN HPROPERTY hProperty,
|
|
IN DWORD IFlags
|
|
)
|
|
{
|
|
DWORD dw = ERROR_SUCCESS;
|
|
DWORD Length;
|
|
ULPVOID Address;
|
|
|
|
switch( Value->ut )
|
|
{
|
|
case utGeneralizedTime:
|
|
|
|
Length = sizeof( Value->st );
|
|
Address = &Value->st;
|
|
break;
|
|
|
|
case utBoolean:
|
|
|
|
Length = sizeof( Value->b );
|
|
Address = &Value->b;
|
|
break;
|
|
|
|
case utInteger:
|
|
case utBitString:
|
|
|
|
//
|
|
// ASN.1 integers are optimally encoded using the fewest number of bytes
|
|
// This does not bode well with Netmon which insists on knowing how long
|
|
// a value is before displaying it. The mapping below will show both
|
|
// the raw buffer and the corresponding value properly
|
|
//
|
|
|
|
Length = sizeof( Value->dw );
|
|
Address = &Value->dw;
|
|
break;
|
|
|
|
case utGeneralString:
|
|
case utOctetString:
|
|
|
|
if ( Value->string.l == 0 )
|
|
{
|
|
Address = "<empty string>";
|
|
Length = strlen(( const char * )Address );
|
|
}
|
|
else
|
|
{
|
|
Address = Value->string.s;
|
|
Length = Value->string.l;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// By default, display unadulterated raw data pointed to by 'Value'
|
|
//
|
|
|
|
Length = Value->Length;
|
|
Address = Value->Address;
|
|
}
|
|
|
|
if ( FALSE == AttachPropertyInstanceEx(
|
|
Frame->hFrame,
|
|
hProperty,
|
|
Value->Length,
|
|
Value->Address,
|
|
Length,
|
|
Address,
|
|
0,
|
|
Frame->Level,
|
|
IFlags ))
|
|
{
|
|
dw = ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
return dw;
|
|
}
|