Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

923 lines
20 KiB

#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