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

  1. #if DBG
  2. #include <nt.h>
  3. #include <ntrtl.h>
  4. #include <nturtl.h>
  5. #include <windows.h>
  6. #include <ntsdexts.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "ber.h"
  11. #define iso_member 0x2a, // iso(1) memberbody(2)
  12. #define us 0x86, 0x48, // us(840)
  13. #define rsadsi 0x86, 0xf7, 0x0d, // rsadsi(113549)
  14. #define pkcs 0x01, // pkcs(1)
  15. #define rsa_ iso_member us rsadsi
  16. #define rsa_len 6
  17. #define rsa_text "iso(2) member-body(2) us(840) rsadsi(113549) "
  18. #define pkcs_1 iso_member us rsadsi pkcs
  19. #define pkcs_len 7
  20. #define pkcs_text "iso(2) member-body(2) us(840) rsadsi(113549) pkcs(1) "
  21. #define joint_iso_ccitt_ds 0x55,
  22. #define attributetype 0x04,
  23. #define attributeType joint_iso_ccitt_ds attributetype
  24. #define attrtype_len 2
  25. DWORD DebugLevel = H323_DEBUG_LEVEL;
  26. typedef struct _ObjectId {
  27. UCHAR Sequence[16];
  28. DWORD SequenceLen;
  29. PSTR Name;
  30. } ObjectId;
  31. ObjectId KnownObjectIds[] = {
  32. { {pkcs_1 1, 1}, pkcs_len + 2, pkcs_text "RSA"},
  33. { {pkcs_1 1, 2}, pkcs_len + 2, pkcs_text "MD2/RSA"},
  34. { {pkcs_1 1, 4}, pkcs_len + 2, pkcs_text "MD5/RSA"},
  35. { {rsa_ 3, 4}, rsa_len + 2, rsa_text "RC4"},
  36. { {attributeType 3}, attrtype_len + 1, "CN="},
  37. { {attributeType 6}, attrtype_len + 1, "C="},
  38. { {attributeType 7}, attrtype_len + 1, "L="},
  39. { {attributeType 8}, attrtype_len + 1, "S="},
  40. { {attributeType 10}, attrtype_len + 1, "O="},
  41. { {attributeType 11}, attrtype_len + 1, "OU="},
  42. };
  43. ObjectId KnownPrefixes[] = {
  44. { {pkcs_1}, pkcs_len, pkcs_text},
  45. { {iso_member us rsadsi}, pkcs_len - 1, "iso(2) member-body(2) us(840) rsadsi(113549) "},
  46. { {iso_member us}, pkcs_len - 4, "iso(2) member-body(2) us(840) "},
  47. { {iso_member}, pkcs_len - 6, "iso(2) member-body(2) " }
  48. };
  49. typedef struct _NameTypes {
  50. PSTR Prefix;
  51. UCHAR Sequence[8];
  52. DWORD SequenceLen;
  53. } NameTypes;
  54. NameTypes KnownNameTypes[] = { {"CN=", {attributeType 3}, attrtype_len + 1},
  55. {"C=", {attributeType 6}, attrtype_len + 1},
  56. {"L=", {attributeType 7}, attrtype_len + 1},
  57. {"S=", {attributeType 8}, attrtype_len + 1},
  58. {"O=", {attributeType 10}, attrtype_len + 1},
  59. {"OU=", {attributeType 11}, attrtype_len + 1}
  60. };
  61. BYTE Buffer[1024];
  62. BOOL BerVerbose = FALSE ;
  63. char maparray[] = "0123456789abcdef";
  64. #define MAX_OID_VALS 32
  65. typedef struct _OID {
  66. unsigned cVal;
  67. unsigned Val[MAX_OID_VALS];
  68. } OID;
  69. typedef enum _OidResult {
  70. OidExact,
  71. OidPartial,
  72. OidMiss,
  73. OidError
  74. } OidResult;
  75. #if 0
  76. extern PNTSD_EXTENSION_APIS pExtApis;
  77. extern HANDLE hDbgThread;
  78. extern HANDLE hDbgProcess;
  79. #define DebuggerOut (pExtApis->lpOutputRoutine)
  80. #define GetSymbol (pExtApis->lpGetSymbolRoutine)
  81. #define GetExpr (PVOID) (pExtApis->lpGetExpressionRoutine)
  82. #define InitDebugHelp(hProc,hThd,pApis) {hDbgProcess = hProc; hDbgThread = hThd; pExtApis = pApis;}
  83. #define ExitIfCtrlC() if (pExtApis->lpCheckControlCRoutine()) return;
  84. #define BreakIfCtrlC() if (pExtApis->lpCheckControlCRoutine()) break;
  85. #else
  86. #define DebuggerOut OutputDebugString
  87. #define ExitifCtrlC() ((void)0)
  88. #define BreakIfCtrlC() ((void)0)
  89. #endif
  90. #define LINE_SIZE 192
  91. #define INDENT_SIZE 4
  92. #define OID_VERBOSE 0x0002
  93. #define OID_PARTIAL 0x0001
  94. char * DefaultTree =
  95. "1 iso\n"
  96. " 2 memberbody\n"
  97. " 840 us\n"
  98. " 113549 rsadsi\n"
  99. " 1 pkcs\n"
  100. " 1 RSA\n"
  101. " 3 pkcs-3\n"
  102. " 1 dhKeyAgreement\n"
  103. " 2 digestAlgorithm\n"
  104. " 2 MD2\n"
  105. " 4 MD4\n"
  106. " 5 MD5\n"
  107. " 113554 mit\n"
  108. " 1 infosys\n"
  109. " 2 gssapi\n"
  110. " 1 generic\n"
  111. " 1 user_name\n"
  112. " 2 machine_uid_name\n"
  113. " 3 string_uid_name\n"
  114. " 113556 microsoft\n"
  115. " 1 ds\n"
  116. " 3 org\n"
  117. " 6 dod\n"
  118. " 1 internet\n"
  119. " 4 private\n"
  120. " 1 enterprise\n"
  121. " 311 microsoft\n"
  122. " 1 software\n"
  123. " 1 systems\n"
  124. " 2 wins\n"
  125. " 3 dhcp\n"
  126. " 4 apps\n"
  127. " 5 mos\n"
  128. " 7 InternetServer\n"
  129. " 8 ipx\n"
  130. " 9 ripsap\n"
  131. " 2 security\n"
  132. " 1 certificates\n"
  133. " 2 mechanisms\n"
  134. " 9 Negotiator\n"
  135. " 10 NTLM\n"
  136. " 12 SSL\n"
  137. " 5 security\n"
  138. " 3 integrity\n"
  139. " 1 md5-DES-CBC\n"
  140. " 2 sum64-DES-CBC\n"
  141. " 5 mechanisms\n"
  142. " 1 spkm\n"
  143. " 1 spkm-1\n"
  144. " 2 spkm-2\n"
  145. " 10 spkmGssTokens\n"
  146. " 6 nametypes\n"
  147. " 2 gss-host-based-services\n"
  148. " 3 gss-anonymous-name\n"
  149. " 4 gss-api-exported-name\n"
  150. " 14 oiw\n"
  151. " 3 secsig\n"
  152. " 2 algorithm\n"
  153. " 7 DES-CBC\n"
  154. " 10 DES-MAC\n"
  155. " 18 SHA\n"
  156. " 22 id-rsa-key-transport\n"
  157. "2 joint-iso-ccitt\n"
  158. " 5 ds\n"
  159. " 4 attribute-type\n"
  160. " 3 CommonName\n"
  161. " 6 Country\n"
  162. " 7 Locality\n"
  163. " 8 State\n"
  164. " 10 Organization\n"
  165. " 11 OrgUnit\n"
  166. ;
  167. typedef struct _TreeFile {
  168. CHAR * Buffer;
  169. CHAR * Line;
  170. CHAR * CurNul;
  171. } TreeFile, * PTreeFile ;
  172. BOOL
  173. TreeFileInit(
  174. PTreeFile pFile,
  175. PSTR pStr)
  176. {
  177. int l;
  178. l = strlen( pStr );
  179. if ( (pStr[l - 1] != '\r') &&
  180. (pStr[l - 1] != '\n') )
  181. {
  182. l++;
  183. }
  184. pFile->Buffer = LocalAlloc( LMEM_FIXED, l );
  185. if ( pFile->Buffer )
  186. {
  187. strcpy( pFile->Buffer, pStr );
  188. pFile->Line = pFile->Buffer ;
  189. pFile->CurNul = NULL ;
  190. }
  191. return (pFile->Buffer != NULL);
  192. }
  193. VOID
  194. TreeFileDelete(
  195. PTreeFile pFile
  196. )
  197. {
  198. LocalFree( pFile->Buffer );
  199. }
  200. PSTR
  201. TreeFileGetLine(
  202. PTreeFile pFile )
  203. {
  204. PSTR Scan;
  205. PSTR Line;
  206. if ( !pFile->Line )
  207. {
  208. return( NULL );
  209. }
  210. if ( pFile->CurNul )
  211. {
  212. *pFile->CurNul = '\n';
  213. }
  214. pFile->CurNul = NULL ;
  215. Scan = pFile->Line ;
  216. while ( *Scan && (*Scan != '\n') && (*Scan != '\r'))
  217. {
  218. Scan++;
  219. }
  220. //
  221. // Okay, get the line to return
  222. //
  223. Line = pFile->Line;
  224. //
  225. // If this is not the end, touch up the pointers:
  226. //
  227. if ( *Scan )
  228. {
  229. *Scan = '\0';
  230. pFile->CurNul = Scan;
  231. Scan += 1;
  232. while ( *Scan && ( (*Scan == '\r' ) || ( *Scan == '\n') ))
  233. {
  234. Scan++ ;
  235. }
  236. //
  237. // If this is the end, reset line
  238. //
  239. if ( *Scan == '\0' )
  240. {
  241. pFile->Line = NULL ;
  242. }
  243. else
  244. {
  245. pFile->Line = Scan;
  246. }
  247. }
  248. else
  249. {
  250. pFile->Line = NULL ;
  251. }
  252. return( Line );
  253. }
  254. VOID
  255. TreeFileRewind(
  256. PTreeFile pFile )
  257. {
  258. if ( pFile->CurNul )
  259. {
  260. *pFile->CurNul = '\n';
  261. }
  262. pFile->CurNul = NULL ;
  263. pFile->Line = pFile->Buffer ;
  264. }
  265. int
  266. tohex(
  267. BYTE b,
  268. PSTR psz)
  269. {
  270. BYTE b1, b2;
  271. b1 = b >> 4;
  272. b2 = b & 0xF;
  273. *psz++ = maparray[b1];
  274. *psz = maparray[b2];
  275. return(3);
  276. }
  277. //+---------------------------------------------------------------------------
  278. //
  279. // Function: DecodeOID
  280. //
  281. // Synopsis: Decodes an OID into a simple structure
  282. //
  283. // Arguments: [pEncoded] --
  284. // [len] --
  285. // [pOID] --
  286. //
  287. // History: 8-07-96 RichardW Stolen directly from DonH
  288. //
  289. // Notes:
  290. //
  291. //----------------------------------------------------------------------------
  292. BOOL
  293. DecodeOID(unsigned char *pEncoded, int len, OID *pOID)
  294. {
  295. unsigned cval;
  296. unsigned val;
  297. int i, j;
  298. if (len <=2) {
  299. return FALSE;
  300. }
  301. // The first two values are encoded in the first octet.
  302. pOID->Val[0] = pEncoded[0] / 40;
  303. pOID->Val[1] = pEncoded[0] % 40;
  304. //DebuggerOut("Encoded value %02x turned into %d and %d\n", pEncoded[0],
  305. // pOID->Val[0], pOID->Val[1] );
  306. cval = 2;
  307. i = 1;
  308. while (i < len) {
  309. j = 0;
  310. val = pEncoded[i] & 0x7f;
  311. while (pEncoded[i] & 0x80) {
  312. val <<= 7;
  313. ++i;
  314. if (++j > 4 || i >= len) {
  315. // Either this value is bigger than we can handle (we
  316. // don't handle values that span more than four octets)
  317. // -or- the last octet in the encoded string has its
  318. // high bit set, indicating that it's not supposed to
  319. // be the last octet. In either case, we're sunk.
  320. return FALSE;
  321. }
  322. val |= pEncoded[i] & 0x7f;
  323. }
  324. //ASSERT(i < len);
  325. pOID->Val[cval] = val;
  326. ++cval;
  327. ++i;
  328. }
  329. pOID->cVal = cval;
  330. return TRUE;
  331. }
  332. PSTR
  333. GetLineWithIndent(
  334. PTreeFile ptf,
  335. DWORD i)
  336. {
  337. PSTR Scan;
  338. DWORD test;
  339. do
  340. {
  341. Scan = TreeFileGetLine( ptf );
  342. if ( Scan && i )
  343. {
  344. if ( i < INDENT_SIZE )
  345. {
  346. test = 0;
  347. }
  348. else
  349. {
  350. test = i - INDENT_SIZE ;
  351. }
  352. if ( Scan[ test ] != ' ' )
  353. {
  354. {
  355. Scan = NULL ;
  356. break;
  357. }
  358. }
  359. }
  360. else
  361. test = 0;
  362. } while ( Scan && (Scan[i] == ' ') );
  363. return( Scan );
  364. }
  365. OidResult
  366. scan_oid_table(
  367. char * Table,
  368. DWORD Flags,
  369. PUCHAR ObjectId,
  370. DWORD Len,
  371. PSTR pszRep,
  372. DWORD MaxRep)
  373. {
  374. CHAR OidPath[ MAX_PATH ];
  375. OID Oid;
  376. DWORD i;
  377. DWORD Indent;
  378. TreeFile tf;
  379. PSTR Scan;
  380. PSTR Tag;
  381. PSTR SubScan;
  382. DWORD Index;
  383. DWORD size;
  384. DWORD TagSize;
  385. if (!DecodeOID( ObjectId, Len, &Oid ))
  386. {
  387. return( OidError );
  388. }
  389. i = 0;
  390. Indent = 0;
  391. if ( !TreeFileInit( &tf, Table ) )
  392. {
  393. if (DebugLevel > 0) {
  394. DebuggerOut("Unable to load prefix table\n");
  395. }
  396. return OidError ;
  397. }
  398. Tag = OidPath;
  399. size = 0;
  400. TagSize = 0;
  401. if ( (Flags & OID_VERBOSE) == 0 )
  402. {
  403. while ( i < Oid.cVal )
  404. {
  405. TagSize = _snprintf( Tag, MAX_PATH - size, "%d.",
  406. Oid.Val[i] );
  407. size += TagSize;
  408. Tag += TagSize;
  409. i++;
  410. }
  411. strncpy( pszRep, OidPath, MaxRep );
  412. TreeFileDelete( &tf );
  413. return( OidExact );
  414. }
  415. while ( i < Oid.cVal )
  416. {
  417. do
  418. {
  419. Scan = GetLineWithIndent( &tf, Indent );
  420. if ( Scan )
  421. {
  422. Index = atoi(Scan);
  423. }
  424. else
  425. {
  426. Index = (DWORD) -1;
  427. }
  428. if ( Index == Oid.Val[i] )
  429. {
  430. break;
  431. }
  432. } while ( Scan );
  433. //
  434. // If Scan is NULL, we didn't get a match
  435. //
  436. if ( !Scan )
  437. {
  438. if ( i > 0 )
  439. {
  440. if ( Flags & OID_PARTIAL )
  441. {
  442. while ( i < Oid.cVal )
  443. {
  444. TagSize = _snprintf( Tag, MAX_PATH - size, "%d ",
  445. Oid.Val[i] );
  446. size += TagSize;
  447. Tag += TagSize;
  448. i++;
  449. }
  450. strncpy( pszRep, OidPath, MaxRep );
  451. }
  452. TreeFileDelete( &tf );
  453. return( OidPartial );
  454. }
  455. TreeFileDelete( &tf );
  456. return( OidMiss );
  457. }
  458. //
  459. // Got a hit:
  460. //
  461. SubScan = &Scan[Indent];
  462. while (*SubScan != ' ')
  463. {
  464. SubScan++;
  465. }
  466. SubScan++;
  467. TagSize = _snprintf( Tag, MAX_PATH - size, "%s(%d) ", SubScan, Index );
  468. size += TagSize;
  469. Tag += TagSize ;
  470. Indent += INDENT_SIZE ;
  471. i ++;
  472. }
  473. strncpy( pszRep, OidPath, MaxRep );
  474. TreeFileDelete( &tf );
  475. return( OidExact );
  476. }
  477. decode_to_string(
  478. LPBYTE pBuffer,
  479. DWORD Flags,
  480. DWORD Type,
  481. DWORD Len,
  482. PSTR pszRep,
  483. DWORD RepLen)
  484. {
  485. PSTR pstr;
  486. PSTR lineptr;
  487. DWORD i;
  488. switch (Type)
  489. {
  490. case BER_NULL:
  491. strcpy(pszRep, "<empty>");
  492. break;
  493. case BER_OBJECT_ID:
  494. scan_oid_table( DefaultTree,
  495. OID_PARTIAL | (Flags & DECODE_VERBOSE_OIDS ? OID_VERBOSE : 0 ),
  496. pBuffer, Len, pszRep, RepLen );
  497. break;
  498. case BER_PRINTABLE_STRING:
  499. case BER_TELETEX_STRING:
  500. case BER_GRAPHIC_STRING:
  501. case BER_VISIBLE_STRING:
  502. case BER_GENERAL_STRING:
  503. CopyMemory(pszRep, pBuffer, min(Len, RepLen - 1) );
  504. pszRep[min(Len, RepLen - 1)] = '\0';
  505. break;
  506. default:
  507. pstr = &pszRep[30];
  508. lineptr = pszRep;
  509. for (i = 0; i < min(Len, 8) ; i++ )
  510. {
  511. lineptr += tohex(*pBuffer, lineptr);
  512. if ((*pBuffer >= ' ') && (*pBuffer <= '|'))
  513. {
  514. *pstr++ = *pBuffer;
  515. }
  516. else
  517. {
  518. *pstr++ = '.';
  519. }
  520. pBuffer++;
  521. }
  522. *pstr++ = '\0';
  523. }
  524. return(0);
  525. }
  526. int
  527. ber_decode(
  528. OutputFn Out,
  529. StopFn Stop,
  530. LPBYTE pBuffer,
  531. DWORD Flags,
  532. int Indent,
  533. int Offset,
  534. int TotalLength,
  535. int BarDepth)
  536. {
  537. char * TypeName = NULL;
  538. char msg[32];
  539. char * pstr;
  540. int i;
  541. int Len;
  542. int ByteCount;
  543. int Accumulated;
  544. DWORD Type;
  545. int subsize;
  546. char line[ LINE_SIZE ];
  547. BOOL Nested;
  548. BOOL Leaf;
  549. int NewBarDepth;
  550. char nonuniversal[ LINE_SIZE ];
  551. if ((Stop)())
  552. {
  553. return(0);
  554. }
  555. Type = *pBuffer;
  556. switch (Type & 0xC0) {
  557. case BER_UNIVERSAL:
  558. switch ( Type & 0x1F )
  559. {
  560. case BER_BOOL:
  561. TypeName = "Bool";
  562. break;
  563. case BER_INTEGER:
  564. TypeName = "Integer";
  565. break;
  566. case BER_BIT_STRING:
  567. TypeName = "Bit String";
  568. break;
  569. case BER_OCTET_STRING:
  570. TypeName = "Octet String";
  571. if ( Flags & DECODE_NEST_OCTET_STRINGS )
  572. {
  573. TypeName = "Octet String (Expanding)";
  574. Type |= BER_CONSTRUCTED ;
  575. Flags &= ~( DECODE_NEST_OCTET_STRINGS );
  576. }
  577. break;
  578. case BER_NULL:
  579. TypeName = "Null";
  580. break;
  581. case BER_OBJECT_ID:
  582. TypeName = "Object ID";
  583. break;
  584. case BER_OBJECT_DESC:
  585. TypeName = "Object Descriptor";
  586. break;
  587. case BER_SEQUENCE:
  588. TypeName = "Sequence";
  589. break;
  590. case BER_SET:
  591. TypeName = "Set";
  592. break;
  593. case BER_NUMERIC_STRING:
  594. TypeName = "Numeric String";
  595. break;
  596. case BER_PRINTABLE_STRING:
  597. TypeName = "Printable String";
  598. break;
  599. case BER_TELETEX_STRING:
  600. TypeName = "TeleTex String";
  601. break;
  602. case BER_VIDEOTEX_STRING:
  603. TypeName = "VideoTex String";
  604. break;
  605. case BER_VISIBLE_STRING:
  606. TypeName = "Visible String";
  607. break;
  608. case BER_GENERAL_STRING:
  609. TypeName = "General String";
  610. break;
  611. case BER_GRAPHIC_STRING:
  612. TypeName = "Graphic String";
  613. break;
  614. case BER_UTC_TIME:
  615. TypeName = "UTC Time";
  616. break;
  617. default:
  618. TypeName = "Unknown";
  619. break;
  620. }
  621. break;
  622. case BER_APPLICATION:
  623. sprintf( nonuniversal, "[Application %d]", Type & 0x1F);
  624. TypeName = nonuniversal;
  625. break;
  626. case BER_CONTEXT_SPECIFIC:
  627. sprintf( nonuniversal, "[Context Specific %d]", Type & 0x1F);
  628. TypeName = nonuniversal;
  629. break;
  630. case BER_PRIVATE:
  631. sprintf( nonuniversal, "[Private %d]", Type & 0x1F);
  632. TypeName = nonuniversal ;
  633. break;
  634. }
  635. pstr = msg;
  636. for (i = 0; i < Indent ; i++ )
  637. {
  638. if (i < BarDepth)
  639. {
  640. *pstr++ = '|';
  641. }
  642. else
  643. {
  644. *pstr++ = ' ';
  645. }
  646. *pstr++ = ' ';
  647. }
  648. *pstr++ = '\0';
  649. pBuffer ++;
  650. Len = 0;
  651. if (*pBuffer & 0x80)
  652. {
  653. ByteCount = *pBuffer++ & 0x7f;
  654. for (i = 0; i < ByteCount ; i++ )
  655. {
  656. Len <<= 8;
  657. Len += *pBuffer++;
  658. }
  659. }
  660. else
  661. {
  662. ByteCount = 0;
  663. Len = *pBuffer++;
  664. }
  665. if (Offset + Len + 2 + ByteCount == TotalLength)
  666. {
  667. Leaf = TRUE;
  668. }
  669. else
  670. {
  671. Leaf = FALSE;
  672. }
  673. if (Type & BER_CONSTRUCTED)
  674. {
  675. Nested = TRUE;
  676. }
  677. else
  678. {
  679. Nested = FALSE;
  680. }
  681. (Out)("%s%c-%cType = %s [%02XH], Length = %d, %s ",
  682. msg,
  683. Leaf ? '+' /* supposed to be top-to-right bar */ : '+',
  684. Nested ? '+' : '-',
  685. TypeName, Type, Len,
  686. (Type & BER_CONSTRUCTED) ? "Constructed" : "Primitive");
  687. if (Type & BER_CONSTRUCTED)
  688. {
  689. (Out)("\n");
  690. Accumulated = 0;
  691. while (Accumulated < Len)
  692. {
  693. if (BarDepth < Indent)
  694. {
  695. NewBarDepth = BarDepth;
  696. }
  697. else
  698. {
  699. NewBarDepth = (Nested && Leaf) ? BarDepth : Indent + 1;
  700. }
  701. subsize = ber_decode(Out, Stop, pBuffer, Flags, Indent + 1,
  702. Accumulated, Len, NewBarDepth);
  703. Accumulated += subsize;
  704. pBuffer += subsize;
  705. }
  706. (Out)("%s%c\n", msg, ((Indent <= BarDepth) && !Leaf) ? 179 : 32);
  707. }
  708. else
  709. {
  710. memset(line, ' ', LINE_SIZE - 1);
  711. line[ LINE_SIZE - 1 ] = '\0';
  712. decode_to_string(pBuffer, Flags, Type, Len, line, LINE_SIZE);
  713. (Out)(" Value = %s\n", line);
  714. }
  715. return(Len + 2 + ByteCount);
  716. }
  717. BOOL
  718. NeverStop(void)
  719. {
  720. return(FALSE);
  721. }
  722. #endif