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.
 
 
 
 
 
 

2719 lines
71 KiB

//==============================================================================
//
// MODULE: ASN1Parser.hxx
//
// Description:
//
// Basic building blocks for ASN.1 parsing
//
// Modification History
//
// Mark Pustilnik Date: 06/08/02 - created
//
//==============================================================================
#ifndef __ASN1PARSER_HXX
#define __ASN1PARSER_HXX
#include <windows.h>
#include <netmon.h>
#include <kerbcon.h>
#include <ntsecapi.h>
#include "..\inc\kerberr.h"
//
// Utility macros
//
#define ARRAY_COUNT( a ) ( sizeof( a ) / sizeof ( a[ 0 ] ) )
#define SET_OF( s ) { ARRAY_COUNT( s ), s }
//
// Shortcut for property access
//
#define PROP( a ) g_KerberosDatabase[a].hProperty
//
// Kerberos packet types
//
enum
{
ASN1_KRB_AS_REQ = 0x0A,
ASN1_KRB_AS_REP = 0x0B,
ASN1_KRB_TGS_REQ = 0x0C,
ASN1_KRB_TGS_REP = 0x0D,
ASN1_KRB_AP_REQ = 0x0E,
ASN1_KRB_AP_REP = 0x0F,
ASN1_KRB_SAFE = 0x14,
ASN1_KRB_PRIV = 0x15,
ASN1_KRB_CRED = 0x16,
ASN1_KRB_ERROR = 0x1E,
};
//
// Kerberos address types
//
enum
{
KERB_ADDRTYPE_UNSPEC = 0x0,
KERB_ADDRTYPE_LOCAL = 0x1,
KERB_ADDRTYPE_INET = 0x2,
KERB_ADDRTYPE_IMPLINK = 0x3,
KERB_ADDRTYPE_PUP = 0x4,
KERB_ADDRTYPE_CHAOS = 0x5,
KERB_ADDRTYPE_NS = 0x6,
KERB_ADDRTYPE_NBS = 0x7,
KERB_ADDRTYPE_ECMA = 0x8,
KERB_ADDRTYPE_DATAKIT = 0x9,
KERB_ADDRTYPE_CCITT = 0xA,
KERB_ADDRTYPE_SNA = 0xB,
KERB_ADDRTYPE_DECnet = 0xC,
KERB_ADDRTYPE_DLI = 0xD,
KERB_ADDRTYPE_LAT = 0xE,
KERB_ADDRTYPE_HYLINK = 0xF,
KERB_ADDRTYPE_APPLETALK = 0x10,
KERB_ADDRTYPE_BSC = 0x11,
KERB_ADDRTYPE_DSS = 0x12,
KERB_ADDRTYPE_OSI = 0x13,
KERB_ADDRTYPE_NETBIOS = 0x14,
KERB_ADDRTYPE_X25 = 0x15,
KERB_ADDRTYPE_IPv6 = 0x18,
};
//
// PAC Sections
//
enum
{
PAC_LOGON_INFO = 1,
PAC_CREDENTIAL_TYPE = 2,
PAC_SERVER_CHECKSUM = 6,
PAC_PRIVSVR_CHECKSUM = 7,
PAC_CLIENT_INFO_TYPE = 10,
PAC_DELEGATION_INFO = 11,
PAC_CLIENT_IDENTITY = 13,
PAC_COMPOUND_IDENTITY = 14,
};
//
// Netmon property IDs
//
enum
{
KRB_AS_REQ,
KRB_AS_REP,
KRB_TGS_REQ,
KRB_TGS_REP,
KRB_AP_REQ,
KRB_AP_REP,
KRB_SAFE,
KRB_PRIV,
KRB_CRED,
KRB_ERROR,
HostAddresses_HostAddress,
EncryptedData_etype,
EncryptedData_kvno,
EncryptedData_cipher,
PA_DATA_type,
PA_DATA_value,
PrincipalName_type,
PrincipalName_string,
Ticket_tkt_vno,
Ticket_realm,
Ticket_sname,
Ticket_enc_part,
AP_REQ_pvno,
AP_REQ_msg_type,
AP_REQ_ap_options_summary,
AP_REQ_ap_options_value,
AP_REQ_ticket,
AP_REQ_authenticator,
KDC_REQ_BODY_kdc_options_summary,
KDC_REQ_BODY_kdc_options_value,
KDC_REQ_BODY_cname,
KDC_REQ_BODY_realm,
KDC_REQ_BODY_sname,
KDC_REQ_BODY_from,
KDC_REQ_BODY_till,
KDC_REQ_BODY_rtime,
KDC_REQ_BODY_nonce,
KDC_REQ_BODY_etype,
KDC_REQ_BODY_addresses,
KDC_REQ_BODY_enc_authorization_data,
KDC_REQ_BODY_additional_tickets,
KDC_REQ,
KDC_REQ_pvno,
KDC_REQ_msg_type,
KDC_REQ_padata,
KDC_REQ_req_body,
KDC_REP_pvno,
KDC_REP_msg_type,
KDC_REP_padata,
KDC_REP_crealm,
KDC_REP_cname,
KDC_REP_ticket,
KDC_REP_enc_part,
KRB_ERR_pvno,
KRB_ERR_msg_type,
KRB_ERR_ctime,
KRB_ERR_cusec,
KRB_ERR_stime,
KRB_ERR_susec,
KRB_ERR_error_code,
KRB_ERR_crealm,
KRB_ERR_cname,
KRB_ERR_realm,
KRB_ERR_sname,
KRB_ERR_e_text,
KRB_ERR_e_data,
KERB_PA_PAC_REQUEST_include_pac,
KERB_PA_PAC_REQUEST_EX_include_pac,
KERB_PA_PAC_REQUEST_EX_pac_sections,
KERB_PA_PAC_REQUEST_EX_pac_sections_desc,
KERB_ETYPE_INFO_ENTRY_encryption_type,
KERB_ETYPE_INFO_ENTRY_salt,
KERB_PREAUTH_DATA_LIST,
TYPED_DATA_type,
TYPED_DATA_value,
PA_PW_SALT_salt,
PA_FOR_USER_userName,
PA_FOR_USER_userRealm,
PA_FOR_USER_cksum,
PA_FOR_USER_authentication_package,
PA_FOR_USER_authorization_data,
KERB_CHECKSUM_type,
KERB_CHECKSUM_checksum,
AdditionalTicket,
EncryptionType,
ContinuationPacket,
INTEGER_NOT_IN_ASN,
CompoundIdentity,
CompoundIdentityTicket,
MAX_PROP_VALUE, // dummy value to ensure consistency
};
//
// externs
//
extern PROPERTYINFO g_KerberosDatabase[MAX_PROP_VALUE];
//==============================================================================
//
// ASN.1 constructs
//
//==============================================================================
//
// Class tags
//
typedef enum ClassTag
{
ctUniversal = 0x00, // 00000000
ctApplication = 0x40, // 01000000
ctContextSpecific = 0x80, // 10000000
ctPrivate = 0xC0, // 11000000
};
inline
ClassTag
ClassTagFromByte(
IN BYTE b
)
{
return (ClassTag)( b & 0xC0 );
}
//
// Primitive-Constructed
//
typedef enum PC
{
pcPrimitive = 0x00, // 00000000
pcConstructed = 0x20, // 00100000
};
inline
PC
PCFromByte(
IN BYTE b
)
{
return (PC)( b & 0x20 );
}
//
// Tags
//
const BYTE MaxTag = 0x1F; // Max value of a tag
inline
BYTE
TagFromByte(
IN BYTE b
)
{
return ( b & 0x1F ); // Tags are 5 bits long
}
//
// Universal tags
//
typedef enum UniversalTag
{
utBoolean = 0x01, // 00001
utInteger = 0x02, // 00010
utBitString = 0x03, // 00011
utOctetString = 0x04, // 00100
utNULL = 0x05, // 00101
utObjectIdentifer = 0x06, // 00110
utObjectDescriptor = 0x07, // 00111
utExternal = 0x08, // 01000
utReal = 0x09, // 01001
utEnumerated = 0x0A, // 01010
utSequence = 0x10, // 10000
utSet = 0x11, // 10001
utNumericString = 0x12, // 10010
utPrintableString = 0x13, // 10011
utT61String = 0x14, // 10100
utVideotexString = 0x15, // 10101
utIA5String = 0x16, // 10110
utUTCTime = 0x17, // 10111
utGeneralizedTime = 0x18, // 11000
utGraphicString = 0x19, // 11001
utVisibleString = 0x1A, // 11010
utGeneralString = 0x1B, // 11011
};
inline
BYTE
BuildDescriptor(
IN ClassTag ct,
IN PC pc,
IN ULONG tag
)
{
//
// TODO: add an assert that tag fits in one byte (or rather 0x1F bits)
//
return (BYTE)ct | (BYTE)pc | ((BYTE)tag & 0x1F );
}
//==============================================================================
//
// Class declarations
//
//==============================================================================
struct ASN1FRAME
{
//
// Starting address of the frame
//
ULPBYTE Address;
//
// Netmon frame handle
//
HFRAME hFrame;
//
// Netmon indentation offset
//
DWORD Level;
};
// Necessary forward declaration for the subparser member
class ASN1ParserBase;
struct ASN1VALUE
{
//
// Constructor and destructor
//
ASN1VALUE(
) : Address( NULL ),
Length( 0 ),
ut( utNULL ),
Allocated( FALSE ),
SubParser( NULL ) {}
~ASN1VALUE();
void
Purge()
{
if ( Allocated &&
( ut == utOctetString ||
ut == utGeneralString ))
{
delete [] string.s;
string.s = NULL;
string.l = 0;
}
}
//
// Creates dynamically allocated copy of ASN1VALUE passed in
//
ASN1VALUE *
Clone();
//
// Address of the actual unadulterated value
//
ULPBYTE Address;
//
// Length of the actual unadulterated value
//
DWORD Length;
//
// Type of value that follows
//
UniversalTag ut;
//
// Dynamically allocated? ('s' only)
//
BOOL Allocated;
union
{
BOOL b; // utBoolean
DWORD dw; // utInteger, utBitString
struct {
ULONG l;
ULPBYTE s;
} string; // utOctetString, utGeneralString
SYSTEMTIME st; // utGeneralizedTime
};
//
// Subparser (for binary blob types only)
//
ASN1ParserBase * SubParser; // TODO: refcount this type if deep copy becomes necessary
};
typedef ASN1VALUE * PASN1VALUE;
// -----------------------------------------------------------------------------
//
// +----------------+
// | ASN1ParserBase |<------------------------+
// +----------------+ |
// ^ |
// | |
// +----------------+------------------+ |
// | | |
// +----------------+ +--------------------+ |
// | ASN1ParserUnit | | ASN1ParserSequence |<>--+
// +----------------+ +--------------------+
//
// -----------------------------------------------------------------------------
class ASN1ParserSequence; // necessary forward declaration for value collectors
class ASN1ParserBase
{
public:
//
// Constructor and destructor
//
ASN1ParserBase(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertySummary,
IN HPROPERTY hPropertyValue
) : m_IsOptional( IsOptional ),
m_Descriptor( Descriptor ),
m_AppDescriptor( 0 ),
m_hPropertySummary( hPropertySummary ),
m_hPropertyValue( hPropertyValue ),
m_Modifier( NULL ),
m_Modifyee( NULL ),
m_ValueCollector( NULL ) {}
virtual
~ASN1ParserBase() { delete m_Modifier; }
//
// Parses the data in the block pointed to by the Frame,
// and displays the resulting data in the appropriate format
// Upon exit, Frame points to the next block to be parsed
//
virtual
DWORD
Parse(
IN OUT ASN1FRAME * Frame ) = 0;
DWORD
Display(
IN ASN1FRAME * Frame,
IN ASN1VALUE * Value,
IN HPROPERTY hProperty,
IN DWORD IFlags );
//
// Computes length of the block pointed to by Frame
//
DWORD
DataLength(
IN ASN1FRAME * Frame );
//
// Queries "optionality" of this parser block
//
BOOL
IsOptional() { return m_IsOptional; }
//
// "Modifiers" are values which affect subsequent parsing
// in a context-specific fashion
//
DWORD
SetModifier(
IN ASN1VALUE * NewModifier )
{
ASN1VALUE * Modifier = NewModifier->Clone();
if ( Modifier == NULL )
{
return ERROR_NOT_ENOUGH_MEMORY;
}
delete m_Modifier;
m_Modifier = Modifier;
return ERROR_SUCCESS;
}
ASN1VALUE *
QueryModifier() { return m_Modifier; }
//
// "Modifyees" are objects being modified during parsing
//
void
SetModifyee(
IN ASN1ParserBase * Modifyee ) { m_Modifyee = Modifyee; }
ASN1ParserBase *
QueryModifyee() { return m_Modifyee; }
//
// A parser can have a 'value collector' - a sequence object
// which collects the values parsed out by this parser for subsequent
// processing and display
//
void
SetValueCollector(
IN ASN1ParserSequence * ValueCollector ) { m_ValueCollector = ValueCollector; }
ASN1ParserSequence *
QueryValueCollector() { return m_ValueCollector; }
protected:
//
// Verifies the item header and skips past the item length block
// that follows it
//
DWORD
VerifyAndSkipHeader(
IN OUT ASN1FRAME * Frame );
//
// Computes the length of the length header
//
ULONG
HeaderLength(
IN ULPBYTE Address );
//
// Netmon property handles
// Either is optional, if both are present, they are displayed
// in a hierarchical fashion
//
HPROPERTY m_hPropertySummary;
HPROPERTY m_hPropertyValue;
//
// Set the application descriptor (rare so better not done during construction time)
//
void
SetAppDescriptor(
IN BYTE AppDescriptor ) { m_AppDescriptor = AppDescriptor; }
private:
//
// If TRUE, the item is optional and may not be present
//
BOOL m_IsOptional;
//
// One-BYTE Descriptor of the expected data that follows,
// for example 10 1 00001 (Context-Specific[10] Constructed[1] pvno[1])
// m_AppDescriptor exists for [APPLICATION 1] types of situations
//
BYTE m_Descriptor;
BYTE m_AppDescriptor;
//
// Modifier value
//
ASN1VALUE * m_Modifier;
//
// Modifyee value
//
ASN1ParserBase * m_Modifyee;
//
// Value collector
//
ASN1ParserSequence * m_ValueCollector;
};
// -----------------------------------------------------------------------------
//
// Derived classes of ASN1ParserBase follow
//
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
// +----------------+
// | ASN1ParserUnit |
// +----------------+
// ^
// |
// +--------------+--------+--------- ... ... ...
// ^ ^
// +-------------------+ +-------------------+
// | ASN1ParserInteger | | ASN1ParserBoolean |
// +-------------------+ +-------------------+
//
// -----------------------------------------------------------------------------
//
// A 'unit' is essentially anything that is a leaf in the parse tree
// Most units have values, some don't
//
class ASN1ParserUnit : public ASN1ParserBase
{
public:
//
// Constructor
//
ASN1ParserUnit(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertySummary,
IN HPROPERTY hPropertyValue,
IN DWORD IFlags
) : ASN1ParserBase(
IsOptional,
Descriptor,
hPropertySummary,
hPropertyValue ),
m_IFlags( IFlags ) {}
//
// Parses the unit and calls into the derived class (through Display)
// to display it in Netmon
//
DWORD
Parse(
IN OUT ASN1FRAME * Frame );
//
// A Unit-descendant that does not have a value should set the value type
// to 'void' and still delineate the value and length of the octet string
// properly so that it can be displayed correctly
//
virtual
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value ) = 0;
protected:
//
// Netmon display flags
//
DWORD m_IFlags;
};
// -----------------------------------------------------------------------------
//
// Derived classes of ASN1ParserUnit follow
//
// -----------------------------------------------------------------------------
class ASN1ParserBitString : public ASN1ParserUnit
{
public:
//
// Constructor
//
ASN1ParserBitString(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertySummary,
IN HPROPERTY hPropertyValue,
IN DWORD IFlags,
IN DWORD BitMask = 0xFFFFFFFF
) : ASN1ParserUnit(
IsOptional,
Descriptor,
hPropertySummary,
hPropertyValue,
IFlags ),
m_BitMask( BitMask ) {}
//
// Parses the bit string
//
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value
);
protected:
DWORD m_BitMask;
};
class ASN1ParserBoolean : public ASN1ParserUnit
{
public:
//
// Constructor
//
ASN1ParserBoolean(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertyValue,
IN DWORD IFlags
) : ASN1ParserUnit(
IsOptional,
Descriptor,
NULL, // Boolean is directly displayable, no need for summary
hPropertyValue,
IFlags ) {}
//
// Parses the boolean
//
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value
);
};
class ASN1ParserInteger : public ASN1ParserUnit
{
public:
//
// Constructor
//
ASN1ParserInteger(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertyValue,
IN DWORD IFlags,
IN DWORD BitMask = 0xFFFFFFFF
) : ASN1ParserUnit(
IsOptional,
Descriptor,
NULL, // Integer is directly displayable, no need for summary
hPropertyValue,
IFlags ),
m_BitMask( BitMask ) {}
//
// Parses the integer
//
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value
);
protected:
DWORD m_BitMask;
};
class ASN1ParserGeneralizedTime : public ASN1ParserUnit
{
public:
//
// Constructor
//
ASN1ParserGeneralizedTime(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertyValue
) : ASN1ParserUnit(
IsOptional,
Descriptor,
NULL, // Time is directly displayable, no need for summary
hPropertyValue,
0 ) {}
//
// Parses the octet string
//
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value );
};
class ASN1ParserGeneralString : public ASN1ParserUnit
{
public:
//
// Constructor
//
ASN1ParserGeneralString(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertyValue,
IN DWORD IFlags
) : ASN1ParserUnit(
IsOptional,
Descriptor,
NULL, // String is directly displayable, no need for summary
hPropertyValue,
IFlags ) {}
//
// Parses the octet string
//
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value );
};
//
// An octet string is just a binary blob that needs special decoding
// in most cases. In those cases, the class needs to be subclassed to parse
// out the actual value
//
class ASN1ParserOctetString : public ASN1ParserUnit
{
public:
//
// Constructor
//
ASN1ParserOctetString(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertyValue,
IN DWORD IFlags
) : ASN1ParserUnit(
IsOptional,
Descriptor,
NULL, // String is directly displayable, no need for summary
hPropertyValue,
IFlags ) {}
//
// Parses the octet string
//
DWORD
GetValue(
IN OUT ASN1FRAME * Frame,
OUT ASN1VALUE * Value );
protected:
virtual
DWORD
ParseBlob(
IN OUT ASN1VALUE * Value ) { return ERROR_SUCCESS; }
};
class ASN1ParserAddressBuffer : public ASN1ParserOctetString
{
public:
//
// Constructor
//
ASN1ParserAddressBuffer(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserOctetString(
IsOptional,
Descriptor,
hProperty,
0 ) {}
protected:
DWORD
ParseBlob(
IN OUT ASN1VALUE * Value );
};
class ASN1ParserErrorData : public ASN1ParserOctetString
{
public:
//
// Constructor
//
ASN1ParserErrorData(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserOctetString(
IsOptional,
Descriptor,
hProperty,
0 ) {}
protected:
DWORD
ParseBlob(
IN OUT ASN1VALUE * Value );
};
// -----------------------------------------------------------------------------
//
// +--------------------+
// | ASN1ParserSequence |
// +--------------------+
// ^
// |
// +---------------+---------+--------- ... ... ...
// ^ ^
// +------------------+ +-------------------------+
// | ASN1ParserPaData | | ASN1ParserPrincipalName |
// +------------------+ +-------------------------+
//
// -----------------------------------------------------------------------------
//
// A sequence is a collection of units or sequences, much like a directory
// contains files or other directories
//
class ASN1ParserSequence : public ASN1ParserBase
{
public:
//
// Constructor
//
ASN1ParserSequence(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertySummary,
IN ULONG Count,
IN ASN1ParserBase * * Parsers,
IN OPTIONAL BOOL Extensible = FALSE
) : ASN1ParserBase(
IsOptional,
Descriptor,
hPropertySummary,
NULL ), // no value property on sequences (yet?)
m_Count( Count ),
m_Parsers( Parsers ),
m_ValueCount( 0 ),
m_ValuesCollected( NULL ),
m_Extensible( Extensible ) {}
~ASN1ParserSequence() { PurgeCollectedValues(); }
//
// Parses the sequence by invoking successive sub-parsers as necessary
//
DWORD
Parse(
IN OUT ASN1FRAME * Frame );
//
// This method is called if this object is acting as a value collector for
// another object. A value collected is appended to the end of the array
// of like values
//
DWORD
CollectValue(
IN ASN1VALUE * Value );
ULONG
QueryCollectedCount() { return m_ValueCount; }
ASN1VALUE *
QueryCollectedValue(
IN ULONG Index ) { return m_ValuesCollected[Index]; } // TODO: add range-check assert
void
PurgeCollectedValues()
{
for ( ULONG i = 0; i < m_ValueCount; i++)
{
delete m_ValuesCollected[i];
}
delete [] m_ValuesCollected;
m_ValuesCollected = NULL;
m_ValueCount = 0;
}
protected:
virtual
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address )
{
//
// TODO: add an assert in addition to this error check
//
return QueryCollectedCount() > 0 ?
ERROR_NOT_SUPPORTED :
ERROR_SUCCESS;
}
private:
//
// Number of items in the sequence
//
ULONG m_Count;
//
// Array of parser objects - one for every sequence item
//
ASN1ParserBase * * m_Parsers;
//
// Values collected
//
ULONG m_ValueCount;
PASN1VALUE * m_ValuesCollected;
//
// Are extensibility markers employed in the ASN.1 syntax?
//
BOOL m_Extensible;
};
// -----------------------------------------------------------------------------
//
// Derived classes of ASN1ParserSequence follow
//
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// HostAddress ::= SEQUENCE {
// addr-type[0] INTEGER,
// address[1] OCTET STRING
// }
// -----------------------------------------------------------------------------
class ASN1ParserHostAddress : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserHostAddress(
IN BOOL IsOptional,
IN BYTE Descriptor
) : ASN1ParserSequence(
IsOptional,
Descriptor,
NULL,
ARRAY_COUNT( m_p ),
m_p ),
m_addr_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_addr_type ),
NULL,
0 ),
m_address(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_address ),
NULL )
{
m_p[0] = &m_addr_type;
m_p[1] = &m_address;
//
// Address type affects the parsing of the address portion
//
m_addr_type.SetModifyee( &m_address );
//
// We would like to handle the display of address type and address
// value ourselves (allows for user-friendly display on the same line)
//
m_addr_type.SetValueCollector( this );
m_address.SetValueCollector( this );
}
protected:
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address );
private:
enum
{
e_addr_type = 0,
e_address = 1,
};
ASN1ParserBase * m_p[2];
ASN1ParserInteger m_addr_type;
ASN1ParserAddressBuffer m_address;
};
// -----------------------------------------------------------------------------
// HostAddresses ::= SEQUENCE OF HostAddress
// -----------------------------------------------------------------------------
class ASN1ParserHostAddresses : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserHostAddresses(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_HostAddress(
FALSE,
0 ) // no descriptor on individual addresses sequences
{
m_p[0] = &m_HostAddress;
}
private:
ASN1ParserBase * m_p[1];
ASN1ParserHostAddress m_HostAddress;
};
// -----------------------------------------------------------------------------
// EncryptedData ::= SEQUENCE {
// etype[0] INTEGER, -- EncryptionType
// kvno[1] INTEGER OPTIONAL,
// cipher[2] OCTET STRING -- ciphertext
// }
// -----------------------------------------------------------------------------
class ASN1ParserEncryptedData : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserEncryptedData(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p
),
m_etype(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_etype ),
PROP( EncryptedData_etype ),
0 ),
m_kvno(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_kvno ),
PROP( EncryptedData_kvno ),
0 ),
m_cipher(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_cipher ),
PROP( EncryptedData_cipher ),
0 )
{
m_p[0] = &m_etype;
m_p[1] = &m_kvno;
m_p[2] = &m_cipher;
//
// m_etype type is not modifying either m_kvno or m_cipher,
// but it conceivably could
//
}
private:
enum
{
e_etype = 0,
e_kvno = 1,
e_cipher = 2,
};
ASN1ParserBase * m_p[3];
ASN1ParserInteger m_etype;
ASN1ParserInteger m_kvno;
ASN1ParserOctetString m_cipher;
};
class ASN1ParserGStringSequence : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserGStringSequence(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_string(
FALSE,
0, // No descriptor on individual general string entries
NULL, // No property since we're acting as the value collector
0 )
{
m_p[0] = &m_string;
//
// Act as the value collector for the string sequence
//
m_string.SetValueCollector( this );
}
private:
ASN1ParserBase * m_p[1];
ASN1ParserGeneralString m_string;
};
class ASN1ParserPrincipalNameSequence : public ASN1ParserGStringSequence
{
public:
//
// Constructor
//
ASN1ParserPrincipalNameSequence(
IN BOOL IsOptional,
IN BYTE Descriptor
) : ASN1ParserGStringSequence(
IsOptional,
Descriptor,
NULL ) {} // let the value collector display the value
protected:
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address );
};
class ASN1ParserIntegerSequence : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserIntegerSequence(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertySeq,
IN HPROPERTY hPropertyInteger
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hPropertySeq,
ARRAY_COUNT( m_p ),
m_p ),
m_integer(
FALSE,
0, // No descriptor on individual integer entries
NULL, // No property since we're acting as the value collector
0 ),
m_hPropertyInteger( hPropertyInteger )
{
m_p[0] = &m_integer;
//
// Act as the value collector for the integer sequence
//
m_integer.SetValueCollector( this );
}
protected:
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address );
private:
ASN1ParserBase * m_p[1];
ASN1ParserInteger m_integer;
HPROPERTY m_hPropertyInteger;
};
// -----------------------------------------------------------------------------
// KERB-PA-PAC-REQUEST ::= SEQUENCE {
// include-pac[0] BOOLEAN
// -- if TRUE, and no pac present,
// -- include PAC. If FALSE, and pac
// -- PAC present, remove PAC
// } --#public--
// -----------------------------------------------------------------------------
class ASN1ParserKerbPaPacRequest : public ASN1ParserSequence
{
public:
ASN1ParserKerbPaPacRequest(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p
),
m_include_pac(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_include_pac ),
PROP( KERB_PA_PAC_REQUEST_include_pac ),
0 )
{
m_p[0] = &m_include_pac;
}
private:
enum
{
e_include_pac = 0,
};
ASN1ParserBase * m_p[1];
ASN1ParserBoolean m_include_pac;
};
// -----------------------------------------------------------------------------
// KERB-PA-PAC-REQUEST-EX ::= SEQUENCE {
// include-pac[0] BOOLEAN,
// -- if TRUE, and no pac present,
// -- include PAC. If FALSE, and pac
// -- PAC present, remove PAC
// pac-sections[1] SEQUENCE OF INTEGER OPTIONAL
// } --#public--
// -----------------------------------------------------------------------------
class ASN1ParserPaPacRequestEx : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserPaPacRequestEx(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p
),
m_include_pac(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_include_pac ),
PROP( KERB_PA_PAC_REQUEST_EX_include_pac ),
0 ),
m_pac_sections(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_pac_sections ),
PROP( KERB_PA_PAC_REQUEST_EX_pac_sections ),
PROP( KERB_PA_PAC_REQUEST_EX_pac_sections_desc ))
{
m_p[0] = &m_include_pac;
m_p[1] = &m_pac_sections;
}
private:
enum
{
e_include_pac = 0,
e_pac_sections = 1,
};
ASN1ParserBase * m_p[2];
ASN1ParserBoolean m_include_pac;
ASN1ParserIntegerSequence m_pac_sections;
};
// -----------------------------------------------------------------------------
// PA-DATA ::= SEQUENCE {
// padata-type[1] INTEGER,
// padata-value[2] OCTET STRING, -- might be encoded AP-REQ
// }
// -----------------------------------------------------------------------------
//
// PA-DATA types
//
enum
{
PA_NONE = 0x00,
PA_APTGS_REQ = 0x01,
PA_ENC_TIMESTAMP = 0x02,
PA_PW_SALT = 0x03,
PA_RESERVED = 0x04,
PA_ENC_UNIX_TIME = 0x05,
PA_SANDIA_SECUREID = 0x06,
PA_SESAME = 0x07,
PA_OSF_DCE = 0x08,
PA_CYBERSAFE_SECUREID = 0x09,
PA_AFS3_SALT = 0x0A,
PA_ETYPE_INFO = 0x0B,
SAM_CHALLENGE = 0x0C,
SAM_RESPONSE = 0x0D,
PA_PK_AS_REQ = 0x0E,
PA_PK_AS_REP = 0x0F,
PA_PK_AS_SIGN = 0x10,
PA_PK_KEY_REQ = 0x11,
PA_PK_KEY_REP = 0x12,
PA_USE_SPECIFIED_KVNO = 0x14,
SAM_REDIRECT = 0x15,
PA_GET_FROM_TYPED_DATA = 0x16,
PA_SAM_ETYPE_INFO = 0x17,
PA_ALT_PRINC = 0x18,
PA_REFERRAL_INFO = 0x20,
TD_PKINIT_CMS_CERTIFICATES = 0x65,
TD_KRB_PRINCIPAL = 0x66,
TD_KRB_REALM = 0x67,
TD_TRUSTED_CERTIFIERS = 0x68,
TD_CERTIFICATE_INDEX = 0x69,
TD_APP_DEFINED_ERROR = 0x6A,
TD_REQ_NONCE = 0x6B,
TD_REQ_SEQ = 0x6C,
PA_PAC_REQUEST = 0x80,
PA_FOR_USER = 0x81,
PA_COMPOUND_IDENTITY = 0x82,
PA_PAC_REQUEST_EX = 0x83,
PA_CLIENT_VERSION = 0x84,
PA_XBOX_SERVICE_REQUEST = 0xC9,
PA_XBOX_SERVICE_ADDRESS = 0xCA,
PA_XBOX_ACCOUNT_CREATION = 0xCB,
PA_XBOX_PPA = 0xCC,
PA_XBOX_ECHO = 0xCD,
};
class ASN1ParserPaData : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserPaData(
IN BOOL IsOptional,
IN BYTE Descriptor
) : ASN1ParserSequence(
IsOptional,
Descriptor,
NULL,
ARRAY_COUNT( m_p ),
m_p ),
m_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_type ),
NULL,
0 ),
m_value(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_value ),
NULL,
0 )
{
m_p[0] = &m_type;
m_p[1] = &m_value;
//
// Name type affects the parsing of the value portion
//
m_type.SetModifyee( &m_value );
//
// Collect the values for both type and value for later processing
//
m_type.SetValueCollector( this );
m_value.SetValueCollector( this );
}
protected:
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address );
private:
enum
{
e_type = 1,
e_value = 2,
};
ASN1ParserBase * m_p[2];
ASN1ParserInteger m_type;
ASN1ParserOctetString m_value; // TODO: subclass for pa-data-type modifications
};
class ASN1ParserPaDataSequence : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserPaDataSequence(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_padata(
FALSE,
0 ) // No descriptor on individual pa-data entries
{
m_p[0] = &m_padata;
}
private:
ASN1ParserBase * m_p[1];
ASN1ParserPaData m_padata;
};
// -----------------------------------------------------------------------------
// KERB-TYPED-DATA ::= SEQUENCE {
// data-type [0] INTEGER,
// data-value [1] OCTET STRING
// }
// -----------------------------------------------------------------------------
class ASN1ParserTypedData : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserTypedData(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_data_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_data_type ),
PROP( TYPED_DATA_type ),
0 ),
m_data_value(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_data_value ),
PROP( TYPED_DATA_value ),
0 )
{
m_p[0] = &m_data_type;
m_p[1] = &m_data_value;
//
// Data type affects how data value is parsed
//
m_data_type.SetModifyee( &m_data_value );
}
private:
enum
{
e_data_type = 0,
e_data_value = 1,
};
ASN1ParserBase * m_p[2];
ASN1ParserInteger m_data_type;
ASN1ParserOctetString m_data_value; // TODO: change type to allow subparsers
};
// -----------------------------------------------------------------------------
//
// PrincipalName ::= SEQUENCE {
// name-type[0] INTEGER,
// name-string[1] SEQUENCE OF GeneralString
// }
// -----------------------------------------------------------------------------
class ASN1ParserPrincipalName : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserPrincipalName(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
NULL,
ARRAY_COUNT( m_p ),
m_p ),
m_hPropertyTopLevel( hProperty ),
m_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_type ),
NULL,
0 ),
m_string_seq(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_string ))
{
m_p[0] = &m_type;
m_p[1] = &m_string_seq;
//
// Act as the value collector for the data inside the sequence
//
m_type.SetValueCollector( this );
m_string_seq.SetValueCollector( this );
}
protected:
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address );
HPROPERTY m_hPropertyTopLevel;
private:
enum
{
e_type = 0,
e_string = 1,
};
ASN1ParserBase * m_p[2];
ASN1ParserInteger m_type;
ASN1ParserPrincipalNameSequence m_string_seq;
};
// -----------------------------------------------------------------------------
// KERB-CHECKSUM ::= SEQUENCE {
// checksum-type[0] INTEGER,
// checksum[1] OCTET STRING
// } --#public--
// -----------------------------------------------------------------------------
class ASN1ParserKerbChecksum : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKerbChecksum(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_checksum_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_checksum_type ),
PROP( KERB_CHECKSUM_type ),
0 ),
m_checksum(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_checksum ),
PROP( KERB_CHECKSUM_checksum ),
0 )
{
m_p[0] = &m_checksum_type;
m_p[1] = &m_checksum;
}
private:
enum
{
e_checksum_type = 0,
e_checksum = 1,
};
ASN1ParserBase * m_p[2];
ASN1ParserInteger m_checksum_type;
ASN1ParserOctetString m_checksum;
};
// -----------------------------------------------------------------------------
// Ticket ::= [APPLICATION 1] SEQUENCE {
// tkt-vno[0] INTEGER,
// realm[1] Realm,
// sname[2] PrincipalName,
// enc-part[3] EncryptedData
// }
// -----------------------------------------------------------------------------
class ASN1ParserTicket : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserTicket(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_tkt_vno(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_tkt_vno ),
PROP( Ticket_tkt_vno ),
0 ),
m_realm(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_realm ),
PROP( Ticket_realm ),
0 ),
m_sname(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_sname ),
PROP( Ticket_sname )),
m_enc_part(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_enc_part ),
PROP( Ticket_enc_part ))
{
SetAppDescriptor(
BuildDescriptor( ctApplication, pcConstructed, 1 )
);
m_p[0] = &m_tkt_vno;
m_p[1] = &m_realm;
m_p[2] = &m_sname;
m_p[3] = &m_enc_part;
}
private:
enum
{
e_tkt_vno = 0,
e_realm = 1,
e_sname = 2,
e_enc_part = 3
};
ASN1ParserBase * m_p[4];
ASN1ParserInteger m_tkt_vno;
ASN1ParserGeneralString m_realm;
ASN1ParserPrincipalName m_sname;
ASN1ParserEncryptedData m_enc_part;
};
class ASN1ParserTicketSequence : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserTicketSequence(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hPropertySeq,
IN HPROPERTY hPropertyTicket
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hPropertySeq,
ARRAY_COUNT( m_p ),
m_p ),
m_ticket(
FALSE,
0, // No descriptor on sequences of tickets
hPropertyTicket )
{
m_p[0] = &m_ticket;
}
private:
ASN1ParserBase * m_p[1];
ASN1ParserTicket m_ticket;
};
// -----------------------------------------------------------------------------
// KDC-REQ-BODY ::= SEQUENCE {
// kdc-options[0] KDCOptions,
// cname[1] PrincipalName OPTIONAL,
// -- Used only in AS-REQ
// realm[2] Realm, -- Server's realm
// -- Also client's in AS-REQ
// sname[3] PrincipalName OPTIONAL,
// from[4] KerberosTime OPTIONAL,
// till[5] KerberosTime,
// rtime[6] KerberosTime OPTIONAL,
// nonce[7] INTEGER,
// etype[8] SEQUENCE OF INTEGER,
// -- EncryptionType,
// -- in preference order
// addresses[9] HostAddresses OPTIONAL,
// enc-authorization-data[10] EncryptedData OPTIONAL,
// -- Encrypted AuthorizationData encoding
// additional-tickets[11] SEQUENCE OF Ticket OPTIONAL
// }
// -----------------------------------------------------------------------------
class ASN1ParserKdcReqBody : public ASN1ParserSequence
{
public:
ASN1ParserKdcReqBody(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_kdc_options(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_kdc_options ),
PROP( KDC_REQ_BODY_kdc_options_summary ),
PROP( KDC_REQ_BODY_kdc_options_value ),
0 ),
m_cname( // TODO: enforce the fact that TGS KDC-REQ-BODY does not have this
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_cname ),
PROP( KDC_REQ_BODY_cname )),
m_realm(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_realm ),
PROP( KDC_REQ_BODY_realm ),
0 ),
m_sname(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_sname ),
PROP( KDC_REQ_BODY_sname )),
m_from(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_from ),
PROP( KDC_REQ_BODY_from)),
m_till(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_till ),
PROP( KDC_REQ_BODY_till )),
m_rtime(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_rtime ),
PROP( KDC_REQ_BODY_rtime )),
m_nonce(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_nonce ),
PROP( KDC_REQ_BODY_nonce ),
0 ),
m_etype(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_etype ),
PROP( KDC_REQ_BODY_etype ),
PROP( EncryptionType )),
m_addresses(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_addresses ),
PROP( KDC_REQ_BODY_addresses )),
m_enc_authorization_data(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_enc_authorization_data ),
PROP( KDC_REQ_BODY_enc_authorization_data)),
m_additional_tickets(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_additional_tickets ),
PROP( KDC_REQ_BODY_additional_tickets ),
PROP( AdditionalTicket ))
{
m_p[0] = &m_kdc_options;
m_p[1] = &m_cname;
m_p[2] = &m_realm;
m_p[3] = &m_sname;
m_p[4] = &m_from;
m_p[5] = &m_till;
m_p[6] = &m_rtime;
m_p[7] = &m_nonce;
m_p[8] = &m_etype;
m_p[9] = &m_addresses;
m_p[10] = &m_enc_authorization_data;
m_p[11] = &m_additional_tickets;
}
private:
enum
{
e_kdc_options = 0,
e_cname = 1,
e_realm = 2,
e_sname = 3,
e_from = 4,
e_till = 5,
e_rtime = 6,
e_nonce = 7,
e_etype = 8,
e_addresses = 9,
e_enc_authorization_data = 10,
e_additional_tickets = 11,
};
ASN1ParserBase * m_p[12];
ASN1ParserBitString m_kdc_options;
ASN1ParserPrincipalName m_cname;
ASN1ParserGeneralString m_realm;
ASN1ParserPrincipalName m_sname;
ASN1ParserGeneralizedTime m_from;
ASN1ParserGeneralizedTime m_till;
ASN1ParserGeneralizedTime m_rtime;
ASN1ParserInteger m_nonce;
ASN1ParserIntegerSequence m_etype;
ASN1ParserHostAddresses m_addresses;
ASN1ParserEncryptedData m_enc_authorization_data;
ASN1ParserTicketSequence m_additional_tickets;
};
// -----------------------------------------------------------------------------
// KDC-REQ ::= SEQUENCE {
// pvno[1] INTEGER,
// msg-type[2] INTEGER,
// padata[3] SEQUENCE OF PA-DATA OPTIONAL,
// req-body[4] KDC-REQ-BODY
// }
// -----------------------------------------------------------------------------
class ASN1ParserKdcReq : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKdcReq(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_pvno(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_pvno ),
PROP( KDC_REQ_pvno ),
0 ),
m_msg_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_msg_type ),
PROP( KDC_REQ_msg_type ),
0,
0x1F ), // only care about the bottom five bits of the value
m_padata(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_padata ),
PROP( KDC_REQ_padata )),
m_kdc_req_body(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_req_body ),
PROP( KDC_REQ_req_body ))
{
m_p[0] = &m_pvno;
m_p[1] = &m_msg_type;
m_p[2] = &m_padata;
m_p[3] = &m_kdc_req_body;
}
private:
enum
{
e_pvno = 1,
e_msg_type = 2,
e_padata = 3,
e_req_body = 4,
};
ASN1ParserBase * m_p[4];
ASN1ParserInteger m_pvno;
ASN1ParserInteger m_msg_type;
ASN1ParserPaDataSequence m_padata;
ASN1ParserKdcReqBody m_kdc_req_body;
};
// -----------------------------------------------------------------------------
// KDC-REP ::= SEQUENCE {
// pvno[0] INTEGER,
// msg-type[1] INTEGER,
// padata[2] SEQUENCE OF PA-DATA OPTIONAL,
// crealm[3] Realm,
// cname[4] PrincipalName,
// ticket[5] Ticket,
// enc-part[6] EncryptedData
// }
// -----------------------------------------------------------------------------
class ASN1ParserKdcRep : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKdcRep(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_pvno(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_pvno ),
PROP( KDC_REP_pvno ),
0 ),
m_msg_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_msg_type ),
PROP( KDC_REP_msg_type ),
0 ),
m_padata(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_padata ),
PROP( KDC_REP_padata )),
m_crealm(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_crealm ),
PROP( KDC_REP_crealm ),
0 ),
m_cname(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_cname ),
PROP( KDC_REP_cname )),
m_ticket(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_ticket ),
PROP( KDC_REP_ticket )),
m_enc_part(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_enc_part ),
PROP( KDC_REP_enc_part ))
{
m_p[0] = &m_pvno;
m_p[1] = &m_msg_type;
m_p[2] = &m_padata;
m_p[3] = &m_crealm;
m_p[4] = &m_cname;
m_p[5] = &m_ticket;
m_p[6] = &m_enc_part;
}
private:
enum
{
e_pvno = 0,
e_msg_type = 1,
e_padata = 2,
e_crealm = 3,
e_cname = 4,
e_ticket = 5,
e_enc_part = 6,
};
ASN1ParserBase * m_p[7];
ASN1ParserInteger m_pvno;
ASN1ParserInteger m_msg_type;
ASN1ParserPaDataSequence m_padata;
ASN1ParserGeneralString m_crealm;
ASN1ParserPrincipalName m_cname;
ASN1ParserTicket m_ticket;
ASN1ParserEncryptedData m_enc_part;
};
// -----------------------------------------------------------------------------
// KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
// pvno[0] INTEGER,
// msg-type[1] INTEGER,
// ctime[2] KerberosTime OPTIONAL,
// cusec[3] INTEGER OPTIONAL,
// stime[4] KerberosTime,
// susec[5] INTEGER,
// error-code[6] INTEGER,
// crealm[7] Realm OPTIONAL,
// cname[8] PrincipalName OPTIONAL,
// realm[9] Realm, -- Correct realm
// sname[10] PrincipalName, -- Correct name
// e-text[11] GeneralString OPTIONAL,
// e-data[12] OCTET STRING OPTIONAL
// }
// -----------------------------------------------------------------------------
class ASN1ParserKrbError : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKrbError(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_pvno(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_pvno ),
PROP( KRB_ERR_pvno ),
0 ),
m_msg_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_msg_type ),
PROP( KRB_ERR_msg_type ),
0 ),
m_ctime(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_ctime ),
PROP( KRB_ERR_ctime )),
m_cusec(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_cusec ),
PROP( KRB_ERR_cusec ),
0 ),
m_stime(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_stime ),
PROP( KRB_ERR_stime )),
m_susec(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_susec ),
PROP( KRB_ERR_susec ),
0 ),
m_error_code(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_error_code ),
PROP( KRB_ERR_error_code ),
0 ),
m_crealm(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_crealm ),
PROP( KRB_ERR_crealm ),
0 ),
m_cname(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_cname ),
PROP( KRB_ERR_cname )),
m_realm(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_realm ),
PROP( KRB_ERR_realm ),
0 ),
m_sname(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_sname ),
PROP( KRB_ERR_sname )),
m_e_text(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_e_text ),
PROP( KRB_ERR_e_text ),
0 ),
m_e_data(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_e_data ),
PROP( KRB_ERR_e_data ))
{
m_p[0] = &m_pvno;
m_p[1] = &m_msg_type;
m_p[2] = &m_ctime;
m_p[3] = &m_cusec;
m_p[4] = &m_stime;
m_p[5] = &m_susec;
m_p[6] = &m_error_code;
m_p[7] = &m_crealm;
m_p[8] = &m_cname;
m_p[9] = &m_realm;
m_p[10] = &m_sname;
m_p[11] = &m_e_text;
m_p[12] = &m_e_data;
//
// Address type affects the parsing of the error data portion
//
m_error_code.SetModifyee( &m_e_data );
}
private:
enum
{
e_pvno = 0,
e_msg_type = 1,
e_ctime = 2,
e_cusec = 3,
e_stime = 4,
e_susec = 5,
e_error_code = 6,
e_crealm = 7,
e_cname = 8,
e_realm = 9,
e_sname = 10,
e_e_text = 11,
e_e_data = 12,
};
ASN1ParserBase * m_p[13];
ASN1ParserInteger m_pvno;
ASN1ParserInteger m_msg_type;
ASN1ParserGeneralizedTime m_ctime;
ASN1ParserInteger m_cusec;
ASN1ParserGeneralizedTime m_stime;
ASN1ParserInteger m_susec;
ASN1ParserInteger m_error_code;
ASN1ParserGeneralString m_crealm;
ASN1ParserPrincipalName m_cname;
ASN1ParserGeneralString m_realm;
ASN1ParserPrincipalName m_sname;
ASN1ParserGeneralString m_e_text;
ASN1ParserErrorData m_e_data;
};
// -----------------------------------------------------------------------------
// KERB-ETYPE-INFO-ENTRY ::= SEQUENCE {
// encryption-type[0] INTEGER,
// salt[1] OCTET STRING OPTIONAL
// }
// -----------------------------------------------------------------------------
class ASN1ParserKerbEtypeInfoEntry : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKerbEtypeInfoEntry(
IN BOOL IsOptional,
IN BYTE Descriptor
) : ASN1ParserSequence(
IsOptional,
Descriptor,
NULL,
ARRAY_COUNT( m_p ),
m_p ),
m_encryption_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_encryption_type ),
NULL,
0 ),
m_salt(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_salt ),
NULL,
0 ),
m_what_is_this_integer(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_what_is_this_integer ),
NULL,
0 )
{
m_p[0] = &m_encryption_type;
m_p[1] = &m_salt;
m_p[2] = &m_what_is_this_integer;
//
// Handle the display of this one for ease of readability
//
m_encryption_type.SetValueCollector( this );
m_salt.SetValueCollector( this );
m_what_is_this_integer.SetValueCollector( this );
}
protected:
DWORD
DisplayCollectedValues(
IN ASN1FRAME * Frame,
IN ULONG Length,
IN ULPBYTE Address );
private:
enum
{
e_encryption_type = 0,
e_salt = 1,
e_what_is_this_integer = 2,
};
ASN1ParserBase * m_p[3];
ASN1ParserInteger m_encryption_type;
ASN1ParserOctetString m_salt;
ASN1ParserInteger m_what_is_this_integer;
};
// -----------------------------------------------------------------------------
// PKERB-ETYPE-INFO ::= SEQUENCE OF KERB-ETYPE-INFO-ENTRY
// -----------------------------------------------------------------------------
class ASN1ParserKerbEtypeInfo : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKerbEtypeInfo(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_kerb_etype_info_entry(
FALSE,
0 ) // no descriptor on individual addresses sequences
{
m_p[0] = &m_kerb_etype_info_entry;
}
private:
ASN1ParserBase * m_p[1];
ASN1ParserKerbEtypeInfoEntry m_kerb_etype_info_entry;
};
// -----------------------------------------------------------------------------
// KERB-PA-FOR-USER ::= SEQUENCE {
// -- PA TYPE 129
// userName [0] KERB-PRINCIPAL-NAME,
// userRealm [1] KERB-REALM,
// cksum [2] KERB-CHECKSUM,
// authentication-package [3] GeneralString,
// authorization-data [4] OCTET STRING OPTIONAL,
// ...
// }--#public--
// -----------------------------------------------------------------------------
class ASN1ParserKerbPaForUser : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserKerbPaForUser(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p,
TRUE ),
m_userName(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_userName ),
PROP( PA_FOR_USER_userName )),
m_userRealm(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_userRealm ),
PROP( PA_FOR_USER_userRealm ),
0 ),
m_cksum(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_cksum ),
PROP( PA_FOR_USER_cksum )),
m_authentication_package(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_authentication_package ),
PROP( PA_FOR_USER_authentication_package ),
0 ),
m_authorization_data(
TRUE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_authorization_data ),
PROP( PA_FOR_USER_authorization_data ),
0 )
{
m_p[0] = &m_userName;
m_p[1] = &m_userRealm;
m_p[2] = &m_cksum;
m_p[3] = &m_authentication_package;
m_p[4] = &m_authorization_data;
}
private:
enum
{
e_userName = 0,
e_userRealm = 1,
e_cksum = 2,
e_authentication_package = 3,
e_authorization_data = 4,
};
ASN1ParserBase * m_p[5];
ASN1ParserPrincipalName m_userName;
ASN1ParserGeneralString m_userRealm;
ASN1ParserKerbChecksum m_cksum;
ASN1ParserGeneralString m_authentication_package;
ASN1ParserOctetString m_authorization_data;
};
// -----------------------------------------------------------------------------
// AP-REQ ::= [APPLICATION 14] SEQUENCE {
// pvno[0] INTEGER,
// msg-type[1] INTEGER,
// ap-options[2] APOptions,
// ticket[3] Ticket,
// authenticator[4] EncryptedData
// }
// -----------------------------------------------------------------------------
class ASN1ParserApReq : public ASN1ParserSequence
{
public:
//
// Constructor
//
ASN1ParserApReq(
IN BOOL IsOptional,
IN BYTE Descriptor,
IN HPROPERTY hProperty
) : ASN1ParserSequence(
IsOptional,
Descriptor,
hProperty,
ARRAY_COUNT( m_p ),
m_p ),
m_pvno(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_pvno ),
PROP( AP_REQ_pvno ),
0 ),
m_msg_type(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_msg_type ),
PROP( AP_REQ_msg_type ),
0 ),
m_ap_options(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_ap_options ),
PROP( AP_REQ_ap_options_summary ),
PROP( AP_REQ_ap_options_value ),
0 ),
m_ticket(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_ticket ),
PROP( AP_REQ_ticket )),
m_authenticator(
FALSE,
BuildDescriptor( ctContextSpecific, pcConstructed, e_authenticator ),
PROP( AP_REQ_authenticator ))
{
SetAppDescriptor(
BuildDescriptor( ctApplication, pcConstructed, ASN1_KRB_AP_REQ )
);
m_p[0] = &m_pvno;
m_p[1] = &m_msg_type;
m_p[2] = &m_ap_options;
m_p[3] = &m_ticket;
m_p[4] = &m_authenticator;
}
private:
enum
{
e_pvno = 0,
e_msg_type = 1,
e_ap_options = 2,
e_ticket = 3,
e_authenticator = 4,
};
ASN1ParserBase * m_p[5];
ASN1ParserInteger m_pvno;
ASN1ParserInteger m_msg_type;
ASN1ParserBitString m_ap_options;
ASN1ParserTicket m_ticket;
ASN1ParserEncryptedData m_authenticator;
};
#endif // __ASN1PARSER_HXX