#if DBG #include #include #include #include #include #include #include #include #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, ""); 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