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.
222 lines
4.9 KiB
222 lines
4.9 KiB
//=============================================================================
|
|
//
|
|
// MODULE: ASN1Sequence.cxx
|
|
//
|
|
// Description:
|
|
//
|
|
// Implementation of ASN.1 sequence parsing logic
|
|
//
|
|
// Modification History
|
|
//
|
|
// Mark Pustilnik Date: 06/08/02 - created
|
|
//
|
|
//=============================================================================
|
|
|
|
#include "ASN1Parser.hxx"
|
|
|
|
//
|
|
// Parsing a sequence with optional elements entails invoking successive parsers
|
|
// and stepping over optional blocks which were not found in the sequence
|
|
//
|
|
|
|
DWORD
|
|
ASN1ParserSequence::Parse(
|
|
IN OUT ASN1FRAME * Frame
|
|
)
|
|
{
|
|
DWORD dw;
|
|
ASN1FRAME FrameIn = *Frame;
|
|
DWORD Length = DataLength( Frame );
|
|
BOOLEAN FrameLevelChanged = FALSE;
|
|
ULPBYTE SequenceEnd;
|
|
|
|
dw = VerifyAndSkipHeader( Frame );
|
|
|
|
if ( dw != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( *Frame->Address != BuildDescriptor(
|
|
ctUniversal,
|
|
pcConstructed,
|
|
utSequence ))
|
|
{
|
|
dw = ERROR_INVALID_DATA;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Remember the length of the sequence
|
|
//
|
|
|
|
Length = DataLength( Frame );
|
|
|
|
//
|
|
// Skip over the the descriptor
|
|
//
|
|
|
|
Frame->Address++;
|
|
|
|
//
|
|
// Skip over the length header
|
|
//
|
|
|
|
Frame->Address += HeaderLength( Frame->Address );
|
|
|
|
//
|
|
// Remember where the sequence ends so we know when to stop iterating
|
|
//
|
|
|
|
SequenceEnd = Frame->Address + Length;
|
|
|
|
//
|
|
// Display the sequence summary
|
|
//
|
|
|
|
if ( m_hPropertySummary )
|
|
{
|
|
if ( FALSE == AttachPropertyInstanceEx(
|
|
Frame->hFrame,
|
|
m_hPropertySummary,
|
|
(DWORD)(SequenceEnd - FrameIn.Address),
|
|
FrameIn.Address,
|
|
0,
|
|
NULL,
|
|
0,
|
|
Frame->Level,
|
|
0 ))
|
|
{
|
|
dw = ERROR_CAN_NOT_COMPLETE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Anything from this point on is indented
|
|
//
|
|
|
|
Frame->Level += 1;
|
|
FrameLevelChanged = TRUE;
|
|
}
|
|
|
|
while ( Frame->Address < SequenceEnd )
|
|
{
|
|
for ( ULONG i = 0; i < m_Count; i++ )
|
|
{
|
|
ASN1ParserBase * Parser = m_Parsers[i];
|
|
|
|
dw = Parser->Parse( Frame );
|
|
|
|
if ( dw == ERROR_INVALID_USER_BUFFER &&
|
|
Parser->IsOptional())
|
|
{
|
|
//
|
|
// Failed to parse, but it was optional anyway
|
|
// Clear the error code and proceed
|
|
//
|
|
|
|
dw = ERROR_SUCCESS;
|
|
continue;
|
|
}
|
|
else if ( dw != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Make sure the sequence is not overstepped
|
|
//
|
|
|
|
if ( Frame->Address > SequenceEnd )
|
|
{
|
|
dw = ERROR_INVALID_DATA;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !m_Extensible )
|
|
{
|
|
//
|
|
// Any ASN.1 encoding worth it salt is exact, so enforce that
|
|
//
|
|
|
|
if ( Frame->Address != SequenceEnd )
|
|
{
|
|
dw = ERROR_INVALID_DATA;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Pretend we've parsed the rest successfully
|
|
//
|
|
|
|
Frame->Address = SequenceEnd;
|
|
}
|
|
|
|
//
|
|
// If we are a value collector, display the collected values now
|
|
//
|
|
|
|
dw = DisplayCollectedValues(
|
|
Frame,
|
|
(DWORD)(SequenceEnd-FrameIn.Address),
|
|
FrameIn.Address
|
|
);
|
|
|
|
PurgeCollectedValues();
|
|
|
|
if ( dw != ERROR_SUCCESS )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// Restore the indent level
|
|
//
|
|
|
|
if ( dw != ERROR_SUCCESS )
|
|
{
|
|
*Frame = FrameIn;
|
|
}
|
|
else if ( FrameLevelChanged )
|
|
{
|
|
Frame->Level -= 1;
|
|
}
|
|
|
|
return dw;
|
|
}
|
|
|
|
DWORD
|
|
ASN1ParserSequence::CollectValue(
|
|
IN ASN1VALUE * Value
|
|
)
|
|
{
|
|
ASN1VALUE * NewValue = Value ? Value->Clone() : NULL;
|
|
PASN1VALUE * NewValuesCollected = new PASN1VALUE[m_ValueCount + 1];
|
|
|
|
if (( Value != NULL && NewValue == NULL ) ||
|
|
NewValuesCollected == NULL )
|
|
{
|
|
delete NewValue;
|
|
delete [] NewValuesCollected;
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
NewValuesCollected,
|
|
m_ValuesCollected,
|
|
m_ValueCount * sizeof( PASN1VALUE )
|
|
);
|
|
|
|
delete [] m_ValuesCollected;
|
|
m_ValuesCollected = NewValuesCollected;
|
|
m_ValuesCollected[m_ValueCount++] = NewValue;
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|