924 lines
20 KiB
C
924 lines
20 KiB
C
#if DBG
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <ntsdexts.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "ber.h"
|
|
|
|
#define iso_member 0x2a, // iso(1) memberbody(2)
|
|
#define us 0x86, 0x48, // us(840)
|
|
#define rsadsi 0x86, 0xf7, 0x0d, // rsadsi(113549)
|
|
#define pkcs 0x01, // pkcs(1)
|
|
|
|
#define rsa_ iso_member us rsadsi
|
|
#define rsa_len 6
|
|
#define rsa_text "iso(2) member-body(2) us(840) rsadsi(113549) "
|
|
#define pkcs_1 iso_member us rsadsi pkcs
|
|
#define pkcs_len 7
|
|
#define pkcs_text "iso(2) member-body(2) us(840) rsadsi(113549) pkcs(1) "
|
|
|
|
|
|
#define joint_iso_ccitt_ds 0x55,
|
|
#define attributetype 0x04,
|
|
|
|
#define attributeType joint_iso_ccitt_ds attributetype
|
|
#define attrtype_len 2
|
|
|
|
DWORD DebugLevel = H323_DEBUG_LEVEL;
|
|
|
|
typedef struct _ObjectId {
|
|
UCHAR Sequence[16];
|
|
DWORD SequenceLen;
|
|
PSTR Name;
|
|
} ObjectId;
|
|
|
|
ObjectId KnownObjectIds[] = {
|
|
{ {pkcs_1 1, 1}, pkcs_len + 2, pkcs_text "RSA"},
|
|
{ {pkcs_1 1, 2}, pkcs_len + 2, pkcs_text "MD2/RSA"},
|
|
{ {pkcs_1 1, 4}, pkcs_len + 2, pkcs_text "MD5/RSA"},
|
|
{ {rsa_ 3, 4}, rsa_len + 2, rsa_text "RC4"},
|
|
{ {attributeType 3}, attrtype_len + 1, "CN="},
|
|
{ {attributeType 6}, attrtype_len + 1, "C="},
|
|
{ {attributeType 7}, attrtype_len + 1, "L="},
|
|
{ {attributeType 8}, attrtype_len + 1, "S="},
|
|
{ {attributeType 10}, attrtype_len + 1, "O="},
|
|
{ {attributeType 11}, attrtype_len + 1, "OU="},
|
|
};
|
|
|
|
ObjectId KnownPrefixes[] = {
|
|
{ {pkcs_1}, pkcs_len, pkcs_text},
|
|
{ {iso_member us rsadsi}, pkcs_len - 1, "iso(2) member-body(2) us(840) rsadsi(113549) "},
|
|
{ {iso_member us}, pkcs_len - 4, "iso(2) member-body(2) us(840) "},
|
|
{ {iso_member}, pkcs_len - 6, "iso(2) member-body(2) " }
|
|
};
|
|
|
|
|
|
typedef struct _NameTypes {
|
|
PSTR Prefix;
|
|
UCHAR Sequence[8];
|
|
DWORD SequenceLen;
|
|
} NameTypes;
|
|
|
|
NameTypes KnownNameTypes[] = { {"CN=", {attributeType 3}, attrtype_len + 1},
|
|
{"C=", {attributeType 6}, attrtype_len + 1},
|
|
{"L=", {attributeType 7}, attrtype_len + 1},
|
|
{"S=", {attributeType 8}, attrtype_len + 1},
|
|
{"O=", {attributeType 10}, attrtype_len + 1},
|
|
{"OU=", {attributeType 11}, attrtype_len + 1}
|
|
};
|
|
BYTE Buffer[1024];
|
|
|
|
BOOL BerVerbose = FALSE ;
|
|
|
|
char maparray[] = "0123456789abcdef";
|
|
|
|
#define MAX_OID_VALS 32
|
|
|
|
typedef struct _OID {
|
|
unsigned cVal;
|
|
unsigned Val[MAX_OID_VALS];
|
|
} OID;
|
|
|
|
typedef enum _OidResult {
|
|
OidExact,
|
|
OidPartial,
|
|
OidMiss,
|
|
OidError
|
|
} OidResult;
|
|
|
|
|
|
#if 0
|
|
|
|
extern PNTSD_EXTENSION_APIS pExtApis;
|
|
extern HANDLE hDbgThread;
|
|
extern HANDLE hDbgProcess;
|
|
|
|
#define DebuggerOut (pExtApis->lpOutputRoutine)
|
|
#define GetSymbol (pExtApis->lpGetSymbolRoutine)
|
|
#define GetExpr (PVOID) (pExtApis->lpGetExpressionRoutine)
|
|
#define InitDebugHelp(hProc,hThd,pApis) {hDbgProcess = hProc; hDbgThread = hThd; pExtApis = pApis;}
|
|
|
|
#define ExitIfCtrlC() if (pExtApis->lpCheckControlCRoutine()) return;
|
|
#define BreakIfCtrlC() if (pExtApis->lpCheckControlCRoutine()) break;
|
|
|
|
#else
|
|
|
|
#define DebuggerOut OutputDebugString
|
|
#define ExitifCtrlC() ((void)0)
|
|
#define BreakIfCtrlC() ((void)0)
|
|
|
|
#endif
|
|
|
|
|
|
#define LINE_SIZE 192
|
|
#define INDENT_SIZE 4
|
|
|
|
#define OID_VERBOSE 0x0002
|
|
#define OID_PARTIAL 0x0001
|
|
|
|
char * DefaultTree =
|
|
"1 iso\n"
|
|
" 2 memberbody\n"
|
|
" 840 us\n"
|
|
" 113549 rsadsi\n"
|
|
" 1 pkcs\n"
|
|
" 1 RSA\n"
|
|
" 3 pkcs-3\n"
|
|
" 1 dhKeyAgreement\n"
|
|
" 2 digestAlgorithm\n"
|
|
" 2 MD2\n"
|
|
" 4 MD4\n"
|
|
" 5 MD5\n"
|
|
" 113554 mit\n"
|
|
" 1 infosys\n"
|
|
" 2 gssapi\n"
|
|
" 1 generic\n"
|
|
" 1 user_name\n"
|
|
" 2 machine_uid_name\n"
|
|
" 3 string_uid_name\n"
|
|
" 113556 microsoft\n"
|
|
" 1 ds\n"
|
|
" 3 org\n"
|
|
" 6 dod\n"
|
|
" 1 internet\n"
|
|
" 4 private\n"
|
|
" 1 enterprise\n"
|
|
" 311 microsoft\n"
|
|
" 1 software\n"
|
|
" 1 systems\n"
|
|
" 2 wins\n"
|
|
" 3 dhcp\n"
|
|
" 4 apps\n"
|
|
" 5 mos\n"
|
|
" 7 InternetServer\n"
|
|
" 8 ipx\n"
|
|
" 9 ripsap\n"
|
|
" 2 security\n"
|
|
" 1 certificates\n"
|
|
" 2 mechanisms\n"
|
|
" 9 Negotiator\n"
|
|
" 10 NTLM\n"
|
|
" 12 SSL\n"
|
|
" 5 security\n"
|
|
" 3 integrity\n"
|
|
" 1 md5-DES-CBC\n"
|
|
" 2 sum64-DES-CBC\n"
|
|
" 5 mechanisms\n"
|
|
" 1 spkm\n"
|
|
" 1 spkm-1\n"
|
|
" 2 spkm-2\n"
|
|
" 10 spkmGssTokens\n"
|
|
" 6 nametypes\n"
|
|
" 2 gss-host-based-services\n"
|
|
" 3 gss-anonymous-name\n"
|
|
" 4 gss-api-exported-name\n"
|
|
" 14 oiw\n"
|
|
" 3 secsig\n"
|
|
" 2 algorithm\n"
|
|
" 7 DES-CBC\n"
|
|
" 10 DES-MAC\n"
|
|
" 18 SHA\n"
|
|
" 22 id-rsa-key-transport\n"
|
|
"2 joint-iso-ccitt\n"
|
|
" 5 ds\n"
|
|
" 4 attribute-type\n"
|
|
" 3 CommonName\n"
|
|
" 6 Country\n"
|
|
" 7 Locality\n"
|
|
" 8 State\n"
|
|
" 10 Organization\n"
|
|
" 11 OrgUnit\n"
|
|
;
|
|
|
|
|
|
typedef struct _TreeFile {
|
|
CHAR * Buffer;
|
|
CHAR * Line;
|
|
CHAR * CurNul;
|
|
} TreeFile, * PTreeFile ;
|
|
|
|
|
|
BOOL
|
|
TreeFileInit(
|
|
PTreeFile pFile,
|
|
PSTR pStr)
|
|
{
|
|
int l;
|
|
|
|
|
|
l = strlen( pStr );
|
|
|
|
if ( (pStr[l - 1] != '\r') &&
|
|
(pStr[l - 1] != '\n') )
|
|
{
|
|
l++;
|
|
}
|
|
|
|
pFile->Buffer = LocalAlloc( LMEM_FIXED, l );
|
|
|
|
if ( pFile->Buffer )
|
|
{
|
|
strcpy( pFile->Buffer, pStr );
|
|
pFile->Line = pFile->Buffer ;
|
|
pFile->CurNul = NULL ;
|
|
}
|
|
|
|
return (pFile->Buffer != NULL);
|
|
|
|
}
|
|
|
|
VOID
|
|
TreeFileDelete(
|
|
PTreeFile pFile
|
|
)
|
|
{
|
|
LocalFree( pFile->Buffer );
|
|
|
|
}
|
|
|
|
PSTR
|
|
TreeFileGetLine(
|
|
PTreeFile pFile )
|
|
{
|
|
PSTR Scan;
|
|
PSTR Line;
|
|
|
|
if ( !pFile->Line )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
if ( pFile->CurNul )
|
|
{
|
|
*pFile->CurNul = '\n';
|
|
}
|
|
|
|
pFile->CurNul = NULL ;
|
|
|
|
Scan = pFile->Line ;
|
|
|
|
while ( *Scan && (*Scan != '\n') && (*Scan != '\r'))
|
|
{
|
|
Scan++;
|
|
}
|
|
|
|
//
|
|
// Okay, get the line to return
|
|
//
|
|
|
|
Line = pFile->Line;
|
|
|
|
//
|
|
// If this is not the end, touch up the pointers:
|
|
//
|
|
|
|
if ( *Scan )
|
|
{
|
|
*Scan = '\0';
|
|
|
|
pFile->CurNul = Scan;
|
|
|
|
Scan += 1;
|
|
|
|
while ( *Scan && ( (*Scan == '\r' ) || ( *Scan == '\n') ))
|
|
{
|
|
Scan++ ;
|
|
}
|
|
|
|
//
|
|
// If this is the end, reset line
|
|
//
|
|
|
|
if ( *Scan == '\0' )
|
|
{
|
|
pFile->Line = NULL ;
|
|
}
|
|
else
|
|
{
|
|
pFile->Line = Scan;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
pFile->Line = NULL ;
|
|
}
|
|
|
|
return( Line );
|
|
|
|
}
|
|
|
|
VOID
|
|
TreeFileRewind(
|
|
PTreeFile pFile )
|
|
{
|
|
|
|
if ( pFile->CurNul )
|
|
{
|
|
*pFile->CurNul = '\n';
|
|
}
|
|
|
|
pFile->CurNul = NULL ;
|
|
|
|
pFile->Line = pFile->Buffer ;
|
|
}
|
|
|
|
int
|
|
tohex(
|
|
BYTE b,
|
|
PSTR psz)
|
|
{
|
|
BYTE b1, b2;
|
|
|
|
b1 = b >> 4;
|
|
b2 = b & 0xF;
|
|
|
|
*psz++ = maparray[b1];
|
|
*psz = maparray[b2];
|
|
|
|
return(3);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DecodeOID
|
|
//
|
|
// Synopsis: Decodes an OID into a simple structure
|
|
//
|
|
// Arguments: [pEncoded] --
|
|
// [len] --
|
|
// [pOID] --
|
|
//
|
|
// History: 8-07-96 RichardW Stolen directly from DonH
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
DecodeOID(unsigned char *pEncoded, int len, OID *pOID)
|
|
{
|
|
unsigned cval;
|
|
unsigned val;
|
|
int i, j;
|
|
|
|
if (len <=2) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// The first two values are encoded in the first octet.
|
|
|
|
pOID->Val[0] = pEncoded[0] / 40;
|
|
pOID->Val[1] = pEncoded[0] % 40;
|
|
|
|
//DebuggerOut("Encoded value %02x turned into %d and %d\n", pEncoded[0],
|
|
// pOID->Val[0], pOID->Val[1] );
|
|
|
|
cval = 2;
|
|
i = 1;
|
|
|
|
while (i < len) {
|
|
j = 0;
|
|
val = pEncoded[i] & 0x7f;
|
|
while (pEncoded[i] & 0x80) {
|
|
val <<= 7;
|
|
++i;
|
|
if (++j > 4 || i >= len) {
|
|
// Either this value is bigger than we can handle (we
|
|
// don't handle values that span more than four octets)
|
|
// -or- the last octet in the encoded string has its
|
|
// high bit set, indicating that it's not supposed to
|
|
// be the last octet. In either case, we're sunk.
|
|
return FALSE;
|
|
}
|
|
val |= pEncoded[i] & 0x7f;
|
|
}
|
|
//ASSERT(i < len);
|
|
pOID->Val[cval] = val;
|
|
++cval;
|
|
++i;
|
|
}
|
|
pOID->cVal = cval;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PSTR
|
|
GetLineWithIndent(
|
|
PTreeFile ptf,
|
|
DWORD i)
|
|
{
|
|
PSTR Scan;
|
|
DWORD test;
|
|
|
|
|
|
do
|
|
{
|
|
Scan = TreeFileGetLine( ptf );
|
|
|
|
|
|
if ( Scan && i )
|
|
{
|
|
if ( i < INDENT_SIZE )
|
|
{
|
|
test = 0;
|
|
}
|
|
else
|
|
{
|
|
test = i - INDENT_SIZE ;
|
|
}
|
|
|
|
if ( Scan[ test ] != ' ' )
|
|
{
|
|
{
|
|
Scan = NULL ;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
test = 0;
|
|
|
|
} while ( Scan && (Scan[i] == ' ') );
|
|
|
|
return( Scan );
|
|
}
|
|
|
|
OidResult
|
|
scan_oid_table(
|
|
char * Table,
|
|
DWORD Flags,
|
|
PUCHAR ObjectId,
|
|
DWORD Len,
|
|
PSTR pszRep,
|
|
DWORD MaxRep)
|
|
{
|
|
CHAR OidPath[ MAX_PATH ];
|
|
OID Oid;
|
|
DWORD i;
|
|
DWORD Indent;
|
|
TreeFile tf;
|
|
PSTR Scan;
|
|
PSTR Tag;
|
|
PSTR SubScan;
|
|
DWORD Index;
|
|
DWORD size;
|
|
DWORD TagSize;
|
|
|
|
if (!DecodeOID( ObjectId, Len, &Oid ))
|
|
{
|
|
return( OidError );
|
|
}
|
|
|
|
|
|
i = 0;
|
|
|
|
Indent = 0;
|
|
|
|
if ( !TreeFileInit( &tf, Table ) )
|
|
{
|
|
if (DebugLevel > 0) {
|
|
|
|
DebuggerOut("Unable to load prefix table\n");
|
|
|
|
}
|
|
|
|
return OidError ;
|
|
}
|
|
|
|
Tag = OidPath;
|
|
|
|
size = 0;
|
|
|
|
TagSize = 0;
|
|
|
|
|
|
if ( (Flags & OID_VERBOSE) == 0 )
|
|
{
|
|
while ( i < Oid.cVal )
|
|
{
|
|
TagSize = _snprintf( Tag, MAX_PATH - size, "%d.",
|
|
Oid.Val[i] );
|
|
|
|
size += TagSize;
|
|
|
|
Tag += TagSize;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
strncpy( pszRep, OidPath, MaxRep );
|
|
|
|
TreeFileDelete( &tf );
|
|
|
|
return( OidExact );
|
|
}
|
|
|
|
while ( i < Oid.cVal )
|
|
{
|
|
|
|
do
|
|
{
|
|
|
|
Scan = GetLineWithIndent( &tf, Indent );
|
|
|
|
|
|
if ( Scan )
|
|
{
|
|
Index = atoi(Scan);
|
|
}
|
|
else
|
|
{
|
|
Index = (DWORD) -1;
|
|
}
|
|
|
|
if ( Index == Oid.Val[i] )
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( Scan );
|
|
|
|
|
|
//
|
|
// If Scan is NULL, we didn't get a match
|
|
//
|
|
|
|
if ( !Scan )
|
|
{
|
|
if ( i > 0 )
|
|
{
|
|
if ( Flags & OID_PARTIAL )
|
|
{
|
|
while ( i < Oid.cVal )
|
|
{
|
|
TagSize = _snprintf( Tag, MAX_PATH - size, "%d ",
|
|
Oid.Val[i] );
|
|
|
|
size += TagSize;
|
|
|
|
Tag += TagSize;
|
|
|
|
i++;
|
|
|
|
}
|
|
strncpy( pszRep, OidPath, MaxRep );
|
|
}
|
|
|
|
TreeFileDelete( &tf );
|
|
|
|
return( OidPartial );
|
|
|
|
}
|
|
|
|
TreeFileDelete( &tf );
|
|
|
|
return( OidMiss );
|
|
}
|
|
|
|
//
|
|
// Got a hit:
|
|
//
|
|
|
|
SubScan = &Scan[Indent];
|
|
|
|
while (*SubScan != ' ')
|
|
{
|
|
SubScan++;
|
|
}
|
|
|
|
SubScan++;
|
|
|
|
TagSize = _snprintf( Tag, MAX_PATH - size, "%s(%d) ", SubScan, Index );
|
|
|
|
size += TagSize;
|
|
|
|
Tag += TagSize ;
|
|
|
|
Indent += INDENT_SIZE ;
|
|
|
|
i ++;
|
|
|
|
|
|
}
|
|
|
|
strncpy( pszRep, OidPath, MaxRep );
|
|
|
|
TreeFileDelete( &tf );
|
|
|
|
return( OidExact );
|
|
|
|
|
|
}
|
|
|
|
decode_to_string(
|
|
LPBYTE pBuffer,
|
|
DWORD Flags,
|
|
DWORD Type,
|
|
DWORD Len,
|
|
PSTR pszRep,
|
|
DWORD RepLen)
|
|
{
|
|
PSTR pstr;
|
|
PSTR lineptr;
|
|
DWORD i;
|
|
|
|
|
|
switch (Type)
|
|
{
|
|
case BER_NULL:
|
|
strcpy(pszRep, "<empty>");
|
|
break;
|
|
|
|
case BER_OBJECT_ID:
|
|
scan_oid_table( DefaultTree,
|
|
OID_PARTIAL | (Flags & DECODE_VERBOSE_OIDS ? OID_VERBOSE : 0 ),
|
|
pBuffer, Len, pszRep, RepLen );
|
|
|
|
break;
|
|
|
|
case BER_PRINTABLE_STRING:
|
|
case BER_TELETEX_STRING:
|
|
case BER_GRAPHIC_STRING:
|
|
case BER_VISIBLE_STRING:
|
|
case BER_GENERAL_STRING:
|
|
CopyMemory(pszRep, pBuffer, min(Len, RepLen - 1) );
|
|
pszRep[min(Len, RepLen - 1)] = '\0';
|
|
break;
|
|
|
|
default:
|
|
|
|
pstr = &pszRep[30];
|
|
lineptr = pszRep;
|
|
for (i = 0; i < min(Len, 8) ; i++ )
|
|
{
|
|
lineptr += tohex(*pBuffer, lineptr);
|
|
if ((*pBuffer >= ' ') && (*pBuffer <= '|'))
|
|
{
|
|
*pstr++ = *pBuffer;
|
|
}
|
|
else
|
|
{
|
|
*pstr++ = '.';
|
|
}
|
|
|
|
pBuffer++;
|
|
|
|
}
|
|
*pstr++ = '\0';
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
ber_decode(
|
|
OutputFn Out,
|
|
StopFn Stop,
|
|
LPBYTE pBuffer,
|
|
DWORD Flags,
|
|
int Indent,
|
|
int Offset,
|
|
int TotalLength,
|
|
int BarDepth)
|
|
{
|
|
char * TypeName = NULL;
|
|
char msg[32];
|
|
char * pstr;
|
|
int i;
|
|
int Len;
|
|
int ByteCount;
|
|
int Accumulated;
|
|
DWORD Type;
|
|
int subsize;
|
|
char line[ LINE_SIZE ];
|
|
BOOL Nested;
|
|
BOOL Leaf;
|
|
int NewBarDepth;
|
|
char nonuniversal[ LINE_SIZE ];
|
|
|
|
|
|
|
|
if ((Stop)())
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
Type = *pBuffer;
|
|
|
|
|
|
switch (Type & 0xC0) {
|
|
case BER_UNIVERSAL:
|
|
|
|
switch ( Type & 0x1F )
|
|
{
|
|
case BER_BOOL:
|
|
TypeName = "Bool";
|
|
break;
|
|
|
|
case BER_INTEGER:
|
|
TypeName = "Integer";
|
|
break;
|
|
|
|
case BER_BIT_STRING:
|
|
TypeName = "Bit String";
|
|
break;
|
|
|
|
case BER_OCTET_STRING:
|
|
TypeName = "Octet String";
|
|
if ( Flags & DECODE_NEST_OCTET_STRINGS )
|
|
{
|
|
TypeName = "Octet String (Expanding)";
|
|
Type |= BER_CONSTRUCTED ;
|
|
Flags &= ~( DECODE_NEST_OCTET_STRINGS );
|
|
}
|
|
break;
|
|
|
|
case BER_NULL:
|
|
TypeName = "Null";
|
|
break;
|
|
|
|
case BER_OBJECT_ID:
|
|
TypeName = "Object ID";
|
|
break;
|
|
|
|
case BER_OBJECT_DESC:
|
|
TypeName = "Object Descriptor";
|
|
break;
|
|
|
|
case BER_SEQUENCE:
|
|
TypeName = "Sequence";
|
|
break;
|
|
|
|
case BER_SET:
|
|
TypeName = "Set";
|
|
break;
|
|
|
|
case BER_NUMERIC_STRING:
|
|
TypeName = "Numeric String";
|
|
break;
|
|
|
|
case BER_PRINTABLE_STRING:
|
|
TypeName = "Printable String";
|
|
break;
|
|
|
|
case BER_TELETEX_STRING:
|
|
TypeName = "TeleTex String";
|
|
break;
|
|
|
|
case BER_VIDEOTEX_STRING:
|
|
TypeName = "VideoTex String";
|
|
break;
|
|
|
|
case BER_VISIBLE_STRING:
|
|
TypeName = "Visible String";
|
|
break;
|
|
|
|
case BER_GENERAL_STRING:
|
|
TypeName = "General String";
|
|
break;
|
|
|
|
case BER_GRAPHIC_STRING:
|
|
TypeName = "Graphic String";
|
|
break;
|
|
|
|
case BER_UTC_TIME:
|
|
TypeName = "UTC Time";
|
|
break;
|
|
|
|
|
|
default:
|
|
TypeName = "Unknown";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case BER_APPLICATION:
|
|
sprintf( nonuniversal, "[Application %d]", Type & 0x1F);
|
|
TypeName = nonuniversal;
|
|
break;
|
|
|
|
case BER_CONTEXT_SPECIFIC:
|
|
sprintf( nonuniversal, "[Context Specific %d]", Type & 0x1F);
|
|
TypeName = nonuniversal;
|
|
break;
|
|
|
|
case BER_PRIVATE:
|
|
sprintf( nonuniversal, "[Private %d]", Type & 0x1F);
|
|
TypeName = nonuniversal ;
|
|
break;
|
|
}
|
|
|
|
|
|
pstr = msg;
|
|
for (i = 0; i < Indent ; i++ )
|
|
{
|
|
if (i < BarDepth)
|
|
{
|
|
*pstr++ = '|';
|
|
}
|
|
else
|
|
{
|
|
*pstr++ = ' ';
|
|
}
|
|
*pstr++ = ' ';
|
|
}
|
|
*pstr++ = '\0';
|
|
|
|
pBuffer ++;
|
|
Len = 0;
|
|
|
|
if (*pBuffer & 0x80)
|
|
{
|
|
ByteCount = *pBuffer++ & 0x7f;
|
|
|
|
for (i = 0; i < ByteCount ; i++ )
|
|
{
|
|
Len <<= 8;
|
|
Len += *pBuffer++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ByteCount = 0;
|
|
Len = *pBuffer++;
|
|
}
|
|
|
|
if (Offset + Len + 2 + ByteCount == TotalLength)
|
|
{
|
|
Leaf = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Leaf = FALSE;
|
|
}
|
|
|
|
if (Type & BER_CONSTRUCTED)
|
|
{
|
|
Nested = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Nested = FALSE;
|
|
}
|
|
|
|
(Out)("%s%c-%cType = %s [%02XH], Length = %d, %s ",
|
|
msg,
|
|
Leaf ? '+' /* supposed to be top-to-right bar */ : '+',
|
|
Nested ? '+' : '-',
|
|
TypeName, Type, Len,
|
|
(Type & BER_CONSTRUCTED) ? "Constructed" : "Primitive");
|
|
|
|
if (Type & BER_CONSTRUCTED)
|
|
{
|
|
(Out)("\n");
|
|
Accumulated = 0;
|
|
while (Accumulated < Len)
|
|
{
|
|
if (BarDepth < Indent)
|
|
{
|
|
NewBarDepth = BarDepth;
|
|
}
|
|
else
|
|
{
|
|
NewBarDepth = (Nested && Leaf) ? BarDepth : Indent + 1;
|
|
}
|
|
|
|
subsize = ber_decode(Out, Stop, pBuffer, Flags, Indent + 1,
|
|
Accumulated, Len, NewBarDepth);
|
|
Accumulated += subsize;
|
|
pBuffer += subsize;
|
|
}
|
|
|
|
(Out)("%s%c\n", msg, ((Indent <= BarDepth) && !Leaf) ? 179 : 32);
|
|
}
|
|
else
|
|
{
|
|
memset(line, ' ', LINE_SIZE - 1);
|
|
line[ LINE_SIZE - 1 ] = '\0';
|
|
|
|
decode_to_string(pBuffer, Flags, Type, Len, line, LINE_SIZE);
|
|
|
|
(Out)(" Value = %s\n", line);
|
|
|
|
}
|
|
|
|
return(Len + 2 + ByteCount);
|
|
}
|
|
|
|
BOOL
|
|
NeverStop(void)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
#endif
|